Author: jkim
Date: Mon Jul 26 19:53:09 2010
New Revision: 210514
URL: http://svn.freebsd.org/changeset/base/210514

Log:
  Re-implement FPU suspend/resume for amd64.  This removes superfluous uses
  of critical_enter(9) and critical_exit(9) by fpugetregs() and fpusetregs().
  Also, we do not touch PCB flags any more.
  
  MFC after:    1 month

Modified:
  head/sys/amd64/acpica/acpi_switch.S
  head/sys/amd64/acpica/acpi_wakeup.c
  head/sys/amd64/amd64/cpu_switch.S
  head/sys/amd64/amd64/genassym.c
  head/sys/amd64/amd64/mp_machdep.c

Modified: head/sys/amd64/acpica/acpi_switch.S
==============================================================================
--- head/sys/amd64/acpica/acpi_switch.S Mon Jul 26 18:55:18 2010        
(r210513)
+++ head/sys/amd64/acpica/acpi_switch.S Mon Jul 26 19:53:09 2010        
(r210514)
@@ -102,9 +102,12 @@ ENTRY(acpi_restorecpu)
        movl    WAKEUP_CTX(sfmask), %eax
        wrmsr
 
-       /* Restore CR0, CR2 and CR4. */
+       /* Restore CR0 except for FPU mode. */
        movq    WAKEUP_XPCB(CR0), %rax
+       andq    $~(CR0_EM | CR0_TS), %rax
        movq    %rax, %cr0
+
+       /* Restore CR2 and CR4. */
        movq    WAKEUP_XPCB(CR2), %rax
        movq    %rax, %cr2
        movq    WAKEUP_XPCB(CR4), %rax
@@ -149,6 +152,17 @@ ENTRY(acpi_restorecpu)
        movq    WAKEUP_PCB(DR7), %rax
        movq    %rax, %dr7
 
+       /* Restore FPU state. */
+       movq    PCPU(FPCURTHREAD), %rax
+       testq   %rax, %rax
+       je      1f
+       fxrstor WAKEUP_PCB(USER_FPU)
+1:
+
+       /* Restore CR0 with FPU mode. */
+       movq    WAKEUP_XPCB(CR0), %rax
+       movq    %rax, %cr0
+
        /* Restore return address. */
        movq    WAKEUP_PCB(RIP), %rax
        movq    %rax, (%rsp)

Modified: head/sys/amd64/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/amd64/acpica/acpi_wakeup.c Mon Jul 26 18:55:18 2010        
(r210513)
+++ head/sys/amd64/acpica/acpi_wakeup.c Mon Jul 26 19:53:09 2010        
(r210514)
@@ -216,7 +216,6 @@ acpi_wakeup_cpus(struct acpi_softc *sc, 
 int
 acpi_sleep_machdep(struct acpi_softc *sc, int state)
 {
-       struct savefpu  *stopfpu;
 #ifdef SMP
        cpumask_t       wakeup_cpus;
 #endif
@@ -246,10 +245,7 @@ acpi_sleep_machdep(struct acpi_softc *sc
        cr3 = rcr3();
        load_cr3(KPML4phys);
 
-       stopfpu = &stopxpcbs[0]->xpcb_pcb.pcb_user_save;
        if (acpi_savecpu(stopxpcbs[0])) {
-               fpugetregs(curthread, stopfpu);
-
 #ifdef SMP
                if (wakeup_cpus != 0 && suspend_cpus(wakeup_cpus) == 0) {
                        device_printf(sc->acpi_dev,
@@ -285,7 +281,6 @@ acpi_sleep_machdep(struct acpi_softc *sc
                for (;;)
                        ia32_pause();
        } else {
-               fpusetregs(curthread, stopfpu);
 #ifdef SMP
                if (wakeup_cpus != 0)
                        acpi_wakeup_cpus(sc, wakeup_cpus);

Modified: head/sys/amd64/amd64/cpu_switch.S
==============================================================================
--- head/sys/amd64/amd64/cpu_switch.S   Mon Jul 26 18:55:18 2010        
(r210513)
+++ head/sys/amd64/amd64/cpu_switch.S   Mon Jul 26 19:53:09 2010        
(r210514)
@@ -417,6 +417,13 @@ ENTRY(savectx2)
        leaq    (%rax,%rdx),%rax
        movq    %rax,XPCB_KGSBASE(%r8)
 
+       movq    PCPU(FPCURTHREAD),%rax
+       testq   %rax,%rax
+       je      1f
+       clts
+       fxsave  PCB_USER_FPU(%r8)
+1:
+
        movl    $1, %eax
        ret
 END(savectx2)

Modified: head/sys/amd64/amd64/genassym.c
==============================================================================
--- head/sys/amd64/amd64/genassym.c     Mon Jul 26 18:55:18 2010        
(r210513)
+++ head/sys/amd64/amd64/genassym.c     Mon Jul 26 19:53:09 2010        
(r210514)
@@ -140,6 +140,7 @@ ASSYM(PCB_DR2, offsetof(struct pcb, pcb_
 ASSYM(PCB_DR3, offsetof(struct pcb, pcb_dr3));
 ASSYM(PCB_DR6, offsetof(struct pcb, pcb_dr6));
 ASSYM(PCB_DR7, offsetof(struct pcb, pcb_dr7));
+ASSYM(PCB_USER_FPU, offsetof(struct pcb, pcb_user_save));
 ASSYM(PCB_TSSP, offsetof(struct pcb, pcb_tssp));
 ASSYM(PCB_FULL_IRET, offsetof(struct pcb, pcb_full_iret));
 ASSYM(PCB_DBREGS, PCB_DBREGS);

Modified: head/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- head/sys/amd64/amd64/mp_machdep.c   Mon Jul 26 18:55:18 2010        
(r210513)
+++ head/sys/amd64/amd64/mp_machdep.c   Mon Jul 26 19:53:09 2010        
(r210514)
@@ -1329,20 +1329,17 @@ cpustop_handler(void)
 void
 cpususpend_handler(void)
 {
-       struct savefpu *stopfpu;
        register_t cr3, rf;
        int cpu = PCPU_GET(cpuid);
        int cpumask = PCPU_GET(cpumask);
 
        rf = intr_disable();
        cr3 = rcr3();
-       stopfpu = &stopxpcbs[cpu]->xpcb_pcb.pcb_user_save;
+
        if (savectx2(stopxpcbs[cpu])) {
-               fpugetregs(curthread, stopfpu);
                wbinvd();
                atomic_set_int(&stopped_cpus, cpumask);
-       } else
-               fpusetregs(curthread, stopfpu);
+       }
 
        /* Wait for resume */
        while (!(started_cpus & cpumask))
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to