From owner-p4-projects Sun Sep 15 19:43:43 2002 Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id AC51537B401; Sun, 15 Sep 2002 19:43:39 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5B81337B400 for ; Sun, 15 Sep 2002 19:43:39 -0700 (PDT) Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0B4FC43E4A for ; Sun, 15 Sep 2002 19:43:39 -0700 (PDT) (envelope-from mini@freebsd.org) Received: from freefall.freebsd.org (perforce@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.4/8.12.4) with ESMTP id g8G2hcJU005603 for ; Sun, 15 Sep 2002 19:43:38 -0700 (PDT) (envelope-from mini@freebsd.org) Received: (from perforce@localhost) by freefall.freebsd.org (8.12.4/8.12.4/Submit) id g8G2hc0w005586 for perforce@freebsd.org; Sun, 15 Sep 2002 19:43:38 -0700 (PDT) Date: Sun, 15 Sep 2002 19:43:38 -0700 (PDT) Message-Id: <200209160243.g8G2hc0w005586@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: perforce set sender to mini@freebsd.org using -f From: Jonathan Mini Subject: PERFORCE change 17551 for review To: Perforce Change Reviews Sender: owner-p4-projects@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG http://people.freebsd.org/~peter/p4db/chv.cgi?CH=17551 Change 17551 by mini@mini_stylus on 2002/09/15 19:43:22 Add Bruce's fix for two NPX problems: 1) a panic in npxdna() where emulation was enabled, but we owned the coprocessor. 2) a trap 9 in fxrstor, caused by unaligned access. Affected files ... .. //depot/projects/kse/sys/i386/i386/machdep.c#59 edit Differences ... ==== //depot/projects/kse/sys/i386/i386/machdep.c#59 (text+ko) ==== @@ -917,6 +917,20 @@ */ load_cr0(rcr0() | CR0_MP | CR0_TS); + /* Initialize the npx (if any) for the current process. */ + /* + * XXX the above load_cr0() also initializes it and is a layering + * violation if NPX is configured. It drops the npx partially + * and this would be fatal if we were interrupted now, and decided + * to force the state to the pcb, and checked the invariant + * (CR0_TS clear) if and only if PCPU_GET(fpcurthread) != NULL). + * ALL of this can happen except the check. The check used to + * happen and be fatal later when we didn't complete the drop + * before returning to user mode. This should be fixed properly + * soon. + */ + fpstate_drop(td); + /* * XXX - Linux emulator * Make sure sure edx is 0x0 on entry. Linux binaries depend @@ -2139,7 +2153,32 @@ mcp->mc_fpformat = _MC_FPFMT_NODEV; mcp->mc_ownedfp = _MC_FPOWNED_NONE; #else - mcp->mc_ownedfp = npxgetregs(td, (union savefpu *)&mcp->mc_fpstate); + union savefpu *addr; + + /* + * XXX mc_fpstate might be misaligned, since its declaration is not + * unportabilized using __attribute__((aligned(16))) like the + * declaration of struct savemm, and anyway, alignment doesn't work + * for auto variables since we don't use gcc's pessimal stack + * alignment. Work around this by abusing the spare fields after + * mcp->mc_fpstate. + * + * XXX unpessimize most cases by only aligning when fxsave might be + * called, although this requires knowing too much about + * npxgetregs()'s internals. + */ + addr = (union savefpu *)&mcp->mc_fpstate; + if (td == PCPU_GET(fpcurthread) && cpu_fxsr && + ((uintptr_t)(void *)addr & 0xF)) { + do + addr = (void *)((char *)addr + 4); + while ((uintptr_t)(void *)addr & 0xF); + } + mcp->mc_ownedfp = npxgetregs(td, addr); + if (addr != (union savefpu *)&mcp->mc_fpstate) { + bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate)); + bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2)); + } mcp->mc_fpformat = npxformat(); #endif } @@ -2147,19 +2186,40 @@ static int set_fpcontext(struct thread *td, const mcontext_t *mcp) { + union savefpu *addr; if (mcp->mc_fpformat == _MC_FPFMT_NODEV) return (0); - else if ((mcp->mc_fpformat != _MC_FPFMT_387) && - ((mcp->mc_fpformat != _MC_FPFMT_XMM))) + else if (mcp->mc_fpformat != _MC_FPFMT_387 && + mcp->mc_fpformat != _MC_FPFMT_XMM) return (EINVAL); else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) /* We don't care what state is left in the FPU or PCB. */ fpstate_drop(td); else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || - mcp->mc_ownedfp == _MC_FPOWNED_PCB) - npxsetregs(td, (union savefpu *)&mcp->mc_fpstate); - else + mcp->mc_ownedfp == _MC_FPOWNED_PCB) { + /* XXX align as above. */ + addr = (union savefpu *)&mcp->mc_fpstate; + if (td == PCPU_GET(fpcurthread) && cpu_fxsr && + ((uintptr_t)(void *)addr & 0xF)) { + do + addr = (void *)((char *)addr + 4); + while ((uintptr_t)(void *)addr & 0xF); + bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate)); + } +#ifdef DEV_NPX + /* + * XXX we violate the dubious requirement that npxsetregs() + * be called with interrupts disabled. + */ + npxsetregs(td, addr); +#endif + /* + * Don't bother putting things back where they were in the + * misaligned case, since we know that the caller won't use + * them again. + */ + } else return (EINVAL); return (0); } @@ -2170,8 +2230,21 @@ register_t s; s = intr_disable(); +#ifdef DEV_NPX if (PCPU_GET(fpcurthread) == td) npxdrop(); +#endif + /* + * XXX force a full drop of the npx. The above only drops it if we + * owned it. npxgetregs() has the same bug in the !cpu_fxsr case. + * + * XXX I don't much like npxgetregs()'s semantics of doing a full + * drop. Dropping only to the pcb matches fnsave's behaviour. + * We only need to drop to !PCB_INITDONE in sendsig(). But + * sendsig() is the only caller of npxgetregs()... perhaps we just + * have too many layers. + */ + curthread->td_pcb->pcb_flags &= ~PCB_NPXINITDONE; intr_restore(s); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message