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>
This commit is contained in:
@ -136,6 +136,7 @@ void foo(void)
|
||||
#ifdef CONFIG_LGUEST_GUEST
|
||||
BLANK();
|
||||
OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled);
|
||||
OFFSET(LGUEST_DATA_pgdir, lguest_data, pgdir);
|
||||
OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc);
|
||||
OFFSET(LGUEST_PAGES_host_idt_desc, lguest_pages, state.host_idt_desc);
|
||||
OFFSET(LGUEST_PAGES_host_cr3, lguest_pages, state.host_cr3);
|
||||
|
@ -86,6 +86,7 @@ struct lguest_data lguest_data = {
|
||||
.hcall_status = { [0 ... LHCALL_RING_SIZE-1] = 0xFF },
|
||||
.noirq_start = (u32)lguest_noirq_start,
|
||||
.noirq_end = (u32)lguest_noirq_end,
|
||||
.kernel_address = PAGE_OFFSET,
|
||||
.blocked_interrupts = { 1 }, /* Block timer interrupts */
|
||||
.syscall_vec = SYSCALL_VECTOR,
|
||||
};
|
||||
@ -1033,11 +1034,7 @@ __init void lguest_init(void *boot)
|
||||
|
||||
/*G:070 Now we've seen all the paravirt_ops, we return to
|
||||
* lguest_init() where the rest of the fairly chaotic boot setup
|
||||
* occurs.
|
||||
*
|
||||
* The Host expects our first hypercall to tell it where our "struct
|
||||
* lguest_data" is, so we do that first. */
|
||||
hcall(LHCALL_LGUEST_INIT, __pa(&lguest_data), 0, 0);
|
||||
* occurs. */
|
||||
|
||||
/* The native boot code sets up initial page tables immediately after
|
||||
* the kernel itself, and sets init_pg_tables_end so they're not
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user