Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Oct 2017 13:12:59 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r324315 - head/sys/amd64/amd64
Message-ID:  <201710051312.v95DCxVm061349@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710051312.v95DCxVm061349>