diff options
Diffstat (limited to 'arch/x86/lguest/i386_head.S')
-rw-r--r-- | arch/x86/lguest/i386_head.S | 41 |
1 files changed, 36 insertions, 5 deletions
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 @@ #include <linux/linkage.h> #include <linux/lguest.h> +#include <asm/lguest_hcall.h> #include <asm/asm-offsets.h> #include <asm/thread_info.h> #include <asm/processor-flags.h> @@ -8,18 +9,48 @@ * looks for. The plan is that the Linux boot protocol will be extended with a * "platform type" field which will guide us here from the normal entry point, * but for the moment this suffices. The normal boot code uses %esi for the - * boot header, so we do too. We convert it to a virtual address by adding - * PAGE_OFFSET, and hand it to lguest_init() as its argument (ie. %eax). + * boot header, so we do too. + * + * WARNING: be very careful here! We're running at addresses equal to physical + * addesses (around 0), not above PAGE_OFFSET as most code expectes + * (eg. 0xC0000000). Jumps are relative, so they're OK, but we can't touch any + * data. * * The .section line puts this code in .init.text so it will be discarded after * boot. */ .section .init.text, "ax", @progbits .ascii "GenuineLguest" - /* Set up initial stack. */ - movl $(init_thread_union+THREAD_SIZE),%esp + /* Make initial hypercall now, so we can set up the pagetables. */ + movl $LHCALL_LGUEST_INIT, %eax + movl $lguest_data - __PAGE_OFFSET, %edx + int $LGUEST_TRAP_ENTRY + + /* Set up boot information pointer to hand to lguest_init(): it wants + * a virtual address. */ movl %esi, %eax addl $__PAGE_OFFSET, %eax - jmp lguest_init + + /* The Host put the toplevel pagetable in lguest_data.pgdir. The movsl + * instruction uses %esi, so we needed to save it above. */ + movl lguest_data - __PAGE_OFFSET + LGUEST_DATA_pgdir, %esi + + /* Copy first 32 entries of page directory to __PAGE_OFFSET entries. + * This means the first 128M of kernel memory will be mapped at + * PAGE_OFFSET where the kernel expects to run. This will get it far + * enough through boot to switch to its own pagetables. */ + movl $32, %ecx + movl %esi, %edi + addl $((__PAGE_OFFSET >> 22) * 4), %edi + rep + movsl + + /* Set up the initial stack so we can run C code. */ + movl $(init_thread_union+THREAD_SIZE),%esp + + + /* Jumps are relative, and we're running __PAGE_OFFSET too low at the + * moment. */ + jmp lguest_init+__PAGE_OFFSET /*G:055 We create a macro which puts the assembler code between lgstart_ and * lgend_ markers. These templates are put in the .text section: they can't be |