From owner-svn-src-head@freebsd.org Mon Oct 9 16:07:29 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 17206E34A73; Mon, 9 Oct 2017 16:07:29 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8FA86206F; Mon, 9 Oct 2017 16:07:28 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v99G7R51054973; Mon, 9 Oct 2017 16:07:27 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v99G7Rhl054971; Mon, 9 Oct 2017 16:07:27 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201710091607.v99G7Rhl054971@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Mon, 9 Oct 2017 16:07:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r324437 - head/sys/i386/i386 X-SVN-Group: head X-SVN-Commit-Author: kib X-SVN-Commit-Paths: head/sys/i386/i386 X-SVN-Commit-Revision: 324437 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Oct 2017 16:07:29 -0000 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) {