diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-06-07 19:41:59 +0100 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-06-07 19:41:59 +0100 |
commit | 45542203a2930a1fe77a9d3a6ab8f3461434d01b (patch) | |
tree | 7bc1de41a0aaa86fa4518566626ec4431f8188b1 /xen/arch/x86/boot/trampoline.S | |
parent | 79669c1728d9ce1fd6d697aa6ae0ff113d9c16db (diff) | |
download | xen-45542203a2930a1fe77a9d3a6ab8f3461434d01b.tar.gz xen-45542203a2930a1fe77a9d3a6ab8f3461434d01b.tar.bz2 xen-45542203a2930a1fe77a9d3a6ab8f3461434d01b.zip |
x86: Return to real-mode when booting primary CPU, and gather
memory-map information (from int15{e820,e801,88} and int12 bios
calls).
Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'xen/arch/x86/boot/trampoline.S')
-rw-r--r-- | xen/arch/x86/boot/trampoline.S | 93 |
1 files changed, 82 insertions, 11 deletions
diff --git a/xen/arch/x86/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S index 0eb9dcee8c..3f90993951 100644 --- a/xen/arch/x86/boot/trampoline.S +++ b/xen/arch/x86/boot/trampoline.S @@ -1,28 +1,34 @@ .code16 +/* NB. bootsym() is only usable in real mode, or via BOOT_PSEUDORM_DS. */ +#undef bootsym +#define bootsym(s) ((s)-trampoline_start) + .globl trampoline_realmode_entry trampoline_realmode_entry: nop # We use this byte as a progress flag - movb $0xA5,trampoline_cpu_started - trampoline_start + movb $0xA5,bootsym(trampoline_cpu_started) cld cli - lidt %cs:idt_48 - trampoline_start - lgdt %cs:gdt_48 - trampoline_start + lidt %cs:bootsym(idt_48) + lgdt %cs:bootsym(gdt_48) xor %ax, %ax inc %ax lmsw %ax # CR0.PE = 1 (enter protected mode) mov $1,%bl # EBX != 0 indicates we are an AP jmp 1f -1: ljmpl $TRAMP_CS32,$SYM_TRAMP_PHYS(trampoline_protmode_entry) +1: ljmpl $BOOT_CS32,$bootsym_phys(trampoline_protmode_entry) idt_48: .word 0, 0, 0 # base = limit = 0 -gdt_48: .word 4*8-1 - .long SYM_TRAMP_PHYS(trampoline_gdt) +gdt_48: .word 6*8-1 + .long bootsym_phys(trampoline_gdt) trampoline_gdt: .quad 0x0000000000000000 /* 0x0000: unused */ .quad 0x00cf9a000000ffff /* 0x0008: ring 0 code, 32-bit mode */ .quad 0x00af9a000000ffff /* 0x0010: ring 0 code, 64-bit mode */ .quad 0x00cf92000000ffff /* 0x0018: ring 0 data */ + .quad 0x00009a090000ffff /* 0x0020: real-mode code @ 0x90000 */ + .quad 0x000092090000ffff /* 0x0028: real-mode data @ 0x90000 */ cpuid_ext_features: .long 0 @@ -38,7 +44,7 @@ trampoline_cpu_started: .code32 trampoline_protmode_entry: /* Set up a few descriptors: on entry only CS is guaranteed good. */ - mov $TRAMP_DS,%eax + mov $BOOT_DS,%eax mov %eax,%ds mov %eax,%es @@ -54,13 +60,13 @@ trampoline_protmode_entry: mov %ecx,%cr4 /* Load pagetable base register. */ - mov $SYM_PHYS(idle_pg_table),%eax - add SYM_TRAMP_PHYS(trampoline_xen_phys_start),%eax + mov $sym_phys(idle_pg_table),%eax + add bootsym_phys(trampoline_xen_phys_start),%eax mov %eax,%cr3 #if CONFIG_PAGING_LEVELS != 2 /* Set up EFER (Extended Feature Enable Register). */ - mov SYM_TRAMP_PHYS(cpuid_ext_features),%edi + mov bootsym_phys(cpuid_ext_features),%edi test $0x20100800,%edi /* SYSCALL/SYSRET, No Execute, Long Mode? */ jz .Lskip_efer movl $MSR_EFER,%ecx @@ -84,7 +90,7 @@ trampoline_protmode_entry: #if defined(__x86_64__) /* Now in compatibility mode. Long-jump into 64-bit mode. */ - ljmp $TRAMP_CS64,$SYM_TRAMP_PHYS(start64) + ljmp $BOOT_CS64,$bootsym_phys(start64) .code64 start64: @@ -108,3 +114,68 @@ high_start: ljmp $(__HYPERVISOR_CS),$__high_start #endif + + .code32 +trampoline_boot_cpu_entry: + /* Load pseudo-real-mode segments. */ + mov $BOOT_PSEUDORM_DS,%eax + mov %eax,%ds + mov %eax,%es + mov %eax,%fs + mov %eax,%gs + mov %eax,%ss + + /* Switch to pseudo-rm CS, enter real mode, and flush insn queue. */ + mov %cr0,%eax + dec %eax + ljmp $BOOT_PSEUDORM_CS,$bootsym(1f) + .code16 +1: mov %eax,%cr0 # CR0.PE = 0 (leave protected mode) + jmp 1f + + /* Load proper real-mode values into %cs, %ds, %es and %ss. */ +1: ljmp $(BOOT_TRAMPOLINE>>4),$bootsym(1f) +1: mov $(BOOT_TRAMPOLINE>>4),%ax + mov %ax,%ds + mov %ax,%es + mov %ax,%ss + + /* Stack grows down from 0x9200. Initialise IDT and enable irqs. */ + mov $0x2000,%sp + lidt bootsym(rm_idt) + sti + + /* + * Do real-mode work: + * 1. Get memory map. + */ + call get_memory_map + + /* Disable irqs before returning to protected mode. */ + cli + + /* Enter protected mode, and flush insn queue. */ + xor %ax,%ax + inc %ax + lmsw %ax # CR0.PE = 1 (enter protected mode) + jmp 1f + + /* Load proper protected-mode values into all segment registers. */ +1: ljmpl $BOOT_CS32,$bootsym_phys(1f) + .code32 +1: mov $BOOT_DS,%eax + mov %eax,%ds + mov %eax,%es + mov %eax,%fs + mov %eax,%gs + mov %eax,%ss + + /* EBX == 0 indicates we are the BP (Boot Processor). */ + xor %ebx,%ebx + + /* Jump to the common bootstrap entry point. */ + jmp trampoline_protmode_entry + +rm_idt: .word 256*4-1, 0, 0 + +#include "mem.S" |