aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/boot/trampoline.S
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-06-07 19:41:59 +0100
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-06-07 19:41:59 +0100
commit45542203a2930a1fe77a9d3a6ab8f3461434d01b (patch)
tree7bc1de41a0aaa86fa4518566626ec4431f8188b1 /xen/arch/x86/boot/trampoline.S
parent79669c1728d9ce1fd6d697aa6ae0ff113d9c16db (diff)
downloadxen-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.S93
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"