summaryrefslogtreecommitdiffstats
path: root/sys/amd64/acpica
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2010-07-26 19:53:09 +0000
committerjkim <jkim@FreeBSD.org>2010-07-26 19:53:09 +0000
commit48a6a38cdceac157ad249834defe382c21e39f7d (patch)
tree9183d2c80109a896ebadce43f6a4516a52e9f275 /sys/amd64/acpica
parent488a727a00e4e0a41095d9f56222741550a97d92 (diff)
downloadFreeBSD-src-48a6a38cdceac157ad249834defe382c21e39f7d.zip
FreeBSD-src-48a6a38cdceac157ad249834defe382c21e39f7d.tar.gz
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
Diffstat (limited to 'sys/amd64/acpica')
-rw-r--r--sys/amd64/acpica/acpi_switch.S16
-rw-r--r--sys/amd64/acpica/acpi_wakeup.c5
2 files changed, 15 insertions, 6 deletions
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);
OpenPOWER on IntegriCloud