NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
port-amd64/49174: acpi resume doesn't restore xcr0
>Number: 49174
>Category: port-amd64
>Synopsis: acpi resume doesn't restore xcr0
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: port-amd64-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Sep 03 14:45:00 +0000 2014
>Originator: Cherry G. Mathew
>Release: -current, -7
>Organization:
>Environment:
>Description:
The acpi resume path from wakeup doesn't restore the intel xcr0 register, which
causes an fpu panic not much later.
PoC patch below, but the implementation should probably be higher level.
>How-To-Repeat:
suspend acpi laptop. Resume it. Panic ensues.
>Fix:
diff -r 9c5992049309 sys/arch/amd64/acpi/acpi_wakeup_low.S
--- a/sys/arch/amd64/acpi/acpi_wakeup_low.S Tue Sep 02 19:34:11 2014 +0530
+++ b/sys/arch/amd64/acpi/acpi_wakeup_low.S Wed Sep 03 20:11:21 2014 +0530
@@ -73,6 +73,15 @@
movq %rax,%cr8
movq ACPI_SUSPEND_CR4(%r8),%rax
movq %rax,%cr4
+
+ andq $CR4_OSXSAVE, %rax
+ jz 1f
+ xorq %rcx, %rcx
+ movl ACPI_SUSPEND_XCR0(%r8), %eax
+ movl ACPI_SUSPEND_XCR0+4(%r8), %edx
+ xsetbv
+
+1:
movq ACPI_SUSPEND_CR3(%r8),%rax
movq %rax,%cr3
movq ACPI_SUSPEND_CR2(%r8),%rax
@@ -80,8 +89,8 @@
movq ACPI_SUSPEND_CR0(%r8),%rax
movq %rax,%cr0
- jmp 1f
-1:
+ jmp 2f
+2:
movq CPUVAR(GDT),%rax
movzwq ACPI_SUSPEND_TR(%r8),%rdx
@@ -131,6 +140,16 @@
pushfq
popq ACPI_SUSPEND_REG+(7*8)(%r8)
+ movq %cr4,%rax
+ andq $CR4_OSXSAVE, %rax
+ jz 1f
+
+ xorq %rcx, %rcx
+ xgetbv
+ movl %edx,ACPI_SUSPEND_XCR0+4(%r8)
+ movl %eax,ACPI_SUSPEND_XCR0(%r8)
+
+1:
movq %rsp,ACPI_SUSPEND_REG+(0*8)(%r8)
movl $MSR_FSBASE,%ecx
diff -r 9c5992049309 sys/arch/amd64/amd64/genassym.cf
--- a/sys/arch/amd64/amd64/genassym.cf Tue Sep 02 19:34:11 2014 +0530
+++ b/sys/arch/amd64/amd64/genassym.cf Wed Sep 03 20:11:21 2014 +0530
@@ -265,6 +265,7 @@
define ACPI_SUSPEND_CR3 offsetof(struct cpu_info, ci_suspend_cr3)
define ACPI_SUSPEND_CR4 offsetof(struct cpu_info, ci_suspend_cr4)
define ACPI_SUSPEND_CR8 offsetof(struct cpu_info, ci_suspend_cr8)
+define ACPI_SUSPEND_XCR0 offsetof(struct cpu_info, ci_suspend_xcr0)
if NIOAPIC > 0
define PIC_IOAPIC offsetof(struct pic, pic_ioapic)
diff -r 9c5992049309 sys/arch/x86/include/cpu.h
--- a/sys/arch/x86/include/cpu.h Tue Sep 02 19:34:11 2014 +0530
+++ b/sys/arch/x86/include/cpu.h Wed Sep 03 20:11:21 2014 +0530
@@ -235,6 +235,7 @@
uintptr_t ci_suspend_cr3;
uintptr_t ci_suspend_cr4;
uintptr_t ci_suspend_cr8;
+ uintptr_t ci_suspend_xcr0;
/* The following must be in a single cache line. */
int ci_want_resched __aligned(64);
Home |
Main Index |
Thread Index |
Old Index