diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-21 21:03:36 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-23 01:49:54 -0400 |
commit | 47436aa4ad054c1c7c8231618e86ebd9305308dc (patch) | |
tree | a9ba6e0521f9116442144a86e781a3164ec86094 /arch/x86 | |
parent | c18acd73ffc209def08003a1927473096f66c5ad (diff) |
Boot with virtual == physical to get closer to native Linux.
1) This allows us to get alot closer to booting bzImages.
2) It means we don't have to know page_offset.
3) The Guest needs to modify the boot pagetables to create the
PAGE_OFFSET mapping before jumping to C code.
4) guest_pa() walks the page tables rather than using page_offset.
5) We don't use page_offset to figure out whether to emulate: it was
always kinda quesationable, and won't work for instructions done
before remapping (bzImage unpacking in particular).
6) We still want the kernel address for tlb flushing: have the initial
hypercall give us that, too.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/asm-offsets_32.c | 1 | ||||
-rw-r--r-- | arch/x86/lguest/boot.c | 7 | ||||
-rw-r--r-- | arch/x86/lguest/i386_head.S | 41 |
3 files changed, 39 insertions, 10 deletions
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index f8764716b0c0..0e45981b2dd7 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c | |||
@@ -136,6 +136,7 @@ void foo(void) | |||
136 | #ifdef CONFIG_LGUEST_GUEST | 136 | #ifdef CONFIG_LGUEST_GUEST |
137 | BLANK(); | 137 | BLANK(); |
138 | OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled); | 138 | OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled); |
139 | OFFSET(LGUEST_DATA_pgdir, lguest_data, pgdir); | ||
139 | OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc); | 140 | OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc); |
140 | OFFSET(LGUEST_PAGES_host_idt_desc, lguest_pages, state.host_idt_desc); | 141 | OFFSET(LGUEST_PAGES_host_idt_desc, lguest_pages, state.host_idt_desc); |
141 | OFFSET(LGUEST_PAGES_host_cr3, lguest_pages, state.host_cr3); | 142 | OFFSET(LGUEST_PAGES_host_cr3, lguest_pages, state.host_cr3); |
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 3a06b51c98ad..090f30cbf24c 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -86,6 +86,7 @@ struct lguest_data lguest_data = { | |||
86 | .hcall_status = { [0 ... LHCALL_RING_SIZE-1] = 0xFF }, | 86 | .hcall_status = { [0 ... LHCALL_RING_SIZE-1] = 0xFF }, |
87 | .noirq_start = (u32)lguest_noirq_start, | 87 | .noirq_start = (u32)lguest_noirq_start, |
88 | .noirq_end = (u32)lguest_noirq_end, | 88 | .noirq_end = (u32)lguest_noirq_end, |
89 | .kernel_address = PAGE_OFFSET, | ||
89 | .blocked_interrupts = { 1 }, /* Block timer interrupts */ | 90 | .blocked_interrupts = { 1 }, /* Block timer interrupts */ |
90 | .syscall_vec = SYSCALL_VECTOR, | 91 | .syscall_vec = SYSCALL_VECTOR, |
91 | }; | 92 | }; |
@@ -1033,11 +1034,7 @@ __init void lguest_init(void *boot) | |||
1033 | 1034 | ||
1034 | /*G:070 Now we've seen all the paravirt_ops, we return to | 1035 | /*G:070 Now we've seen all the paravirt_ops, we return to |
1035 | * lguest_init() where the rest of the fairly chaotic boot setup | 1036 | * lguest_init() where the rest of the fairly chaotic boot setup |
1036 | * occurs. | 1037 | * occurs. */ |
1037 | * | ||
1038 | * The Host expects our first hypercall to tell it where our "struct | ||
1039 | * lguest_data" is, so we do that first. */ | ||
1040 | hcall(LHCALL_LGUEST_INIT, __pa(&lguest_data), 0, 0); | ||
1041 | 1038 | ||
1042 | /* The native boot code sets up initial page tables immediately after | 1039 | /* The native boot code sets up initial page tables immediately after |
1043 | * the kernel itself, and sets init_pg_tables_end so they're not | 1040 | * the kernel itself, and sets init_pg_tables_end so they're not |
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 6d7a74f07c41..ba4282eba5bf 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/linkage.h> | 1 | #include <linux/linkage.h> |
2 | #include <linux/lguest.h> | 2 | #include <linux/lguest.h> |
3 | #include <asm/lguest_hcall.h> | ||
3 | #include <asm/asm-offsets.h> | 4 | #include <asm/asm-offsets.h> |
4 | #include <asm/thread_info.h> | 5 | #include <asm/thread_info.h> |
5 | #include <asm/processor-flags.h> | 6 | #include <asm/processor-flags.h> |
@@ -8,18 +9,48 @@ | |||
8 | * looks for. The plan is that the Linux boot protocol will be extended with a | 9 | * looks for. The plan is that the Linux boot protocol will be extended with a |
9 | * "platform type" field which will guide us here from the normal entry point, | 10 | * "platform type" field which will guide us here from the normal entry point, |
10 | * but for the moment this suffices. The normal boot code uses %esi for the | 11 | * but for the moment this suffices. The normal boot code uses %esi for the |
11 | * boot header, so we do too. We convert it to a virtual address by adding | 12 | * boot header, so we do too. |
12 | * PAGE_OFFSET, and hand it to lguest_init() as its argument (ie. %eax). | 13 | * |
14 | * WARNING: be very careful here! We're running at addresses equal to physical | ||
15 | * addesses (around 0), not above PAGE_OFFSET as most code expectes | ||
16 | * (eg. 0xC0000000). Jumps are relative, so they're OK, but we can't touch any | ||
17 | * data. | ||
13 | * | 18 | * |
14 | * The .section line puts this code in .init.text so it will be discarded after | 19 | * The .section line puts this code in .init.text so it will be discarded after |
15 | * boot. */ | 20 | * boot. */ |
16 | .section .init.text, "ax", @progbits | 21 | .section .init.text, "ax", @progbits |
17 | .ascii "GenuineLguest" | 22 | .ascii "GenuineLguest" |
18 | /* Set up initial stack. */ | 23 | /* Make initial hypercall now, so we can set up the pagetables. */ |
19 | movl $(init_thread_union+THREAD_SIZE),%esp | 24 | movl $LHCALL_LGUEST_INIT, %eax |
25 | movl $lguest_data - __PAGE_OFFSET, %edx | ||
26 | int $LGUEST_TRAP_ENTRY | ||
27 | |||
28 | /* Set up boot information pointer to hand to lguest_init(): it wants | ||
29 | * a virtual address. */ | ||
20 | movl %esi, %eax | 30 | movl %esi, %eax |
21 | addl $__PAGE_OFFSET, %eax | 31 | addl $__PAGE_OFFSET, %eax |
22 | jmp lguest_init | 32 | |
33 | /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl | ||
34 | * instruction uses %esi, so we needed to save it above. */ | ||
35 | movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi | ||
36 | |||
37 | /* Copy first 32 entries of page directory to __PAGE_OFFSET entries. | ||
38 | * This means the first 128M of kernel memory will be mapped at | ||
39 | * PAGE_OFFSET where the kernel expects to run. This will get it far | ||
40 | * enough through boot to switch to its own pagetables. */ | ||
41 | movl $32, %ecx | ||
42 | movl %esi, %edi | ||
43 | addl $((__PAGE_OFFSET >> 22) * 4), %edi | ||
44 | rep | ||
45 | movsl | ||
46 | |||
47 | /* Set up the initial stack so we can run C code. */ | ||
48 | movl $(init_thread_union+THREAD_SIZE),%esp | ||
49 | |||
50 | |||
51 | /* Jumps are relative, and we're running __PAGE_OFFSET too low at the | ||
52 | * moment. */ | ||
53 | jmp lguest_init+__PAGE_OFFSET | ||
23 | 54 | ||
24 | /*G:055 We create a macro which puts the assembler code between lgstart_ and | 55 | /*G:055 We create a macro which puts the assembler code between lgstart_ and |
25 | * lgend_ markers. These templates are put in the .text section: they can't be | 56 | * lgend_ markers. These templates are put in the .text section: they can't be |