svn commit: r324437 - head/sys/i386/i386
Konstantin Belousov
kib at FreeBSD.org
Mon Oct 9 16:07:29 UTC 2017
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) {
More information about the svn-src-all
mailing list