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