diff options
-rw-r--r-- | sys/arch/amd64/amd64/acpi_wakecode.S | 49 | ||||
-rw-r--r-- | sys/arch/i386/i386/acpi_wakecode.S | 47 |
2 files changed, 95 insertions, 1 deletions
diff --git a/sys/arch/amd64/amd64/acpi_wakecode.S b/sys/arch/amd64/amd64/acpi_wakecode.S index bd0763d46ab..d1f86ecfa21 100644 --- a/sys/arch/amd64/amd64/acpi_wakecode.S +++ b/sys/arch/amd64/amd64/acpi_wakecode.S @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi_wakecode.S,v 1.5 2009/11/24 17:00:01 mlarkin Exp $ */ +/* $OpenBSD: acpi_wakecode.S,v 1.6 2009/11/25 15:41:43 pirofti Exp $ */ /* * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org> * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org> @@ -57,6 +57,7 @@ #define _ACPI_TRMP_LABEL(a) a = . - _C_LABEL(acpi_real_mode_resume) + ACPI_TRAMPOLINE #define _ACPI_TRMP_OFFSET(a) a = . - _C_LABEL(acpi_real_mode_resume) +#define _ACPI_RM_SEGMENT (ACPI_TRAMPOLINE >> 4) /* * On wakeup, we'll start executing at acpi_real_mode_resume. @@ -91,6 +92,28 @@ _C_LABEL(acpi_real_mode_resume): cli cld + /* Some BIOS vendors screw up the gdt, make sure we clean it */ + movw $0x10, %cx + lgdtl %cs:clean_gdt + movl %cr0, %eax + orb $(CR0_PE), %al + movl %eax, %cr0 + jmp 1f +1: ljmpw $0x8, $clean1 + +_ACPI_TRMP_OFFSET(clean1) + movw %cx, %ds + movw %cx, %es + movw %cx, %ss + movw %cx, %fs + movw %cx, %gs + + andb $~(CR0_PE), %al + movl %eax, %cr0 + ljmpw $_ACPI_RM_SEGMENT , $clean2 + +_ACPI_TRMP_OFFSET(clean2) + /* * Set up segment registers for real mode. * We'll only be in real mode for a moment, and we don't have @@ -99,7 +122,9 @@ _C_LABEL(acpi_real_mode_resume): */ movw %cs,%ax movw %ax,%ds + movw %ax,%es movw %ax,%ss + lidtl clean_idt /* * Set up stack to grow down from offset 0x0FFE. @@ -419,6 +444,28 @@ _ACPI_TRMP_LABEL(tmp_gdtable) .byte 0, 0x93, 0xcf, 0 _ACPI_TRMP_LABEL(tmp_gdt_end) + .align 8, 0 +_ACPI_TRMP_OFFSET(clean_idt) + .word 0xffff + .long 0 + .word 0 + +_ACPI_TRMP_OFFSET(clean_gdt) + .word clean_gdt_end - clean_gdtable + .long clean_gdtable + + .align 8, 0 +_ACPI_TRMP_LABEL(clean_gdtable) + .word 0, 0 + .byte 0, 0, 0, 0 + + .word 0xffff, ACPI_TRAMPOLINE + .byte 0, 0x9b, 0, 0 + + .word 0xffff, ACPI_TRAMPOLINE + .byte 0, 0x93, 0, 0 +_ACPI_TRMP_LABEL(clean_gdt_end) + .align 8 _ACPI_TRMP_LABEL(tmp_gdt64) .word tmp_gdt64_end - tmp_gdtable64 diff --git a/sys/arch/i386/i386/acpi_wakecode.S b/sys/arch/i386/i386/acpi_wakecode.S index 3f80542bf8a..04c6c52b598 100644 --- a/sys/arch/i386/i386/acpi_wakecode.S +++ b/sys/arch/i386/i386/acpi_wakecode.S @@ -56,6 +56,7 @@ #define _ACPI_TRMP_LABEL(a) a = . - _C_LABEL(acpi_real_mode_resume) + ACPI_TRAMPOLINE #define _ACPI_TRMP_OFFSET(a) a = . - _C_LABEL(acpi_real_mode_resume) +#define _ACPI_RM_SEGMENT (ACPI_TRAMPOLINE >> 4) /* * On wakeup, we'll start executing at acpi_real_mode_resume. @@ -87,6 +88,28 @@ _C_LABEL(acpi_real_mode_resume): cli cld + /* Some BIOS vendors screw up the gdt, make sure we clean it */ + movw $0x10, %cx + lgdtl %cs:clean_gdt + movl %cr0, %eax + orb $(CR0_PE), %al + movl %eax, %cr0 + jmp 1f +1: ljmpw $0x8, $clean1 + +_ACPI_TRMP_OFFSET(clean1) + movw %cx, %ds + movw %cx, %es + movw %cx, %ss + movw %cx, %fs + movw %cx, %gs + + andb $~(CR0_PE), %al + movl %eax, %cr0 + ljmpw $_ACPI_RM_SEGMENT , $clean2 + +_ACPI_TRMP_OFFSET(clean2) + /* * Set up segment registers for real mode. * We'll only be in real mode for a moment, and we don't have @@ -95,7 +118,9 @@ _C_LABEL(acpi_real_mode_resume): */ movw %cs,%ax movw %ax,%ds + movw %ax,%es movw %ax,%ss + lidtl clean_idt /* * Set up stack to grow down from offset 0x0FFE. @@ -362,6 +387,28 @@ _ACPI_TRMP_LABEL(tmp_gdtable) .byte 0, 0x93, 0xcf, 0 _ACPI_TRMP_LABEL(tmp_gdt_end) + .align 8, 0 +_ACPI_TRMP_OFFSET(clean_idt) + .word 0xffff + .long 0 + .word 0 + +_ACPI_TRMP_OFFSET(clean_gdt) + .word clean_gdt_end - clean_gdtable + .long clean_gdtable + + .align 8, 0 +_ACPI_TRMP_LABEL(clean_gdtable) + .word 0, 0 + .byte 0, 0, 0, 0 + + .word 0xffff, ACPI_TRAMPOLINE + .byte 0, 0x9b, 0, 0 + + .word 0xffff, ACPI_TRAMPOLINE + .byte 0, 0x93, 0, 0 +_ACPI_TRMP_LABEL(clean_gdt_end) + .align 4 _ACPI_TRMP_LABEL(acpi_saved_ebx) .long 0 |