Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Oct 2017 16:07:27 +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: r324437 - head/sys/i386/i386
Message-ID:  <201710091607.v99G7Rhl054971@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Mon Oct  9 16:07:27 2017
New Revision: 324437
URL: https://svnweb.freebsd.org/changeset/base/324437

Log:
  Improvements to set_user_ldt().
  
  Remove mtx_owned() checks from set_user_ldt().  Split the function
  into _locked() version which requires the dt_lock spinlock owned, and
  make set_user_ldt() a wrapper.  Add a comment in swtch.s noting that
  the call to the new set_user_ldt() cannot recurse on dt_lock.
  
  Remove #ifdef SMP block, the addend is always zero on UP.
  
  Fix type of set_user_ldt_rv(), making it match the type used for
  smb_rendezvous() callback, and remove the cast.  Use curproc.
  
  Reviewed by:	bde
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

Modified:
  head/sys/i386/i386/swtch.s
  head/sys/i386/i386/sys_machdep.c

Modified: head/sys/i386/i386/swtch.s
==============================================================================
--- head/sys/i386/i386/swtch.s	Mon Oct  9 16:02:15 2017	(r324436)
+++ head/sys/i386/i386/swtch.s	Mon Oct  9 16:07:27 2017	(r324437)
@@ -279,6 +279,10 @@ sw1:
 	pushl	%edx				/* Preserve pointer to pcb. */
 	addl	$P_MD,%eax			/* Pointer to mdproc is arg. */
 	pushl	%eax
+	/*
+	 * Holding dt_lock prevents context switches, so dt_lock cannot
+	 * be held now and set_user_ldt() will not deadlock acquiring it.
+	 */
 	call	set_user_ldt
 	addl	$4,%esp
 	popl	%edx

Modified: head/sys/i386/i386/sys_machdep.c
==============================================================================
--- head/sys/i386/i386/sys_machdep.c	Mon Oct  9 16:02:15 2017	(r324436)
+++ head/sys/i386/i386/sys_machdep.c	Mon Oct  9 16:07:27 2017	(r324437)
@@ -69,10 +69,10 @@ __FBSDID("$FreeBSD$");
 #define	NULL_LDT_BASE	((caddr_t)NULL)
 
 #ifdef SMP
-static void set_user_ldt_rv(struct vmspace *vmsp);
+static void set_user_ldt_rv(void *arg);
 #endif
 static int i386_set_ldt_data(struct thread *, int start, int num,
-	union descriptor *descs);
+    union descriptor *descs);
 static int i386_ldt_grow(struct thread *td, int len);
 
 void
@@ -405,41 +405,40 @@ done:
  * Update the GDT entry pointing to the LDT to point to the LDT of the
  * current process. Manage dt_lock holding/unholding autonomously.
  */   
-void
-set_user_ldt(struct mdproc *mdp)
+static void
+set_user_ldt_locked(struct mdproc *mdp)
 {
 	struct proc_ldt *pldt;
-	int dtlocked;
+	int gdt_idx;
 
-	dtlocked = 0;
-	if (!mtx_owned(&dt_lock)) {
-		mtx_lock_spin(&dt_lock);
-		dtlocked = 1;
-	}
+	mtx_assert(&dt_lock, MA_OWNED);
 
 	pldt = mdp->md_ldt;
-#ifdef SMP
-	gdt[PCPU_GET(cpuid) * NGDT + GUSERLDT_SEL].sd = pldt->ldt_sd;
-#else
-	gdt[GUSERLDT_SEL].sd = pldt->ldt_sd;
-#endif
+	gdt_idx = GUSERLDT_SEL;
+	gdt_idx += PCPU_GET(cpuid) * NGDT;	/* always 0 on UP */
+	gdt[gdt_idx].sd = pldt->ldt_sd;
 	lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
 	PCPU_SET(currentldt, GSEL(GUSERLDT_SEL, SEL_KPL));
-	if (dtlocked)
-		mtx_unlock_spin(&dt_lock);
 }
 
+void
+set_user_ldt(struct mdproc *mdp)
+{
+
+	mtx_lock_spin(&dt_lock);
+	set_user_ldt_locked(mdp);
+	mtx_unlock_spin(&dt_lock);
+}
+
 #ifdef SMP
 static void
-set_user_ldt_rv(struct vmspace *vmsp)
+set_user_ldt_rv(void *arg)
 {
-	struct thread *td;
+	struct proc *p;
 
-	td = curthread;
-	if (vmsp != td->td_proc->p_vmspace)
-		return;
-
-	set_user_ldt(&td->td_proc->p_md);
+	p = curproc;
+	if (arg == p->p_vmspace)
+		set_user_ldt(&p->p_md);
 }
 #endif
 
@@ -796,10 +795,10 @@ i386_ldt_grow(struct thread *td, int len) 
 		 * to acquire it.
 		 */
 		mtx_unlock_spin(&dt_lock);
-		smp_rendezvous(NULL, (void (*)(void *))set_user_ldt_rv,
-		    NULL, td->td_proc->p_vmspace);
+		smp_rendezvous(NULL, set_user_ldt_rv, NULL,
+		    td->td_proc->p_vmspace);
 #else
-		set_user_ldt(&td->td_proc->p_md);
+		set_user_ldt_locked(&td->td_proc->p_md);
 		mtx_unlock_spin(&dt_lock);
 #endif
 		if (old_ldt_base != NULL_LDT_BASE) {



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