summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/amd64/amd64/acpi_wakecode.S49
-rw-r--r--sys/arch/i386/i386/acpi_wakecode.S47
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