Commit 537388bb authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-fixes-for-linus' of...

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
parents 20cbc972 a1716d50
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <asm/msr-index.h> #include <asm/msr-index.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/processor-flags.h>
.code16 .code16
.section ".header", "a" .section ".header", "a"
...@@ -24,6 +25,11 @@ pmode_gdt: .quad 0 ...@@ -24,6 +25,11 @@ pmode_gdt: .quad 0
realmode_flags: .long 0 realmode_flags: .long 0
real_magic: .long 0 real_magic: .long 0
trampoline_segment: .word 0 trampoline_segment: .word 0
_pad1: .byte 0
wakeup_jmp: .byte 0xea /* ljmpw */
wakeup_jmp_off: .word 3f
wakeup_jmp_seg: .word 0
wakeup_gdt: .quad 0, 0, 0
signature: .long 0x51ee1111 signature: .long 0x51ee1111
.text .text
...@@ -34,11 +40,34 @@ _start: ...@@ -34,11 +40,34 @@ _start:
cli cli
cld cld
/* Apparently some dimwit BIOS programmers don't know how to
program a PM to RM transition, and we might end up here with
junk in the data segment descriptor registers. The only way
to repair that is to go into PM and fix it ourselves... */
movw $16, %cx
lgdtl %cs:wakeup_gdt
movl %cr0, %eax
orb $X86_CR0_PE, %al
movl %eax, %cr0
jmp 1f
1: ljmpw $8, $2f
2:
movw %cx, %ds
movw %cx, %es
movw %cx, %ss
movw %cx, %fs
movw %cx, %gs
andb $~X86_CR0_PE, %al
movl %eax, %cr0
jmp wakeup_jmp
3:
/* Set up segments */ /* Set up segments */
movw %cs, %ax movw %cs, %ax
movw %ax, %ds movw %ax, %ds
movw %ax, %es movw %ax, %es
movw %ax, %ss movw %ax, %ss
lidtl wakeup_idt
movl $wakeup_stack_end, %esp movl $wakeup_stack_end, %esp
...@@ -98,7 +127,14 @@ bogus_real_magic: ...@@ -98,7 +127,14 @@ bogus_real_magic:
jmp 1b jmp 1b
.data .data
.balign 4 .balign 8
/* This is the standard real-mode IDT */
wakeup_idt:
.word 0xffff /* limit */
.long 0 /* address */
.word 0
.globl HEAP, heap_end .globl HEAP, heap_end
HEAP: HEAP:
.long wakeup_heap .long wakeup_heap
......
...@@ -24,6 +24,11 @@ struct wakeup_header { ...@@ -24,6 +24,11 @@ struct wakeup_header {
u32 realmode_flags; u32 realmode_flags;
u32 real_magic; u32 real_magic;
u16 trampoline_segment; /* segment with trampoline code, 64-bit only */ u16 trampoline_segment; /* segment with trampoline code, 64-bit only */
u8 _pad1;
u8 wakeup_jmp;
u16 wakeup_jmp_off;
u16 wakeup_jmp_seg;
u64 wakeup_gdt[3];
u32 signature; /* To check we have correct structure */ u32 signature; /* To check we have correct structure */
} __attribute__((__packed__)); } __attribute__((__packed__));
......
...@@ -50,6 +50,20 @@ int acpi_save_state_mem(void) ...@@ -50,6 +50,20 @@ int acpi_save_state_mem(void)
header->video_mode = saved_video_mode; header->video_mode = saved_video_mode;
header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
/* GDT[0]: GDT self-pointer */
header->wakeup_gdt[0] =
(u64)(sizeof(header->wakeup_gdt) - 1) +
((u64)(acpi_wakeup_address +
((char *)&header->wakeup_gdt - (char *)acpi_realmode))
<< 16);
/* GDT[1]: real-mode-like code segment */
header->wakeup_gdt[1] = (0x009bULL << 40) +
((u64)acpi_wakeup_address << 16) + 0xffff;
/* GDT[2]: real-mode-like data segment */
header->wakeup_gdt[2] = (0x0093ULL << 40) +
((u64)acpi_wakeup_address << 16) + 0xffff;
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
store_gdt((struct desc_ptr *)&header->pmode_gdt); store_gdt((struct desc_ptr *)&header->pmode_gdt);
...@@ -111,7 +125,7 @@ void __init acpi_reserve_bootmem(void) ...@@ -111,7 +125,7 @@ void __init acpi_reserve_bootmem(void)
return; return;
} }
acpi_wakeup_address = acpi_realmode; acpi_wakeup_address = virt_to_phys((void *)acpi_realmode);
} }
......
...@@ -128,7 +128,7 @@ ident_complete: ...@@ -128,7 +128,7 @@ ident_complete:
/* Fixup phys_base */ /* Fixup phys_base */
addq %rbp, phys_base(%rip) addq %rbp, phys_base(%rip)
#ifdef CONFIG_SMP #ifdef CONFIG_X86_TRAMPOLINE
addq %rbp, trampoline_level4_pgt + 0(%rip) addq %rbp, trampoline_level4_pgt + 0(%rip)
addq %rbp, trampoline_level4_pgt + (511*8)(%rip) addq %rbp, trampoline_level4_pgt + (511*8)(%rip)
#endif #endif
......
...@@ -36,9 +36,8 @@ static int acpi_sleep_prepare(u32 acpi_state) ...@@ -36,9 +36,8 @@ static int acpi_sleep_prepare(u32 acpi_state)
if (!acpi_wakeup_address) { if (!acpi_wakeup_address) {
return -EFAULT; return -EFAULT;
} }
acpi_set_firmware_waking_vector((acpi_physical_address) acpi_set_firmware_waking_vector(
virt_to_phys((void *) (acpi_physical_address)acpi_wakeup_address);
acpi_wakeup_address));
} }
ACPI_FLUSH_CPU_CACHE(); ACPI_FLUSH_CPU_CACHE();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment