History

Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86 ACPI: fix resume from suspend to RAM on uniprocessor x86-64 x86 ACPI: normalize segment descriptor register on resume

Linus Torvalds committed 18 years ago

Commit 537388b2 parents 20cbc97 a1716d55 files · +60 −6Browse files

Unified · Split

5 files
  1. arch/x86/kernel/acpi/realmode/wakeup.S +37 −1
  2. arch/x86/kernel/acpi/realmode/wakeup.h +5 −0
  3. arch/x86/kernel/acpi/sleep.c +15 −1
  4. arch/x86/kernel/head_64.S +1 −1
  5. drivers/acpi/sleep/main.c +2 −3
arch/x86/kernel/acpi/realmode/wakeup.S+37−1
@@ -5,6 +5,7 @@ · 4 unmodified lines
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 · 13 unmodified lines
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: · 4 unmodified lines
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: · 53 unmodified lines
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+5−0
@@ -24,6 +24,11 @@ struct wakeup_header { · 23 unmodified lines
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+15−1
@@ -50,6 +50,20 @@ int acpi_save_state_mem(void) · 49 unmodified lines
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) · 55 unmodified lines
111125 return;
112126 }
113127
114− acpi_wakeup_address = acpi_realmode;
128+ acpi_wakeup_address = virt_to_phys((void *)acpi_realmode);
115129 }
116130
117131
arch/x86/kernel/head_64.S+1−1
@@ -128,7 +128,7 @@ ident_complete: · 127 unmodified lines
128128 /* Fixup phys_base */
129129 addq %rbp, phys_base(%rip)
130130
131−#ifdef CONFIG_SMP
131+#ifdef CONFIG_X86_TRAMPOLINE
132132 addq %rbp, trampoline_level4_pgt + 0(%rip)
133133 addq %rbp, trampoline_level4_pgt + (511*8)(%rip)
134134 #endif
drivers/acpi/sleep/main.c+2−3
@@ -36,9 +36,8 @@ static int acpi_sleep_prepare(u32 acpi_state) · 35 unmodified lines
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();