Skip to content

Commit a1716d5

Browse files
author
Ingo Molnar
committed
Merge branch 'x86/s2ram-fix' into x86/urgent
2 parents 64e83b5 + 4b4f728 commit a1716d5

File tree

4 files changed

+59
-5
lines changed

4 files changed

+59
-5
lines changed

arch/x86/kernel/acpi/realmode/wakeup.S

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <asm/msr-index.h>
66
#include <asm/page.h>
77
#include <asm/pgtable.h>
8+
#include <asm/processor-flags.h>
89

910
.code16
1011
.section ".header", "a"
@@ -24,6 +25,11 @@ pmode_gdt: .quad 0
2425
realmode_flags: .long 0
2526
real_magic: .long 0
2627
trampoline_segment: .word 0
28+
_pad1: .byte 0
29+
wakeup_jmp: .byte 0xea /* ljmpw */
30+
wakeup_jmp_off: .word 3f
31+
wakeup_jmp_seg: .word 0
32+
wakeup_gdt: .quad 0, 0, 0
2733
signature: .long 0x51ee1111
2834

2935
.text
@@ -34,11 +40,34 @@ _start:
3440
cli
3541
cld
3642

43+
/* Apparently some dimwit BIOS programmers don't know how to
44+
program a PM to RM transition, and we might end up here with
45+
junk in the data segment descriptor registers. The only way
46+
to repair that is to go into PM and fix it ourselves... */
47+
movw $16, %cx
48+
lgdtl %cs:wakeup_gdt
49+
movl %cr0, %eax
50+
orb $X86_CR0_PE, %al
51+
movl %eax, %cr0
52+
jmp 1f
53+
1: ljmpw $8, $2f
54+
2:
55+
movw %cx, %ds
56+
movw %cx, %es
57+
movw %cx, %ss
58+
movw %cx, %fs
59+
movw %cx, %gs
60+
61+
andb $~X86_CR0_PE, %al
62+
movl %eax, %cr0
63+
jmp wakeup_jmp
64+
3:
3765
/* Set up segments */
3866
movw %cs, %ax
3967
movw %ax, %ds
4068
movw %ax, %es
4169
movw %ax, %ss
70+
lidtl wakeup_idt
4271

4372
movl $wakeup_stack_end, %esp
4473

@@ -98,7 +127,14 @@ bogus_real_magic:
98127
jmp 1b
99128

100129
.data
101-
.balign 4
130+
.balign 8
131+
132+
/* This is the standard real-mode IDT */
133+
wakeup_idt:
134+
.word 0xffff /* limit */
135+
.long 0 /* address */
136+
.word 0
137+
102138
.globl HEAP, heap_end
103139
HEAP:
104140
.long wakeup_heap

arch/x86/kernel/acpi/realmode/wakeup.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ struct wakeup_header {
2424
u32 realmode_flags;
2525
u32 real_magic;
2626
u16 trampoline_segment; /* segment with trampoline code, 64-bit only */
27+
u8 _pad1;
28+
u8 wakeup_jmp;
29+
u16 wakeup_jmp_off;
30+
u16 wakeup_jmp_seg;
31+
u64 wakeup_gdt[3];
2732
u32 signature; /* To check we have correct structure */
2833
} __attribute__((__packed__));
2934

arch/x86/kernel/acpi/sleep.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ int acpi_save_state_mem(void)
5050

5151
header->video_mode = saved_video_mode;
5252

53+
header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
54+
/* GDT[0]: GDT self-pointer */
55+
header->wakeup_gdt[0] =
56+
(u64)(sizeof(header->wakeup_gdt) - 1) +
57+
((u64)(acpi_wakeup_address +
58+
((char *)&header->wakeup_gdt - (char *)acpi_realmode))
59+
<< 16);
60+
/* GDT[1]: real-mode-like code segment */
61+
header->wakeup_gdt[1] = (0x009bULL << 40) +
62+
((u64)acpi_wakeup_address << 16) + 0xffff;
63+
/* GDT[2]: real-mode-like data segment */
64+
header->wakeup_gdt[2] = (0x0093ULL << 40) +
65+
((u64)acpi_wakeup_address << 16) + 0xffff;
66+
5367
#ifndef CONFIG_64BIT
5468
store_gdt((struct desc_ptr *)&header->pmode_gdt);
5569

@@ -111,7 +125,7 @@ void __init acpi_reserve_bootmem(void)
111125
return;
112126
}
113127

114-
acpi_wakeup_address = acpi_realmode;
128+
acpi_wakeup_address = virt_to_phys((void *)acpi_realmode);
115129
}
116130

117131

drivers/acpi/sleep/main.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,8 @@ static int acpi_sleep_prepare(u32 acpi_state)
3636
if (!acpi_wakeup_address) {
3737
return -EFAULT;
3838
}
39-
acpi_set_firmware_waking_vector((acpi_physical_address)
40-
virt_to_phys((void *)
41-
acpi_wakeup_address));
39+
acpi_set_firmware_waking_vector(
40+
(acpi_physical_address)acpi_wakeup_address);
4241

4342
}
4443
ACPI_FLUSH_CPU_CACHE();

0 commit comments

Comments
 (0)