Commit 5dea1c88 authored by Rusty Russell's avatar Rusty Russell

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 d50d8fe1 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: default avatarRusty Russell <rusty@rustcorp.com.au>
parent e0377e25
...@@ -63,7 +63,6 @@ void foo(void) ...@@ -63,7 +63,6 @@ void foo(void)
BLANK(); BLANK();
OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled); OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled);
OFFSET(LGUEST_DATA_irq_pending, lguest_data, irq_pending); OFFSET(LGUEST_DATA_irq_pending, lguest_data, irq_pending);
OFFSET(LGUEST_DATA_pgdir, lguest_data, pgdir);
BLANK(); BLANK();
OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc); OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc);
......
...@@ -520,17 +520,16 @@ static unsigned long lguest_read_cr2(void) ...@@ -520,17 +520,16 @@ static unsigned long lguest_read_cr2(void)
/* See lguest_set_pte() below. */ /* See lguest_set_pte() below. */
static bool cr3_changed = false; static bool cr3_changed = false;
static unsigned long current_cr3;
/* /*
* cr3 is the current toplevel pagetable page: the principle is the same as * cr3 is the current toplevel pagetable page: the principle is the same as
* cr0. Keep a local copy, and tell the Host when it changes. The only * cr0. Keep a local copy, and tell the Host when it changes.
* difference is that our local copy is in lguest_data because the Host needs
* to set it upon our initial hypercall.
*/ */
static void lguest_write_cr3(unsigned long cr3) static void lguest_write_cr3(unsigned long cr3)
{ {
lguest_data.pgdir = cr3;
lazy_hcall1(LHCALL_NEW_PGTABLE, cr3); lazy_hcall1(LHCALL_NEW_PGTABLE, cr3);
current_cr3 = cr3;
/* These two page tables are simple, linear, and used during boot */ /* These two page tables are simple, linear, and used during boot */
if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table)) if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table))
...@@ -539,7 +538,7 @@ static void lguest_write_cr3(unsigned long cr3) ...@@ -539,7 +538,7 @@ static void lguest_write_cr3(unsigned long cr3)
static unsigned long lguest_read_cr3(void) static unsigned long lguest_read_cr3(void)
{ {
return lguest_data.pgdir; return current_cr3;
} }
/* cr4 is used to enable and disable PGE, but we don't care. */ /* 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,7 +757,7 @@ static void lguest_pmd_clear(pmd_t *pmdp)
static void lguest_flush_tlb_single(unsigned long addr) static void lguest_flush_tlb_single(unsigned long addr)
{ {
/* Simply set it to zero: if it was not, it will fault back in. */ /* Simply set it to zero: if it was not, it will fault back in. */
lazy_hcall3(LHCALL_SET_PTE, lguest_data.pgdir, addr, 0); lazy_hcall3(LHCALL_SET_PTE, current_cr3, addr, 0);
} }
/* /*
......
...@@ -27,13 +27,18 @@ ...@@ -27,13 +27,18 @@
.section .init.text, "ax", @progbits .section .init.text, "ax", @progbits
ENTRY(lguest_entry) ENTRY(lguest_entry)
/* /*
* We make the "initialization" hypercall now to tell the Host about * We make the "initialization" hypercall now to tell the Host where
* us, and also find out where it put our page tables. * our lguest_data struct is.
*/ */
movl $LHCALL_LGUEST_INIT, %eax movl $LHCALL_LGUEST_INIT, %eax
movl $lguest_data - __PAGE_OFFSET, %ebx movl $lguest_data - __PAGE_OFFSET, %ebx
int $LGUEST_TRAP_ENTRY int $LGUEST_TRAP_ENTRY
/* Now turn our pagetables on; setup by arch/x86/kernel/head_32.S. */
movl $LHCALL_NEW_PGTABLE, %eax
movl $(initial_page_table - __PAGE_OFFSET), %ebx
int $LGUEST_TRAP_ENTRY
/* Set up the initial stack so we can run C code. */ /* Set up the initial stack so we can run C code. */
movl $(init_thread_union+THREAD_SIZE),%esp movl $(init_thread_union+THREAD_SIZE),%esp
......
...@@ -59,6 +59,8 @@ struct lg_cpu { ...@@ -59,6 +59,8 @@ struct lg_cpu {
struct lguest_pages *last_pages; struct lguest_pages *last_pages;
/* Initialization mode: linear map everything. */
bool linear_pages;
int cpu_pgd; /* Which pgd this cpu is currently using */ int cpu_pgd; /* Which pgd this cpu is currently using */
/* If a hypercall was asked for, this points to the arguments. */ /* If a hypercall was asked for, this points to the arguments. */
......
This diff is collapsed.
...@@ -59,8 +59,6 @@ struct lguest_data { ...@@ -59,8 +59,6 @@ struct lguest_data {
unsigned long reserve_mem; unsigned long reserve_mem;
/* KHz for the TSC clock. */ /* KHz for the TSC clock. */
u32 tsc_khz; u32 tsc_khz;
/* Page where the top-level pagetable is */
unsigned long pgdir;
/* Fields initialized by the Guest at boot: */ /* Fields initialized by the Guest at boot: */
/* Instruction range to suppress interrupts even if enabled */ /* Instruction range to suppress interrupts even if enabled */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment