From owner-svn-src-head@FreeBSD.ORG Sat Aug 30 17:48:40 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 3F4C8B6F; Sat, 30 Aug 2014 17:48:40 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::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 1ED5813D0; Sat, 30 Aug 2014 17:48:40 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s7UHmdSi059710; Sat, 30 Aug 2014 17:48:39 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s7UHmc6H059701; Sat, 30 Aug 2014 17:48:38 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201408301748.s7UHmc6H059701@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Sat, 30 Aug 2014 17:48:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r270850 - in head/sys: i386/i386 i386/include i386/isa x86/acpica X-SVN-Group: head 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.18-1 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: Sat, 30 Aug 2014 17:48:40 -0000 Author: jhb Date: Sat Aug 30 17:48:38 2014 New Revision: 270850 URL: http://svnweb.freebsd.org/changeset/base/270850 Log: Save and restore FPU state across suspend and resume. In earlier revisions of this patch, resumectx() called npxresume() directly, but that doesn't work because resumectx() runs with a non-standard %cs selector. Instead, all of the FPU suspend/resume handling is done in C. MFC after: 1 week Modified: head/sys/i386/i386/mp_machdep.c head/sys/i386/i386/swtch.s head/sys/i386/include/npx.h head/sys/i386/include/pcb.h head/sys/i386/isa/npx.c head/sys/x86/acpica/acpi_wakeup.c Modified: head/sys/i386/i386/mp_machdep.c ============================================================================== --- head/sys/i386/i386/mp_machdep.c Sat Aug 30 17:39:28 2014 (r270849) +++ head/sys/i386/i386/mp_machdep.c Sat Aug 30 17:48:38 2014 (r270850) @@ -1522,9 +1522,15 @@ cpususpend_handler(void) cpu = PCPU_GET(cpuid); if (savectx(susppcbs[cpu])) { +#ifdef DEV_NPX + npxsuspend(&suspcbs[cpu]->pcb_fpususpend); +#endif wbinvd(); CPU_SET_ATOMIC(cpu, &suspended_cpus); } else { +#ifdef DEV_NPX + npxresume(&suspcbs[cpu]->pcb_fpususpend); +#endif pmap_init_pat(); PCPU_SET(switchtime, 0); PCPU_SET(switchticks, ticks); Modified: head/sys/i386/i386/swtch.s ============================================================================== --- head/sys/i386/i386/swtch.s Sat Aug 30 17:39:28 2014 (r270849) +++ head/sys/i386/i386/swtch.s Sat Aug 30 17:48:38 2014 (r270850) @@ -416,45 +416,6 @@ ENTRY(savectx) sldt PCB_LDT(%ecx) str PCB_TR(%ecx) -#ifdef DEV_NPX - /* - * If fpcurthread == NULL, then the npx h/w state is irrelevant and the - * state had better already be in the pcb. This is true for forks - * but not for dumps (the old book-keeping with FP flags in the pcb - * always lost for dumps because the dump pcb has 0 flags). - * - * If fpcurthread != NULL, then we have to save the npx h/w state to - * fpcurthread's pcb and copy it to the requested pcb, or save to the - * requested pcb and reload. Copying is easier because we would - * have to handle h/w bugs for reloading. We used to lose the - * parent's npx state for forks by forgetting to reload. - */ - pushfl - CLI - movl PCPU(FPCURTHREAD),%eax - testl %eax,%eax - je 1f - - pushl %ecx - movl TD_PCB(%eax),%eax - movl PCB_SAVEFPU(%eax),%eax - pushl %eax - pushl %eax - call npxsave - addl $4,%esp - popl %eax - popl %ecx - - pushl $PCB_SAVEFPU_SIZE - leal PCB_USERFPU(%ecx),%ecx - pushl %ecx - pushl %eax - call bcopy - addl $12,%esp -1: - popfl -#endif /* DEV_NPX */ - movl $1,%eax ret END(savectx) @@ -519,10 +480,6 @@ ENTRY(resumectx) movl PCB_DR7(%ecx),%eax movl %eax,%dr7 -#ifdef DEV_NPX - /* XXX FIX ME */ -#endif - /* Restore other registers */ movl PCB_EDI(%ecx),%edi movl PCB_ESI(%ecx),%esi Modified: head/sys/i386/include/npx.h ============================================================================== --- head/sys/i386/include/npx.h Sat Aug 30 17:39:28 2014 (r270849) +++ head/sys/i386/include/npx.h Sat Aug 30 17:48:38 2014 (r270850) @@ -53,8 +53,10 @@ void npxexit(struct thread *td); int npxformat(void); int npxgetregs(struct thread *td); void npxinit(void); +void npxresume(union savefpu *addr); void npxsave(union savefpu *addr); void npxsetregs(struct thread *td, union savefpu *addr); +void npxsuspend(union savefpu *addr); int npxtrap_x87(void); int npxtrap_sse(void); void npxuserinited(struct thread *); Modified: head/sys/i386/include/pcb.h ============================================================================== --- head/sys/i386/include/pcb.h Sat Aug 30 17:39:28 2014 (r270849) +++ head/sys/i386/include/pcb.h Sat Aug 30 17:48:38 2014 (r270850) @@ -90,6 +90,8 @@ struct pcb { struct region_descriptor pcb_idt; uint16_t pcb_ldt; uint16_t pcb_tr; + + union savefpu pcb_fpususpend; }; #ifdef _KERNEL Modified: head/sys/i386/isa/npx.c ============================================================================== --- head/sys/i386/isa/npx.c Sat Aug 30 17:39:28 2014 (r270849) +++ head/sys/i386/isa/npx.c Sat Aug 30 17:48:38 2014 (r270850) @@ -761,6 +761,43 @@ npxsave(addr) PCPU_SET(fpcurthread, NULL); } +/* + * Unconditionally save the current co-processor state across suspend and + * resume. + */ +void +npxsuspend(union savefpu *addr) +{ + register_t cr0; + + if (!hw_float) + return; + if (PCPU_GET(fpcurthread) == NULL) { + *addr = npx_initialstate; + return; + } + cr0 = rcr0(); + clts(); + fpusave(addr); + load_cr0(cr0); +} + +void +npxresume(union savefpu *addr) +{ + register_t cr0; + + if (!hw_float) + return; + + cr0 = rcr0(); + clts(); + npxinit(); + stop_emulating(); + fpurstor(addr); + load_cr0(cr0); +} + void npxdrop() { Modified: head/sys/x86/acpica/acpi_wakeup.c ============================================================================== --- head/sys/x86/acpica/acpi_wakeup.c Sat Aug 30 17:39:28 2014 (r270849) +++ head/sys/x86/acpica/acpi_wakeup.c Sat Aug 30 17:48:38 2014 (r270850) @@ -30,6 +30,10 @@ #include __FBSDID("$FreeBSD$"); +#ifdef __i386__ +#include "opt_npx.h" +#endif + #include #include #include @@ -203,6 +207,8 @@ acpi_sleep_machdep(struct acpi_softc *sc if (savectx(susppcbs[0])) { #ifdef __amd64__ fpususpend(susppcbs[0]->pcb_fpususpend); +#elif defined(DEV_NPX) + npxsuspend(&susppcbs[0]->pcb_fpususpend); #endif #ifdef SMP if (!CPU_EMPTY(&suspcpus) && suspend_cpus(suspcpus) == 0) { @@ -237,6 +243,10 @@ acpi_sleep_machdep(struct acpi_softc *sc for (;;) ia32_pause(); + } else { +#ifdef DEV_NPX + npxresume(&susppcbs[0]->pcb_fpususpend); +#endif } return (1); /* wakeup successfully */