From d7695033a89b2cb3702a181fb6a584dc2e85b278 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Tue, 8 May 2012 21:22:27 +0300 Subject: [PATCH] --- yaml --- r: 309143 b: refs/heads/master c: 5a8c9aebe04a78b069828d364798d5f24c5a42bd h: refs/heads/master i: 309141: ee9bcbf4528110e18797dee62aa5d9068ab2eb7a 309139: 7c8e18a874c7f714c4c0845fdb749c7a879942b6 309135: 217b68133e2f4043f52e87ee5386121406aad823 v: v3 --- [refs] | 2 +- trunk/arch/x86/include/asm/realmode.h | 4 + trunk/arch/x86/kernel/Makefile | 1 - trunk/arch/x86/kernel/reboot.c | 25 +----- trunk/arch/x86/realmode/rm/Makefile | 1 + trunk/arch/x86/realmode/rm/header.S | 3 + .../x86/{kernel => realmode/rm}/reboot_32.S | 83 +++++++++---------- 7 files changed, 53 insertions(+), 66 deletions(-) rename trunk/arch/x86/{kernel => realmode/rm}/reboot_32.S (73%) diff --git a/[refs] b/[refs] index 545e4e29dc6c..cabc9c793a95 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 084ee1c641a068bfd1194d545f7dc9ab2043eb35 +refs/heads/master: 5a8c9aebe04a78b069828d364798d5f24c5a42bd diff --git a/trunk/arch/x86/include/asm/realmode.h b/trunk/arch/x86/include/asm/realmode.h index dc1bba534c14..bf26b0681931 100644 --- a/trunk/arch/x86/include/asm/realmode.h +++ b/trunk/arch/x86/include/asm/realmode.h @@ -9,6 +9,10 @@ struct real_mode_header { u32 text_start; u32 ro_end; u32 end; + /* reboot */ +#ifdef CONFIG_X86_32 + u32 machine_real_restart_asm; +#endif } __attribute__((__packed__)); extern struct real_mode_header real_mode_header; diff --git a/trunk/arch/x86/kernel/Makefile b/trunk/arch/x86/kernel/Makefile index f9e19d4eb984..b71ef35c7d77 100644 --- a/trunk/arch/x86/kernel/Makefile +++ b/trunk/arch/x86/kernel/Makefile @@ -49,7 +49,6 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += cpu/ obj-y += acpi/ obj-y += reboot.o -obj-$(CONFIG_X86_32) += reboot_32.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o diff --git a/trunk/arch/x86/kernel/reboot.c b/trunk/arch/x86/kernel/reboot.c index d840e69a853c..050eff29a4bb 100644 --- a/trunk/arch/x86/kernel/reboot.c +++ b/trunk/arch/x86/kernel/reboot.c @@ -24,6 +24,7 @@ #ifdef CONFIG_X86_32 # include # include +# include #else # include #endif @@ -332,15 +333,10 @@ static int __init reboot_init(void) } core_initcall(reboot_init); -extern const unsigned char machine_real_restart_asm[]; -extern const u64 machine_real_restart_gdt[3]; - void machine_real_restart(unsigned int type) { - void *restart_va; - unsigned long restart_pa; - void (*restart_lowmem)(unsigned int); - u64 *lowmem_gdt; + void (*restart_lowmem)(unsigned int) = (void (*)(unsigned int)) + real_mode_header.machine_real_restart_asm; local_irq_disable(); @@ -369,21 +365,6 @@ void machine_real_restart(unsigned int type) too. */ *((unsigned short *)0x472) = reboot_mode; - /* Patch the GDT in the low memory trampoline */ - lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt); - - restart_va = TRAMPOLINE_SYM(machine_real_restart_asm); - restart_pa = virt_to_phys(restart_va); - restart_lowmem = (void (*)(unsigned int))restart_pa; - - /* GDT[0]: GDT self-pointer */ - lowmem_gdt[0] = - (u64)(sizeof(machine_real_restart_gdt) - 1) + - ((u64)virt_to_phys(lowmem_gdt) << 16); - /* GDT[1]: 64K real mode code segment */ - lowmem_gdt[1] = - GDT_ENTRY(0x009b, restart_pa, 0xffff); - /* Jump to the identity-mapped low memory code */ restart_lowmem(type); } diff --git a/trunk/arch/x86/realmode/rm/Makefile b/trunk/arch/x86/realmode/rm/Makefile index 7c3f202cbccf..3f851c488593 100644 --- a/trunk/arch/x86/realmode/rm/Makefile +++ b/trunk/arch/x86/realmode/rm/Makefile @@ -12,6 +12,7 @@ subdir- := wakeup always := realmode.bin realmode-y += header.o +realmode-$(CONFIG_X86_32) += reboot_32.o targets += $(realmode-y) diff --git a/trunk/arch/x86/realmode/rm/header.S b/trunk/arch/x86/realmode/rm/header.S index 7be17f2c65a3..db21401c0c57 100644 --- a/trunk/arch/x86/realmode/rm/header.S +++ b/trunk/arch/x86/realmode/rm/header.S @@ -13,4 +13,7 @@ ENTRY(real_mode_header) .long pa_text_start .long pa_ro_end .long pa_end +#ifdef CONFIG_X86_32 + .long pa_machine_real_restart_asm +#endif END(real_mode_header) diff --git a/trunk/arch/x86/kernel/reboot_32.S b/trunk/arch/x86/realmode/rm/reboot_32.S similarity index 73% rename from trunk/arch/x86/kernel/reboot_32.S rename to trunk/arch/x86/realmode/rm/reboot_32.S index 1d5c46df0d78..83803c222b4a 100644 --- a/trunk/arch/x86/kernel/reboot_32.S +++ b/trunk/arch/x86/realmode/rm/reboot_32.S @@ -13,34 +13,21 @@ * * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax. */ - .section ".x86_trampoline","a" - .balign 16 + .section ".text32", "ax" .code32 -ENTRY(machine_real_restart_asm) -r_base = . - /* Get our own relocated address */ - call 1f -1: popl %ebx - subl $(1b - r_base), %ebx - - /* Compute the equivalent real-mode segment */ - movl %ebx, %ecx - shrl $4, %ecx - - /* Patch post-real-mode segment jump */ - movw (dispatch_table - r_base)(%ebx,%eax,2),%ax - movw %ax, (101f - r_base)(%ebx) - movw %cx, (102f - r_base)(%ebx) + .globl machine_real_restart_asm + .balign 16 +machine_real_restart_asm: /* Set up the IDT for real mode. */ - lidtl (machine_real_restart_idt - r_base)(%ebx) + lidtl pa_machine_real_restart_idt /* * Set up a GDT from which we can load segment descriptors for real * mode. The GDT is not used in real mode; it is just needed here to * prepare the descriptors. */ - lgdtl (machine_real_restart_gdt - r_base)(%ebx) + lgdtl pa_machine_real_restart_gdt /* * Load the data segment registers with 16-bit compatible values @@ -51,7 +38,7 @@ r_base = . movl %ecx, %fs movl %ecx, %gs movl %ecx, %ss - ljmpl $8, $1f - r_base + ljmpw $8, $1f /* * This is 16-bit protected mode code to disable paging and the cache, @@ -76,27 +63,32 @@ r_base = . * * Most of this work is probably excessive, but it is what is tested. */ + .text .code16 + + .balign 16 +machine_real_restart_asm16: 1: xorl %ecx, %ecx - movl %cr0, %eax - andl $0x00000011, %eax - orl $0x60000000, %eax - movl %eax, %cr0 + movl %cr0, %edx + andl $0x00000011, %edx + orl $0x60000000, %edx + movl %edx, %cr0 movl %ecx, %cr3 movl %cr0, %edx andl $0x60000000, %edx /* If no cache bits -> no wbinvd */ jz 2f wbinvd 2: - andb $0x10, %al - movl %eax, %cr0 + andb $0x10, %dl + movl %edx, %cr0 .byte 0xea /* ljmpw */ -101: .word 0 /* Offset */ -102: .word 0 /* Segment */ + .word 3f /* Offset */ + .word real_mode_seg /* Segment */ -bios: - ljmpw $0xf000, $0xfff0 +3: + testb $0, %al + jz bios apm: movw $0x1000, %ax @@ -106,30 +98,37 @@ apm: movw $0x0001, %bx movw $0x0003, %cx int $0x15 + /* This should never return... */ -END(machine_real_restart_asm) +bios: + ljmpw $0xf000, $0xfff0 - .balign 16 - /* These must match