svn commit: r324315 - head/sys/amd64/amd64
Konstantin Belousov
kib at FreeBSD.org
Thu Oct 5 13:13:01 UTC 2017
Author: kib
Date: Thu Oct 5 13:12:59 2017
New Revision: 324315
URL: https://svnweb.freebsd.org/changeset/base/324315
Log:
Ensure that after sucessfull i386_set_ldt() call, other threads can
use LDT segments immediately.
If the i386_set_ldt() call created a first LDT descriptor (and
consequently created the LDT) for our address space, LDTR is currently
loaded only on the CPU executing the syscall. Other CPUs executing
threads sharing the address space, would only load LDTR after context
switch.
Uncomment set_user_ldt_rv() and call it on all CPUs. Remove critical
section inside set_user_ldt(), it is not needed in the context of call
from smp_rendezvous().
Set md_ldt after md_ldt_sd is initialized using the same code sequence
as in user_ldt_free(). Do the whole initialization in a critical
section, to not race with the context switching while we set LDT.
Discussed with: bde
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Modified:
head/sys/amd64/amd64/sys_machdep.c
Modified: head/sys/amd64/amd64/sys_machdep.c
==============================================================================
--- head/sys/amd64/amd64/sys_machdep.c Thu Oct 5 13:01:18 2017 (r324314)
+++ head/sys/amd64/amd64/sys_machdep.c Thu Oct 5 13:12:59 2017 (r324315)
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/priv.h>
#include <sys/proc.h>
+#include <sys/smp.h>
#include <sys/sysproto.h>
#include <sys/uio.h>
@@ -80,11 +81,6 @@ max_ldt_segment_init(void *arg __unused)
}
SYSINIT(maxldt, SI_SUB_VM_CONF, SI_ORDER_ANY, max_ldt_segment_init, NULL);
-#ifdef notyet
-#ifdef SMP
-static void set_user_ldt_rv(struct vmspace *vmsp);
-#endif
-#endif
static void user_ldt_derefl(struct proc_ldt *pldt);
#ifndef _SYS_SYSPROTO_H_
@@ -430,14 +426,10 @@ static void
set_user_ldt(struct mdproc *mdp)
{
- critical_enter();
*PCPU_GET(ldt) = mdp->md_ldt_sd;
lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
- critical_exit();
}
-#ifdef notyet
-#ifdef SMP
static void
set_user_ldt_rv(struct vmspace *vmsp)
{
@@ -449,8 +441,6 @@ set_user_ldt_rv(struct vmspace *vmsp)
set_user_ldt(&td->td_proc->p_md);
}
-#endif
-#endif
struct proc_ldt *
user_ldt_alloc(struct proc *p, int force)
@@ -492,11 +482,13 @@ user_ldt_alloc(struct proc *p, int force)
sizeof(struct user_segment_descriptor));
user_ldt_derefl(pldt);
}
+ critical_enter();
ssdtosyssd(&sldt, &p->p_md.md_ldt_sd);
- atomic_store_rel_ptr((volatile uintptr_t *)&mdp->md_ldt,
- (uintptr_t)new_ldt);
- if (p == curproc)
- set_user_ldt(mdp);
+ atomic_thread_fence_rel();
+ mdp->md_ldt = new_ldt;
+ critical_exit();
+ smp_rendezvous(NULL, (void (*)(void *))set_user_ldt_rv, NULL,
+ p->p_vmspace);
return (mdp->md_ldt);
}
More information about the svn-src-all
mailing list