diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2011-07-22 01:09:48 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2011-07-22 01:09:48 -0400 |
commit | 5dea1c88ed11a1221581c4b202f053c4fc138704 (patch) | |
tree | 59e15d3c696712e26ffb229ff987f33bcc72affe /arch/x86/lguest | |
parent | e0377e25206328998d036cafddcd00a7c3252e3e (diff) |
lguest: use a special 1:1 linear pagetable mode until first switch.
The Host used to create some page tables for the Guest to use at the
top of Guest memory; it would then tell the Guest where this was. In
particular, it created linear mappings for 0 and 0xC0000000 addresses
because lguest used to switch to its real page tables quite late in
boot.
However, since d50d8fe19 Linux initialized boot page tables in
head_32.S even before the "are we lguest?" boot jump. So, now we can
simplify things: the Host pagetable code assumes 1:1 linear mapping
until it first calls the LHCALL_NEW_PGTABLE hypercall, which we now do
before we reach C code.
This also means that the Host doesn't need to know anything about the
Guest's PAGE_OFFSET. (Non-Linux guests might not even have such a
thing).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'arch/x86/lguest')
-rw-r--r-- | arch/x86/lguest/boot.c | 11 | ||||
-rw-r--r-- | arch/x86/lguest/i386_head.S | 9 |
2 files changed, 12 insertions, 8 deletions
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index db832fd65ecb..719a32c60516 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -520,17 +520,16 @@ static unsigned long lguest_read_cr2(void) | |||
520 | 520 | ||
521 | /* See lguest_set_pte() below. */ | 521 | /* See lguest_set_pte() below. */ |
522 | static bool cr3_changed = false; | 522 | static bool cr3_changed = false; |
523 | static unsigned long current_cr3; | ||
523 | 524 | ||
524 | /* | 525 | /* |
525 | * cr3 is the current toplevel pagetable page: the principle is the same as | 526 | * cr3 is the current toplevel pagetable page: the principle is the same as |
526 | * cr0. Keep a local copy, and tell the Host when it changes. The only | 527 | * cr0. Keep a local copy, and tell the Host when it changes. |
527 | * difference is that our local copy is in lguest_data because the Host needs | ||
528 | * to set it upon our initial hypercall. | ||
529 | */ | 528 | */ |
530 | static void lguest_write_cr3(unsigned long cr3) | 529 | static void lguest_write_cr3(unsigned long cr3) |
531 | { | 530 | { |
532 | lguest_data.pgdir = cr3; | ||
533 | lazy_hcall1(LHCALL_NEW_PGTABLE, cr3); | 531 | lazy_hcall1(LHCALL_NEW_PGTABLE, cr3); |
532 | current_cr3 = cr3; | ||
534 | 533 | ||
535 | /* These two page tables are simple, linear, and used during boot */ | 534 | /* These two page tables are simple, linear, and used during boot */ |
536 | if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table)) | 535 | if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table)) |
@@ -539,7 +538,7 @@ static void lguest_write_cr3(unsigned long cr3) | |||
539 | 538 | ||
540 | static unsigned long lguest_read_cr3(void) | 539 | static unsigned long lguest_read_cr3(void) |
541 | { | 540 | { |
542 | return lguest_data.pgdir; | 541 | return current_cr3; |
543 | } | 542 | } |
544 | 543 | ||
545 | /* cr4 is used to enable and disable PGE, but we don't care. */ | 544 | /* cr4 is used to enable and disable PGE, but we don't care. */ |
@@ -758,7 +757,7 @@ static void lguest_pmd_clear(pmd_t *pmdp) | |||
758 | static void lguest_flush_tlb_single(unsigned long addr) | 757 | static void lguest_flush_tlb_single(unsigned long addr) |
759 | { | 758 | { |
760 | /* Simply set it to zero: if it was not, it will fault back in. */ | 759 | /* Simply set it to zero: if it was not, it will fault back in. */ |
761 | lazy_hcall3(LHCALL_SET_PTE, lguest_data.pgdir, addr, 0); | 760 | lazy_hcall3(LHCALL_SET_PTE, current_cr3, addr, 0); |
762 | } | 761 | } |
763 | 762 | ||
764 | /* | 763 | /* |
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 4f420c2f2d55..863b03a9fbff 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S | |||
@@ -27,13 +27,18 @@ | |||
27 | .section .init.text, "ax", @progbits | 27 | .section .init.text, "ax", @progbits |
28 | ENTRY(lguest_entry) | 28 | ENTRY(lguest_entry) |
29 | /* | 29 | /* |
30 | * We make the "initialization" hypercall now to tell the Host about | 30 | * We make the "initialization" hypercall now to tell the Host where |
31 | * us, and also find out where it put our page tables. | 31 | * our lguest_data struct is. |
32 | */ | 32 | */ |
33 | movl $LHCALL_LGUEST_INIT, %eax | 33 | movl $LHCALL_LGUEST_INIT, %eax |
34 | movl $lguest_data - __PAGE_OFFSET, %ebx | 34 | movl $lguest_data - __PAGE_OFFSET, %ebx |
35 | int $LGUEST_TRAP_ENTRY | 35 | int $LGUEST_TRAP_ENTRY |
36 | 36 | ||
37 | /* Now turn our pagetables on; setup by arch/x86/kernel/head_32.S. */ | ||
38 | movl $LHCALL_NEW_PGTABLE, %eax | ||
39 | movl $(initial_page_table - __PAGE_OFFSET), %ebx | ||
40 | int $LGUEST_TRAP_ENTRY | ||
41 | |||
37 | /* Set up the initial stack so we can run C code. */ | 42 | /* Set up the initial stack so we can run C code. */ |
38 | movl $(init_thread_union+THREAD_SIZE),%esp | 43 | movl $(init_thread_union+THREAD_SIZE),%esp |
39 | 44 | ||