From 48a6a38cdceac157ad249834defe382c21e39f7d Mon Sep 17 00:00:00 2001 From: jkim Date: Mon, 26 Jul 2010 19:53:09 +0000 Subject: 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 --- sys/amd64/acpica/acpi_switch.S | 16 +++++++++++++++- sys/amd64/acpica/acpi_wakeup.c | 5 ----- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'sys/amd64/acpica') diff --git a/sys/amd64/acpica/acpi_switch.S b/sys/amd64/acpica/acpi_switch.S index 39f18e5..57a3aa8 100644 --- a/sys/amd64/acpica/acpi_switch.S +++ b/sys/amd64/acpica/acpi_switch.S @@ -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) diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c index 5c35593..982809b 100644 --- a/sys/amd64/acpica/acpi_wakeup.c +++ b/sys/amd64/acpica/acpi_wakeup.c @@ -216,7 +216,6 @@ acpi_wakeup_cpus(struct acpi_softc *sc, cpumask_t wakeup_cpus) 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, int state) 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, int state) for (;;) ia32_pause(); } else { - fpusetregs(curthread, stopfpu); #ifdef SMP if (wakeup_cpus != 0) acpi_wakeup_cpus(sc, wakeup_cpus); -- cgit v1.1