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
This commit is contained in:
Коммит
537388bb65
|
@ -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
|
||||||
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:
|
||||||
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:
|
||||||
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 {
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
acpi_wakeup_address = acpi_realmode;
|
acpi_wakeup_address = virt_to_phys((void *)acpi_realmode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
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();
|
||||||
|
|
Загрузка…
Ссылка в новой задаче