x86, realmode: Move reboot_32.S to unified realmode code
Migrated reboot_32.S from x86_trampoline to the real-mode blob. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com> Link: http://lkml.kernel.org/r/1336501366-28617-5-git-send-email-jarkko.sakkinen@intel.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
parent
084ee1c641
commit
5a8c9aebe0
|
@ -9,6 +9,10 @@ struct real_mode_header {
|
||||||
u32 text_start;
|
u32 text_start;
|
||||||
u32 ro_end;
|
u32 ro_end;
|
||||||
u32 end;
|
u32 end;
|
||||||
|
/* reboot */
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
u32 machine_real_restart_asm;
|
||||||
|
#endif
|
||||||
} __attribute__((__packed__));
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
extern struct real_mode_header real_mode_header;
|
extern struct real_mode_header real_mode_header;
|
||||||
|
|
|
@ -49,7 +49,6 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||||
obj-y += cpu/
|
obj-y += cpu/
|
||||||
obj-y += acpi/
|
obj-y += acpi/
|
||||||
obj-y += reboot.o
|
obj-y += reboot.o
|
||||||
obj-$(CONFIG_X86_32) += reboot_32.o
|
|
||||||
obj-$(CONFIG_MCA) += mca_32.o
|
obj-$(CONFIG_MCA) += mca_32.o
|
||||||
obj-$(CONFIG_X86_MSR) += msr.o
|
obj-$(CONFIG_X86_MSR) += msr.o
|
||||||
obj-$(CONFIG_X86_CPUID) += cpuid.o
|
obj-$(CONFIG_X86_CPUID) += cpuid.o
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
# include <linux/ctype.h>
|
# include <linux/ctype.h>
|
||||||
# include <linux/mc146818rtc.h>
|
# include <linux/mc146818rtc.h>
|
||||||
|
# include <asm/realmode.h>
|
||||||
#else
|
#else
|
||||||
# include <asm/x86_init.h>
|
# include <asm/x86_init.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -332,15 +333,10 @@ static int __init reboot_init(void)
|
||||||
}
|
}
|
||||||
core_initcall(reboot_init);
|
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 machine_real_restart(unsigned int type)
|
||||||
{
|
{
|
||||||
void *restart_va;
|
void (*restart_lowmem)(unsigned int) = (void (*)(unsigned int))
|
||||||
unsigned long restart_pa;
|
real_mode_header.machine_real_restart_asm;
|
||||||
void (*restart_lowmem)(unsigned int);
|
|
||||||
u64 *lowmem_gdt;
|
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
|
||||||
|
@ -369,21 +365,6 @@ void machine_real_restart(unsigned int type)
|
||||||
too. */
|
too. */
|
||||||
*((unsigned short *)0x472) = reboot_mode;
|
*((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 */
|
/* Jump to the identity-mapped low memory code */
|
||||||
restart_lowmem(type);
|
restart_lowmem(type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ subdir- := wakeup
|
||||||
always := realmode.bin
|
always := realmode.bin
|
||||||
|
|
||||||
realmode-y += header.o
|
realmode-y += header.o
|
||||||
|
realmode-$(CONFIG_X86_32) += reboot_32.o
|
||||||
|
|
||||||
targets += $(realmode-y)
|
targets += $(realmode-y)
|
||||||
|
|
||||||
|
|
|
@ -13,4 +13,7 @@ ENTRY(real_mode_header)
|
||||||
.long pa_text_start
|
.long pa_text_start
|
||||||
.long pa_ro_end
|
.long pa_ro_end
|
||||||
.long pa_end
|
.long pa_end
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
.long pa_machine_real_restart_asm
|
||||||
|
#endif
|
||||||
END(real_mode_header)
|
END(real_mode_header)
|
||||||
|
|
|
@ -13,34 +13,21 @@
|
||||||
*
|
*
|
||||||
* This code is called with the restart type (0 = BIOS, 1 = APM) in %eax.
|
* This code is called with the restart type (0 = BIOS, 1 = APM) in %eax.
|
||||||
*/
|
*/
|
||||||
.section ".x86_trampoline","a"
|
.section ".text32", "ax"
|
||||||
.balign 16
|
|
||||||
.code32
|
.code32
|
||||||
ENTRY(machine_real_restart_asm)
|
.globl 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)
|
|
||||||
|
|
||||||
|
.balign 16
|
||||||
|
machine_real_restart_asm:
|
||||||
/* Set up the IDT for real mode. */
|
/* 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
|
* 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
|
* mode. The GDT is not used in real mode; it is just needed here to
|
||||||
* prepare the descriptors.
|
* 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
|
* Load the data segment registers with 16-bit compatible values
|
||||||
|
@ -51,7 +38,7 @@ r_base = .
|
||||||
movl %ecx, %fs
|
movl %ecx, %fs
|
||||||
movl %ecx, %gs
|
movl %ecx, %gs
|
||||||
movl %ecx, %ss
|
movl %ecx, %ss
|
||||||
ljmpl $8, $1f - r_base
|
ljmpw $8, $1f
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is 16-bit protected mode code to disable paging and the cache,
|
* 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.
|
* Most of this work is probably excessive, but it is what is tested.
|
||||||
*/
|
*/
|
||||||
|
.text
|
||||||
.code16
|
.code16
|
||||||
|
|
||||||
|
.balign 16
|
||||||
|
machine_real_restart_asm16:
|
||||||
1:
|
1:
|
||||||
xorl %ecx, %ecx
|
xorl %ecx, %ecx
|
||||||
movl %cr0, %eax
|
movl %cr0, %edx
|
||||||
andl $0x00000011, %eax
|
andl $0x00000011, %edx
|
||||||
orl $0x60000000, %eax
|
orl $0x60000000, %edx
|
||||||
movl %eax, %cr0
|
movl %edx, %cr0
|
||||||
movl %ecx, %cr3
|
movl %ecx, %cr3
|
||||||
movl %cr0, %edx
|
movl %cr0, %edx
|
||||||
andl $0x60000000, %edx /* If no cache bits -> no wbinvd */
|
andl $0x60000000, %edx /* If no cache bits -> no wbinvd */
|
||||||
jz 2f
|
jz 2f
|
||||||
wbinvd
|
wbinvd
|
||||||
2:
|
2:
|
||||||
andb $0x10, %al
|
andb $0x10, %dl
|
||||||
movl %eax, %cr0
|
movl %edx, %cr0
|
||||||
.byte 0xea /* ljmpw */
|
.byte 0xea /* ljmpw */
|
||||||
101: .word 0 /* Offset */
|
.word 3f /* Offset */
|
||||||
102: .word 0 /* Segment */
|
.word real_mode_seg /* Segment */
|
||||||
|
|
||||||
bios:
|
3:
|
||||||
ljmpw $0xf000, $0xfff0
|
testb $0, %al
|
||||||
|
jz bios
|
||||||
|
|
||||||
apm:
|
apm:
|
||||||
movw $0x1000, %ax
|
movw $0x1000, %ax
|
||||||
|
@ -106,30 +98,37 @@ apm:
|
||||||
movw $0x0001, %bx
|
movw $0x0001, %bx
|
||||||
movw $0x0003, %cx
|
movw $0x0003, %cx
|
||||||
int $0x15
|
int $0x15
|
||||||
|
/* This should never return... */
|
||||||
|
|
||||||
END(machine_real_restart_asm)
|
bios:
|
||||||
|
ljmpw $0xf000, $0xfff0
|
||||||
|
|
||||||
.balign 16
|
.section ".rodata", "a"
|
||||||
/* These must match <asm/reboot.h */
|
.globl machine_real_restart_idt, machine_real_restart_gdt
|
||||||
dispatch_table:
|
|
||||||
.word bios - r_base
|
|
||||||
.word apm - r_base
|
|
||||||
END(dispatch_table)
|
|
||||||
|
|
||||||
.balign 16
|
.balign 16
|
||||||
machine_real_restart_idt:
|
machine_real_restart_idt:
|
||||||
.word 0xffff /* Length - real mode default value */
|
.word 0xffff /* Length - real mode default value */
|
||||||
.long 0 /* Base - real mode default value */
|
.long 0 /* Base - real mode default value */
|
||||||
END(machine_real_restart_idt)
|
|
||||||
|
|
||||||
.balign 16
|
.balign 16
|
||||||
ENTRY(machine_real_restart_gdt)
|
machine_real_restart_gdt:
|
||||||
.quad 0 /* Self-pointer, filled in by PM code */
|
/* Self-pointer */
|
||||||
.quad 0 /* 16-bit code segment, filled in by PM code */
|
.word 0xffff /* Length - real mode default value */
|
||||||
|
.long pa_machine_real_restart_gdt
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 16-bit code segment pointing to real_mode_seg
|
||||||
|
* Selector value 8
|
||||||
|
*/
|
||||||
|
.word 0xffff /* Limit */
|
||||||
|
.long 0x9b000000 + pa_real_mode_base
|
||||||
|
.word 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 16-bit data segment with the selector value 16 = 0x10 and
|
* 16-bit data segment with the selector value 16 = 0x10 and
|
||||||
* base value 0x100; since this is consistent with real mode
|
* base value 0x100; since this is consistent with real mode
|
||||||
* semantics we don't have to reload the segments once CR0.PE = 0.
|
* semantics we don't have to reload the segments once CR0.PE = 0.
|
||||||
*/
|
*/
|
||||||
.quad GDT_ENTRY(0x0093, 0x100, 0xffff)
|
.quad GDT_ENTRY(0x0093, 0x100, 0xffff)
|
||||||
END(machine_real_restart_gdt)
|
|
Loading…
Reference in New Issue