aboutsummaryrefslogtreecommitdiff
path: root/drivers/lguest
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest')
-rw-r--r--drivers/lguest/Kconfig25
-rw-r--r--drivers/lguest/Makefile20
-rw-r--r--drivers/lguest/core.c779
-rw-r--r--drivers/lguest/hypercalls.c364
-rw-r--r--drivers/lguest/interrupts_and_traps.c629
-rw-r--r--drivers/lguest/io.c626
-rw-r--r--drivers/lguest/lg.h356
-rw-r--r--drivers/lguest/lguest.c1102
-rw-r--r--drivers/lguest/lguest_asm.S93
-rw-r--r--drivers/lguest/lguest_bus.c218
-rw-r--r--drivers/lguest/lguest_device.c535
-rw-r--r--drivers/lguest/lguest_user.c574
-rw-r--r--drivers/lguest/page_tables.c1334
-rw-r--r--drivers/lguest/segments.c189
-rw-r--r--drivers/lguest/x86/core.c720
-rw-r--r--drivers/lguest/x86/switcher_32.S (renamed from drivers/lguest/switcher.S)92
16 files changed, 3705 insertions, 3951 deletions
diff --git a/drivers/lguest/Kconfig b/drivers/lguest/Kconfig
index 41e2250613a..ee035ec4526 100644
--- a/drivers/lguest/Kconfig
+++ b/drivers/lguest/Kconfig
@@ -1,30 +1,13 @@
config LGUEST
tristate "Linux hypervisor example code"
- depends on X86 && PARAVIRT && EXPERIMENTAL && !X86_PAE && FUTEX
- select LGUEST_GUEST
+ depends on X86_32 && EVENTFD && TTY
select HVC_DRIVER
---help---
This is a very simple module which allows you to run
multiple instances of the same Linux kernel, using the
- "lguest" command found in the Documentation/lguest directory.
+ "lguest" command found in the tools/lguest directory.
+
Note that "lguest" is pronounced to rhyme with "fell quest",
- not "rustyvisor". See Documentation/lguest/lguest.txt.
+ not "rustyvisor". See tools/lguest/lguest.txt.
If unsure, say N. If curious, say M. If masochistic, say Y.
-
-config LGUEST_GUEST
- bool
- help
- The guest needs code built-in, even if the host has lguest
- support as a module. The drivers are tiny, so we build them
- in too.
-
-config LGUEST_NET
- tristate
- default y
- depends on LGUEST_GUEST && NET
-
-config LGUEST_BLOCK
- tristate
- default y
- depends on LGUEST_GUEST && BLOCK
diff --git a/drivers/lguest/Makefile b/drivers/lguest/Makefile
index e5047471c33..c4197503900 100644
--- a/drivers/lguest/Makefile
+++ b/drivers/lguest/Makefile
@@ -1,10 +1,12 @@
-# Guest requires the paravirt_ops replacement and the bus driver.
-obj-$(CONFIG_LGUEST_GUEST) += lguest.o lguest_asm.o lguest_bus.o
+# Guest requires the device configuration and probing code.
+obj-$(CONFIG_LGUEST_GUEST) += lguest_device.o
# Host requires the other files, which can be a module.
obj-$(CONFIG_LGUEST) += lg.o
-lg-y := core.o hypercalls.o page_tables.o interrupts_and_traps.o \
- segments.o io.o lguest_user.o switcher.o
+lg-y = core.o hypercalls.o page_tables.o interrupts_and_traps.o \
+ segments.o lguest_user.o
+
+lg-$(CONFIG_X86_32) += x86/switcher_32.o x86/core.o
Preparation Preparation!: PREFIX=P
Guest: PREFIX=G
@@ -16,4 +18,12 @@ Mastery: PREFIX=M
Beer:
@for f in Preparation Guest Drivers Launcher Host Switcher Mastery; do echo "{==- $$f -==}"; make -s $$f; done; echo "{==-==}"
Preparation Preparation! Guest Drivers Launcher Host Switcher Mastery:
- @sh ../../Documentation/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'`
+ @sh ../../tools/lguest/extract $(PREFIX) `find ../../* -name '*.[chS]' -wholename '*lguest*'`
+Puppy:
+ @clear
+ @printf " __ \n (___()'\`;\n /, /\`\n \\\\\\\"--\\\\\\ \n"
+ @sleep 2; clear; printf "\n\n Sit!\n\n"; sleep 1; clear
+ @printf " __ \n ()'\`; \n /\\|\` \n / | \n(/_)_|_ \n"
+ @sleep 2; clear; printf "\n\n Stand!\n\n"; sleep 1; clear
+ @printf " __ \n ()'\`; \n /\\|\` \n /._.= \n /| / \n(_\_)_ \n"
+ @sleep 2; clear; printf "\n\n Good puppy!\n\n"; sleep 1; clear
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 4a315f08a56..0bf1e4edf04 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -1,8 +1,8 @@
-/*P:400 This contains run_guest() which actually calls into the Host<->Guest
+/*P:400
+ * This contains run_guest() which actually calls into the Host<->Guest
* Switcher and analyzes the return, such as determining if the Guest wants the
- * Host to do something. This file also contains useful helper routines, and a
- * couple of non-obvious setup and teardown pieces which were implemented after
- * days of debugging pain. :*/
+ * Host to do something. This file also contains useful helper routines.
+:*/
#include <linux/module.h>
#include <linux/stringify.h>
#include <linux/stddef.h>
@@ -11,60 +11,24 @@
#include <linux/vmalloc.h>
#include <linux/cpu.h>
#include <linux/freezer.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
#include <asm/paravirt.h>
-#include <asm/desc.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/poll.h>
-#include <asm/highmem.h>
#include <asm/asm-offsets.h>
-#include <asm/i387.h>
#include "lg.h"
-/* Found in switcher.S */
-extern char start_switcher_text[], end_switcher_text[], switch_to_guest[];
-extern unsigned long default_idt_entries[];
-
-/* Every guest maps the core switcher code. */
-#define SHARED_SWITCHER_PAGES \
- DIV_ROUND_UP(end_switcher_text - start_switcher_text, PAGE_SIZE)
-/* Pages for switcher itself, then two pages per cpu */
-#define TOTAL_SWITCHER_PAGES (SHARED_SWITCHER_PAGES + 2 * NR_CPUS)
-
-/* We map at -4M for ease of mapping into the guest (one PTE page). */
-#define SWITCHER_ADDR 0xFFC00000
-
+unsigned long switcher_addr;
+struct page **lg_switcher_pages;
static struct vm_struct *switcher_vma;
-static struct page **switcher_page;
-
-static int cpu_had_pge;
-static struct {
- unsigned long offset;
- unsigned short segment;
-} lguest_entry;
/* This One Big lock protects all inter-guest data structures. */
DEFINE_MUTEX(lguest_lock);
-static DEFINE_PER_CPU(struct lguest *, last_guest);
-
-/* FIXME: Make dynamic. */
-#define MAX_LGUEST_GUESTS 16
-struct lguest lguests[MAX_LGUEST_GUESTS];
-
-/* Offset from where switcher.S was compiled to where we've copied it */
-static unsigned long switcher_offset(void)
-{
- return SWITCHER_ADDR - (unsigned long)start_switcher_text;
-}
-/* This cpu's struct lguest_pages. */
-static struct lguest_pages *lguest_pages(unsigned int cpu)
-{
- return &(((struct lguest_pages *)
- (SWITCHER_ADDR + SHARED_SWITCHER_PAGES*PAGE_SIZE))[cpu]);
-}
-
-/*H:010 We need to set up the Switcher at a high virtual address. Remember the
+/*H:010
+ * We need to set up the Switcher at a high virtual address. Remember the
* Switcher is a few hundred bytes of assembler code which actually changes the
* CPU to run the Guest, and then changes back to the Host when a trap or
* interrupt happens.
@@ -73,8 +37,7 @@ static struct lguest_pages *lguest_pages(unsigned int cpu)
* Host since it will be running as the switchover occurs.
*
* Trying to map memory at a particular address is an unusual thing to do, so
- * it's not a simple one-liner. We also set up the per-cpu parts of the
- * Switcher here.
+ * it's not a simple one-liner.
*/
static __init int map_switcher(void)
{
@@ -89,132 +52,80 @@ static __init int map_switcher(void)
* easy.
*/
- /* We allocate an array of "struct page"s. map_vm_area() wants the
- * pages in this form, rather than just an array of pointers. */
- switcher_page = kmalloc(sizeof(switcher_page[0])*TOTAL_SWITCHER_PAGES,
- GFP_KERNEL);
- if (!switcher_page) {
+ /* We assume Switcher text fits into a single page. */
+ if (end_switcher_text - start_switcher_text > PAGE_SIZE) {
+ printk(KERN_ERR "lguest: switcher text too large (%zu)\n",
+ end_switcher_text - start_switcher_text);
+ return -EINVAL;
+ }
+
+ /*
+ * We allocate an array of struct page pointers. map_vm_area() wants
+ * this, rather than just an array of pages.
+ */
+ lg_switcher_pages = kmalloc(sizeof(lg_switcher_pages[0])
+ * TOTAL_SWITCHER_PAGES,
+ GFP_KERNEL);
+ if (!lg_switcher_pages) {
err = -ENOMEM;
goto out;
}
- /* Now we actually allocate the pages. The Guest will see these pages,
- * so we make sure they're zeroed. */
+ /*
+ * Now we actually allocate the pages. The Guest will see these pages,
+ * so we make sure they're zeroed.
+ */
for (i = 0; i < TOTAL_SWITCHER_PAGES; i++) {
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- if (!addr) {
+ lg_switcher_pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO);
+ if (!lg_switcher_pages[i]) {
err = -ENOMEM;
goto free_some_pages;
}
- switcher_page[i] = virt_to_page(addr);
}
- /* Now we reserve the "virtual memory area" we want: 0xFFC00000
- * (SWITCHER_ADDR). We might not get it in theory, but in practice
- * it's worked so far. */
+ /*
+ * We place the Switcher underneath the fixmap area, which is the
+ * highest virtual address we can get. This is important, since we
+ * tell the Guest it can't access this memory, so we want its ceiling
+ * as high as possible.
+ */
+ switcher_addr = FIXADDR_START - (TOTAL_SWITCHER_PAGES+1)*PAGE_SIZE;
+
+ /*
+ * Now we reserve the "virtual memory area" we want. We might
+ * not get it in theory, but in practice it's worked so far.
+ * The end address needs +1 because __get_vm_area allocates an
+ * extra guard page, so we need space for that.
+ */
switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
- VM_ALLOC, SWITCHER_ADDR, VMALLOC_END);
+ VM_ALLOC, switcher_addr, switcher_addr
+ + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
if (!switcher_vma) {
err = -ENOMEM;
printk("lguest: could not map switcher pages high\n");
goto free_pages;
}
- /* This code actually sets up the pages we've allocated to appear at
- * SWITCHER_ADDR. map_vm_area() takes the vma we allocated above, the
+ /*
+ * This code actually sets up the pages we've allocated to appear at
+ * switcher_addr. map_vm_area() takes the vma we allocated above, the
* kind of pages we're mapping (kernel pages), and a pointer to our
* array of struct pages. It increments that pointer, but we don't
- * care. */
- pagep = switcher_page;
- err = map_vm_area(switcher_vma, PAGE_KERNEL, &pagep);
+ * care.
+ */
+ pagep = lg_switcher_pages;
+ err = map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, &pagep);
if (err) {
printk("lguest: map_vm_area failed: %i\n", err);
goto free_vma;
}
- /* Now the switcher is mapped at the right address, we can't fail!
- * Copy in the compiled-in Switcher code (from switcher.S). */
- memcpy(switcher_vma->addr, start_switcher_text,
- end_switcher_text - start_switcher_text);
-
- /* Most of the switcher.S doesn't care that it's been moved; on Intel,
- * jumps are relative, and it doesn't access any references to external
- * code or data.
- *
- * The only exception is the interrupt handlers in switcher.S: their
- * addresses are placed in a table (default_idt_entries), so we need to
- * update the table with the new addresses. switcher_offset() is a
- * convenience function which returns the distance between the builtin
- * switcher code and the high-mapped copy we just made. */
- for (i = 0; i < IDT_ENTRIES; i++)
- default_idt_entries[i] += switcher_offset();
-
/*
- * Set up the Switcher's per-cpu areas.
- *
- * Each CPU gets two pages of its own within the high-mapped region
- * (aka. "struct lguest_pages"). Much of this can be initialized now,
- * but some depends on what Guest we are running (which is set up in
- * copy_in_guest_info()).
+ * Now the Switcher is mapped at the right address, we can't fail!
+ * Copy in the compiled-in Switcher code (from x86/switcher_32.S).
*/
- for_each_possible_cpu(i) {
- /* lguest_pages() returns this CPU's two pages. */
- struct lguest_pages *pages = lguest_pages(i);
- /* This is a convenience pointer to make the code fit one
- * statement to a line. */
- struct lguest_ro_state *state = &pages->state;
-
- /* The Global Descriptor Table: the Host has a different one
- * for each CPU. We keep a descriptor for the GDT which says
- * where it is and how big it is (the size is actually the last
- * byte, not the size, hence the "-1"). */
- state->host_gdt_desc.size = GDT_SIZE-1;
- state->host_gdt_desc.address = (long)get_cpu_gdt_table(i);
-
- /* All CPUs on the Host use the same Interrupt Descriptor
- * Table, so we just use store_idt(), which gets this CPU's IDT
- * descriptor. */
- store_idt(&state->host_idt_desc);
-
- /* The descriptors for the Guest's GDT and IDT can be filled
- * out now, too. We copy the GDT & IDT into ->guest_gdt and
- * ->guest_idt before actually running the Guest. */
- state->guest_idt_desc.size = sizeof(state->guest_idt)-1;
- state->guest_idt_desc.address = (long)&state->guest_idt;
- state->guest_gdt_desc.size = sizeof(state->guest_gdt)-1;
- state->guest_gdt_desc.address = (long)&state->guest_gdt;
-
- /* We know where we want the stack to be when the Guest enters
- * the switcher: in pages->regs. The stack grows upwards, so
- * we start it at the end of that structure. */
- state->guest_tss.esp0 = (long)(&pages->regs + 1);
- /* And this is the GDT entry to use for the stack: we keep a
- * couple of special LGUEST entries. */
- state->guest_tss.ss0 = LGUEST_DS;
-
- /* x86 can have a finegrained bitmap which indicates what I/O
- * ports the process can use. We set it to the end of our
- * structure, meaning "none". */
- state->guest_tss.io_bitmap_base = sizeof(state->guest_tss);
-
- /* Some GDT entries are the same across all Guests, so we can
- * set them up now. */
- setup_default_gdt_entries(state);
- /* Most IDT entries are the same for all Guests, too.*/
- setup_default_idt_entries(state, default_idt_entries);
-
- /* The Host needs to be able to use the LGUEST segments on this
- * CPU, too, so put them in the Host GDT. */
- get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
- get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
- }
-
- /* In the Switcher, we want the %cs segment register to use the
- * LGUEST_CS GDT entry: we've put that in the Host and Guest GDTs, so
- * it will be undisturbed when we switch. To change %cs and jump we
- * need this structure to feed to Intel's "lcall" instruction. */
- lguest_entry.offset = (long)switch_to_guest + switcher_offset();
- lguest_entry.segment = LGUEST_CS;
+ memcpy(switcher_vma->addr, start_switcher_text,
+ end_switcher_text - start_switcher_text);
printk(KERN_INFO "lguest: mapped switcher at %p\n",
switcher_vma->addr);
@@ -227,15 +138,14 @@ free_pages:
i = TOTAL_SWITCHER_PAGES;
free_some_pages:
for (--i; i >= 0; i--)
- __free_pages(switcher_page[i], 0);
- kfree(switcher_page);
+ __free_pages(lg_switcher_pages[i], 0);
+ kfree(lg_switcher_pages);
out:
return err;
}
/*:*/
-/* Cleaning up the mapping when the module is unloaded is almost...
- * too easy. */
+/* Cleaning up the mapping when the module is unloaded is almost... too easy. */
static void unmap_switcher(void)
{
unsigned int i;
@@ -244,442 +154,157 @@ static void unmap_switcher(void)
vunmap(switcher_vma->addr);
/* Now we just need to free the pages we copied the switcher into */
for (i = 0; i < TOTAL_SWITCHER_PAGES; i++)
- __free_pages(switcher_page[i], 0);
+ __free_pages(lg_switcher_pages[i], 0);
+ kfree(lg_switcher_pages);
}
-/*H:130 Our Guest is usually so well behaved; it never tries to do things it
- * isn't allowed to. Unfortunately, "struct paravirt_ops" isn't quite
- * complete, because it doesn't contain replacements for the Intel I/O
- * instructions. As a result, the Guest sometimes fumbles across one during
- * the boot process as it probes for various things which are usually attached
- * to a PC.
- *
- * When the Guest uses one of these instructions, we get trap #13 (General
- * Protection Fault) and come here. We see if it's one of those troublesome
- * instructions and skip over it. We return true if we did. */
-static int emulate_insn(struct lguest *lg)
-{
- u8 insn;
- unsigned int insnlen = 0, in = 0, shift = 0;
- /* The eip contains the *virtual* address of the Guest's instruction:
- * guest_pa just subtracts the Guest's page_offset. */
- unsigned long physaddr = guest_pa(lg, lg->regs->eip);
-
- /* The guest_pa() function only works for Guest kernel addresses, but
- * that's all we're trying to do anyway. */
- if (lg->regs->eip < lg->page_offset)
- return 0;
-
- /* Decoding x86 instructions is icky. */
- lgread(lg, &insn, physaddr, 1);
-
- /* 0x66 is an "operand prefix". It means it's using the upper 16 bits
- of the eax register. */
- if (insn == 0x66) {
- shift = 16;
- /* The instruction is 1 byte so far, read the next byte. */
- insnlen = 1;
- lgread(lg, &insn, physaddr + insnlen, 1);
- }
-
- /* We can ignore the lower bit for the moment and decode the 4 opcodes
- * we need to emulate. */
- switch (insn & 0xFE) {
- case 0xE4: /* in <next byte>,%al */
- insnlen += 2;
- in = 1;
- break;
- case 0xEC: /* in (%dx),%al */
- insnlen += 1;
- in = 1;
- break;
- case 0xE6: /* out %al,<next byte> */
- insnlen += 2;
- break;
- case 0xEE: /* out %al,(%dx) */
- insnlen += 1;
- break;
- default:
- /* OK, we don't know what this is, can't emulate. */
- return 0;
- }
-
- /* If it was an "IN" instruction, they expect the result to be read
- * into %eax, so we change %eax. We always return all-ones, which
- * traditionally means "there's nothing there". */
- if (in) {
- /* Lower bit tells is whether it's a 16 or 32 bit access */
- if (insn & 0x1)
- lg->regs->eax = 0xFFFFFFFF;
- else
- lg->regs->eax |= (0xFFFF << shift);
- }
- /* Finally, we've "done" the instruction, so move past it. */
- lg->regs->eip += insnlen;
- /* Success! */
- return 1;
-}
-/*:*/
-
-/*L:305
+/*H:032
* Dealing With Guest Memory.
*
+ * Before we go too much further into the Host, we need to grok the routines
+ * we use to deal with Guest memory.
+ *
* When the Guest gives us (what it thinks is) a physical address, we can use
- * the normal copy_from_user() & copy_to_user() on that address: remember,
- * Guest physical == Launcher virtual.
+ * the normal copy_from_user() & copy_to_user() on the corresponding place in
+ * the memory region allocated by the Launcher.
*
* But we can't trust the Guest: it might be trying to access the Launcher
* code. We have to check that the range is below the pfn_limit the Launcher
* gave us. We have to make sure that addr + len doesn't give us a false
- * positive by overflowing, too. */
-int lguest_address_ok(const struct lguest *lg,
- unsigned long addr, unsigned long len)
+ * positive by overflowing, too.
+ */
+bool lguest_address_ok(const struct lguest *lg,
+ unsigned long addr, unsigned long len)
{
return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr);
}
-/* This is a convenient routine to get a 32-bit value from the Guest (a very
- * common operation). Here we can see how useful the kill_lguest() routine we
- * met in the Launcher can be: we return a random value (0) instead of needing
- * to return an error. */
-u32 lgread_u32(struct lguest *lg, unsigned long addr)
-{
- u32 val = 0;
-
- /* Don't let them access lguest binary. */
- if (!lguest_address_ok(lg, addr, sizeof(val))
- || get_user(val, (u32 __user *)addr) != 0)
- kill_guest(lg, "bad read address %#lx", addr);
- return val;
-}
-
-/* Same thing for writing a value. */
-void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val)
-{
- if (!lguest_address_ok(lg, addr, sizeof(val))
- || put_user(val, (u32 __user *)addr) != 0)
- kill_guest(lg, "bad write address %#lx", addr);
-}
-
-/* This routine is more generic, and copies a range of Guest bytes into a
- * buffer. If the copy_from_user() fails, we fill the buffer with zeroes, so
- * the caller doesn't end up using uninitialized kernel memory. */
-void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
+/*
+ * This routine copies memory from the Guest. Here we can see how useful the
+ * kill_lguest() routine we met in the Launcher can be: we return a random
+ * value (all zeroes) instead of needing to return an error.
+ */
+void __lgread(struct lg_cpu *cpu, void *b, unsigned long addr, unsigned bytes)
{
- if (!lguest_address_ok(lg, addr, bytes)
- || copy_from_user(b, (void __user *)addr, bytes) != 0) {
+ if (!lguest_address_ok(cpu->lg, addr, bytes)
+ || copy_from_user(b, cpu->lg->mem_base + addr, bytes) != 0) {
/* copy_from_user should do this, but as we rely on it... */
memset(b, 0, bytes);
- kill_guest(lg, "bad read address %#lx len %u", addr, bytes);
+ kill_guest(cpu, "bad read address %#lx len %u", addr, bytes);
}
}
-/* Similarly, our generic routine to copy into a range of Guest bytes. */
-void lgwrite(struct lguest *lg, unsigned long addr, const void *b,
- unsigned bytes)
+/* This is the write (copy into Guest) version. */
+void __lgwrite(struct lg_cpu *cpu, unsigned long addr, const void *b,
+ unsigned bytes)
{
- if (!lguest_address_ok(lg, addr, bytes)
- || copy_to_user((void __user *)addr, b, bytes) != 0)
- kill_guest(lg, "bad write address %#lx len %u", addr, bytes);
-}
-/* (end of memory access helper routines) :*/
-
-static void set_ts(void)
-{
- u32 cr0;
-
- cr0 = read_cr0();
- if (!(cr0 & 8))
- write_cr0(cr0|8);
-}
-
-/*S:010
- * We are getting close to the Switcher.
- *
- * Remember that each CPU has two pages which are visible to the Guest when it
- * runs on that CPU. This has to contain the state for that Guest: we copy the
- * state in just before we run the Guest.
- *
- * Each Guest has "changed" flags which indicate what has changed in the Guest
- * since it last ran. We saw this set in interrupts_and_traps.c and
- * segments.c.
- */
-static void copy_in_guest_info(struct lguest *lg, struct lguest_pages *pages)
-{
- /* Copying all this data can be quite expensive. We usually run the
- * same Guest we ran last time (and that Guest hasn't run anywhere else
- * meanwhile). If that's not the case, we pretend everything in the
- * Guest has changed. */
- if (__get_cpu_var(last_guest) != lg || lg->last_pages != pages) {
- __get_cpu_var(last_guest) = lg;
- lg->last_pages = pages;
- lg->changed = CHANGED_ALL;
- }
-
- /* These copies are pretty cheap, so we do them unconditionally: */
- /* Save the current Host top-level page directory. */
- pages->state.host_cr3 = __pa(current->mm->pgd);
- /* Set up the Guest's page tables to see this CPU's pages (and no
- * other CPU's pages). */
- map_switcher_in_guest(lg, pages);
- /* Set up the two "TSS" members which tell the CPU what stack to use
- * for traps which do directly into the Guest (ie. traps at privilege
- * level 1). */
- pages->state.guest_tss.esp1 = lg->esp1;
- pages->state.guest_tss.ss1 = lg->ss1;
-
- /* Copy direct-to-Guest trap entries. */
- if (lg->changed & CHANGED_IDT)
- copy_traps(lg, pages->state.guest_idt, default_idt_entries);
-
- /* Copy all GDT entries which the Guest can change. */
- if (lg->changed & CHANGED_GDT)
- copy_gdt(lg, pages->state.guest_gdt);
- /* If only the TLS entries have changed, copy them. */
- else if (lg->changed & CHANGED_GDT_TLS)
- copy_gdt_tls(lg, pages->state.guest_gdt);
-
- /* Mark the Guest as unchanged for next time. */
- lg->changed = 0;
-}
-
-/* Finally: the code to actually call into the Switcher to run the Guest. */
-static void run_guest_once(struct lguest *lg, struct lguest_pages *pages)
-{
- /* This is a dummy value we need for GCC's sake. */
- unsigned int clobber;
-
- /* Copy the guest-specific information into this CPU's "struct
- * lguest_pages". */
- copy_in_guest_info(lg, pages);
-
- /* Set the trap number to 256 (impossible value). If we fault while
- * switching to the Guest (bad segment registers or bug), this will
- * cause us to abort the Guest. */
- lg->regs->trapnum = 256;
-
- /* Now: we push the "eflags" register on the stack, then do an "lcall".
- * This is how we change from using the kernel code segment to using
- * the dedicated lguest code segment, as well as jumping into the
- * Switcher.
- *
- * The lcall also pushes the old code segment (KERNEL_CS) onto the
- * stack, then the address of this call. This stack layout happens to
- * exactly match the stack of an interrupt... */
- asm volatile("pushf; lcall *lguest_entry"
- /* This is how we tell GCC that %eax ("a") and %ebx ("b")
- * are changed by this routine. The "=" means output. */
- : "=a"(clobber), "=b"(clobber)
- /* %eax contains the pages pointer. ("0" refers to the
- * 0-th argument above, ie "a"). %ebx contains the
- * physical address of the Guest's top-level page
- * directory. */
- : "0"(pages), "1"(__pa(lg->pgdirs[lg->pgdidx].pgdir))
- /* We tell gcc that all these registers could change,
- * which means we don't have to save and restore them in
- * the Switcher. */
- : "memory", "%edx", "%ecx", "%edi", "%esi");
+ if (!lguest_address_ok(cpu->lg, addr, bytes)
+ || copy_to_user(cpu->lg->mem_base + addr, b, bytes) != 0)
+ kill_guest(cpu, "bad write address %#lx len %u", addr, bytes);
}
/*:*/
-/*H:030 Let's jump straight to the the main loop which runs the Guest.
+/*H:030
+ * Let's jump straight to the the main loop which runs the Guest.
* Remember, this is called by the Launcher reading /dev/lguest, and we keep
- * going around and around until something interesting happens. */
-int run_guest(struct lguest *lg, unsigned long __user *user)
+ * going around and around until something interesting happens.
+ */
+int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
{
/* We stop running once the Guest is dead. */
- while (!lg->dead) {
- /* We need to initialize this, otherwise gcc complains. It's
- * not (yet) clever enough to see that it's initialized when we
- * need it. */
- unsigned int cr2 = 0; /* Damn gcc */
-
- /* First we run any hypercalls the Guest wants done: either in
- * the hypercall ring in "struct lguest_data", or directly by
- * using int 31 (LGUEST_TRAP_ENTRY). */
- do_hypercalls(lg);
- /* It's possible the Guest did a SEND_DMA hypercall to the
- * Launcher, in which case we return from the read() now. */
- if (lg->dma_is_pending) {
- if (put_user(lg->pending_dma, user) ||
- put_user(lg->pending_key, user+1))
- return -EFAULT;
- return sizeof(unsigned long)*2;
+ while (!cpu->lg->dead) {
+ unsigned int irq;
+ bool more;
+
+ /* First we run any hypercalls the Guest wants done. */
+ if (cpu->hcall)
+ do_hypercalls(cpu);
+
+ /*
+ * It's possible the Guest did a NOTIFY hypercall to the
+ * Launcher.
+ */
+ if (cpu->pending_notify) {
+ /*
+ * Does it just needs to write to a registered
+ * eventfd (ie. the appropriate virtqueue thread)?
+ */
+ if (!send_notify_to_eventfd(cpu)) {
+ /* OK, we tell the main Launcher. */
+ if (put_user(cpu->pending_notify, user))
+ return -EFAULT;
+ return sizeof(cpu->pending_notify);
+ }
}
+ /*
+ * All long-lived kernel loops need to check with this horrible
+ * thing called the freezer. If the Host is trying to suspend,
+ * it stops us.
+ */
+ try_to_freeze();
+
/* Check for signals */
if (signal_pending(current))
return -ERESTARTSYS;
- /* If Waker set break_out, return to Launcher. */
- if (lg->break_out)
- return -EAGAIN;
-
- /* Check if there are any interrupts which can be delivered
- * now: if so, this sets up the hander to be executed when we
- * next run the Guest. */
- maybe_do_interrupt(lg);
-
- /* All long-lived kernel loops need to check with this horrible
- * thing called the freezer. If the Host is trying to suspend,
- * it stops us. */
- try_to_freeze();
-
- /* Just make absolutely sure the Guest is still alive. One of
- * those hypercalls could have been fatal, for example. */
- if (lg->dead)
+ /*
+ * Check if there are any interrupts which can be delivered now:
+ * if so, this sets up the hander to be executed when we next
+ * run the Guest.
+ */
+ irq = interrupt_pending(cpu, &more);
+ if (irq < LGUEST_IRQS)
+ try_deliver_interrupt(cpu, irq, more);
+
+ /*
+ * Just make absolutely sure the Guest is still alive. One of
+ * those hypercalls could have been fatal, for example.
+ */
+ if (cpu->lg->dead)
break;
- /* If the Guest asked to be stopped, we sleep. The Guest's
- * clock timer or LHCALL_BREAK from the Waker will wake us. */
- if (lg->halted) {
+ /*
+ * If the Guest asked to be stopped, we sleep. The Guest's
+ * clock timer will wake us.
+ */
+ if (cpu->halted) {
set_current_state(TASK_INTERRUPTIBLE);
- schedule();
+ /*
+ * Just before we sleep, make sure no interrupt snuck in
+ * which we should be doing.
+ */
+ if (interrupt_pending(cpu, &more) < LGUEST_IRQS)
+ set_current_state(TASK_RUNNING);
+ else
+ schedule();
continue;
}
- /* OK, now we're ready to jump into the Guest. First we put up
- * the "Do Not Disturb" sign: */
+ /*
+ * OK, now we're ready to jump into the Guest. First we put up
+ * the "Do Not Disturb" sign:
+ */
local_irq_disable();
- /* Remember the awfully-named TS bit? If the Guest has asked
- * to set it we set it now, so we can trap and pass that trap
- * to the Guest if it uses the FPU. */
- if (lg->ts)
- set_ts();
-
- /* SYSENTER is an optimized way of doing system calls. We
- * can't allow it because it always jumps to privilege level 0.
- * A normal Guest won't try it because we don't advertise it in
- * CPUID, but a malicious Guest (or malicious Guest userspace
- * program) could, so we tell the CPU to disable it before
- * running the Guest. */
- if (boot_cpu_has(X86_FEATURE_SEP))
- wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
-
- /* Now we actually run the Guest. It will pop back out when
- * something interesting happens, and we can examine its
- * registers to see what it was doing. */
- run_guest_once(lg, lguest_pages(raw_smp_processor_id()));
-
- /* The "regs" pointer contains two extra entries which are not
- * really registers: a trap number which says what interrupt or
- * trap made the switcher code come back, and an error code
- * which some traps set. */
-
- /* If the Guest page faulted, then the cr2 register will tell
- * us the bad virtual address. We have to grab this now,
- * because once we re-enable interrupts an interrupt could
- * fault and thus overwrite cr2, or we could even move off to a
- * different CPU. */
- if (lg->regs->trapnum == 14)
- cr2 = read_cr2();
- /* Similarly, if we took a trap because the Guest used the FPU,
- * we have to restore the FPU it expects to see. */
- else if (lg->regs->trapnum == 7)
- math_state_restore();
-
- /* Restore SYSENTER if it's supposed to be on. */
- if (boot_cpu_has(X86_FEATURE_SEP))
- wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
+ /* Actually run the Guest until something happens. */
+ lguest_arch_run_guest(cpu);
/* Now we're ready to be interrupted or moved to other CPUs */
local_irq_enable();
- /* OK, so what happened? */
- switch (lg->regs->trapnum) {
- case 13: /* We've intercepted a GPF. */
- /* Check if this was one of those annoying IN or OUT
- * instructions which we need to emulate. If so, we
- * just go back into the Guest after we've done it. */
- if (lg->regs->errcode == 0) {
- if (emulate_insn(lg))
- continue;
- }
- break;
- case 14: /* We've intercepted a page fault. */
- /* The Guest accessed a virtual address that wasn't
- * mapped. This happens a lot: we don't actually set
- * up most of the page tables for the Guest at all when
- * we start: as it runs it asks for more and more, and
- * we set them up as required. In this case, we don't
- * even tell the Guest that the fault happened.
- *
- * The errcode tells whether this was a read or a
- * write, and whether kernel or userspace code. */
- if (demand_page(lg, cr2, lg->regs->errcode))
- continue;
-
- /* OK, it's really not there (or not OK): the Guest
- * needs to know. We write out the cr2 value so it
- * knows where the fault occurred.
- *
- * Note that if the Guest were really messed up, this
- * could happen before it's done the INITIALIZE
- * hypercall, so lg->lguest_data will be NULL, so
- * &lg->lguest_data->cr2 will be address 8. Writing
- * into that address won't hurt the Host at all,
- * though. */
- if (put_user(cr2, &lg->lguest_data->cr2))
- kill_guest(lg, "Writing cr2");
- break;
- case 7: /* We've intercepted a Device Not Available fault. */
- /* If the Guest doesn't want to know, we already
- * restored the Floating Point Unit, so we just
- * continue without telling it. */
- if (!lg->ts)
- continue;
- break;
- case 32 ... 255:
- /* These values mean a real interrupt occurred, in
- * which case the Host handler has already been run.
- * We just do a friendly check if another process
- * should now be run, then fall through to loop
- * around: */
- cond_resched();
- case LGUEST_TRAP_ENTRY: /* Handled at top of loop */
- continue;
- }
+ /* Now we deal with whatever happened to the Guest. */
+ lguest_arch_handle_trap(cpu);
+ }
- /* If we get here, it's a trap the Guest wants to know
- * about. */
- if (deliver_trap(lg, lg->regs->trapnum))
- continue;
+ /* Special case: Guest is 'dead' but wants a reboot. */
+ if (cpu->lg->dead == ERR_PTR(-ERESTART))
+ return -ERESTART;
- /* If the Guest doesn't have a handler (either it hasn't
- * registered any yet, or it's one of the faults we don't let
- * it handle), it dies with a cryptic error message. */
- kill_guest(lg, "unhandled trap %li at %#lx (%#lx)",
- lg->regs->trapnum, lg->regs->eip,
- lg->regs->trapnum == 14 ? cr2 : lg->regs->errcode);
- }
/* The Guest is dead => "No such file or directory" */
return -ENOENT;
}
-/* Now we can look at each of the routines this calls, in increasing order of
- * complexity: do_hypercalls(), emulate_insn(), maybe_do_interrupt(),
- * deliver_trap() and demand_page(). After all those, we'll be ready to
- * examine the Switcher, and our philosophical understanding of the Host/Guest
- * duality will be complete. :*/
-
-int find_free_guest(void)
-{
- unsigned int i;
- for (i = 0; i < MAX_LGUEST_GUESTS; i++)
- if (!lguests[i].tsk)
- return i;
- return -1;
-}
-
-static void adjust_pge(void *on)
-{
- if (on)
- write_cr4(read_cr4() | X86_CR4_PGE);
- else
- write_cr4(read_cr4() & ~X86_CR4_PGE);
-}
-
/*H:000
* Welcome to the Host!
*
@@ -693,83 +318,55 @@ static int __init init(void)
int err;
/* Lguest can't run under Xen, VMI or itself. It does Tricky Stuff. */
- if (paravirt_enabled()) {
- printk("lguest is afraid of %s\n", paravirt_ops.name);
+ if (get_kernel_rpl() != 0) {
+ printk("lguest is afraid of being a guest\n");
return -EPERM;
}
/* First we put the Switcher up in very high virtual memory. */
err = map_switcher();
if (err)
- return err;
-
- /* Now we set up the pagetable implementation for the Guests. */
- err = init_pagetables(switcher_page, SHARED_SWITCHER_PAGES);
- if (err) {
- unmap_switcher();
- return err;
- }
+ goto out;
- /* The I/O subsystem needs some things initialized. */
- lguest_io_init();
+ /* We might need to reserve an interrupt vector. */
+ err = init_interrupts();
+ if (err)
+ goto unmap;
/* /dev/lguest needs to be registered. */
err = lguest_device_init();
- if (err) {
- free_pagetables();
- unmap_switcher();
- return err;
- }
+ if (err)
+ goto free_interrupts;
- /* Finally, we need to turn off "Page Global Enable". PGE is an
- * optimization where page table entries are specially marked to show
- * they never change. The Host kernel marks all the kernel pages this
- * way because it's always present, even when userspace is running.
- *
- * Lguest breaks this: unbeknownst to the rest of the Host kernel, we
- * switch to the Guest kernel. If you don't disable this on all CPUs,
- * you'll get really weird bugs that you'll chase for two days.
- *
- * I used to turn PGE off every time we switched to the Guest and back
- * on when we return, but that slowed the Switcher down noticibly. */
-
- /* We don't need the complexity of CPUs coming and going while we're
- * doing this. */
- lock_cpu_hotplug();
- if (cpu_has_pge) { /* We have a broader idea of "global". */
- /* Remember that this was originally set (for cleanup). */
- cpu_had_pge = 1;
- /* adjust_pge is a helper function which sets or unsets the PGE
- * bit on its CPU, depending on the argument (0 == unset). */
- on_each_cpu(adjust_pge, (void *)0, 0, 1);
- /* Turn off the feature in the global feature set. */
- clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
- }
- unlock_cpu_hotplug();
+ /* Finally we do some architecture-specific setup. */
+ lguest_arch_host_init();
/* All good! */
return 0;
+
+free_interrupts:
+ free_interrupts();
+unmap:
+ unmap_switcher();
+out:
+ return err;
}
/* Cleaning up is just the same code, backwards. With a little French. */
static void __exit fini(void)
{
lguest_device_remove();
- free_pagetables();
+ free_interrupts();
unmap_switcher();
- /* If we had PGE before we started, turn it back on now. */
- lock_cpu_hotplug();
- if (cpu_had_pge) {
- set_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
- /* adjust_pge's argument "1" means set PGE. */
- on_each_cpu(adjust_pge, (void *)1, 0, 1);
- }
- unlock_cpu_hotplug();
+ lguest_arch_host_fini();
}
+/*:*/
-/* The Host side of lguest can be a module. This is a nice way for people to
- * play with it. */
+/*
+ * The Host side of lguest can be a module. This is a nice way for people to
+ * play with it.
+ */
module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
index db6caace3b9..83511eb0923 100644
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -1,8 +1,10 @@
-/*P:500 Just as userspace programs request kernel operations through a system
+/*P:500
+ * Just as userspace programs request kernel operations through a system
* call, the Guest requests Host operations through a "hypercall". You might
* notice this nomenclature doesn't really follow any logic, but the name has
* been around for long enough that we're stuck with it. As you'd expect, this
- * code is basically a one big switch statement. :*/
+ * code is basically a one big switch statement.
+:*/
/* Copyright (C) 2006 Rusty Russell IBM Corporation
@@ -23,235 +25,231 @@
#include <linux/uaccess.h>
#include <linux/syscalls.h>
#include <linux/mm.h>
+#include <linux/ktime.h>
#include <asm/page.h>
#include <asm/pgtable.h>
-#include <irq_vectors.h>
#include "lg.h"
-/*H:120 This is the core hypercall routine: where the Guest gets what it
- * wants. Or gets killed. Or, in the case of LHCALL_CRASH, both.
- *
- * Remember from the Guest: %eax == which call to make, and the arguments are
- * packed into %edx, %ebx and %ecx if needed. */
-static void do_hcall(struct lguest *lg, struct lguest_regs *regs)
+/*H:120
+ * This is the core hypercall routine: where the Guest gets what it wants.
+ * Or gets killed. Or, in the case of LHCALL_SHUTDOWN, both.
+ */
+static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
{
- switch (regs->eax) {
+ switch (args->arg0) {
case LHCALL_FLUSH_ASYNC:
- /* This call does nothing, except by breaking out of the Guest
- * it makes us process all the asynchronous hypercalls. */
+ /*
+ * This call does nothing, except by breaking out of the Guest
+ * it makes us process all the asynchronous hypercalls.
+ */
+ break;
+ case LHCALL_SEND_INTERRUPTS:
+ /*
+ * This call does nothing too, but by breaking out of the Guest
+ * it makes us process any pending interrupts.
+ */
break;
case LHCALL_LGUEST_INIT:
- /* You can't get here unless you're already initialized. Don't
- * do that. */
- kill_guest(lg, "already have lguest_data");
+ /*
+ * You can't get here unless you're already initialized. Don't
+ * do that.
+ */
+ kill_guest(cpu, "already have lguest_data");
break;
- case LHCALL_CRASH: {
- /* Crash is such a trivial hypercall that we do it in four
- * lines right here. */
+ case LHCALL_SHUTDOWN: {
char msg[128];
- /* If the lgread fails, it will call kill_guest() itself; the
- * kill_guest() with the message will be ignored. */
- lgread(lg, msg, regs->edx, sizeof(msg));
+ /*
+ * Shutdown is such a trivial hypercall that we do it in five
+ * lines right here.
+ *
+ * If the lgread fails, it will call kill_guest() itself; the
+ * kill_guest() with the message will be ignored.
+ */
+ __lgread(cpu, msg, args->arg1, sizeof(msg));
msg[sizeof(msg)-1] = '\0';
- kill_guest(lg, "CRASH: %s", msg);
+ kill_guest(cpu, "CRASH: %s", msg);
+ if (args->arg2 == LGUEST_SHUTDOWN_RESTART)
+ cpu->lg->dead = ERR_PTR(-ERESTART);
break;
}
case LHCALL_FLUSH_TLB:
- /* FLUSH_TLB comes in two flavors, depending on the
- * argument: */
- if (regs->edx)
- guest_pagetable_clear_all(lg);
+ /* FLUSH_TLB comes in two flavors, depending on the argument: */
+ if (args->arg1)
+ guest_pagetable_clear_all(cpu);
else
- guest_pagetable_flush_user(lg);
- break;
- case LHCALL_BIND_DMA:
- /* BIND_DMA really wants four arguments, but it's the only call
- * which does. So the Guest packs the number of buffers and
- * the interrupt number into the final argument, and we decode
- * it here. This can legitimately fail, since we currently
- * place a limit on the number of DMA pools a Guest can have.
- * So we return true or false from this call. */
- regs->eax = bind_dma(lg, regs->edx, regs->ebx,
- regs->ecx >> 8, regs->ecx & 0xFF);
+ guest_pagetable_flush_user(cpu);
break;
- /* All these calls simply pass the arguments through to the right
- * routines. */
- case LHCALL_SEND_DMA:
- send_dma(lg, regs->edx, regs->ebx);
- break;
- case LHCALL_LOAD_GDT:
- load_guest_gdt(lg, regs->edx, regs->ebx);
- break;
- case LHCALL_LOAD_IDT_ENTRY:
- load_guest_idt_entry(lg, regs->edx, regs->ebx, regs->ecx);
- break;
+ /*
+ * All these calls simply pass the arguments through to the right
+ * routines.
+ */
case LHCALL_NEW_PGTABLE:
- guest_new_pagetable(lg, regs->edx);
+ guest_new_pagetable(cpu, args->arg1);
break;
case LHCALL_SET_STACK:
- guest_set_stack(lg, regs->edx, regs->ebx, regs->ecx);
+ guest_set_stack(cpu, args->arg1, args->arg2, args->arg3);
break;
case LHCALL_SET_PTE:
- guest_set_pte(lg, regs->edx, regs->ebx, mkgpte(regs->ecx));
+#ifdef CONFIG_X86_PAE
+ guest_set_pte(cpu, args->arg1, args->arg2,
+ __pte(args->arg3 | (u64)args->arg4 << 32));
+#else
+ guest_set_pte(cpu, args->arg1, args->arg2, __pte(args->arg3));
+#endif
break;
- case LHCALL_SET_PMD:
- guest_set_pmd(lg, regs->edx, regs->ebx);
+ case LHCALL_SET_PGD:
+ guest_set_pgd(cpu->lg, args->arg1, args->arg2);
break;
- case LHCALL_LOAD_TLS:
- guest_load_tls(lg, regs->edx);
+#ifdef CONFIG_X86_PAE
+ case LHCALL_SET_PMD:
+ guest_set_pmd(cpu->lg, args->arg1, args->arg2);
break;
+#endif
case LHCALL_SET_CLOCKEVENT:
- guest_set_clockevent(lg, regs->edx);
+ guest_set_clockevent(cpu, args->arg1);
break;
-
case LHCALL_TS:
/* This sets the TS flag, as we saw used in run_guest(). */
- lg->ts = regs->edx;
+ cpu->ts = args->arg1;
break;
case LHCALL_HALT:
/* Similarly, this sets the halted flag for run_guest(). */
- lg->halted = 1;
+ cpu->halted = 1;
+ break;
+ case LHCALL_NOTIFY:
+ cpu->pending_notify = args->arg1;
break;
default:
- kill_guest(lg, "Bad hypercall %li\n", regs->eax);
+ /* It should be an architecture-specific hypercall. */
+ if (lguest_arch_do_hcall(cpu, args))
+ kill_guest(cpu, "Bad hypercall %li\n", args->arg0);
}
}
-/* Asynchronous hypercalls are easy: we just look in the array in the Guest's
- * "struct lguest_data" and see if there are any new ones marked "ready".
+/*H:124
+ * Asynchronous hypercalls are easy: we just look in the array in the
+ * Guest's "struct lguest_data" to see if any new ones are marked "ready".
*
* We are careful to do these in order: obviously we respect the order the
* Guest put them in the ring, but we also promise the Guest that they will
* happen before any normal hypercall (which is why we check this before
- * checking for a normal hcall). */
-static void do_async_hcalls(struct lguest *lg)
+ * checking for a normal hcall).
+ */
+static void do_async_hcalls(struct lg_cpu *cpu)
{
unsigned int i;
u8 st[LHCALL_RING_SIZE];
/* For simplicity, we copy the entire call status array in at once. */
- if (copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st)))
+ if (copy_from_user(&st, &cpu->lg->lguest_data->hcall_status, sizeof(st)))
return;
-
/* We process "struct lguest_data"s hcalls[] ring once. */
for (i = 0; i < ARRAY_SIZE(st); i++) {
- struct lguest_regs regs;
- /* We remember where we were up to from last time. This makes
+ struct hcall_args args;
+ /*
+ * We remember where we were up to from last time. This makes
* sure that the hypercalls are done in the order the Guest
- * places them in the ring. */
- unsigned int n = lg->next_hcall;
+ * places them in the ring.
+ */
+ unsigned int n = cpu->next_hcall;
/* 0xFF means there's no call here (yet). */
if (st[n] == 0xFF)
break;
- /* OK, we have hypercall. Increment the "next_hcall" cursor,
- * and wrap back to 0 if we reach the end. */
- if (++lg->next_hcall == LHCALL_RING_SIZE)
- lg->next_hcall = 0;
+ /*
+ * OK, we have hypercall. Increment the "next_hcall" cursor,
+ * and wrap back to 0 if we reach the end.
+ */
+ if (++cpu->next_hcall == LHCALL_RING_SIZE)
+ cpu->next_hcall = 0;
- /* We copy the hypercall arguments into a fake register
- * structure. This makes life simple for do_hcall(). */
- if (get_user(regs.eax, &lg->lguest_data->hcalls[n].eax)
- || get_user(regs.edx, &lg->lguest_data->hcalls[n].edx)
- || get_user(regs.ecx, &lg->lguest_data->hcalls[n].ecx)
- || get_user(regs.ebx, &lg->lguest_data->hcalls[n].ebx)) {
- kill_guest(lg, "Fetching async hypercalls");
+ /*
+ * Copy the hypercall arguments into a local copy of the
+ * hcall_args struct.
+ */
+ if (copy_from_user(&args, &cpu->lg->lguest_data->hcalls[n],
+ sizeof(struct hcall_args))) {
+ kill_guest(cpu, "Fetching async hypercalls");
break;
}
/* Do the hypercall, same as a normal one. */
- do_hcall(lg, &regs);
+ do_hcall(cpu, &args);
/* Mark the hypercall done. */
- if (put_user(0xFF, &lg->lguest_data->hcall_status[n])) {
- kill_guest(lg, "Writing result for async hypercall");
+ if (put_user(0xFF, &cpu->lg->lguest_data->hcall_status[n])) {
+ kill_guest(cpu, "Writing result for async hypercall");
break;
}
- /* Stop doing hypercalls if we've just done a DMA to the
- * Launcher: it needs to service this first. */
- if (lg->dma_is_pending)
+ /*
+ * Stop doing hypercalls if they want to notify the Launcher:
+ * it needs to service this first.
+ */
+ if (cpu->pending_notify)
break;
}
}
-/* Last of all, we look at what happens first of all. The very first time the
- * Guest makes a hypercall, we end up here to set things up: */
-static void initialize(struct lguest *lg)
+/*
+ * Last of all, we look at what happens first of all. The very first time the
+ * Guest makes a hypercall, we end up here to set things up:
+ */
+static void initialize(struct lg_cpu *cpu)
{
- u32 tsc_speed;
-
- /* You can't do anything until you're initialized. The Guest knows the
- * rules, so we're unforgiving here. */
- if (lg->regs->eax != LHCALL_LGUEST_INIT) {
- kill_guest(lg, "hypercall %li before LGUEST_INIT",
- lg->regs->eax);
+ /*
+ * You can't do anything until you're initialized. The Guest knows the
+ * rules, so we're unforgiving here.
+ */
+ if (cpu->hcall->arg0 != LHCALL_LGUEST_INIT) {
+ kill_guest(cpu, "hypercall %li before INIT", cpu->hcall->arg0);
return;
}
- /* We insist that the Time Stamp Counter exist and doesn't change with
- * cpu frequency. Some devious chip manufacturers decided that TSC
- * changes could be handled in software. I decided that time going
- * backwards might be good for benchmarks, but it's bad for users.
- *
- * We also insist that the TSC be stable: the kernel detects unreliable
- * TSCs for its own purposes, and we use that here. */
- if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable())
- tsc_speed = tsc_khz;
- else
- tsc_speed = 0;
+ if (lguest_arch_init_hypercalls(cpu))
+ kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
- /* The pointer to the Guest's "struct lguest_data" is the only
- * argument. */
- lg->lguest_data = (struct lguest_data __user *)lg->regs->edx;
- /* If we check the address they gave is OK now, we can simply
- * copy_to_user/from_user from now on rather than using lgread/lgwrite.
- * I put this in to show that I'm not immune to writing stupid
- * optimizations. */
- if (!lguest_address_ok(lg, lg->regs->edx, sizeof(*lg->lguest_data))) {
- kill_guest(lg, "bad guest page %p", lg->lguest_data);
- return;
- }
- /* The Guest tells us where we're not to deliver interrupts by putting
- * the range of addresses into "struct lguest_data". */
- if (get_user(lg->noirq_start, &lg->lguest_data->noirq_start)
- || get_user(lg->noirq_end, &lg->lguest_data->noirq_end)
- /* We tell the Guest that it can't use the top 4MB of virtual
- * addresses used by the Switcher. */
- || put_user(4U*1024*1024, &lg->lguest_data->reserve_mem)
- || put_user(tsc_speed, &lg->lguest_data->tsc_khz)
- /* We also give the Guest a unique id, as used in lguest_net.c. */
- || put_user(lg->guestid, &lg->lguest_data->guestid))
- kill_guest(lg, "bad guest page %p", lg->lguest_data);
+ /*
+ * The Guest tells us where we're not to deliver interrupts by putting
+ * the range of addresses into "struct lguest_data".
+ */
+ if (get_user(cpu->lg->noirq_start, &cpu->lg->lguest_data->noirq_start)
+ || get_user(cpu->lg->noirq_end, &cpu->lg->lguest_data->noirq_end))
+ kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
- /* We write the current time into the Guest's data page once now. */
- write_timestamp(lg);
+ /*
+ * We write the current time into the Guest's data page once so it can
+ * set its clock.
+ */
+ write_timestamp(cpu);
- /* This is the one case where the above accesses might have been the
+ /* page_tables.c will also do some setup. */
+ page_table_guest_data_init(cpu);
+
+ /*
+ * This is the one case where the above accesses might have been the
* first write to a Guest page. This may have caused a copy-on-write
- * fault, but the Guest might be referring to the old (read-only)
- * page. */
- guest_pagetable_clear_all(lg);
+ * fault, but the old page might be (read-only) in the Guest
+ * pagetable.
+ */
+ guest_pagetable_clear_all(cpu);
}
-/* Now we've examined the hypercall code; our Guest can make requests. There
- * is one other way we can do things for the Guest, as we see in
- * emulate_insn(). */
+/*:*/
-/*H:110 Tricky point: we mark the hypercall as "done" once we've done it.
- * Normally we don't need to do this: the Guest will run again and update the
- * trap number before we come back around the run_guest() loop to
- * do_hypercalls().
+/*M:013
+ * If a Guest reads from a page (so creates a mapping) that it has never
+ * written to, and then the Launcher writes to it (ie. the output of a virtual
+ * device), the Guest will still see the old page. In practice, this never
+ * happens: why would the Guest read a page which it has never written to? But
+ * a similar scenario might one day bite us, so it's worth mentioning.
*
- * However, if we are signalled or the Guest sends DMA to the Launcher, that
- * loop will exit without running the Guest. When it comes back it would try
- * to re-run the hypercall. */
-static void clear_hcall(struct lguest *lg)
-{
- lg->regs->trapnum = 255;
-}
+ * Note that if we used a shared anonymous mapping in the Launcher instead of
+ * mapping /dev/zero private, we wouldn't worry about cop-on-write. And we
+ * need that to switch the Launcher to processes (away from threads) anyway.
+:*/
/*H:100
* Hypercalls
@@ -259,42 +257,56 @@ static void clear_hcall(struct lguest *lg)
* Remember from the Guest, hypercalls come in two flavors: normal and
* asynchronous. This file handles both of types.
*/
-void do_hypercalls(struct lguest *lg)
+void do_hypercalls(struct lg_cpu *cpu)
{
- /* Not initialized yet? */
- if (unlikely(!lg->lguest_data)) {
- /* Did the Guest make a hypercall? We might have come back for
- * some other reason (an interrupt, a different trap). */
- if (lg->regs->trapnum == LGUEST_TRAP_ENTRY) {
- /* Set up the "struct lguest_data" */
- initialize(lg);
- /* The hypercall is done. */
- clear_hcall(lg);
- }
+ /* Not initialized yet? This hypercall must do it. */
+ if (unlikely(!cpu->lg->lguest_data)) {
+ /* Set up the "struct lguest_data" */
+ initialize(cpu);
+ /* Hcall is done. */
+ cpu->hcall = NULL;
return;
}
- /* The Guest has initialized.
+ /*
+ * The Guest has initialized.
*
- * Look in the hypercall ring for the async hypercalls: */
- do_async_hcalls(lg);
+ * Look in the hypercall ring for the async hypercalls:
+ */
+ do_async_hcalls(cpu);
- /* If we stopped reading the hypercall ring because the Guest did a
- * SEND_DMA to the Launcher, we want to return now. Otherwise if the
- * Guest asked us to do a hypercall, we do it. */
- if (!lg->dma_is_pending && lg->regs->trapnum == LGUEST_TRAP_ENTRY) {
- do_hcall(lg, lg->regs);
- /* The hypercall is done. */
- clear_hcall(lg);
+ /*
+ * If we stopped reading the hypercall ring because the Guest did a
+ * NOTIFY to the Launcher, we want to return now. Otherwise we do
+ * the hypercall.
+ */
+ if (!cpu->pending_notify) {
+ do_hcall(cpu, cpu->hcall);
+ /*
+ * Tricky point: we reset the hcall pointer to mark the
+ * hypercall as "done". We use the hcall pointer rather than
+ * the trap number to indicate a hypercall is pending.
+ * Normally it doesn't matter: the Guest will run again and
+ * update the trap number before we come back here.
+ *
+ * However, if we are signalled or the Guest sends I/O to the
+ * Launcher, the run_guest() loop will exit without running the
+ * Guest. When it comes back it would try to re-run the
+ * hypercall. Finding that bug sucked.
+ */
+ cpu->hcall = NULL;
}
}
-/* This routine supplies the Guest with time: it's used for wallclock time at
- * initial boot and as a rough time source if the TSC isn't available. */
-void write_timestamp(struct lguest *lg)
+/*
+ * This routine supplies the Guest with time: it's used for wallclock time at
+ * initial boot and as a rough time source if the TSC isn't available.
+ */
+void write_timestamp(struct lg_cpu *cpu)
{
struct timespec now;
ktime_get_real_ts(&now);
- if (put_user(now, &lg->lguest_data->time))
- kill_guest(lg, "Writing timestamp");
+ if (copy_to_user(&cpu->lg->lguest_data->time,
+ &now, sizeof(struct timespec)))
+ kill_guest(cpu, "Writing timestamp");
}
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index 39731232d82..70dfcdc29f1 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -1,4 +1,5 @@
-/*P:800 Interrupts (traps) are complicated enough to earn their own file.
+/*P:800
+ * Interrupts (traps) are complicated enough to earn their own file.
* There are three classes of interrupts:
*
* 1) Real hardware interrupts which occur while we're running the Guest,
@@ -10,39 +11,52 @@
* just like real hardware would deliver them. Traps from the Guest can be set
* up to go directly back into the Guest, but sometimes the Host wants to see
* them first, so we also have a way of "reflecting" them into the Guest as if
- * they had been delivered to it directly. :*/
+ * they had been delivered to it directly.
+:*/
#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/sched.h>
#include "lg.h"
+/* Allow Guests to use a non-128 (ie. non-Linux) syscall trap. */
+static unsigned int syscall_vector = SYSCALL_VECTOR;
+module_param(syscall_vector, uint, 0444);
+
/* The address of the interrupt handler is split into two bits: */
static unsigned long idt_address(u32 lo, u32 hi)
{
return (lo & 0x0000FFFF) | (hi & 0xFFFF0000);
}
-/* The "type" of the interrupt handler is a 4 bit field: we only support a
- * couple of types. */
+/*
+ * The "type" of the interrupt handler is a 4 bit field: we only support a
+ * couple of types.
+ */
static int idt_type(u32 lo, u32 hi)
{
return (hi >> 8) & 0xF;
}
/* An IDT entry can't be used unless the "present" bit is set. */
-static int idt_present(u32 lo, u32 hi)
+static bool idt_present(u32 lo, u32 hi)
{
return (hi & 0x8000);
}
-/* We need a helper to "push" a value onto the Guest's stack, since that's a
- * big part of what delivering an interrupt does. */
-static void push_guest_stack(struct lguest *lg, unsigned long *gstack, u32 val)
+/*
+ * We need a helper to "push" a value onto the Guest's stack, since that's a
+ * big part of what delivering an interrupt does.
+ */
+static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 val)
{
/* Stack grows upwards: move stack then write value. */
*gstack -= 4;
- lgwrite_u32(lg, *gstack, val);
+ lgwrite(cpu, *gstack, u32, val);
}
-/*H:210 The set_guest_interrupt() routine actually delivers the interrupt or
+/*H:210
+ * The set_guest_interrupt() routine actually delivers the interrupt or
* trap. The mechanics of delivering traps and interrupts to the Guest are the
* same, except some traps have an "error code" which gets pushed onto the
* stack as well: the caller tells us if this is one.
@@ -53,261 +67,412 @@ static void push_guest_stack(struct lguest *lg, unsigned long *gstack, u32 val)
*
* We set up the stack just like the CPU does for a real interrupt, so it's
* identical for the Guest (and the standard "iret" instruction will undo
- * it). */
-static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
+ * it).
+ */
+static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
+ bool has_err)
{
- unsigned long gstack;
+ unsigned long gstack, origstack;
u32 eflags, ss, irq_enable;
+ unsigned long virtstack;
- /* There are two cases for interrupts: one where the Guest is already
+ /*
+ * There are two cases for interrupts: one where the Guest is already
* in the kernel, and a more complex one where the Guest is in
- * userspace. We check the privilege level to find out. */
- if ((lg->regs->ss&0x3) != GUEST_PL) {
- /* The Guest told us their kernel stack with the SET_STACK
- * hypercall: both the virtual address and the segment */
- gstack = guest_pa(lg, lg->esp1);
- ss = lg->ss1;
- /* We push the old stack segment and pointer onto the new
+ * userspace. We check the privilege level to find out.
+ */
+ if ((cpu->regs->ss&0x3) != GUEST_PL) {
+ /*
+ * The Guest told us their kernel stack with the SET_STACK
+ * hypercall: both the virtual address and the segment.
+ */
+ virtstack = cpu->esp1;
+ ss = cpu->ss1;
+
+ origstack = gstack = guest_pa(cpu, virtstack);
+ /*
+ * We push the old stack segment and pointer onto the new
* stack: when the Guest does an "iret" back from the interrupt
* handler the CPU will notice they're dropping privilege
- * levels and expect these here. */
- push_guest_stack(lg, &gstack, lg->regs->ss);
- push_guest_stack(lg, &gstack, lg->regs->esp);
+ * levels and expect these here.
+ */
+ push_guest_stack(cpu, &gstack, cpu->regs->ss);
+ push_guest_stack(cpu, &gstack, cpu->regs->esp);
} else {
/* We're staying on the same Guest (kernel) stack. */
- gstack = guest_pa(lg, lg->regs->esp);
- ss = lg->regs->ss;
+ virtstack = cpu->regs->esp;
+ ss = cpu->regs->ss;
+
+ origstack = gstack = guest_pa(cpu, virtstack);
}
- /* Remember that we never let the Guest actually disable interrupts, so
+ /*
+ * Remember that we never let the Guest actually disable interrupts, so
* the "Interrupt Flag" bit is always set. We copy that bit from the
- * Guest's "irq_enabled" field into the eflags word: the Guest copies
- * it back in "lguest_iret". */
- eflags = lg->regs->eflags;
- if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0
+ * Guest's "irq_enabled" field into the eflags word: we saw the Guest
+ * copy it back in "lguest_iret".
+ */
+ eflags = cpu->regs->eflags;
+ if (get_user(irq_enable, &cpu->lg->lguest_data->irq_enabled) == 0
&& !(irq_enable & X86_EFLAGS_IF))
eflags &= ~X86_EFLAGS_IF;
- /* An interrupt is expected to push three things on the stack: the old
+ /*
+ * An interrupt is expected to push three things on the stack: the old
* "eflags" word, the old code segment, and the old instruction
- * pointer. */
- push_guest_stack(lg, &gstack, eflags);
- push_guest_stack(lg, &gstack, lg->regs->cs);
- push_guest_stack(lg, &gstack, lg->regs->eip);
+ * pointer.
+ */
+ push_guest_stack(cpu, &gstack, eflags);
+ push_guest_stack(cpu, &gstack, cpu->regs->cs);
+ push_guest_stack(cpu, &gstack, cpu->regs->eip);
/* For the six traps which supply an error code, we push that, too. */
if (has_err)
- push_guest_stack(lg, &gstack, lg->regs->errcode);
-
- /* Now we've pushed all the old state, we change the stack, the code
- * segment and the address to execute. */
- lg->regs->ss = ss;
- lg->regs->esp = gstack + lg->page_offset;
- lg->regs->cs = (__KERNEL_CS|GUEST_PL);
- lg->regs->eip = idt_address(lo, hi);
-
- /* There are two kinds of interrupt handlers: 0xE is an "interrupt
- * gate" which expects interrupts to be disabled on entry. */
+ push_guest_stack(cpu, &gstack, cpu->regs->errcode);
+
+ /*
+ * Now we've pushed all the old state, we change the stack, the code
+ * segment and the address to execute.
+ */
+ cpu->regs->ss = ss;
+ cpu->regs->esp = virtstack + (gstack - origstack);
+ cpu->regs->cs = (__KERNEL_CS|GUEST_PL);
+ cpu->regs->eip = idt_address(lo, hi);
+
+ /*
+ * Trapping always clears these flags:
+ * TF: Trap flag
+ * VM: Virtual 8086 mode
+ * RF: Resume
+ * NT: Nested task.
+ */
+ cpu->regs->eflags &=
+ ~(X86_EFLAGS_TF|X86_EFLAGS_VM|X86_EFLAGS_RF|X86_EFLAGS_NT);
+
+ /*
+ * There are two kinds of interrupt handlers: 0xE is an "interrupt
+ * gate" which expects interrupts to be disabled on entry.
+ */
if (idt_type(lo, hi) == 0xE)
- if (put_user(0, &lg->lguest_data->irq_enabled))
- kill_guest(lg, "Disabling interrupts");
+ if (put_user(0, &cpu->lg->lguest_data->irq_enabled))
+ kill_guest(cpu, "Disabling interrupts");
}
-/*H:200
+/*H:205
* Virtual Interrupts.
*
- * maybe_do_interrupt() gets called before every entry to the Guest, to see if
- * we should divert the Guest to running an interrupt handler. */
-void maybe_do_interrupt(struct lguest *lg)
+ * interrupt_pending() returns the first pending interrupt which isn't blocked
+ * by the Guest. It is called before every entry to the Guest, and just before
+ * we go to sleep when the Guest has halted itself.
+ */
+unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more)
{
unsigned int irq;
DECLARE_BITMAP(blk, LGUEST_IRQS);
- struct desc_struct *idt;
/* If the Guest hasn't even initialized yet, we can do nothing. */
- if (!lg->lguest_data)
- return;
-
- /* Take our "irqs_pending" array and remove any interrupts the Guest
- * wants blocked: the result ends up in "blk". */
- if (copy_from_user(&blk, lg->lguest_data->blocked_interrupts,
+ if (!cpu->lg->lguest_data)
+ return LGUEST_IRQS;
+
+ /*
+ * Take our "irqs_pending" array and remove any interrupts the Guest
+ * wants blocked: the result ends up in "blk".
+ */
+ if (copy_from_user(&blk, cpu->lg->lguest_data->blocked_interrupts,
sizeof(blk)))
- return;
-
- bitmap_andnot(blk, lg->irqs_pending, blk, LGUEST_IRQS);
+ return LGUEST_IRQS;
+ bitmap_andnot(blk, cpu->irqs_pending, blk, LGUEST_IRQS);
/* Find the first interrupt. */
irq = find_first_bit(blk, LGUEST_IRQS);
- /* None? Nothing to do */
- if (irq >= LGUEST_IRQS)
- return;
+ *more = find_next_bit(blk, LGUEST_IRQS, irq+1);
+
+ return irq;
+}
+
+/*
+ * This actually diverts the Guest to running an interrupt handler, once an
+ * interrupt has been identified by interrupt_pending().
+ */
+void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
+{
+ struct desc_struct *idt;
+
+ BUG_ON(irq >= LGUEST_IRQS);
- /* They may be in the middle of an iret, where they asked us never to
- * deliver interrupts. */
- if (lg->regs->eip >= lg->noirq_start && lg->regs->eip < lg->noirq_end)
+ /*
+ * They may be in the middle of an iret, where they asked us never to
+ * deliver interrupts.
+ */
+ if (cpu->regs->eip >= cpu->lg->noirq_start &&
+ (cpu->regs->eip < cpu->lg->noirq_end))
return;
/* If they're halted, interrupts restart them. */
- if (lg->halted) {
+ if (cpu->halted) {
/* Re-enable interrupts. */
- if (put_user(X86_EFLAGS_IF, &lg->lguest_data->irq_enabled))
- kill_guest(lg, "Re-enabling interrupts");
- lg->halted = 0;
+ if (put_user(X86_EFLAGS_IF, &cpu->lg->lguest_data->irq_enabled))
+ kill_guest(cpu, "Re-enabling interrupts");
+ cpu->halted = 0;
} else {
/* Otherwise we check if they have interrupts disabled. */
u32 irq_enabled;
- if (get_user(irq_enabled, &lg->lguest_data->irq_enabled))
+ if (get_user(irq_enabled, &cpu->lg->lguest_data->irq_enabled))
irq_enabled = 0;
- if (!irq_enabled)
+ if (!irq_enabled) {
+ /* Make sure they know an IRQ is pending. */
+ put_user(X86_EFLAGS_IF,
+ &cpu->lg->lguest_data->irq_pending);
return;
+ }
}
- /* Look at the IDT entry the Guest gave us for this interrupt. The
+ /*
+ * Look at the IDT entry the Guest gave us for this interrupt. The
* first 32 (FIRST_EXTERNAL_VECTOR) entries are for traps, so we skip
- * over them. */
- idt = &lg->idt[FIRST_EXTERNAL_VECTOR+irq];
+ * over them.
+ */
+ idt = &cpu->arch.idt[FIRST_EXTERNAL_VECTOR+irq];
/* If they don't have a handler (yet?), we just ignore it */
if (idt_present(idt->a, idt->b)) {
/* OK, mark it no longer pending and deliver it. */
- clear_bit(irq, lg->irqs_pending);
- /* set_guest_interrupt() takes the interrupt descriptor and a
+ clear_bit(irq, cpu->irqs_pending);
+ /*
+ * set_guest_interrupt() takes the interrupt descriptor and a
* flag to say whether this interrupt pushes an error code onto
- * the stack as well: virtual interrupts never do. */
- set_guest_interrupt(lg, idt->a, idt->b, 0);
+ * the stack as well: virtual interrupts never do.
+ */
+ set_guest_interrupt(cpu, idt->a, idt->b, false);
}
- /* Every time we deliver an interrupt, we update the timestamp in the
+ /*
+ * Every time we deliver an interrupt, we update the timestamp in the
* Guest's lguest_data struct. It would be better for the Guest if we
* did this more often, but it can actually be quite slow: doing it
* here is a compromise which means at least it gets updated every
- * timer interrupt. */
- write_timestamp(lg);
+ * timer interrupt.
+ */
+ write_timestamp(cpu);
+
+ /*
+ * If there are no other interrupts we want to deliver, clear
+ * the pending flag.
+ */
+ if (!more)
+ put_user(0, &cpu->lg->lguest_data->irq_pending);
+}
+
+/* And this is the routine when we want to set an interrupt for the Guest. */
+void set_interrupt(struct lg_cpu *cpu, unsigned int irq)
+{
+ /*
+ * Next time the Guest runs, the core code will see if it can deliver
+ * this interrupt.
+ */
+ set_bit(irq, cpu->irqs_pending);
+
+ /*
+ * Make sure it sees it; it might be asleep (eg. halted), or running
+ * the Guest right now, in which case kick_process() will knock it out.
+ */
+ if (!wake_up_process(cpu->tsk))
+ kick_process(cpu->tsk);
}
+/*:*/
-/*H:220 Now we've got the routines to deliver interrupts, delivering traps
- * like page fault is easy. The only trick is that Intel decided that some
- * traps should have error codes: */
-static int has_err(unsigned int trap)
+/*
+ * Linux uses trap 128 for system calls. Plan9 uses 64, and Ron Minnich sent
+ * me a patch, so we support that too. It'd be a big step for lguest if half
+ * the Plan 9 user base were to start using it.
+ *
+ * Actually now I think of it, it's possible that Ron *is* half the Plan 9
+ * userbase. Oh well.
+ */
+static bool could_be_syscall(unsigned int num)
+{
+ /* Normal Linux SYSCALL_VECTOR or reserved vector? */
+ return num == SYSCALL_VECTOR || num == syscall_vector;
+}
+
+/* The syscall vector it wants must be unused by Host. */
+bool check_syscall_vector(struct lguest *lg)
+{
+ u32 vector;
+
+ if (get_user(vector, &lg->lguest_data->syscall_vec))
+ return false;
+
+ return could_be_syscall(vector);
+}
+
+int init_interrupts(void)
+{
+ /* If they want some strange system call vector, reserve it now */
+ if (syscall_vector != SYSCALL_VECTOR) {
+ if (test_bit(syscall_vector, used_vectors) ||
+ vector_used_by_percpu_irq(syscall_vector)) {
+ printk(KERN_ERR "lg: couldn't reserve syscall %u\n",
+ syscall_vector);
+ return -EBUSY;
+ }
+ set_bit(syscall_vector, used_vectors);
+ }
+
+ return 0;
+}
+
+void free_interrupts(void)
+{
+ if (syscall_vector != SYSCALL_VECTOR)
+ clear_bit(syscall_vector, used_vectors);
+}
+
+/*H:220
+ * Now we've got the routines to deliver interrupts, delivering traps like
+ * page fault is easy. The only trick is that Intel decided that some traps
+ * should have error codes:
+ */
+static bool has_err(unsigned int trap)
{
return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17);
}
/* deliver_trap() returns true if it could deliver the trap. */
-int deliver_trap(struct lguest *lg, unsigned int num)
+bool deliver_trap(struct lg_cpu *cpu, unsigned int num)
{
- /* Trap numbers are always 8 bit, but we set an impossible trap number
- * for traps inside the Switcher, so check that here. */
- if (num >= ARRAY_SIZE(lg->idt))
- return 0;
-
- /* Early on the Guest hasn't set the IDT entries (or maybe it put a
- * bogus one in): if we fail here, the Guest will be killed. */
- if (!idt_present(lg->idt[num].a, lg->idt[num].b))
- return 0;
- set_guest_interrupt(lg, lg->idt[num].a, lg->idt[num].b, has_err(num));
- return 1;
+ /*
+ * Trap numbers are always 8 bit, but we set an impossible trap number
+ * for traps inside the Switcher, so check that here.
+ */
+ if (num >= ARRAY_SIZE(cpu->arch.idt))
+ return false;
+
+ /*
+ * Early on the Guest hasn't set the IDT entries (or maybe it put a
+ * bogus one in): if we fail here, the Guest will be killed.
+ */
+ if (!idt_present(cpu->arch.idt[num].a, cpu->arch.idt[num].b))
+ return false;
+ set_guest_interrupt(cpu, cpu->arch.idt[num].a,
+ cpu->arch.idt[num].b, has_err(num));
+ return true;
}
-/*H:250 Here's the hard part: returning to the Host every time a trap happens
+/*H:250
+ * Here's the hard part: returning to the Host every time a trap happens
* and then calling deliver_trap() and re-entering the Guest is slow.
- * Particularly because Guest userspace system calls are traps (trap 128).
+ * Particularly because Guest userspace system calls are traps (usually trap
+ * 128).
*
* So we'd like to set up the IDT to tell the CPU to deliver traps directly
* into the Guest. This is possible, but the complexities cause the size of
* this file to double! However, 150 lines of code is worth writing for taking
* system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all
- * the other hypervisors would tease it.
+ * the other hypervisors would beat it up at lunchtime.
*
- * This routine determines if a trap can be delivered directly. */
-static int direct_trap(const struct lguest *lg,
- const struct desc_struct *trap,
- unsigned int num)
+ * This routine indicates if a particular trap number could be delivered
+ * directly.
+ */
+static bool direct_trap(unsigned int num)
{
- /* Hardware interrupts don't go to the Guest at all (except system
- * call). */
- if (num >= FIRST_EXTERNAL_VECTOR && num != SYSCALL_VECTOR)
- return 0;
-
- /* The Host needs to see page faults (for shadow paging and to save the
+ /*
+ * Hardware interrupts don't go to the Guest at all (except system
+ * call).
+ */
+ if (num >= FIRST_EXTERNAL_VECTOR && !could_be_syscall(num))
+ return false;
+
+ /*
+ * The Host needs to see page faults (for shadow paging and to save the
* fault address), general protection faults (in/out emulation) and
- * device not available (TS handling), and of course, the hypercall
- * trap. */
- if (num == 14 || num == 13 || num == 7 || num == LGUEST_TRAP_ENTRY)
- return 0;
-
- /* Only trap gates (type 15) can go direct to the Guest. Interrupt
- * gates (type 14) disable interrupts as they are entered, which we
- * never let the Guest do. Not present entries (type 0x0) also can't
- * go direct, of course 8) */
- return idt_type(trap->a, trap->b) == 0xF;
+ * device not available (TS handling) and of course, the hypercall trap.
+ */
+ return num != 14 && num != 13 && num != 7 && num != LGUEST_TRAP_ENTRY;
}
/*:*/
-/*M:005 The Guest has the ability to turn its interrupt gates into trap gates,
+/*M:005
+ * The Guest has the ability to turn its interrupt gates into trap gates,
* if it is careful. The Host will let trap gates can go directly to the
* Guest, but the Guest needs the interrupts atomically disabled for an
* interrupt gate. It can do this by pointing the trap gate at instructions
- * within noirq_start and noirq_end, where it can safely disable interrupts. */
+ * within noirq_start and noirq_end, where it can safely disable interrupts.
+ */
-/*M:006 The Guests do not use the sysenter (fast system call) instruction,
+/*M:006
+ * The Guests do not use the sysenter (fast system call) instruction,
* because it's hardcoded to enter privilege level 0 and so can't go direct.
* It's about twice as fast as the older "int 0x80" system call, so it might
* still be worthwhile to handle it in the Switcher and lcall down to the
* Guest. The sysenter semantics are hairy tho: search for that keyword in
- * entry.S :*/
+ * entry.S
+:*/
-/*H:260 When we make traps go directly into the Guest, we need to make sure
+/*H:260
+ * When we make traps go directly into the Guest, we need to make sure
* the kernel stack is valid (ie. mapped in the page tables). Otherwise, the
* CPU trying to deliver the trap will fault while trying to push the interrupt
* words on the stack: this is called a double fault, and it forces us to kill
* the Guest.
*
- * Which is deeply unfair, because (literally!) it wasn't the Guests' fault. */
-void pin_stack_pages(struct lguest *lg)
+ * Which is deeply unfair, because (literally!) it wasn't the Guests' fault.
+ */
+void pin_stack_pages(struct lg_cpu *cpu)
{
unsigned int i;
- /* Depending on the CONFIG_4KSTACKS option, the Guest can have one or
- * two pages of stack space. */
- for (i = 0; i < lg->stack_pages; i++)
- /* The stack grows *upwards*, so the address we're given is the
+ /*
+ * Depending on the CONFIG_4KSTACKS option, the Guest can have one or
+ * two pages of stack space.
+ */
+ for (i = 0; i < cpu->lg->stack_pages; i++)
+ /*
+ * The stack grows *upwards*, so the address we're given is the
* start of the page after the kernel stack. Subtract one to
* get back onto the first stack page, and keep subtracting to
- * get to the rest of the stack pages. */
- pin_page(lg, lg->esp1 - 1 - i * PAGE_SIZE);
+ * get to the rest of the stack pages.
+ */
+ pin_page(cpu, cpu->esp1 - 1 - i * PAGE_SIZE);
}
-/* Direct traps also mean that we need to know whenever the Guest wants to use
- * a different kernel stack, so we can change the IDT entries to use that
- * stack. The IDT entries expect a virtual address, so unlike most addresses
+/*
+ * Direct traps also mean that we need to know whenever the Guest wants to use
+ * a different kernel stack, so we can change the guest TSS to use that
+ * stack. The TSS entries expect a virtual address, so unlike most addresses
* the Guest gives us, the "esp" (stack pointer) value here is virtual, not
* physical.
*
* In Linux each process has its own kernel stack, so this happens a lot: we
- * change stacks on each context switch. */
-void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages)
+ * change stacks on each context switch.
+ */
+void guest_set_stack(struct lg_cpu *cpu, u32 seg, u32 esp, unsigned int pages)
{
- /* You are not allowd have a stack segment with privilege level 0: bad
- * Guest! */
+ /*
+ * You're not allowed a stack segment with privilege level 0: bad Guest!
+ */
if ((seg & 0x3) != GUEST_PL)
- kill_guest(lg, "bad stack segment %i", seg);
+ kill_guest(cpu, "bad stack segment %i", seg);
/* We only expect one or two stack pages. */
if (pages > 2)
- kill_guest(lg, "bad stack pages %u", pages);
+ kill_guest(cpu, "bad stack pages %u", pages);
/* Save where the stack is, and how many pages */
- lg->ss1 = seg;
- lg->esp1 = esp;
- lg->stack_pages = pages;
+ cpu->ss1 = seg;
+ cpu->esp1 = esp;
+ cpu->lg->stack_pages = pages;
/* Make sure the new stack pages are mapped */
- pin_stack_pages(lg);
+ pin_stack_pages(cpu);
}
-/* All this reference to mapping stacks leads us neatly into the other complex
- * part of the Host: page table handling. */
+/*
+ * All this reference to mapping stacks leads us neatly into the other complex
+ * part of the Host: page table handling.
+ */
-/*H:235 This is the routine which actually checks the Guest's IDT entry and
- * transfers it into our entry in "struct lguest": */
-static void set_trap(struct lguest *lg, struct desc_struct *trap,
+/*H:235
+ * This is the routine which actually checks the Guest's IDT entry and
+ * transfers it into the entry in "struct lguest":
+ */
+static void set_trap(struct lg_cpu *cpu, struct desc_struct *trap,
unsigned int num, u32 lo, u32 hi)
{
u8 type = idt_type(lo, hi);
@@ -320,59 +485,74 @@ static void set_trap(struct lguest *lg, struct desc_struct *trap,
/* We only support interrupt and trap gates. */
if (type != 0xE && type != 0xF)
- kill_guest(lg, "bad IDT type %i", type);
+ kill_guest(cpu, "bad IDT type %i", type);
- /* We only copy the handler address, present bit, privilege level and
+ /*
+ * We only copy the handler address, present bit, privilege level and
* type. The privilege level controls where the trap can be triggered
* manually with an "int" instruction. This is usually GUEST_PL,
- * except for system calls which userspace can use. */
+ * except for system calls which userspace can use.
+ */
trap->a = ((__KERNEL_CS|GUEST_PL)<<16) | (lo&0x0000FFFF);
trap->b = (hi&0xFFFFEF00);
}
-/*H:230 While we're here, dealing with delivering traps and interrupts to the
+/*H:230
+ * While we're here, dealing with delivering traps and interrupts to the
* Guest, we might as well complete the picture: how the Guest tells us where
* it wants them to go. This would be simple, except making traps fast
* requires some tricks.
*
* We saw the Guest setting Interrupt Descriptor Table (IDT) entries with the
- * LHCALL_LOAD_IDT_ENTRY hypercall before: that comes here. */
-void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi)
+ * LHCALL_LOAD_IDT_ENTRY hypercall before: that comes here.
+ */
+void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int num, u32 lo, u32 hi)
{
- /* Guest never handles: NMI, doublefault, spurious interrupt or
- * hypercall. We ignore when it tries to set them. */
+ /*
+ * Guest never handles: NMI, doublefault, spurious interrupt or
+ * hypercall. We ignore when it tries to set them.
+ */
if (num == 2 || num == 8 || num == 15 || num == LGUEST_TRAP_ENTRY)
return;
- /* Mark the IDT as changed: next time the Guest runs we'll know we have
- * to copy this again. */
- lg->changed |= CHANGED_IDT;
-
- /* The IDT which we keep in "struct lguest" only contains 32 entries
- * for the traps and LGUEST_IRQS (32) entries for interrupts. We
- * ignore attempts to set handlers for higher interrupt numbers, except
- * for the system call "interrupt" at 128: we have a special IDT entry
- * for that. */
- if (num < ARRAY_SIZE(lg->idt))
- set_trap(lg, &lg->idt[num], num, lo, hi);
- else if (num == SYSCALL_VECTOR)
- set_trap(lg, &lg->syscall_idt, num, lo, hi);
+ /*
+ * Mark the IDT as changed: next time the Guest runs we'll know we have
+ * to copy this again.
+ */
+ cpu->changed |= CHANGED_IDT;
+
+ /* Check that the Guest doesn't try to step outside the bounds. */
+ if (num >= ARRAY_SIZE(cpu->arch.idt))
+ kill_guest(cpu, "Setting idt entry %u", num);
+ else
+ set_trap(cpu, &cpu->arch.idt[num], num, lo, hi);
}
-/* The default entry for each interrupt points into the Switcher routines which
+/*
+ * The default entry for each interrupt points into the Switcher routines which
* simply return to the Host. The run_guest() loop will then call
- * deliver_trap() to bounce it back into the Guest. */
+ * deliver_trap() to bounce it back into the Guest.
+ */
static void default_idt_entry(struct desc_struct *idt,
int trap,
- const unsigned long handler)
+ const unsigned long handler,
+ const struct desc_struct *base)
{
/* A present interrupt gate. */
u32 flags = 0x8e00;
- /* Set the privilege level on the entry for the hypercall: this allows
- * the Guest to use the "int" instruction to trigger it. */
+ /*
+ * Set the privilege level on the entry for the hypercall: this allows
+ * the Guest to use the "int" instruction to trigger it.
+ */
if (trap == LGUEST_TRAP_ENTRY)
flags |= (GUEST_PL << 13);
+ else if (base)
+ /*
+ * Copy privilege level from what Guest asked for. This allows
+ * debug (int 3) traps from Guest userspace, for example.
+ */
+ flags |= (base->b & 0x6000);
/* Now pack it into the IDT entry in its weird format. */
idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF);
@@ -386,61 +566,92 @@ void setup_default_idt_entries(struct lguest_ro_state *state,
unsigned int i;
for (i = 0; i < ARRAY_SIZE(state->guest_idt); i++)
- default_idt_entry(&state->guest_idt[i], i, def[i]);
+ default_idt_entry(&state->guest_idt[i], i, def[i], NULL);
}
-/*H:240 We don't use the IDT entries in the "struct lguest" directly, instead
+/*H:240
+ * We don't use the IDT entries in the "struct lguest" directly, instead
* we copy them into the IDT which we've set up for Guests on this CPU, just
- * before we run the Guest. This routine does that copy. */
-void copy_traps(const struct lguest *lg, struct desc_struct *idt,
+ * before we run the Guest. This routine does that copy.
+ */
+void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
const unsigned long *def)
{
unsigned int i;
- /* We can simply copy the direct traps, otherwise we use the default
- * ones in the Switcher: they will return to the Host. */
- for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) {
- if (direct_trap(lg, &lg->idt[i], i))
- idt[i] = lg->idt[i];
+ /*
+ * We can simply copy the direct traps, otherwise we use the default
+ * ones in the Switcher: they will return to the Host.
+ */
+ for (i = 0; i < ARRAY_SIZE(cpu->arch.idt); i++) {
+ const struct desc_struct *gidt = &cpu->arch.idt[i];
+
+ /* If no Guest can ever override this trap, leave it alone. */
+ if (!direct_trap(i))
+ continue;
+
+ /*
+ * Only trap gates (type 15) can go direct to the Guest.
+ * Interrupt gates (type 14) disable interrupts as they are
+ * entered, which we never let the Guest do. Not present
+ * entries (type 0x0) also can't go direct, of course.
+ *
+ * If it can't go direct, we still need to copy the priv. level:
+ * they might want to give userspace access to a software
+ * interrupt.
+ */
+ if (idt_type(gidt->a, gidt->b) == 0xF)
+ idt[i] = *gidt;
else
- default_idt_entry(&idt[i], i, def[i]);
+ default_idt_entry(&idt[i], i, def[i], gidt);
}
-
- /* Don't forget the system call trap! The IDT entries for other
- * interupts never change, so no need to copy them. */
- i = SYSCALL_VECTOR;
- if (direct_trap(lg, &lg->syscall_idt, i))
- idt[i] = lg->syscall_idt;
- else
- default_idt_entry(&idt[i], i, def[i]);
}
-void guest_set_clockevent(struct lguest *lg, unsigned long delta)
+/*H:200
+ * The Guest Clock.
+ *
+ * There are two sources of virtual interrupts. We saw one in lguest_user.c:
+ * the Launcher sending interrupts for virtual devices. The other is the Guest
+ * timer interrupt.
+ *
+ * The Guest uses the LHCALL_SET_CLOCKEVENT hypercall to tell us how long to
+ * the next timer interrupt (in nanoseconds). We use the high-resolution timer
+ * infrastructure to set a callback at that time.
+ *
+ * 0 means "turn off the clock".
+ */
+void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta)
{
ktime_t expires;
if (unlikely(delta == 0)) {
/* Clock event device is shutting down. */
- hrtimer_cancel(&lg->hrt);
+ hrtimer_cancel(&cpu->hrt);
return;
}
+ /*
+ * We use wallclock time here, so the Guest might not be running for
+ * all the time between now and the timer interrupt it asked for. This
+ * is almost always the right thing to do.
+ */
expires = ktime_add_ns(ktime_get_real(), delta);
- hrtimer_start(&lg->hrt, expires, HRTIMER_MODE_ABS);
+ hrtimer_start(&cpu->hrt, expires, HRTIMER_MODE_ABS);
}
+/* This is the function called when the Guest's timer expires. */
static enum hrtimer_restart clockdev_fn(struct hrtimer *timer)
{
- struct lguest *lg = container_of(timer, struct lguest, hrt);
+ struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt);
- set_bit(0, lg->irqs_pending);
- if (lg->halted)
- wake_up_process(lg->tsk);
+ /* Remember the first interrupt is the timer interrupt. */
+ set_interrupt(cpu, 0);
return HRTIMER_NORESTART;
}
-void init_clockdev(struct lguest *lg)
+/* This sets up the timer for this Guest. */
+void init_clockdev(struct lg_cpu *cpu)
{
- hrtimer_init(&lg->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS);
- lg->hrt.function = clockdev_fn;
+ hrtimer_init(&cpu->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS);
+ cpu->hrt.function = clockdev_fn;
}
diff --git a/drivers/lguest/io.c b/drivers/lguest/io.c
deleted file mode 100644
index ea68613b43f..00000000000
--- a/drivers/lguest/io.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*P:300 The I/O mechanism in lguest is simple yet flexible, allowing the Guest
- * to talk to the Launcher or directly to another Guest. It uses familiar
- * concepts of DMA and interrupts, plus some neat code stolen from
- * futexes... :*/
-
-/* Copyright (C) 2006 Rusty Russell IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#include <linux/types.h>
-#include <linux/futex.h>
-#include <linux/jhash.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/uaccess.h>
-#include "lg.h"
-
-/*L:300
- * I/O
- *
- * Getting data in and out of the Guest is quite an art. There are numerous
- * ways to do it, and they all suck differently. We try to keep things fairly
- * close to "real" hardware so our Guest's drivers don't look like an alien
- * visitation in the middle of the Linux code, and yet make sure that Guests
- * can talk directly to other Guests, not just the Launcher.
- *
- * To do this, the Guest gives us a key when it binds or sends DMA buffers.
- * The key corresponds to a "physical" address inside the Guest (ie. a virtual
- * address inside the Launcher process). We don't, however, use this key
- * directly.
- *
- * We want Guests which share memory to be able to DMA to each other: two
- * Launchers can mmap memory the same file, then the Guests can communicate.
- * Fortunately, the futex code provides us with a way to get a "union
- * futex_key" corresponding to the memory lying at a virtual address: if the
- * two processes share memory, the "union futex_key" for that memory will match
- * even if the memory is mapped at different addresses in each. So we always
- * convert the keys to "union futex_key"s to compare them.
- *
- * Before we dive into this though, we need to look at another set of helper
- * routines used throughout the Host kernel code to access Guest memory.
- :*/
-static struct list_head dma_hash[61];
-
-/* An unfortunate side effect of the Linux double-linked list implementation is
- * that there's no good way to statically initialize an array of linked
- * lists. */
-void lguest_io_init(void)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(dma_hash); i++)
- INIT_LIST_HEAD(&dma_hash[i]);
-}
-
-/* FIXME: allow multi-page lengths. */
-static int check_dma_list(struct lguest *lg, const struct lguest_dma *dma)
-{
- unsigned int i;
-
- for (i = 0; i < LGUEST_MAX_DMA_SECTIONS; i++) {
- if (!dma->len[i])
- return 1;
- if (!lguest_address_ok(lg, dma->addr[i], dma->len[i]))
- goto kill;
- if (dma->len[i] > PAGE_SIZE)
- goto kill;
- /* We could do over a page, but is it worth it? */
- if ((dma->addr[i] % PAGE_SIZE) + dma->len[i] > PAGE_SIZE)
- goto kill;
- }
- return 1;
-
-kill:
- kill_guest(lg, "bad DMA entry: %u@%#lx", dma->len[i], dma->addr[i]);
- return 0;
-}
-
-/*L:330 This is our hash function, using the wonderful Jenkins hash.
- *
- * The futex key is a union with three parts: an unsigned long word, a pointer,
- * and an int "offset". We could use jhash_2words() which takes three u32s.
- * (Ok, the hash functions are great: the naming sucks though).
- *
- * It's nice to be portable to 64-bit platforms, so we use the more generic
- * jhash2(), which takes an array of u32, the number of u32s, and an initial
- * u32 to roll in. This is uglier, but breaks down to almost the same code on
- * 32-bit platforms like this one.
- *
- * We want a position in the array, so we modulo ARRAY_SIZE(dma_hash) (ie. 61).
- */
-static unsigned int hash(const union futex_key *key)
-{
- return jhash2((u32*)&key->both.word,
- (sizeof(key->both.word)+sizeof(key->both.ptr))/4,
- key->both.offset)
- % ARRAY_SIZE(dma_hash);
-}
-
-/* This is a convenience routine to compare two keys. It's a much bemoaned C
- * weakness that it doesn't allow '==' on structures or unions, so we have to
- * open-code it like this. */
-static inline int key_eq(const union futex_key *a, const union futex_key *b)
-{
- return (a->both.word == b->both.word
- && a->both.ptr == b->both.ptr
- && a->both.offset == b->both.offset);
-}
-
-/*L:360 OK, when we need to actually free up a Guest's DMA array we do several
- * things, so we have a convenient function to do it.
- *
- * The caller must hold a read lock on dmainfo owner's current->mm->mmap_sem
- * for the drop_futex_key_refs(). */
-static void unlink_dma(struct lguest_dma_info *dmainfo)
-{
- /* You locked this too, right? */
- BUG_ON(!mutex_is_locked(&lguest_lock));
- /* This is how we know that the entry is free. */
- dmainfo->interrupt = 0;
- /* Remove it from the hash table. */
- list_del(&dmainfo->list);
- /* Drop the references we were holding (to the inode or mm). */
- drop_futex_key_refs(&dmainfo->key);
-}
-
-/*L:350 This is the routine which we call when the Guest asks to unregister a
- * DMA array attached to a given key. Returns true if the array was found. */
-static int unbind_dma(struct lguest *lg,
- const union futex_key *key,
- unsigned long dmas)
-{
- int i, ret = 0;
-
- /* We don't bother with the hash table, just look through all this
- * Guest's DMA arrays. */
- for (i = 0; i < LGUEST_MAX_DMA; i++) {
- /* In theory it could have more than one array on the same key,
- * or one array on multiple keys, so we check both */
- if (key_eq(key, &lg->dma[i].key) && dmas == lg->dma[i].dmas) {
- unlink_dma(&lg->dma[i]);
- ret = 1;
- break;
- }
- }
- return ret;
-}
-
-/*L:340 BIND_DMA: this is the hypercall which sets up an array of "struct
- * lguest_dma" for receiving I/O.
- *
- * The Guest wants to bind an array of "struct lguest_dma"s to a particular key
- * to receive input. This only happens when the Guest is setting up a new
- * device, so it doesn't have to be very fast.
- *
- * It returns 1 on a successful registration (it can fail if we hit the limit
- * of registrations for this Guest).
- */
-int bind_dma(struct lguest *lg,
- unsigned long ukey, unsigned long dmas, u16 numdmas, u8 interrupt)
-{
- unsigned int i;
- int ret = 0;
- union futex_key key;
- /* Futex code needs the mmap_sem. */
- struct rw_semaphore *fshared = &current->mm->mmap_sem;
-
- /* Invalid interrupt? (We could kill the guest here). */
- if (interrupt >= LGUEST_IRQS)
- return 0;
-
- /* We need to grab the Big Lguest Lock, because other Guests may be
- * trying to look through this Guest's DMAs to send something while
- * we're doing this. */
- mutex_lock(&lguest_lock);
- down_read(fshared);
- if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) {
- kill_guest(lg, "bad dma key %#lx", ukey);
- goto unlock;
- }
-
- /* We want to keep this key valid once we drop mmap_sem, so we have to
- * hold a reference. */
- get_futex_key_refs(&key);
-
- /* If the Guest specified an interrupt of 0, that means they want to
- * unregister this array of "struct lguest_dma"s. */
- if (interrupt == 0)
- ret = unbind_dma(lg, &key, dmas);
- else {
- /* Look through this Guest's dma array for an unused entry. */
- for (i = 0; i < LGUEST_MAX_DMA; i++) {
- /* If the interrupt is non-zero, the entry is already
- * used. */
- if (lg->dma[i].interrupt)
- continue;
-
- /* OK, a free one! Fill on our details. */
- lg->dma[i].dmas = dmas;
- lg->dma[i].num_dmas = numdmas;
- lg->dma[i].next_dma = 0;
- lg->dma[i].key = key;
- lg->dma[i].guestid = lg->guestid;
- lg->dma[i].interrupt = interrupt;
-
- /* Now we add it to the hash table: the position
- * depends on the futex key that we got. */
- list_add(&lg->dma[i].list, &dma_hash[hash(&key)]);
- /* Success! */
- ret = 1;
- goto unlock;
- }
- }
- /* If we didn't find a slot to put the key in, drop the reference
- * again. */
- drop_futex_key_refs(&key);
-unlock:
- /* Unlock and out. */
- up_read(fshared);
- mutex_unlock(&lguest_lock);
- return ret;
-}
-
-/*L:385 Note that our routines to access a different Guest's memory are called
- * lgread_other() and lgwrite_other(): these names emphasize that they are only
- * used when the Guest is *not* the current Guest.
- *
- * The interface for copying from another process's memory is called
- * access_process_vm(), with a final argument of 0 for a read, and 1 for a
- * write.
- *
- * We need lgread_other() to read the destination Guest's "struct lguest_dma"
- * array. */
-static int lgread_other(struct lguest *lg,
- void *buf, u32 addr, unsigned bytes)
-{
- if (!lguest_address_ok(lg, addr, bytes)
- || access_process_vm(lg->tsk, addr, buf, bytes, 0) != bytes) {
- memset(buf, 0, bytes);
- kill_guest(lg, "bad address in registered DMA struct");
- return 0;
- }
- return 1;
-}
-
-/* "lgwrite()" to another Guest: used to update the destination "used_len" once
- * we've transferred data into the buffer. */
-static int lgwrite_other(struct lguest *lg, u32 addr,
- const void *buf, unsigned bytes)
-{
- if (!lguest_address_ok(lg, addr, bytes)
- || (access_process_vm(lg->tsk, addr, (void *)buf, bytes, 1)
- != bytes)) {
- kill_guest(lg, "bad address writing to registered DMA");
- return 0;
- }
- return 1;
-}
-
-/*L:400 This is the generic engine which copies from a source "struct
- * lguest_dma" from this Guest into another Guest's "struct lguest_dma". The
- * destination Guest's pages have already been mapped, as contained in the
- * pages array.
- *
- * If you're wondering if there's a nice "copy from one process to another"
- * routine, so was I. But Linux isn't really set up to copy between two
- * unrelated processes, so we have to write it ourselves.
- */
-static u32 copy_data(struct lguest *srclg,
- const struct lguest_dma *src,
- const struct lguest_dma *dst,
- struct page *pages[])
-{
- unsigned int totlen, si, di, srcoff, dstoff;
- void *maddr = NULL;
-
- /* We return the total length transferred. */
- totlen = 0;
-
- /* We keep indexes into the source and destination "struct lguest_dma",
- * and an offset within each region. */
- si = di = 0;
- srcoff = dstoff = 0;
-
- /* We loop until the source or destination is exhausted. */
- while (si < LGUEST_MAX_DMA_SECTIONS && src->len[si]
- && di < LGUEST_MAX_DMA_SECTIONS && dst->len[di]) {
- /* We can only transfer the rest of the src buffer, or as much
- * as will fit into the destination buffer. */
- u32 len = min(src->len[si] - srcoff, dst->len[di] - dstoff);
-
- /* For systems using "highmem" we need to use kmap() to access
- * the page we want. We often use the same page over and over,
- * so rather than kmap() it on every loop, we set the maddr
- * pointer to NULL when we need to move to the next
- * destination page. */
- if (!maddr)
- maddr = kmap(pages[di]);
-
- /* Copy directly from (this Guest's) source address to the
- * destination Guest's kmap()ed buffer. Note that maddr points
- * to the start of the page: we need to add the offset of the
- * destination address and offset within the buffer. */
-
- /* FIXME: This is not completely portable. I looked at
- * copy_to_user_page(), and some arch's seem to need special
- * flushes. x86 is fine. */
- if (copy_from_user(maddr + (dst->addr[di] + dstoff)%PAGE_SIZE,
- (void __user *)src->addr[si], len) != 0) {
- /* If a copy failed, it's the source's fault. */
- kill_guest(srclg, "bad address in sending DMA");
- totlen = 0;
- break;
- }
-
- /* Increment the total and src & dst offsets */
- totlen += len;
- srcoff += len;
- dstoff += len;
-
- /* Presumably we reached the end of the src or dest buffers: */
- if (srcoff == src->len[si]) {
- /* Move to the next buffer at offset 0 */
- si++;
- srcoff = 0;
- }
- if (dstoff == dst->len[di]) {
- /* We need to unmap that destination page and reset
- * maddr ready for the next one. */
- kunmap(pages[di]);
- maddr = NULL;
- di++;
- dstoff = 0;
- }
- }
-
- /* If we still had a page mapped at the end, unmap now. */
- if (maddr)
- kunmap(pages[di]);
-
- return totlen;
-}
-
-/*L:390 This is how we transfer a "struct lguest_dma" from the source Guest
- * (the current Guest which called SEND_DMA) to another Guest. */
-static u32 do_dma(struct lguest *srclg, const struct lguest_dma *src,
- struct lguest *dstlg, const struct lguest_dma *dst)
-{
- int i;
- u32 ret;
- struct page *pages[LGUEST_MAX_DMA_SECTIONS];
-
- /* We check that both source and destination "struct lguest_dma"s are
- * within the bounds of the source and destination Guests */
- if (!check_dma_list(dstlg, dst) || !check_dma_list(srclg, src))
- return 0;
-
- /* We need to map the pages which correspond to each parts of
- * destination buffer. */
- for (i = 0; i < LGUEST_MAX_DMA_SECTIONS; i++) {
- if (dst->len[i] == 0)
- break;
- /* get_user_pages() is a complicated function, especially since
- * we only want a single page. But it works, and returns the
- * number of pages. Note that we're holding the destination's
- * mmap_sem, as get_user_pages() requires. */
- if (get_user_pages(dstlg->tsk, dstlg->mm,
- dst->addr[i], 1, 1, 1, pages+i, NULL)
- != 1) {
- /* This means the destination gave us a bogus buffer */
- kill_guest(dstlg, "Error mapping DMA pages");
- ret = 0;
- goto drop_pages;
- }
- }
-
- /* Now copy the data until we run out of src or dst. */
- ret = copy_data(srclg, src, dst, pages);
-
-drop_pages:
- while (--i >= 0)
- put_page(pages[i]);
- return ret;
-}
-
-/*L:380 Transferring data from one Guest to another is not as simple as I'd
- * like. We've found the "struct lguest_dma_info" bound to the same address as
- * the send, we need to copy into it.
- *
- * This function returns true if the destination array was empty. */
-static int dma_transfer(struct lguest *srclg,
- unsigned long udma,
- struct lguest_dma_info *dst)
-{
- struct lguest_dma dst_dma, src_dma;
- struct lguest *dstlg;
- u32 i, dma = 0;
-
- /* From the "struct lguest_dma_info" we found in the hash, grab the
- * Guest. */
- dstlg = &lguests[dst->guestid];
- /* Read in the source "struct lguest_dma" handed to SEND_DMA. */
- lgread(srclg, &src_dma, udma, sizeof(src_dma));
-
- /* We need the destination's mmap_sem, and we already hold the source's
- * mmap_sem for the futex key lookup. Normally this would suggest that
- * we could deadlock if the destination Guest was trying to send to
- * this source Guest at the same time, which is another reason that all
- * I/O is done under the big lguest_lock. */
- down_read(&dstlg->mm->mmap_sem);
-
- /* Look through the destination DMA array for an available buffer. */
- for (i = 0; i < dst->num_dmas; i++) {
- /* We keep a "next_dma" pointer which often helps us avoid
- * looking at lots of previously-filled entries. */
- dma = (dst->next_dma + i) % dst->num_dmas;
- if (!lgread_other(dstlg, &dst_dma,
- dst->dmas + dma * sizeof(struct lguest_dma),
- sizeof(dst_dma))) {
- goto fail;
- }
- if (!dst_dma.used_len)
- break;
- }
-
- /* If we found a buffer, we do the actual data copy. */
- if (i != dst->num_dmas) {
- unsigned long used_lenp;
- unsigned int ret;
-
- ret = do_dma(srclg, &src_dma, dstlg, &dst_dma);
- /* Put used length in the source "struct lguest_dma"'s used_len
- * field. It's a little tricky to figure out where that is,
- * though. */
- lgwrite_u32(srclg,
- udma+offsetof(struct lguest_dma, used_len), ret);
- /* Tranferring 0 bytes is OK if the source buffer was empty. */
- if (ret == 0 && src_dma.len[0] != 0)
- goto fail;
-
- /* The destination Guest might be running on a different CPU:
- * we have to make sure that it will see the "used_len" field
- * change to non-zero *after* it sees the data we copied into
- * the buffer. Hence a write memory barrier. */
- wmb();
- /* Figuring out where the destination's used_len field for this
- * "struct lguest_dma" in the array is also a little ugly. */
- used_lenp = dst->dmas
- + dma * sizeof(struct lguest_dma)
- + offsetof(struct lguest_dma, used_len);
- lgwrite_other(dstlg, used_lenp, &ret, sizeof(ret));
- /* Move the cursor for next time. */
- dst->next_dma++;
- }
- up_read(&dstlg->mm->mmap_sem);
-
- /* We trigger the destination interrupt, even if the destination was
- * empty and we didn't transfer anything: this gives them a chance to
- * wake up and refill. */
- set_bit(dst->interrupt, dstlg->irqs_pending);
- /* Wake up the destination process. */
- wake_up_process(dstlg->tsk);
- /* If we passed the last "struct lguest_dma", the receive had no
- * buffers left. */
- return i == dst->num_dmas;
-
-fail:
- up_read(&dstlg->mm->mmap_sem);
- return 0;
-}
-
-/*L:370 This is the counter-side to the BIND_DMA hypercall; the SEND_DMA
- * hypercall. We find out who's listening, and send to them. */
-void send_dma(struct lguest *lg, unsigned long ukey, unsigned long udma)
-{
- union futex_key key;
- int empty = 0;
- struct rw_semaphore *fshared = &current->mm->mmap_sem;
-
-again:
- mutex_lock(&lguest_lock);
- down_read(fshared);
- /* Get the futex key for the key the Guest gave us */
- if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) {
- kill_guest(lg, "bad sending DMA key");
- goto unlock;
- }
- /* Since the key must be a multiple of 4, the futex key uses the lower
- * bit of the "offset" field (which would always be 0) to indicate a
- * mapping which is shared with other processes (ie. Guests). */
- if (key.shared.offset & 1) {
- struct lguest_dma_info *i;
- /* Look through the hash for other Guests. */
- list_for_each_entry(i, &dma_hash[hash(&key)], list) {
- /* Don't send to ourselves. */
- if (i->guestid == lg->guestid)
- continue;
- if (!key_eq(&key, &i->key))
- continue;
-
- /* If dma_transfer() tells us the destination has no
- * available buffers, we increment "empty". */
- empty += dma_transfer(lg, udma, i);
- break;
- }
- /* If the destination is empty, we release our locks and
- * give the destination Guest a brief chance to restock. */
- if (empty == 1) {
- /* Give any recipients one chance to restock. */
- up_read(&current->mm->mmap_sem);
- mutex_unlock(&lguest_lock);
- /* Next time, we won't try again. */
- empty++;
- goto again;
- }
- } else {
- /* Private mapping: Guest is sending to its Launcher. We set
- * the "dma_is_pending" flag so that the main loop will exit
- * and the Launcher's read() from /dev/lguest will return. */
- lg->dma_is_pending = 1;
- lg->pending_dma = udma;
- lg->pending_key = ukey;
- }
-unlock:
- up_read(fshared);
- mutex_unlock(&lguest_lock);
-}
-/*:*/
-
-void release_all_dma(struct lguest *lg)
-{
- unsigned int i;
-
- BUG_ON(!mutex_is_locked(&lguest_lock));
-
- down_read(&lg->mm->mmap_sem);
- for (i = 0; i < LGUEST_MAX_DMA; i++) {
- if (lg->dma[i].interrupt)
- unlink_dma(&lg->dma[i]);
- }
- up_read(&lg->mm->mmap_sem);
-}
-
-/*M:007 We only return a single DMA buffer to the Launcher, but it would be
- * more efficient to return a pointer to the entire array of DMA buffers, which
- * it can cache and choose one whenever it wants.
- *
- * Currently the Launcher uses a write to /dev/lguest, and the return value is
- * the address of the DMA structure with the interrupt number placed in
- * dma->used_len. If we wanted to return the entire array, we need to return
- * the address, array size and interrupt number: this seems to require an
- * ioctl(). :*/
-
-/*L:320 This routine looks for a DMA buffer registered by the Guest on the
- * given key (using the BIND_DMA hypercall). */
-unsigned long get_dma_buffer(struct lguest *lg,
- unsigned long ukey, unsigned long *interrupt)
-{
- unsigned long ret = 0;
- union futex_key key;
- struct lguest_dma_info *i;
- struct rw_semaphore *fshared = &current->mm->mmap_sem;
-
- /* Take the Big Lguest Lock to stop other Guests sending this Guest DMA
- * at the same time. */
- mutex_lock(&lguest_lock);
- /* To match between Guests sharing the same underlying memory we steal
- * code from the futex infrastructure. This requires that we hold the
- * "mmap_sem" for our process (the Launcher), and pass it to the futex
- * code. */
- down_read(fshared);
-
- /* This can fail if it's not a valid address, or if the address is not
- * divisible by 4 (the futex code needs that, we don't really). */
- if (get_futex_key((u32 __user *)ukey, fshared, &key) != 0) {
- kill_guest(lg, "bad registered DMA buffer");
- goto unlock;
- }
- /* Search the hash table for matching entries (the Launcher can only
- * send to its own Guest for the moment, so the entry must be for this
- * Guest) */
- list_for_each_entry(i, &dma_hash[hash(&key)], list) {
- if (key_eq(&key, &i->key) && i->guestid == lg->guestid) {
- unsigned int j;
- /* Look through the registered DMA array for an
- * available buffer. */
- for (j = 0; j < i->num_dmas; j++) {
- struct lguest_dma dma;
-
- ret = i->dmas + j * sizeof(struct lguest_dma);
- lgread(lg, &dma, ret, sizeof(dma));
- if (dma.used_len == 0)
- break;
- }
- /* Store the interrupt the Guest wants when the buffer
- * is used. */
- *interrupt = i->interrupt;
- break;
- }
- }
-unlock:
- up_read(fshared);
- mutex_unlock(&lguest_lock);
- return ret;
-}
-/*:*/
-
-/*L:410 This really has completed the Launcher. Not only have we now finished
- * the longest chapter in our journey, but this also means we are over halfway
- * through!
- *
- * Enough prevaricating around the bush: it is time for us to dive into the
- * core of the Host, in "make Host".
- */
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 64f0abed317..2eef40be4c0 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -1,124 +1,28 @@
#ifndef _LGUEST_H
#define _LGUEST_H
-#include <asm/desc.h>
-
-#define GDT_ENTRY_LGUEST_CS 10
-#define GDT_ENTRY_LGUEST_DS 11
-#define LGUEST_CS (GDT_ENTRY_LGUEST_CS * 8)
-#define LGUEST_DS (GDT_ENTRY_LGUEST_DS * 8)
-
#ifndef __ASSEMBLY__
#include <linux/types.h>
#include <linux/init.h>
#include <linux/stringify.h>
-#include <linux/binfmts.h>
-#include <linux/futex.h>
#include <linux/lguest.h>
#include <linux/lguest_launcher.h>
#include <linux/wait.h>
+#include <linux/hrtimer.h>
#include <linux/err.h>
-#include <asm/semaphore.h>
-#include "irq_vectors.h"
-
-#define GUEST_PL 1
-
-struct lguest_regs
-{
- /* Manually saved part. */
- unsigned long ebx, ecx, edx;
- unsigned long esi, edi, ebp;
- unsigned long gs;
- unsigned long eax;
- unsigned long fs, ds, es;
- unsigned long trapnum, errcode;
- /* Trap pushed part */
- unsigned long eip;
- unsigned long cs;
- unsigned long eflags;
- unsigned long esp;
- unsigned long ss;
-};
-
-void free_pagetables(void);
-int init_pagetables(struct page **switcher_page, unsigned int pages);
-
-/* Full 4G segment descriptors, suitable for CS and DS. */
-#define FULL_EXEC_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9b00})
-#define FULL_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9300})
-
-struct lguest_dma_info
-{
- struct list_head list;
- union futex_key key;
- unsigned long dmas;
- u16 next_dma;
- u16 num_dmas;
- u16 guestid;
- u8 interrupt; /* 0 when not registered */
-};
+#include <linux/slab.h>
-/*H:310 The page-table code owes a great debt of gratitude to Andi Kleen. He
- * reviewed the original code which used "u32" for all page table entries, and
- * insisted that it would be far clearer with explicit typing. I thought it
- * was overkill, but he was right: it is much clearer than it was before.
- *
- * We have separate types for the Guest's ptes & pgds and the shadow ptes &
- * pgds. There's already a Linux type for these (pte_t and pgd_t) but they
- * change depending on kernel config options (PAE). */
-
-/* Each entry is identical: lower 12 bits of flags and upper 20 bits for the
- * "page frame number" (0 == first physical page, etc). They are different
- * types so the compiler will warn us if we mix them improperly. */
-typedef union {
- struct { unsigned flags:12, pfn:20; };
- struct { unsigned long val; } raw;
-} spgd_t;
-typedef union {
- struct { unsigned flags:12, pfn:20; };
- struct { unsigned long val; } raw;
-} spte_t;
-typedef union {
- struct { unsigned flags:12, pfn:20; };
- struct { unsigned long val; } raw;
-} gpgd_t;
-typedef union {
- struct { unsigned flags:12, pfn:20; };
- struct { unsigned long val; } raw;
-} gpte_t;
-
-/* We have two convenient macros to convert a "raw" value as handed to us by
- * the Guest into the correct Guest PGD or PTE type. */
-#define mkgpte(_val) ((gpte_t){.raw.val = _val})
-#define mkgpgd(_val) ((gpgd_t){.raw.val = _val})
-/*:*/
-
-struct pgdir
-{
- unsigned long cr3;
- spgd_t *pgdir;
-};
+#include <asm/lguest.h>
-/* This is a guest-specific page (mapped ro) into the guest. */
-struct lguest_ro_state
-{
- /* Host information we need to restore when we switch back. */
- u32 host_cr3;
- struct Xgt_desc_struct host_idt_desc;
- struct Xgt_desc_struct host_gdt_desc;
- u32 host_sp;
-
- /* Fields which are used when guest is running. */
- struct Xgt_desc_struct guest_idt_desc;
- struct Xgt_desc_struct guest_gdt_desc;
- struct i386_hw_tss guest_tss;
- struct desc_struct guest_idt[IDT_ENTRIES];
- struct desc_struct guest_gdt[GDT_ENTRIES];
+struct pgdir {
+ unsigned long gpgdir;
+ bool switcher_mapped;
+ int last_host_cpu;
+ pgd_t *pgdir;
};
/* We have two pages shared with guests, per cpu. */
-struct lguest_pages
-{
+struct lguest_pages {
/* This is the stack page mapped rw in guest */
char spare[PAGE_SIZE - sizeof(struct lguest_regs)];
struct lguest_regs regs;
@@ -132,137 +36,197 @@ struct lguest_pages
#define CHANGED_GDT_TLS 4 /* Actually a subset of CHANGED_GDT */
#define CHANGED_ALL 3
-/* The private info the thread maintains about the guest. */
-struct lguest
-{
- /* At end of a page shared mapped over lguest_pages in guest. */
- unsigned long regs_page;
- struct lguest_regs *regs;
- struct lguest_data __user *lguest_data;
+struct lg_cpu {
+ unsigned int id;
+ struct lguest *lg;
struct task_struct *tsk;
struct mm_struct *mm; /* == tsk->mm, but that becomes NULL on exit */
- u16 guestid;
- u32 pfn_limit;
- u32 page_offset;
+
u32 cr2;
- int halted;
int ts;
- u32 next_hcall;
u32 esp1;
- u8 ss1;
-
- /* Do we need to stop what we're doing and return to userspace? */
- int break_out;
- wait_queue_head_t break_wq;
+ u16 ss1;
/* Bitmap of what has changed: see CHANGED_* above. */
int changed;
+
+ unsigned long pending_notify; /* pfn from LHCALL_NOTIFY */
+
+ /* At end of a page shared mapped over lguest_pages in guest. */
+ unsigned long regs_page;
+ struct lguest_regs *regs;
+
struct lguest_pages *last_pages;
- /* We keep a small number of these. */
- u32 pgdidx;
- struct pgdir pgdirs[4];
+ /* Initialization mode: linear map everything. */
+ bool linear_pages;
+ int cpu_pgd; /* Which pgd this cpu is currently using */
+
+ /* If a hypercall was asked for, this points to the arguments. */
+ struct hcall_args *hcall;
+ u32 next_hcall;
+
+ /* Virtual clock device */
+ struct hrtimer hrt;
+
+ /* Did the Guest tell us to halt? */
+ int halted;
- /* Cached wakeup: we hold a reference to this task. */
- struct task_struct *wake;
+ /* Pending virtual interrupts */
+ DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
+
+ struct lg_cpu_arch arch;
+};
+
+struct lg_eventfd {
+ unsigned long addr;
+ struct eventfd_ctx *event;
+};
+
+struct lg_eventfd_map {
+ unsigned int num;
+ struct lg_eventfd map[];
+};
+
+/* The private info the thread maintains about the guest. */
+struct lguest {
+ struct lguest_data __user *lguest_data;
+ struct lg_cpu cpus[NR_CPUS];
+ unsigned int nr_cpus;
+
+ u32 pfn_limit;
+
+ /*
+ * This provides the offset to the base of guest-physical memory in the
+ * Launcher.
+ */
+ void __user *mem_base;
+ unsigned long kernel_address;
+
+ struct pgdir pgdirs[4];
unsigned long noirq_start, noirq_end;
- int dma_is_pending;
- unsigned long pending_dma; /* struct lguest_dma */
- unsigned long pending_key; /* address they're sending to */
unsigned int stack_pages;
u32 tsc_khz;
- struct lguest_dma_info dma[LGUEST_MAX_DMA];
+ struct lg_eventfd_map *eventfds;
/* Dead? */
const char *dead;
-
- /* The GDT entries copied into lguest_ro_state when running. */
- struct desc_struct gdt[GDT_ENTRIES];
-
- /* The IDT entries: some copied into lguest_ro_state when running. */
- struct desc_struct idt[FIRST_EXTERNAL_VECTOR+LGUEST_IRQS];
- struct desc_struct syscall_idt;
-
- /* Virtual clock device */
- struct hrtimer hrt;
-
- /* Pending virtual interrupts */
- DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
};
-extern struct lguest lguests[];
extern struct mutex lguest_lock;
/* core.c: */
-u32 lgread_u32(struct lguest *lg, unsigned long addr);
-void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val);
-void lgread(struct lguest *lg, void *buf, unsigned long addr, unsigned len);
-void lgwrite(struct lguest *lg, unsigned long, const void *buf, unsigned len);
-int find_free_guest(void);
-int lguest_address_ok(const struct lguest *lg,
- unsigned long addr, unsigned long len);
-int run_guest(struct lguest *lg, unsigned long __user *user);
-
+bool lguest_address_ok(const struct lguest *lg,
+ unsigned long addr, unsigned long len);
+void __lgread(struct lg_cpu *, void *, unsigned long, unsigned);
+void __lgwrite(struct lg_cpu *, unsigned long, const void *, unsigned);
+extern struct page **lg_switcher_pages;
+
+/*H:035
+ * Using memory-copy operations like that is usually inconvient, so we
+ * have the following helper macros which read and write a specific type (often
+ * an unsigned long).
+ *
+ * This reads into a variable of the given type then returns that.
+ */
+#define lgread(cpu, addr, type) \
+ ({ type _v; __lgread((cpu), &_v, (addr), sizeof(_v)); _v; })
+
+/* This checks that the variable is of the given type, then writes it out. */
+#define lgwrite(cpu, addr, type, val) \
+ do { \
+ typecheck(type, val); \
+ __lgwrite((cpu), (addr), &(val), sizeof(val)); \
+ } while(0)
+/* (end of memory access helper routines) :*/
+
+int run_guest(struct lg_cpu *cpu, unsigned long __user *user);
+
+/*
+ * Helper macros to obtain the first 12 or the last 20 bits, this is only the
+ * first step in the migration to the kernel types. pte_pfn is already defined
+ * in the kernel.
+ */
+#define pgd_flags(x) (pgd_val(x) & ~PAGE_MASK)
+#define pgd_pfn(x) (pgd_val(x) >> PAGE_SHIFT)
+#define pmd_flags(x) (pmd_val(x) & ~PAGE_MASK)
+#define pmd_pfn(x) (pmd_val(x) >> PAGE_SHIFT)
/* interrupts_and_traps.c: */
-void maybe_do_interrupt(struct lguest *lg);
-int deliver_trap(struct lguest *lg, unsigned int num);
-void load_guest_idt_entry(struct lguest *lg, unsigned int i, u32 low, u32 hi);
-void guest_set_stack(struct lguest *lg, u32 seg, u32 esp, unsigned int pages);
-void pin_stack_pages(struct lguest *lg);
+unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more);
+void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more);
+void set_interrupt(struct lg_cpu *cpu, unsigned int irq);
+bool deliver_trap(struct lg_cpu *cpu, unsigned int num);
+void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int i,
+ u32 low, u32 hi);
+void guest_set_stack(struct lg_cpu *cpu, u32 seg, u32 esp, unsigned int pages);
+void pin_stack_pages(struct lg_cpu *cpu);
void setup_default_idt_entries(struct lguest_ro_state *state,
const unsigned long *def);
-void copy_traps(const struct lguest *lg, struct desc_struct *idt,
+void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
const unsigned long *def);
-void guest_set_clockevent(struct lguest *lg, unsigned long delta);
-void init_clockdev(struct lguest *lg);
+void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta);
+bool send_notify_to_eventfd(struct lg_cpu *cpu);
+void init_clockdev(struct lg_cpu *cpu);
+bool check_syscall_vector(struct lguest *lg);
+int init_interrupts(void);
+void free_interrupts(void);
/* segments.c: */
void setup_default_gdt_entries(struct lguest_ro_state *state);
-void setup_guest_gdt(struct lguest *lg);
-void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num);
-void guest_load_tls(struct lguest *lg, unsigned long tls_array);
-void copy_gdt(const struct lguest *lg, struct desc_struct *gdt);
-void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt);
+void setup_guest_gdt(struct lg_cpu *cpu);
+void load_guest_gdt_entry(struct lg_cpu *cpu, unsigned int i,
+ u32 low, u32 hi);
+void guest_load_tls(struct lg_cpu *cpu, unsigned long tls_array);
+void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt);
+void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt);
/* page_tables.c: */
-int init_guest_pagetable(struct lguest *lg, unsigned long pgtable);
+int init_guest_pagetable(struct lguest *lg);
void free_guest_pagetable(struct lguest *lg);
-void guest_new_pagetable(struct lguest *lg, unsigned long pgtable);
-void guest_set_pmd(struct lguest *lg, unsigned long cr3, u32 i);
-void guest_pagetable_clear_all(struct lguest *lg);
-void guest_pagetable_flush_user(struct lguest *lg);
-void guest_set_pte(struct lguest *lg, unsigned long cr3,
- unsigned long vaddr, gpte_t val);
-void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages);
-int demand_page(struct lguest *info, unsigned long cr2, int errcode);
-void pin_page(struct lguest *lg, unsigned long vaddr);
+void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable);
+void guest_set_pgd(struct lguest *lg, unsigned long gpgdir, u32 i);
+#ifdef CONFIG_X86_PAE
+void guest_set_pmd(struct lguest *lg, unsigned long gpgdir, u32 i);
+#endif
+void guest_pagetable_clear_all(struct lg_cpu *cpu);
+void guest_pagetable_flush_user(struct lg_cpu *cpu);
+void guest_set_pte(struct lg_cpu *cpu, unsigned long gpgdir,
+ unsigned long vaddr, pte_t val);
+void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages);
+bool demand_page(struct lg_cpu *cpu, unsigned long cr2, int errcode);
+void pin_page(struct lg_cpu *cpu, unsigned long vaddr);
+unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr);
+void page_table_guest_data_init(struct lg_cpu *cpu);
+
+/* <arch>/core.c: */
+void lguest_arch_host_init(void);
+void lguest_arch_host_fini(void);
+void lguest_arch_run_guest(struct lg_cpu *cpu);
+void lguest_arch_handle_trap(struct lg_cpu *cpu);
+int lguest_arch_init_hypercalls(struct lg_cpu *cpu);
+int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args);
+void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start);
+
+/* <arch>/switcher.S: */
+extern char start_switcher_text[], end_switcher_text[], switch_to_guest[];
/* lguest_user.c: */
int lguest_device_init(void);
void lguest_device_remove(void);
-/* io.c: */
-void lguest_io_init(void);
-int bind_dma(struct lguest *lg,
- unsigned long key, unsigned long udma, u16 numdmas, u8 interrupt);
-void send_dma(struct lguest *info, unsigned long key, unsigned long udma);
-void release_all_dma(struct lguest *lg);
-unsigned long get_dma_buffer(struct lguest *lg, unsigned long key,
- unsigned long *interrupt);
-
/* hypercalls.c: */
-void do_hypercalls(struct lguest *lg);
-void write_timestamp(struct lguest *lg);
+void do_hypercalls(struct lg_cpu *cpu);
+void write_timestamp(struct lg_cpu *cpu);
/*L:035
* Let's step aside for the moment, to study one important routine that's used
* widely in the Host code.
*
- * There are many cases where the Guest does something invalid, like pass crap
+ * There are many cases where the Guest can do something invalid, like pass crap
* to a hypercall. Since only the Guest kernel can make hypercalls, it's quite
* acceptable to simply terminate the Guest and give the Launcher a nicely
* formatted reason. It's also simpler for the Guest itself, which doesn't
@@ -282,19 +246,15 @@ void write_timestamp(struct lguest *lg);
* Like any macro which uses an "if", it is safely wrapped in a run-once "do {
* } while(0)".
*/
-#define kill_guest(lg, fmt...) \
+#define kill_guest(cpu, fmt...) \
do { \
- if (!(lg)->dead) { \
- (lg)->dead = kasprintf(GFP_ATOMIC, fmt); \
- if (!(lg)->dead) \
- (lg)->dead = ERR_PTR(-ENOMEM); \
+ if (!(cpu)->lg->dead) { \
+ (cpu)->lg->dead = kasprintf(GFP_ATOMIC, fmt); \
+ if (!(cpu)->lg->dead) \
+ (cpu)->lg->dead = ERR_PTR(-ENOMEM); \
} \
} while(0)
/* (End of aside) :*/
-static inline unsigned long guest_pa(struct lguest *lg, unsigned long vaddr)
-{
- return vaddr - lg->page_offset;
-}
#endif /* __ASSEMBLY__ */
#endif /* _LGUEST_H */
diff --git a/drivers/lguest/lguest.c b/drivers/lguest/lguest.c
deleted file mode 100644
index ee1c6d05c3d..00000000000
--- a/drivers/lguest/lguest.c
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*P:010
- * A hypervisor allows multiple Operating Systems to run on a single machine.
- * To quote David Wheeler: "Any problem in computer science can be solved with
- * another layer of indirection."
- *
- * We keep things simple in two ways. First, we start with a normal Linux
- * kernel and insert a module (lg.ko) which allows us to run other Linux
- * kernels the same way we'd run processes. We call the first kernel the Host,
- * and the others the Guests. The program which sets up and configures Guests
- * (such as the example in Documentation/lguest/lguest.c) is called the
- * Launcher.
- *
- * Secondly, we only run specially modified Guests, not normal kernels. When
- * you set CONFIG_LGUEST to 'y' or 'm', this automatically sets
- * CONFIG_LGUEST_GUEST=y, which compiles this file into the kernel so it knows
- * how to be a Guest. This means that you can use the same kernel you boot
- * normally (ie. as a Host) as a Guest.
- *
- * These Guests know that they cannot do privileged operations, such as disable
- * interrupts, and that they have to ask the Host to do such things explicitly.
- * This file consists of all the replacements for such low-level native
- * hardware operations: these special Guest versions call the Host.
- *
- * So how does the kernel know it's a Guest? The Guest starts at a special
- * entry point marked with a magic string, which sets up a few things then
- * calls here. We replace the native functions in "struct paravirt_ops"
- * with our Guest versions, then boot like normal. :*/
-
-/*
- * Copyright (C) 2006, Rusty Russell <rusty@rustcorp.com.au> IBM Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/kernel.h>
-#include <linux/start_kernel.h>
-#include <linux/string.h>
-#include <linux/console.h>
-#include <linux/screen_info.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-#include <linux/lguest.h>
-#include <linux/lguest_launcher.h>
-#include <linux/lguest_bus.h>
-#include <asm/paravirt.h>
-#include <asm/param.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/desc.h>
-#include <asm/setup.h>
-#include <asm/e820.h>
-#include <asm/mce.h>
-#include <asm/io.h>
-
-/*G:010 Welcome to the Guest!
- *
- * The Guest in our tale is a simple creature: identical to the Host but
- * behaving in simplified but equivalent ways. In particular, the Guest is the
- * same kernel as the Host (or at least, built from the same source code). :*/
-
-/* Declarations for definitions in lguest_guest.S */
-extern char lguest_noirq_start[], lguest_noirq_end[];
-extern const char lgstart_cli[], lgend_cli[];
-extern const char lgstart_sti[], lgend_sti[];
-extern const char lgstart_popf[], lgend_popf[];
-extern const char lgstart_pushf[], lgend_pushf[];
-extern const char lgstart_iret[], lgend_iret[];
-extern void lguest_iret(void);
-
-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,
- .blocked_interrupts = { 1 }, /* Block timer interrupts */
-};
-struct lguest_device_desc *lguest_devices;
-static cycle_t clock_base;
-
-/*G:035 Notice the lazy_hcall() above, rather than hcall(). This is our first
- * real optimization trick!
- *
- * When lazy_mode is set, it means we're allowed to defer all hypercalls and do
- * them as a batch when lazy_mode is eventually turned off. Because hypercalls
- * are reasonably expensive, batching them up makes sense. For example, a
- * large mmap might update dozens of page table entries: that code calls
- * lguest_lazy_mode(PARAVIRT_LAZY_MMU), does the dozen updates, then calls
- * lguest_lazy_mode(PARAVIRT_LAZY_NONE).
- *
- * So, when we're in lazy mode, we call async_hypercall() to store the call for
- * future processing. When lazy mode is turned off we issue a hypercall to
- * flush the stored calls.
- *
- * There's also a hack where "mode" is set to "PARAVIRT_LAZY_FLUSH" which
- * indicates we're to flush any outstanding calls immediately. This is used
- * when an interrupt handler does a kmap_atomic(): the page table changes must
- * happen immediately even if we're in the middle of a batch. Usually we're
- * not, though, so there's nothing to do. */
-static enum paravirt_lazy_mode lazy_mode; /* Note: not SMP-safe! */
-static void lguest_lazy_mode(enum paravirt_lazy_mode mode)
-{
- if (mode == PARAVIRT_LAZY_FLUSH) {
- if (unlikely(lazy_mode != PARAVIRT_LAZY_NONE))
- hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0);
- } else {
- lazy_mode = mode;
- if (mode == PARAVIRT_LAZY_NONE)
- hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0);
- }
-}
-
-static void lazy_hcall(unsigned long call,
- unsigned long arg1,
- unsigned long arg2,
- unsigned long arg3)
-{
- if (lazy_mode == PARAVIRT_LAZY_NONE)
- hcall(call, arg1, arg2, arg3);
- else
- async_hcall(call, arg1, arg2, arg3);
-}
-
-/* async_hcall() is pretty simple: I'm quite proud of it really. We have a
- * ring buffer of stored hypercalls which the Host will run though next time we
- * do a normal hypercall. Each entry in the ring has 4 slots for the hypercall
- * arguments, and a "hcall_status" word which is 0 if the call is ready to go,
- * and 255 once the Host has finished with it.
- *
- * If we come around to a slot which hasn't been finished, then the table is
- * full and we just make the hypercall directly. This has the nice side
- * effect of causing the Host to run all the stored calls in the ring buffer
- * which empties it for next time! */
-void async_hcall(unsigned long call,
- unsigned long arg1, unsigned long arg2, unsigned long arg3)
-{
- /* Note: This code assumes we're uniprocessor. */
- static unsigned int next_call;
- unsigned long flags;
-
- /* Disable interrupts if not already disabled: we don't want an
- * interrupt handler making a hypercall while we're already doing
- * one! */
- local_irq_save(flags);
- if (lguest_data.hcall_status[next_call] != 0xFF) {
- /* Table full, so do normal hcall which will flush table. */
- hcall(call, arg1, arg2, arg3);
- } else {
- lguest_data.hcalls[next_call].eax = call;
- lguest_data.hcalls[next_call].edx = arg1;
- lguest_data.hcalls[next_call].ebx = arg2;
- lguest_data.hcalls[next_call].ecx = arg3;
- /* Arguments must all be written before we mark it to go */
- wmb();
- lguest_data.hcall_status[next_call] = 0;
- if (++next_call == LHCALL_RING_SIZE)
- next_call = 0;
- }
- local_irq_restore(flags);
-}
-/*:*/
-
-/* Wrappers for the SEND_DMA and BIND_DMA hypercalls. This is mainly because
- * Jeff Garzik complained that __pa() should never appear in drivers, and this
- * helps remove most of them. But also, it wraps some ugliness. */
-void lguest_send_dma(unsigned long key, struct lguest_dma *dma)
-{
- /* The hcall might not write this if something goes wrong */
- dma->used_len = 0;
- hcall(LHCALL_SEND_DMA, key, __pa(dma), 0);
-}
-
-int lguest_bind_dma(unsigned long key, struct lguest_dma *dmas,
- unsigned int num, u8 irq)
-{
- /* This is the only hypercall which actually wants 5 arguments, and we
- * only support 4. Fortunately the interrupt number is always less
- * than 256, so we can pack it with the number of dmas in the final
- * argument. */
- if (!hcall(LHCALL_BIND_DMA, key, __pa(dmas), (num << 8) | irq))
- return -ENOMEM;
- return 0;
-}
-
-/* Unbinding is the same hypercall as binding, but with 0 num & irq. */
-void lguest_unbind_dma(unsigned long key, struct lguest_dma *dmas)
-{
- hcall(LHCALL_BIND_DMA, key, __pa(dmas), 0);
-}
-
-/* For guests, device memory can be used as normal memory, so we cast away the
- * __iomem to quieten sparse. */
-void *lguest_map(unsigned long phys_addr, unsigned long pages)
-{
- return (__force void *)ioremap(phys_addr, PAGE_SIZE*pages);
-}
-
-void lguest_unmap(void *addr)
-{
- iounmap((__force void __iomem *)addr);
-}
-
-/*G:033
- * Here are our first native-instruction replacements: four functions for
- * interrupt control.
- *
- * The simplest way of implementing these would be to have "turn interrupts
- * off" and "turn interrupts on" hypercalls. Unfortunately, this is too slow:
- * these are by far the most commonly called functions of those we override.
- *
- * So instead we keep an "irq_enabled" field inside our "struct lguest_data",
- * which the Guest can update with a single instruction. The Host knows to
- * check there when it wants to deliver an interrupt.
- */
-
-/* save_flags() is expected to return the processor state (ie. "eflags"). The
- * eflags word contains all kind of stuff, but in practice Linux only cares
- * about the interrupt flag. Our "save_flags()" just returns that. */
-static unsigned long save_fl(void)
-{
- return lguest_data.irq_enabled;
-}
-
-/* "restore_flags" just sets the flags back to the value given. */
-static void restore_fl(unsigned long flags)
-{
- lguest_data.irq_enabled = flags;
-}
-
-/* Interrupts go off... */
-static void irq_disable(void)
-{
- lguest_data.irq_enabled = 0;
-}
-
-/* Interrupts go on... */
-static void irq_enable(void)
-{
- lguest_data.irq_enabled = X86_EFLAGS_IF;
-}
-/*:*/
-/*M:003 Note that we don't check for outstanding interrupts when we re-enable
- * them (or when we unmask an interrupt). This seems to work for the moment,
- * since interrupts are rare and we'll just get the interrupt on the next timer
- * tick, but when we turn on CONFIG_NO_HZ, we should revisit this. One way
- * would be to put the "irq_enabled" field in a page by itself, and have the
- * Host write-protect it when an interrupt comes in when irqs are disabled.
- * There will then be a page fault as soon as interrupts are re-enabled. :*/
-
-/*G:034
- * The Interrupt Descriptor Table (IDT).
- *
- * The IDT tells the processor what to do when an interrupt comes in. Each
- * entry in the table is a 64-bit descriptor: this holds the privilege level,
- * address of the handler, and... well, who cares? The Guest just asks the
- * Host to make the change anyway, because the Host controls the real IDT.
- */
-static void lguest_write_idt_entry(struct desc_struct *dt,
- int entrynum, u32 low, u32 high)
-{
- /* Keep the local copy up to date. */
- write_dt_entry(dt, entrynum, low, high);
- /* Tell Host about this new entry. */
- hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, low, high);
-}
-
-/* Changing to a different IDT is very rare: we keep the IDT up-to-date every
- * time it is written, so we can simply loop through all entries and tell the
- * Host about them. */
-static void lguest_load_idt(const struct Xgt_desc_struct *desc)
-{
- unsigned int i;
- struct desc_struct *idt = (void *)desc->address;
-
- for (i = 0; i < (desc->size+1)/8; i++)
- hcall(LHCALL_LOAD_IDT_ENTRY, i, idt[i].a, idt[i].b);
-}
-
-/*
- * The Global Descriptor Table.
- *
- * The Intel architecture defines another table, called the Global Descriptor
- * Table (GDT). You tell the CPU where it is (and its size) using the "lgdt"
- * instruction, and then several other instructions refer to entries in the
- * table. There are three entries which the Switcher needs, so the Host simply
- * controls the entire thing and the Guest asks it to make changes using the
- * LOAD_GDT hypercall.
- *
- * This is the opposite of the IDT code where we have a LOAD_IDT_ENTRY
- * hypercall and use that repeatedly to load a new IDT. I don't think it
- * really matters, but wouldn't it be nice if they were the same?
- */
-static void lguest_load_gdt(const struct Xgt_desc_struct *desc)
-{
- BUG_ON((desc->size+1)/8 != GDT_ENTRIES);
- hcall(LHCALL_LOAD_GDT, __pa(desc->address), GDT_ENTRIES, 0);
-}
-
-/* For a single GDT entry which changes, we do the lazy thing: alter our GDT,
- * then tell the Host to reload the entire thing. This operation is so rare
- * that this naive implementation is reasonable. */
-static void lguest_write_gdt_entry(struct desc_struct *dt,
- int entrynum, u32 low, u32 high)
-{
- write_dt_entry(dt, entrynum, low, high);
- hcall(LHCALL_LOAD_GDT, __pa(dt), GDT_ENTRIES, 0);
-}
-
-/* OK, I lied. There are three "thread local storage" GDT entries which change
- * on every context switch (these three entries are how glibc implements
- * __thread variables). So we have a hypercall specifically for this case. */
-static void lguest_load_tls(struct thread_struct *t, unsigned int cpu)
-{
- /* There's one problem which normal hardware doesn't have: the Host
- * can't handle us removing entries we're currently using. So we clear
- * the GS register here: if it's needed it'll be reloaded anyway. */
- loadsegment(gs, 0);
- lazy_hcall(LHCALL_LOAD_TLS, __pa(&t->tls_array), cpu, 0);
-}
-
-/*G:038 That's enough excitement for now, back to ploughing through each of
- * the paravirt_ops (we're about 1/3 of the way through).
- *
- * This is the Local Descriptor Table, another weird Intel thingy. Linux only
- * uses this for some strange applications like Wine. We don't do anything
- * here, so they'll get an informative and friendly Segmentation Fault. */
-static void lguest_set_ldt(const void *addr, unsigned entries)
-{
-}
-
-/* This loads a GDT entry into the "Task Register": that entry points to a
- * structure called the Task State Segment. Some comments scattered though the
- * kernel code indicate that this used for task switching in ages past, along
- * with blood sacrifice and astrology.
- *
- * Now there's nothing interesting in here that we don't get told elsewhere.
- * But the native version uses the "ltr" instruction, which makes the Host
- * complain to the Guest about a Segmentation Fault and it'll oops. So we
- * override the native version with a do-nothing version. */
-static void lguest_load_tr_desc(void)
-{
-}
-
-/* The "cpuid" instruction is a way of querying both the CPU identity
- * (manufacturer, model, etc) and its features. It was introduced before the
- * Pentium in 1993 and keeps getting extended by both Intel and AMD. As you
- * might imagine, after a decade and a half this treatment, it is now a giant
- * ball of hair. Its entry in the current Intel manual runs to 28 pages.
- *
- * This instruction even it has its own Wikipedia entry. The Wikipedia entry
- * has been translated into 4 languages. I am not making this up!
- *
- * We could get funky here and identify ourselves as "GenuineLguest", but
- * instead we just use the real "cpuid" instruction. Then I pretty much turned
- * off feature bits until the Guest booted. (Don't say that: you'll damage
- * lguest sales!) Shut up, inner voice! (Hey, just pointing out that this is
- * hardly future proof.) Noone's listening! They don't like you anyway,
- * parenthetic weirdo!
- *
- * Replacing the cpuid so we can turn features off is great for the kernel, but
- * anyone (including userspace) can just use the raw "cpuid" instruction and
- * the Host won't even notice since it isn't privileged. So we try not to get
- * too worked up about it. */
-static void lguest_cpuid(unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- int function = *eax;
-
- native_cpuid(eax, ebx, ecx, edx);
- switch (function) {
- case 1: /* Basic feature request. */
- /* We only allow kernel to see SSE3, CMPXCHG16B and SSSE3 */
- *ecx &= 0x00002201;
- /* SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, FPU. */
- *edx &= 0x07808101;
- /* The Host can do a nice optimization if it knows that the
- * kernel mappings (addresses above 0xC0000000 or whatever
- * PAGE_OFFSET is set to) haven't changed. But Linux calls
- * flush_tlb_user() for both user and kernel mappings unless
- * the Page Global Enable (PGE) feature bit is set. */
- *edx |= 0x00002000;
- break;
- case 0x80000000:
- /* Futureproof this a little: if they ask how much extended
- * processor information there is, limit it to known fields. */
- if (*eax > 0x80000008)
- *eax = 0x80000008;
- break;
- }
-}
-
-/* Intel has four control registers, imaginatively named cr0, cr2, cr3 and cr4.
- * I assume there's a cr1, but it hasn't bothered us yet, so we'll not bother
- * it. The Host needs to know when the Guest wants to change them, so we have
- * a whole series of functions like read_cr0() and write_cr0().
- *
- * We start with CR0. CR0 allows you to turn on and off all kinds of basic
- * features, but Linux only really cares about one: the horrifically-named Task
- * Switched (TS) bit at bit 3 (ie. 8)
- *
- * What does the TS bit do? Well, it causes the CPU to trap (interrupt 7) if
- * the floating point unit is used. Which allows us to restore FPU state
- * lazily after a task switch, and Linux uses that gratefully, but wouldn't a
- * name like "FPUTRAP bit" be a little less cryptic?
- *
- * We store cr0 (and cr3) locally, because the Host never changes it. The
- * Guest sometimes wants to read it and we'd prefer not to bother the Host
- * unnecessarily. */
-static unsigned long current_cr0, current_cr3;
-static void lguest_write_cr0(unsigned long val)
-{
- /* 8 == TS bit. */
- lazy_hcall(LHCALL_TS, val & 8, 0, 0);
- current_cr0 = val;
-}
-
-static unsigned long lguest_read_cr0(void)
-{
- return current_cr0;
-}
-
-/* Intel provided a special instruction to clear the TS bit for people too cool
- * to use write_cr0() to do it. This "clts" instruction is faster, because all
- * the vowels have been optimized out. */
-static void lguest_clts(void)
-{
- lazy_hcall(LHCALL_TS, 0, 0, 0);
- current_cr0 &= ~8U;
-}
-
-/* CR2 is the virtual address of the last page fault, which the Guest only ever
- * reads. The Host kindly writes this into our "struct lguest_data", so we
- * just read it out of there. */
-static unsigned long lguest_read_cr2(void)
-{
- return lguest_data.cr2;
-}
-
-/* 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. */
-static void lguest_write_cr3(unsigned long cr3)
-{
- lazy_hcall(LHCALL_NEW_PGTABLE, cr3, 0, 0);
- current_cr3 = cr3;
-}
-
-static unsigned long lguest_read_cr3(void)
-{
- return current_cr3;
-}
-
-/* CR4 is used to enable and disable PGE, but we don't care. */
-static unsigned long lguest_read_cr4(void)
-{
- return 0;
-}
-
-static void lguest_write_cr4(unsigned long val)
-{
-}
-
-/*
- * Page Table Handling.
- *
- * Now would be a good time to take a rest and grab a coffee or similarly
- * relaxing stimulant. The easy parts are behind us, and the trek gradually
- * winds uphill from here.
- *
- * Quick refresher: memory is divided into "pages" of 4096 bytes each. The CPU
- * maps virtual addresses to physical addresses using "page tables". We could
- * use one huge index of 1 million entries: each address is 4 bytes, so that's
- * 1024 pages just to hold the page tables. But since most virtual addresses
- * are unused, we use a two level index which saves space. The CR3 register
- * contains the physical address of the top level "page directory" page, which
- * contains physical addresses of up to 1024 second-level pages. Each of these
- * second level pages contains up to 1024 physical addresses of actual pages,
- * or Page Table Entries (PTEs).
- *
- * Here's a diagram, where arrows indicate physical addresses:
- *
- * CR3 ---> +---------+
- * | --------->+---------+
- * | | | PADDR1 |
- * Top-level | | PADDR2 |
- * (PMD) page | | |
- * | | Lower-level |
- * | | (PTE) page |
- * | | | |
- * .... ....
- *
- * So to convert a virtual address to a physical address, we look up the top
- * level, which points us to the second level, which gives us the physical
- * address of that page. If the top level entry was not present, or the second
- * level entry was not present, then the virtual address is invalid (we
- * say "the page was not mapped").
- *
- * Put another way, a 32-bit virtual address is divided up like so:
- *
- * 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
- * |<---- 10 bits ---->|<---- 10 bits ---->|<------ 12 bits ------>|
- * Index into top Index into second Offset within page
- * page directory page pagetable page
- *
- * The kernel spends a lot of time changing both the top-level page directory
- * and lower-level pagetable pages. The Guest doesn't know physical addresses,
- * so while it maintains these page tables exactly like normal, it also needs
- * to keep the Host informed whenever it makes a change: the Host will create
- * the real page tables based on the Guests'.
- */
-
-/* The Guest calls this to set a second-level entry (pte), ie. to map a page
- * into a process' address space. We set the entry then tell the Host the
- * toplevel and address this corresponds to. The Guest uses one pagetable per
- * process, so we need to tell the Host which one we're changing (mm->pgd). */
-static void lguest_set_pte_at(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep, pte_t pteval)
-{
- *ptep = pteval;
- lazy_hcall(LHCALL_SET_PTE, __pa(mm->pgd), addr, pteval.pte_low);
-}
-
-/* The Guest calls this to set a top-level entry. Again, we set the entry then
- * tell the Host which top-level page we changed, and the index of the entry we
- * changed. */
-static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
-{
- *pmdp = pmdval;
- lazy_hcall(LHCALL_SET_PMD, __pa(pmdp)&PAGE_MASK,
- (__pa(pmdp)&(PAGE_SIZE-1))/4, 0);
-}
-
-/* There are a couple of legacy places where the kernel sets a PTE, but we
- * don't know the top level any more. This is useless for us, since we don't
- * know which pagetable is changing or what address, so we just tell the Host
- * to forget all of them. Fortunately, this is very rare.
- *
- * ... except in early boot when the kernel sets up the initial pagetables,
- * which makes booting astonishingly slow. So we don't even tell the Host
- * anything changed until we've done the first page table switch.
- */
-static void lguest_set_pte(pte_t *ptep, pte_t pteval)
-{
- *ptep = pteval;
- /* Don't bother with hypercall before initial setup. */
- if (current_cr3)
- lazy_hcall(LHCALL_FLUSH_TLB, 1, 0, 0);
-}
-
-/* Unfortunately for Lguest, the paravirt_ops for page tables were based on
- * native page table operations. On native hardware you can set a new page
- * table entry whenever you want, but if you want to remove one you have to do
- * a TLB flush (a TLB is a little cache of page table entries kept by the CPU).
- *
- * So the lguest_set_pte_at() and lguest_set_pmd() functions above are only
- * called when a valid entry is written, not when it's removed (ie. marked not
- * present). Instead, this is where we come when the Guest wants to remove a
- * page table entry: we tell the Host to set that entry to 0 (ie. the present
- * bit is zero). */
-static void lguest_flush_tlb_single(unsigned long addr)
-{
- /* Simply set it to zero: if it was not, it will fault back in. */
- lazy_hcall(LHCALL_SET_PTE, current_cr3, addr, 0);
-}
-
-/* This is what happens after the Guest has removed a large number of entries.
- * This tells the Host that any of the page table entries for userspace might
- * have changed, ie. virtual addresses below PAGE_OFFSET. */
-static void lguest_flush_tlb_user(void)
-{
- lazy_hcall(LHCALL_FLUSH_TLB, 0, 0, 0);
-}
-
-/* This is called when the kernel page tables have changed. That's not very
- * common (unless the Guest is using highmem, which makes the Guest extremely
- * slow), so it's worth separating this from the user flushing above. */
-static void lguest_flush_tlb_kernel(void)
-{
- lazy_hcall(LHCALL_FLUSH_TLB, 1, 0, 0);
-}
-
-/*
- * The Unadvanced Programmable Interrupt Controller.
- *
- * This is an attempt to implement the simplest possible interrupt controller.
- * I spent some time looking though routines like set_irq_chip_and_handler,
- * set_irq_chip_and_handler_name, set_irq_chip_data and set_phasers_to_stun and
- * I *think* this is as simple as it gets.
- *
- * We can tell the Host what interrupts we want blocked ready for using the
- * lguest_data.interrupts bitmap, so disabling (aka "masking") them is as
- * simple as setting a bit. We don't actually "ack" interrupts as such, we
- * just mask and unmask them. I wonder if we should be cleverer?
- */
-static void disable_lguest_irq(unsigned int irq)
-{
- set_bit(irq, lguest_data.blocked_interrupts);
-}
-
-static void enable_lguest_irq(unsigned int irq)
-{
- clear_bit(irq, lguest_data.blocked_interrupts);
-}
-
-/* This structure describes the lguest IRQ controller. */
-static struct irq_chip lguest_irq_controller = {
- .name = "lguest",
- .mask = disable_lguest_irq,
- .mask_ack = disable_lguest_irq,
- .unmask = enable_lguest_irq,
-};
-
-/* This sets up the Interrupt Descriptor Table (IDT) entry for each hardware
- * interrupt (except 128, which is used for system calls), and then tells the
- * Linux infrastructure that each interrupt is controlled by our level-based
- * lguest interrupt controller. */
-static void __init lguest_init_IRQ(void)
-{
- unsigned int i;
-
- for (i = 0; i < LGUEST_IRQS; i++) {
- int vector = FIRST_EXTERNAL_VECTOR + i;
- if (vector != SYSCALL_VECTOR) {
- set_intr_gate(vector, interrupt[i]);
- set_irq_chip_and_handler(i, &lguest_irq_controller,
- handle_level_irq);
- }
- }
- /* This call is required to set up for 4k stacks, where we have
- * separate stacks for hard and soft interrupts. */
- irq_ctx_init(smp_processor_id());
-}
-
-/*
- * Time.
- *
- * It would be far better for everyone if the Guest had its own clock, but
- * until then the Host gives us the time on every interrupt.
- */
-static unsigned long lguest_get_wallclock(void)
-{
- return lguest_data.time.tv_sec;
-}
-
-static cycle_t lguest_clock_read(void)
-{
- unsigned long sec, nsec;
-
- /* If the Host tells the TSC speed, we can trust that. */
- if (lguest_data.tsc_khz)
- return native_read_tsc();
-
- /* If we can't use the TSC, we read the time value written by the Host.
- * Since it's in two parts (seconds and nanoseconds), we risk reading
- * it just as it's changing from 99 & 0.999999999 to 100 and 0, and
- * getting 99 and 0. As Linux tends to come apart under the stress of
- * time travel, we must be careful: */
- do {
- /* First we read the seconds part. */
- sec = lguest_data.time.tv_sec;
- /* This read memory barrier tells the compiler and the CPU that
- * this can't be reordered: we have to complete the above
- * before going on. */
- rmb();
- /* Now we read the nanoseconds part. */
- nsec = lguest_data.time.tv_nsec;
- /* Make sure we've done that. */
- rmb();
- /* Now if the seconds part has changed, try again. */
- } while (unlikely(lguest_data.time.tv_sec != sec));
-
- /* Our non-TSC clock is in real nanoseconds. */
- return sec*1000000000ULL + nsec;
-}
-
-/* This is what we tell the kernel is our clocksource. */
-static struct clocksource lguest_clock = {
- .name = "lguest",
- .rating = 400,
- .read = lguest_clock_read,
- .mask = CLOCKSOURCE_MASK(64),
- .mult = 1 << 22,
- .shift = 22,
-};
-
-/* The "scheduler clock" is just our real clock, adjusted to start at zero */
-static unsigned long long lguest_sched_clock(void)
-{
- return cyc2ns(&lguest_clock, lguest_clock_read() - clock_base);
-}
-
-/* We also need a "struct clock_event_device": Linux asks us to set it to go
- * off some time in the future. Actually, James Morris figured all this out, I
- * just applied the patch. */
-static int lguest_clockevent_set_next_event(unsigned long delta,
- struct clock_event_device *evt)
-{
- if (delta < LG_CLOCK_MIN_DELTA) {
- if (printk_ratelimit())
- printk(KERN_DEBUG "%s: small delta %lu ns\n",
- __FUNCTION__, delta);
- return -ETIME;
- }
- hcall(LHCALL_SET_CLOCKEVENT, delta, 0, 0);
- return 0;
-}
-
-static void lguest_clockevent_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- switch (mode) {
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- /* A 0 argument shuts the clock down. */
- hcall(LHCALL_SET_CLOCKEVENT, 0, 0, 0);
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- /* This is what we expect. */
- break;
- case CLOCK_EVT_MODE_PERIODIC:
- BUG();
- case CLOCK_EVT_MODE_RESUME:
- break;
- }
-}
-
-/* This describes our primitive timer chip. */
-static struct clock_event_device lguest_clockevent = {
- .name = "lguest",
- .features = CLOCK_EVT_FEAT_ONESHOT,
- .set_next_event = lguest_clockevent_set_next_event,
- .set_mode = lguest_clockevent_set_mode,
- .rating = INT_MAX,
- .mult = 1,
- .shift = 0,
- .min_delta_ns = LG_CLOCK_MIN_DELTA,
- .max_delta_ns = LG_CLOCK_MAX_DELTA,
-};
-
-/* This is the Guest timer interrupt handler (hardware interrupt 0). We just
- * call the clockevent infrastructure and it does whatever needs doing. */
-static void lguest_time_irq(unsigned int irq, struct irq_desc *desc)
-{
- unsigned long flags;
-
- /* Don't interrupt us while this is running. */
- local_irq_save(flags);
- lguest_clockevent.event_handler(&lguest_clockevent);
- local_irq_restore(flags);
-}
-
-/* At some point in the boot process, we get asked to set up our timing
- * infrastructure. The kernel doesn't expect timer interrupts before this, but
- * we cleverly initialized the "blocked_interrupts" field of "struct
- * lguest_data" so that timer interrupts were blocked until now. */
-static void lguest_time_init(void)
-{
- /* Set up the timer interrupt (0) to go to our simple timer routine */
- set_irq_handler(0, lguest_time_irq);
-
- /* Our clock structure look like arch/i386/kernel/tsc.c if we can use
- * the TSC, otherwise it's a dumb nanosecond-resolution clock. Either
- * way, the "rating" is initialized so high that it's always chosen
- * over any other clocksource. */
- if (lguest_data.tsc_khz) {
- lguest_clock.mult = clocksource_khz2mult(lguest_data.tsc_khz,
- lguest_clock.shift);
- lguest_clock.flags = CLOCK_SOURCE_IS_CONTINUOUS;
- }
- clock_base = lguest_clock_read();
- clocksource_register(&lguest_clock);
-
- /* Now we've set up our clock, we can use it as the scheduler clock */
- paravirt_ops.sched_clock = lguest_sched_clock;
-
- /* We can't set cpumask in the initializer: damn C limitations! Set it
- * here and register our timer device. */
- lguest_clockevent.cpumask = cpumask_of_cpu(0);
- clockevents_register_device(&lguest_clockevent);
-
- /* Finally, we unblock the timer interrupt. */
- enable_lguest_irq(0);
-}
-
-/*
- * Miscellaneous bits and pieces.
- *
- * Here is an oddball collection of functions which the Guest needs for things
- * to work. They're pretty simple.
- */
-
-/* The Guest needs to tell the host what stack it expects traps to use. For
- * native hardware, this is part of the Task State Segment mentioned above in
- * lguest_load_tr_desc(), but to help hypervisors there's this special call.
- *
- * We tell the Host the segment we want to use (__KERNEL_DS is the kernel data
- * segment), the privilege level (we're privilege level 1, the Host is 0 and
- * will not tolerate us trying to use that), the stack pointer, and the number
- * of pages in the stack. */
-static void lguest_load_esp0(struct tss_struct *tss,
- struct thread_struct *thread)
-{
- lazy_hcall(LHCALL_SET_STACK, __KERNEL_DS|0x1, thread->esp0,
- THREAD_SIZE/PAGE_SIZE);
-}
-
-/* Let's just say, I wouldn't do debugging under a Guest. */
-static void lguest_set_debugreg(int regno, unsigned long value)
-{
- /* FIXME: Implement */
-}
-
-/* There are times when the kernel wants to make sure that no memory writes are
- * caught in the cache (that they've all reached real hardware devices). This
- * doesn't matter for the Guest which has virtual hardware.
- *
- * On the Pentium 4 and above, cpuid() indicates that the Cache Line Flush
- * (clflush) instruction is available and the kernel uses that. Otherwise, it
- * uses the older "Write Back and Invalidate Cache" (wbinvd) instruction.
- * Unlike clflush, wbinvd can only be run at privilege level 0. So we can
- * ignore clflush, but replace wbinvd.
- */
-static void lguest_wbinvd(void)
-{
-}
-
-/* If the Guest expects to have an Advanced Programmable Interrupt Controller,
- * we play dumb by ignoring writes and returning 0 for reads. So it's no
- * longer Programmable nor Controlling anything, and I don't think 8 lines of
- * code qualifies for Advanced. It will also never interrupt anything. It
- * does, however, allow us to get through the Linux boot code. */
-#ifdef CONFIG_X86_LOCAL_APIC
-static void lguest_apic_write(unsigned long reg, unsigned long v)
-{
-}
-
-static unsigned long lguest_apic_read(unsigned long reg)
-{
- return 0;
-}
-#endif
-
-/* STOP! Until an interrupt comes in. */
-static void lguest_safe_halt(void)
-{
- hcall(LHCALL_HALT, 0, 0, 0);
-}
-
-/* Perhaps CRASH isn't the best name for this hypercall, but we use it to get a
- * message out when we're crashing as well as elegant termination like powering
- * off.
- *
- * Note that the Host always prefers that the Guest speak in physical addresses
- * rather than virtual addresses, so we use __pa() here. */
-static void lguest_power_off(void)
-{
- hcall(LHCALL_CRASH, __pa("Power down"), 0, 0);
-}
-
-/*
- * Panicing.
- *
- * Don't. But if you did, this is what happens.
- */
-static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p)
-{
- hcall(LHCALL_CRASH, __pa(p), 0, 0);
- /* The hcall won't return, but to keep gcc happy, we're "done". */
- return NOTIFY_DONE;
-}
-
-static struct notifier_block paniced = {
- .notifier_call = lguest_panic
-};
-
-/* Setting up memory is fairly easy. */
-static __init char *lguest_memory_setup(void)
-{
- /* We do this here and not earlier because lockcheck barfs if we do it
- * before start_kernel() */
- atomic_notifier_chain_register(&panic_notifier_list, &paniced);
-
- /* The Linux bootloader header contains an "e820" memory map: the
- * Launcher populated the first entry with our memory limit. */
- add_memory_region(E820_MAP->addr, E820_MAP->size, E820_MAP->type);
-
- /* This string is for the boot messages. */
- return "LGUEST";
-}
-
-/*G:050
- * Patching (Powerfully Placating Performance Pedants)
- *
- * We have already seen that "struct paravirt_ops" lets us replace simple
- * native instructions with calls to the appropriate back end all throughout
- * the kernel. This allows the same kernel to run as a Guest and as a native
- * kernel, but it's slow because of all the indirect branches.
- *
- * Remember that David Wheeler quote about "Any problem in computer science can
- * be solved with another layer of indirection"? The rest of that quote is
- * "... But that usually will create another problem." This is the first of
- * those problems.
- *
- * Our current solution is to allow the paravirt back end to optionally patch
- * over the indirect calls to replace them with something more efficient. We
- * patch the four most commonly called functions: disable interrupts, enable
- * interrupts, restore interrupts and save interrupts. We usually have 10
- * bytes to patch into: the Guest versions of these operations are small enough
- * that we can fit comfortably.
- *
- * First we need assembly templates of each of the patchable Guest operations,
- * and these are in lguest_asm.S. */
-
-/*G:060 We construct a table from the assembler templates: */
-static const struct lguest_insns
-{
- const char *start, *end;
-} lguest_insns[] = {
- [PARAVIRT_PATCH(irq_disable)] = { lgstart_cli, lgend_cli },
- [PARAVIRT_PATCH(irq_enable)] = { lgstart_sti, lgend_sti },
- [PARAVIRT_PATCH(restore_fl)] = { lgstart_popf, lgend_popf },
- [PARAVIRT_PATCH(save_fl)] = { lgstart_pushf, lgend_pushf },
-};
-
-/* Now our patch routine is fairly simple (based on the native one in
- * paravirt.c). If we have a replacement, we copy it in and return how much of
- * the available space we used. */
-static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf,
- unsigned long addr, unsigned len)
-{
- unsigned int insn_len;
-
- /* Don't do anything special if we don't have a replacement */
- if (type >= ARRAY_SIZE(lguest_insns) || !lguest_insns[type].start)
- return paravirt_patch_default(type, clobber, ibuf, addr, len);
-
- insn_len = lguest_insns[type].end - lguest_insns[type].start;
-
- /* Similarly if we can't fit replacement (shouldn't happen, but let's
- * be thorough). */
- if (len < insn_len)
- return paravirt_patch_default(type, clobber, ibuf, addr, len);
-
- /* Copy in our instructions. */
- memcpy(ibuf, lguest_insns[type].start, insn_len);
- return insn_len;
-}
-
-/*G:030 Once we get to lguest_init(), we know we're a Guest. The paravirt_ops
- * structure in the kernel provides a single point for (almost) every routine
- * we have to override to avoid privileged instructions. */
-__init void lguest_init(void *boot)
-{
- /* Copy boot parameters first: the Launcher put the physical location
- * in %esi, and head.S converted that to a virtual address and handed
- * it to us. We use "__memcpy" because "memcpy" sometimes tries to do
- * tricky things to go faster, and we're not ready for that. */
- __memcpy(&boot_params, boot, PARAM_SIZE);
- /* The boot parameters also tell us where the command-line is: save
- * that, too. */
- __memcpy(boot_command_line, __va(boot_params.hdr.cmd_line_ptr),
- COMMAND_LINE_SIZE);
-
- /* We're under lguest, paravirt is enabled, and we're running at
- * privilege level 1, not 0 as normal. */
- paravirt_ops.name = "lguest";
- paravirt_ops.paravirt_enabled = 1;
- paravirt_ops.kernel_rpl = 1;
-
- /* We set up all the lguest overrides for sensitive operations. These
- * are detailed with the operations themselves. */
- paravirt_ops.save_fl = save_fl;
- paravirt_ops.restore_fl = restore_fl;
- paravirt_ops.irq_disable = irq_disable;
- paravirt_ops.irq_enable = irq_enable;
- paravirt_ops.load_gdt = lguest_load_gdt;
- paravirt_ops.memory_setup = lguest_memory_setup;
- paravirt_ops.cpuid = lguest_cpuid;
- paravirt_ops.write_cr3 = lguest_write_cr3;
- paravirt_ops.flush_tlb_user = lguest_flush_tlb_user;
- paravirt_ops.flush_tlb_single = lguest_flush_tlb_single;
- paravirt_ops.flush_tlb_kernel = lguest_flush_tlb_kernel;
- paravirt_ops.set_pte = lguest_set_pte;
- paravirt_ops.set_pte_at = lguest_set_pte_at;
- paravirt_ops.set_pmd = lguest_set_pmd;
-#ifdef CONFIG_X86_LOCAL_APIC
- paravirt_ops.apic_write = lguest_apic_write;
- paravirt_ops.apic_write_atomic = lguest_apic_write;
- paravirt_ops.apic_read = lguest_apic_read;
-#endif
- paravirt_ops.load_idt = lguest_load_idt;
- paravirt_ops.iret = lguest_iret;
- paravirt_ops.load_esp0 = lguest_load_esp0;
- paravirt_ops.load_tr_desc = lguest_load_tr_desc;
- paravirt_ops.set_ldt = lguest_set_ldt;
- paravirt_ops.load_tls = lguest_load_tls;
- paravirt_ops.set_debugreg = lguest_set_debugreg;
- paravirt_ops.clts = lguest_clts;
- paravirt_ops.read_cr0 = lguest_read_cr0;
- paravirt_ops.write_cr0 = lguest_write_cr0;
- paravirt_ops.init_IRQ = lguest_init_IRQ;
- paravirt_ops.read_cr2 = lguest_read_cr2;
- paravirt_ops.read_cr3 = lguest_read_cr3;
- paravirt_ops.read_cr4 = lguest_read_cr4;
- paravirt_ops.write_cr4 = lguest_write_cr4;
- paravirt_ops.write_gdt_entry = lguest_write_gdt_entry;
- paravirt_ops.write_idt_entry = lguest_write_idt_entry;
- paravirt_ops.patch = lguest_patch;
- paravirt_ops.safe_halt = lguest_safe_halt;
- paravirt_ops.get_wallclock = lguest_get_wallclock;
- paravirt_ops.time_init = lguest_time_init;
- paravirt_ops.set_lazy_mode = lguest_lazy_mode;
- paravirt_ops.wbinvd = lguest_wbinvd;
- /* Now is a good time to look at the implementations of these functions
- * before returning to the rest of lguest_init(). */
-
- /*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);
-
- /* The native boot code sets up initial page tables immediately after
- * the kernel itself, and sets init_pg_tables_end so they're not
- * clobbered. The Launcher places our initial pagetables somewhere at
- * the top of our physical memory, so we don't need extra space: set
- * init_pg_tables_end to the end of the kernel. */
- init_pg_tables_end = __pa(pg0);
-
- /* Load the %fs segment register (the per-cpu segment register) with
- * the normal data segment to get through booting. */
- asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_DS) : "memory");
-
- /* Clear the part of the kernel data which is expected to be zero.
- * Normally it will be anyway, but if we're loading from a bzImage with
- * CONFIG_RELOCATALE=y, the relocations will be sitting here. */
- memset(__bss_start, 0, __bss_stop - __bss_start);
-
- /* The Host uses the top of the Guest's virtual address space for the
- * Host<->Guest Switcher, and it tells us how much it needs in
- * lguest_data.reserve_mem, set up on the LGUEST_INIT hypercall. */
- reserve_top_address(lguest_data.reserve_mem);
-
- /* If we don't initialize the lock dependency checker now, it crashes
- * paravirt_disable_iospace. */
- lockdep_init();
-
- /* The IDE code spends about 3 seconds probing for disks: if we reserve
- * all the I/O ports up front it can't get them and so doesn't probe.
- * Other device drivers are similar (but less severe). This cuts the
- * kernel boot time on my machine from 4.1 seconds to 0.45 seconds. */
- paravirt_disable_iospace();
-
- /* This is messy CPU setup stuff which the native boot code does before
- * start_kernel, so we have to do, too: */
- cpu_detect(&new_cpu_data);
- /* head.S usually sets up the first capability word, so do it here. */
- new_cpu_data.x86_capability[0] = cpuid_edx(1);
-
- /* Math is always hard! */
- new_cpu_data.hard_math = 1;
-
-#ifdef CONFIG_X86_MCE
- mce_disabled = 1;
-#endif
-#ifdef CONFIG_ACPI
- acpi_disabled = 1;
- acpi_ht = 0;
-#endif
-
- /* We set the perferred console to "hvc". This is the "hypervisor
- * virtual console" driver written by the PowerPC people, which we also
- * adapted for lguest's use. */
- add_preferred_console("hvc", 0, NULL);
-
- /* Last of all, we set the power management poweroff hook to point to
- * the Guest routine to power off. */
- pm_power_off = lguest_power_off;
-
- /* Now we're set up, call start_kernel() in init/main.c and we proceed
- * to boot as normal. It never returns. */
- start_kernel();
-}
-/*
- * This marks the end of stage II of our journey, The Guest.
- *
- * It is now time for us to explore the nooks and crannies of the three Guest
- * devices and complete our understanding of the Guest in "make Drivers".
- */
diff --git a/drivers/lguest/lguest_asm.S b/drivers/lguest/lguest_asm.S
deleted file mode 100644
index 1ddcd5cd20f..00000000000
--- a/drivers/lguest/lguest_asm.S
+++ /dev/null
@@ -1,93 +0,0 @@
-#include <linux/linkage.h>
-#include <linux/lguest.h>
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/processor-flags.h>
-
-/*G:020 This is where we begin: we have a magic signature which the launcher
- * 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).
- *
- * 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
- movl %esi, %eax
- addl $__PAGE_OFFSET, %eax
- jmp lguest_init
-
-/*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
- * discarded after boot as we may need to patch modules, too. */
-.text
-#define LGUEST_PATCH(name, insns...) \
- lgstart_##name: insns; lgend_##name:; \
- .globl lgstart_##name; .globl lgend_##name
-
-LGUEST_PATCH(cli, movl $0, lguest_data+LGUEST_DATA_irq_enabled)
-LGUEST_PATCH(sti, movl $X86_EFLAGS_IF, lguest_data+LGUEST_DATA_irq_enabled)
-LGUEST_PATCH(popf, movl %eax, lguest_data+LGUEST_DATA_irq_enabled)
-LGUEST_PATCH(pushf, movl lguest_data+LGUEST_DATA_irq_enabled, %eax)
-/*:*/
-
-/* These demark the EIP range where host should never deliver interrupts. */
-.global lguest_noirq_start
-.global lguest_noirq_end
-
-/*M:004 When the Host reflects a trap or injects an interrupt into the Guest,
- * it sets the eflags interrupt bit on the stack based on
- * lguest_data.irq_enabled, so the Guest iret logic does the right thing when
- * restoring it. However, when the Host sets the Guest up for direct traps,
- * such as system calls, the processor is the one to push eflags onto the
- * stack, and the interrupt bit will be 1 (in reality, interrupts are always
- * enabled in the Guest).
- *
- * This turns out to be harmless: the only trap which should happen under Linux
- * with interrupts disabled is Page Fault (due to our lazy mapping of vmalloc
- * regions), which has to be reflected through the Host anyway. If another
- * trap *does* go off when interrupts are disabled, the Guest will panic, and
- * we'll never get to this iret! :*/
-
-/*G:045 There is one final paravirt_op that the Guest implements, and glancing
- * at it you can see why I left it to last. It's *cool*! It's in *assembler*!
- *
- * The "iret" instruction is used to return from an interrupt or trap. The
- * stack looks like this:
- * old address
- * old code segment & privilege level
- * old processor flags ("eflags")
- *
- * The "iret" instruction pops those values off the stack and restores them all
- * at once. The only problem is that eflags includes the Interrupt Flag which
- * the Guest can't change: the CPU will simply ignore it when we do an "iret".
- * So we have to copy eflags from the stack to lguest_data.irq_enabled before
- * we do the "iret".
- *
- * There are two problems with this: firstly, we need to use a register to do
- * the copy and secondly, the whole thing needs to be atomic. The first
- * problem is easy to solve: push %eax on the stack so we can use it, and then
- * restore it at the end just before the real "iret".
- *
- * The second is harder: copying eflags to lguest_data.irq_enabled will turn
- * interrupts on before we're finished, so we could be interrupted before we
- * return to userspace or wherever. Our solution to this is to surround the
- * code with lguest_noirq_start: and lguest_noirq_end: labels. We tell the
- * Host that it is *never* to interrupt us there, even if interrupts seem to be
- * enabled. */
-ENTRY(lguest_iret)
- pushl %eax
- movl 12(%esp), %eax
-lguest_noirq_start:
- /* Note the %ss: segment prefix here. Normal data accesses use the
- * "ds" segment, but that will have already been restored for whatever
- * we're returning to (such as userspace): we can't trust it. The %ss:
- * prefix makes sure we use the stack segment, which is still valid. */
- movl %eax,%ss:lguest_data+LGUEST_DATA_irq_enabled
- popl %eax
- iret
-lguest_noirq_end:
diff --git a/drivers/lguest/lguest_bus.c b/drivers/lguest/lguest_bus.c
deleted file mode 100644
index 9e7752cc800..00000000000
--- a/drivers/lguest/lguest_bus.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*P:050 Lguest guests use a very simple bus for devices. It's a simple array
- * of device descriptors contained just above the top of normal memory. The
- * lguest bus is 80% tedious boilerplate code. :*/
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/lguest_bus.h>
-#include <asm/io.h>
-#include <asm/paravirt.h>
-
-static ssize_t type_show(struct device *_dev,
- struct device_attribute *attr, char *buf)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- return sprintf(buf, "%hu", lguest_devices[dev->index].type);
-}
-static ssize_t features_show(struct device *_dev,
- struct device_attribute *attr, char *buf)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- return sprintf(buf, "%hx", lguest_devices[dev->index].features);
-}
-static ssize_t pfn_show(struct device *_dev,
- struct device_attribute *attr, char *buf)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- return sprintf(buf, "%u", lguest_devices[dev->index].pfn);
-}
-static ssize_t status_show(struct device *_dev,
- struct device_attribute *attr, char *buf)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- return sprintf(buf, "%hx", lguest_devices[dev->index].status);
-}
-static ssize_t status_store(struct device *_dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- if (sscanf(buf, "%hi", &lguest_devices[dev->index].status) != 1)
- return -EINVAL;
- return count;
-}
-static struct device_attribute lguest_dev_attrs[] = {
- __ATTR_RO(type),
- __ATTR_RO(features),
- __ATTR_RO(pfn),
- __ATTR(status, 0644, status_show, status_store),
- __ATTR_NULL
-};
-
-/*D:130 The generic bus infrastructure requires a function which says whether a
- * device matches a driver. For us, it is simple: "struct lguest_driver"
- * contains a "device_type" field which indicates what type of device it can
- * handle, so we just cast the args and compare: */
-static int lguest_dev_match(struct device *_dev, struct device_driver *_drv)
-{
- struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
- struct lguest_driver *drv = container_of(_drv,struct lguest_driver,drv);
-
- return (drv->device_type == lguest_devices[dev->index].type);
-}
-/*:*/
-
-struct lguest_bus {
- struct bus_type bus;
- struct device dev;
-};
-
-static struct lguest_bus lguest_bus = {
- .bus = {
- .name = "lguest",
- .match = lguest_dev_match,
- .dev_attrs = lguest_dev_attrs,
- },
- .dev = {
- .parent = NULL,
- .bus_id = "lguest",
- }
-};
-
-/*D:140 This is the callback which occurs once the bus infrastructure matches
- * up a device and driver, ie. in response to add_lguest_device() calling
- * device_register(), or register_lguest_driver() calling driver_register().
- *
- * At the moment it's always the latter: the devices are added first, since
- * scan_devices() is called from a "core_initcall", and the drivers themselves
- * called later as a normal "initcall". But it would work the other way too.
- *
- * So now we have the happy couple, we add the status bit to indicate that we
- * found a driver. If the driver truly loves the device, it will return
- * happiness from its probe function (ok, perhaps this wasn't my greatest
- * analogy), and we set the final "driver ok" bit so the Host sees it's all
- * green. */
-static int lguest_dev_probe(struct device *_dev)
-{
- int ret;
- struct lguest_device*dev = container_of(_dev,struct lguest_device,dev);
- struct lguest_driver*drv = container_of(dev->dev.driver,
- struct lguest_driver, drv);
-
- lguest_devices[dev->index].status |= LGUEST_DEVICE_S_DRIVER;
- ret = drv->probe(dev);
- if (ret == 0)
- lguest_devices[dev->index].status |= LGUEST_DEVICE_S_DRIVER_OK;
- return ret;
-}
-
-/* The last part of the bus infrastructure is the function lguest drivers use
- * to register themselves. Firstly, we do nothing if there's no lguest bus
- * (ie. this is not a Guest), otherwise we fill in the embedded generic "struct
- * driver" fields and call the generic driver_register(). */
-int register_lguest_driver(struct lguest_driver *drv)
-{
- if (!lguest_devices)
- return 0;
-
- drv->drv.bus = &lguest_bus.bus;
- drv->drv.name = drv->name;
- drv->drv.owner = drv->owner;
- drv->drv.probe = lguest_dev_probe;
-
- return driver_register(&drv->drv);
-}
-
-/* At the moment we build all the drivers into the kernel because they're so
- * simple: 8144 bytes for all three of them as I type this. And as the console
- * really needs to be built in, it's actually only 3527 bytes for the network
- * and block drivers.
- *
- * If they get complex it will make sense for them to be modularized, so we
- * need to explicitly export the symbol.
- *
- * I don't think non-GPL modules make sense, so it's a GPL-only export.
- */
-EXPORT_SYMBOL_GPL(register_lguest_driver);
-
-/*D:120 This is the core of the lguest bus: actually adding a new device.
- * It's a separate function because it's neater that way, and because an
- * earlier version of the code supported hotplug and unplug. They were removed
- * early on because they were never used.
- *
- * As Andrew Tridgell says, "Untested code is buggy code".
- *
- * It's worth reading this carefully: we start with an index into the array of
- * "struct lguest_device_desc"s indicating the device which is new: */
-static void add_lguest_device(unsigned int index)
-{
- struct lguest_device *new;
-
- /* Each "struct lguest_device_desc" has a "status" field, which the
- * Guest updates as the device is probed. In the worst case, the Host
- * can look at these bits to tell what part of device setup failed,
- * even if the console isn't available. */
- lguest_devices[index].status |= LGUEST_DEVICE_S_ACKNOWLEDGE;
- new = kmalloc(sizeof(struct lguest_device), GFP_KERNEL);
- if (!new) {
- printk(KERN_EMERG "Cannot allocate lguest device %u\n", index);
- lguest_devices[index].status |= LGUEST_DEVICE_S_FAILED;
- return;
- }
-
- /* The "struct lguest_device" setup is pretty straight-forward example
- * code. */
- new->index = index;
- new->private = NULL;
- memset(&new->dev, 0, sizeof(new->dev));
- new->dev.parent = &lguest_bus.dev;
- new->dev.bus = &lguest_bus.bus;
- sprintf(new->dev.bus_id, "%u", index);
-
- /* device_register() causes the bus infrastructure to look for a
- * matching driver. */
- if (device_register(&new->dev) != 0) {
- printk(KERN_EMERG "Cannot register lguest device %u\n", index);
- lguest_devices[index].status |= LGUEST_DEVICE_S_FAILED;
- kfree(new);
- }
-}
-
-/*D:110 scan_devices() simply iterates through the device array. The type 0
- * is reserved to mean "no device", and anything else means we have found a
- * device: add it. */
-static void scan_devices(void)
-{
- unsigned int i;
-
- for (i = 0; i < LGUEST_MAX_DEVICES; i++)
- if (lguest_devices[i].type)
- add_lguest_device(i);
-}
-
-/*D:100 Fairly early in boot, lguest_bus_init() is called to set up the lguest
- * bus. We check that we are a Guest by checking paravirt_ops.name: there are
- * other ways of checking, but this seems most obvious to me.
- *
- * So we can access the array of "struct lguest_device_desc"s easily, we map
- * that memory and store the pointer in the global "lguest_devices". Then we
- * register the bus with the core. Doing two registrations seems clunky to me,
- * but it seems to be the correct sysfs incantation.
- *
- * Finally we call scan_devices() which adds all the devices found in the
- * "struct lguest_device_desc" array. */
-static int __init lguest_bus_init(void)
-{
- if (strcmp(paravirt_ops.name, "lguest") != 0)
- return 0;
-
- /* Devices are in a single page above top of "normal" mem */
- lguest_devices = lguest_map(max_pfn<<PAGE_SHIFT, 1);
-
- if (bus_register(&lguest_bus.bus) != 0
- || device_register(&lguest_bus.dev) != 0)
- panic("lguest bus registration failed");
-
- scan_devices();
- return 0;
-}
-/* Do this after core stuff, before devices. */
-postcore_initcall(lguest_bus_init);
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
new file mode 100644
index 00000000000..d0a1d8a45c8
--- /dev/null
+++ b/drivers/lguest/lguest_device.c
@@ -0,0 +1,535 @@
+/*P:050
+ * Lguest guests use a very simple method to describe devices. It's a
+ * series of device descriptors contained just above the top of normal Guest
+ * memory.
+ *
+ * We use the standard "virtio" device infrastructure, which provides us with a
+ * console, a network and a block driver. Each one expects some configuration
+ * information and a "virtqueue" or two to send and receive data.
+:*/
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/lguest_launcher.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/interrupt.h>
+#include <linux/virtio_ring.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+#include <asm/paravirt.h>
+#include <asm/lguest_hcall.h>
+
+/* The pointer to our (page) of device descriptions. */
+static void *lguest_devices;
+
+/*
+ * For Guests, device memory can be used as normal memory, so we cast away the
+ * __iomem to quieten sparse.
+ */
+static inline void *lguest_map(unsigned long phys_addr, unsigned long pages)
+{
+ return (__force void *)ioremap_cache(phys_addr, PAGE_SIZE*pages);
+}
+
+static inline void lguest_unmap(void *addr)
+{
+ iounmap((__force void __iomem *)addr);
+}
+
+/*D:100
+ * Each lguest device is just a virtio device plus a pointer to its entry
+ * in the lguest_devices page.
+ */
+struct lguest_device {
+ struct virtio_device vdev;
+
+ /* The entry in the lguest_devices page for this device. */
+ struct lguest_device_desc *desc;
+};
+
+/*
+ * Since the virtio infrastructure hands us a pointer to the virtio_device all
+ * the time, it helps to have a curt macro to get a pointer to the struct
+ * lguest_device it's enclosed in.
+ */
+#define to_lgdev(vd) container_of(vd, struct lguest_device, vdev)
+
+/*D:130
+ * Device configurations
+ *
+ * The configuration information for a device consists of one or more
+ * virtqueues, a feature bitmap, and some configuration bytes. The
+ * configuration bytes don't really matter to us: the Launcher sets them up, and
+ * the driver will look at them during setup.
+ *
+ * A convenient routine to return the device's virtqueue config array:
+ * immediately after the descriptor.
+ */
+static struct lguest_vqconfig *lg_vq(const struct lguest_device_desc *desc)
+{
+ return (void *)(desc + 1);
+}
+
+/* The features come immediately after the virtqueues. */
+static u8 *lg_features(const struct lguest_device_desc *desc)
+{
+ return (void *)(lg_vq(desc) + desc->num_vq);
+}
+
+/* The config space comes after the two feature bitmasks. */
+static u8 *lg_config(const struct lguest_device_desc *desc)
+{
+ return lg_features(desc) + desc->feature_len * 2;
+}
+
+/* The total size of the config page used by this device (incl. desc) */
+static unsigned desc_size(const struct lguest_device_desc *desc)
+{
+ return sizeof(*desc)
+ + desc->num_vq * sizeof(struct lguest_vqconfig)
+ + desc->feature_len * 2
+ + desc->config_len;
+}
+
+/* This gets the device's feature bits. */
+static u32 lg_get_features(struct virtio_device *vdev)
+{
+ unsigned int i;
+ u32 features = 0;
+ struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
+ u8 *in_features = lg_features(desc);
+
+ /* We do this the slow but generic way. */
+ for (i = 0; i < min(desc->feature_len * 8, 32); i++)
+ if (in_features[i / 8] & (1 << (i % 8)))
+ features |= (1 << i);
+
+ return features;
+}
+
+/*
+ * To notify on reset or feature finalization, we (ab)use the NOTIFY
+ * hypercall, with the descriptor address of the device.
+ */
+static void status_notify(struct virtio_device *vdev)
+{
+ unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
+
+ hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0);
+}
+
+/*
+ * The virtio core takes the features the Host offers, and copies the ones
+ * supported by the driver into the vdev->features array. Once that's all
+ * sorted out, this routine is called so we can tell the Host which features we
+ * understand and accept.
+ */
+static void lg_finalize_features(struct virtio_device *vdev)
+{
+ unsigned int i, bits;
+ struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
+ /* Second half of bitmap is features we accept. */
+ u8 *out_features = lg_features(desc) + desc->feature_len;
+
+ /* Give virtio_ring a chance to accept features. */
+ vring_transport_features(vdev);
+
+ /*
+ * The vdev->feature array is a Linux bitmask: this isn't the same as a
+ * the simple array of bits used by lguest devices for features. So we
+ * do this slow, manual conversion which is completely general.
+ */
+ memset(out_features, 0, desc->feature_len);
+ bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8;
+ for (i = 0; i < bits; i++) {
+ if (test_bit(i, vdev->features))
+ out_features[i / 8] |= (1 << (i % 8));
+ }
+
+ /* Tell Host we've finished with this device's feature negotiation */
+ status_notify(vdev);
+}
+
+/* Once they've found a field, getting a copy of it is easy. */
+static void lg_get(struct virtio_device *vdev, unsigned int offset,
+ void *buf, unsigned len)
+{
+ struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
+
+ /* Check they didn't ask for more than the length of the config! */
+ BUG_ON(offset + len > desc->config_len);
+ memcpy(buf, lg_config(desc) + offset, len);
+}
+
+/* Setting the contents is also trivial. */
+static void lg_set(struct virtio_device *vdev, unsigned int offset,
+ const void *buf, unsigned len)
+{
+ struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
+
+ /* Check they didn't ask for more than the length of the config! */
+ BUG_ON(offset + len > desc->config_len);
+ memcpy(lg_config(desc) + offset, buf, len);
+}
+
+/*
+ * The operations to get and set the status word just access the status field
+ * of the device descriptor.
+ */
+static u8 lg_get_status(struct virtio_device *vdev)
+{
+ return to_lgdev(vdev)->desc->status;
+}
+
+static void lg_set_status(struct virtio_device *vdev, u8 status)
+{
+ BUG_ON(!status);
+ to_lgdev(vdev)->desc->status = status;
+
+ /* Tell Host immediately if we failed. */
+ if (status & VIRTIO_CONFIG_S_FAILED)
+ status_notify(vdev);
+}
+
+static void lg_reset(struct virtio_device *vdev)
+{
+ /* 0 status means "reset" */
+ to_lgdev(vdev)->desc->status = 0;
+ status_notify(vdev);
+}
+
+/*
+ * Virtqueues
+ *
+ * The other piece of infrastructure virtio needs is a "virtqueue": a way of
+ * the Guest device registering buffers for the other side to read from or
+ * write into (ie. send and receive buffers). Each device can have multiple
+ * virtqueues: for example the console driver uses one queue for sending and
+ * another for receiving.
+ *
+ * Fortunately for us, a very fast shared-memory-plus-descriptors virtqueue
+ * already exists in virtio_ring.c. We just need to connect it up.
+ *
+ * We start with the information we need to keep about each virtqueue.
+ */
+
+/*D:140 This is the information we remember about each virtqueue. */
+struct lguest_vq_info {
+ /* A copy of the information contained in the device config. */
+ struct lguest_vqconfig config;
+
+ /* The address where we mapped the virtio ring, so we can unmap it. */
+ void *pages;
+};
+
+/*
+ * When the virtio_ring code wants to prod the Host, it calls us here and we
+ * make a hypercall. We hand the physical address of the virtqueue so the Host
+ * knows which virtqueue we're talking about.
+ */
+static bool lg_notify(struct virtqueue *vq)
+{
+ /*
+ * We store our virtqueue information in the "priv" pointer of the
+ * virtqueue structure.
+ */
+ struct lguest_vq_info *lvq = vq->priv;
+
+ hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0);
+ return true;
+}
+
+/* An extern declaration inside a C file is bad form. Don't do it. */
+extern int lguest_setup_irq(unsigned int irq);
+
+/*
+ * This routine finds the Nth virtqueue described in the configuration of
+ * this device and sets it up.
+ *
+ * This is kind of an ugly duckling. It'd be nicer to have a standard
+ * representation of a virtqueue in the configuration space, but it seems that
+ * everyone wants to do it differently. The KVM coders want the Guest to
+ * allocate its own pages and tell the Host where they are, but for lguest it's
+ * simpler for the Host to simply tell us where the pages are.
+ */
+static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
+ unsigned index,
+ void (*callback)(struct virtqueue *vq),
+ const char *name)
+{
+ struct lguest_device *ldev = to_lgdev(vdev);
+ struct lguest_vq_info *lvq;
+ struct virtqueue *vq;
+ int err;
+
+ if (!name)
+ return NULL;
+
+ /* We must have this many virtqueues. */
+ if (index >= ldev->desc->num_vq)
+ return ERR_PTR(-ENOENT);
+
+ lvq = kmalloc(sizeof(*lvq), GFP_KERNEL);
+ if (!lvq)
+ return ERR_PTR(-ENOMEM);
+
+ /*
+ * Make a copy of the "struct lguest_vqconfig" entry, which sits after
+ * the descriptor. We need a copy because the config space might not
+ * be aligned correctly.
+ */
+ memcpy(&lvq->config, lg_vq(ldev->desc)+index, sizeof(lvq->config));
+
+ printk("Mapping virtqueue %i addr %lx\n", index,
+ (unsigned long)lvq->config.pfn << PAGE_SHIFT);
+ /* Figure out how many pages the ring will take, and map that memory */
+ lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT,
+ DIV_ROUND_UP(vring_size(lvq->config.num,
+ LGUEST_VRING_ALIGN),
+ PAGE_SIZE));
+ if (!lvq->pages) {
+ err = -ENOMEM;
+ goto free_lvq;
+ }
+
+ /*
+ * OK, tell virtio_ring.c to set up a virtqueue now we know its size
+ * and we've got a pointer to its pages. Note that we set weak_barriers
+ * to 'true': the host just a(nother) SMP CPU, so we only need inter-cpu
+ * barriers.
+ */
+ vq = vring_new_virtqueue(index, lvq->config.num, LGUEST_VRING_ALIGN, vdev,
+ true, lvq->pages, lg_notify, callback, name);
+ if (!vq) {
+ err = -ENOMEM;
+ goto unmap;
+ }
+
+ /* Make sure the interrupt is allocated. */
+ err = lguest_setup_irq(lvq->config.irq);
+ if (err)
+ goto destroy_vring;
+
+ /*
+ * Tell the interrupt for this virtqueue to go to the virtio_ring
+ * interrupt handler.
+ *
+ * FIXME: We used to have a flag for the Host to tell us we could use
+ * the interrupt as a source of randomness: it'd be nice to have that
+ * back.
+ */
+ err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED,
+ dev_name(&vdev->dev), vq);
+ if (err)
+ goto free_desc;
+
+ /*
+ * Last of all we hook up our 'struct lguest_vq_info" to the
+ * virtqueue's priv pointer.
+ */
+ vq->priv = lvq;
+ return vq;
+
+free_desc:
+ irq_free_desc(lvq->config.irq);
+destroy_vring:
+ vring_del_virtqueue(vq);
+unmap:
+ lguest_unmap(lvq->pages);
+free_lvq:
+ kfree(lvq);
+ return ERR_PTR(err);
+}
+/*:*/
+
+/* Cleaning up a virtqueue is easy */
+static void lg_del_vq(struct virtqueue *vq)
+{
+ struct lguest_vq_info *lvq = vq->priv;
+
+ /* Release the interrupt */
+ free_irq(lvq->config.irq, vq);
+ /* Tell virtio_ring.c to free the virtqueue. */
+ vring_del_virtqueue(vq);
+ /* Unmap the pages containing the ring. */
+ lguest_unmap(lvq->pages);
+ /* Free our own queue information. */
+ kfree(lvq);
+}
+
+static void lg_del_vqs(struct virtio_device *vdev)
+{
+ struct virtqueue *vq, *n;
+
+ list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+ lg_del_vq(vq);
+}
+
+static int lg_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+ struct virtqueue *vqs[],
+ vq_callback_t *callbacks[],
+ const char *names[])
+{
+ struct lguest_device *ldev = to_lgdev(vdev);
+ int i;
+
+ /* We must have this many virtqueues. */
+ if (nvqs > ldev->desc->num_vq)
+ return -ENOENT;
+
+ for (i = 0; i < nvqs; ++i) {
+ vqs[i] = lg_find_vq(vdev, i, callbacks[i], names[i]);
+ if (IS_ERR(vqs[i]))
+ goto error;
+ }
+ return 0;
+
+error:
+ lg_del_vqs(vdev);
+ return PTR_ERR(vqs[i]);
+}
+
+static const char *lg_bus_name(struct virtio_device *vdev)
+{
+ return "";
+}
+
+/* The ops structure which hooks everything together. */
+static const struct virtio_config_ops lguest_config_ops = {
+ .get_features = lg_get_features,
+ .finalize_features = lg_finalize_features,
+ .get = lg_get,
+ .set = lg_set,
+ .get_status = lg_get_status,
+ .set_status = lg_set_status,
+ .reset = lg_reset,
+ .find_vqs = lg_find_vqs,
+ .del_vqs = lg_del_vqs,
+ .bus_name = lg_bus_name,
+};
+
+/*
+ * The root device for the lguest virtio devices. This makes them appear as
+ * /sys/devices/lguest/0,1,2 not /sys/devices/0,1,2.
+ */
+static struct device *lguest_root;
+
+/*D:120
+ * This is the core of the lguest bus: actually adding a new device.
+ * It's a separate function because it's neater that way, and because an
+ * earlier version of the code supported hotplug and unplug. They were removed
+ * early on because they were never used.
+ *
+ * As Andrew Tridgell says, "Untested code is buggy code".
+ *
+ * It's worth reading this carefully: we start with a pointer to the new device
+ * descriptor in the "lguest_devices" page, and the offset into the device
+ * descriptor page so we can uniquely identify it if things go badly wrong.
+ */
+static void add_lguest_device(struct lguest_device_desc *d,
+ unsigned int offset)
+{
+ struct lguest_device *ldev;
+
+ /* Start with zeroed memory; Linux's device layer counts on it. */
+ ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
+ if (!ldev) {
+ printk(KERN_EMERG "Cannot allocate lguest dev %u type %u\n",
+ offset, d->type);
+ return;
+ }
+
+ /* This devices' parent is the lguest/ dir. */
+ ldev->vdev.dev.parent = lguest_root;
+ /*
+ * The device type comes straight from the descriptor. There's also a
+ * device vendor field in the virtio_device struct, which we leave as
+ * 0.
+ */
+ ldev->vdev.id.device = d->type;
+ /*
+ * We have a simple set of routines for querying the device's
+ * configuration information and setting its status.
+ */
+ ldev->vdev.config = &lguest_config_ops;
+ /* And we remember the device's descriptor for lguest_config_ops. */
+ ldev->desc = d;
+
+ /*
+ * register_virtio_device() sets up the generic fields for the struct
+ * virtio_device and calls device_register(). This makes the bus
+ * infrastructure look for a matching driver.
+ */
+ if (register_virtio_device(&ldev->vdev) != 0) {
+ printk(KERN_ERR "Failed to register lguest dev %u type %u\n",
+ offset, d->type);
+ kfree(ldev);
+ }
+}
+
+/*D:110
+ * scan_devices() simply iterates through the device page. The type 0 is
+ * reserved to mean "end of devices".
+ */
+static void scan_devices(void)
+{
+ unsigned int i;
+ struct lguest_device_desc *d;
+
+ /* We start at the page beginning, and skip over each entry. */
+ for (i = 0; i < PAGE_SIZE; i += desc_size(d)) {
+ d = lguest_devices + i;
+
+ /* Once we hit a zero, stop. */
+ if (d->type == 0)
+ break;
+
+ printk("Device at %i has size %u\n", i, desc_size(d));
+ add_lguest_device(d, i);
+ }
+}
+
+/*D:105
+ * Fairly early in boot, lguest_devices_init() is called to set up the
+ * lguest device infrastructure. We check that we are a Guest by checking
+ * pv_info.name: there are other ways of checking, but this seems most
+ * obvious to me.
+ *
+ * So we can access the "struct lguest_device_desc"s easily, we map that memory
+ * and store the pointer in the global "lguest_devices". Then we register a
+ * root device from which all our devices will hang (this seems to be the
+ * correct sysfs incantation).
+ *
+ * Finally we call scan_devices() which adds all the devices found in the
+ * lguest_devices page.
+ */
+static int __init lguest_devices_init(void)
+{
+ if (strcmp(pv_info.name, "lguest") != 0)
+ return 0;
+
+ lguest_root = root_device_register("lguest");
+ if (IS_ERR(lguest_root))
+ panic("Could not register lguest root");
+
+ /* Devices are in a single page above top of "normal" mem */
+ lguest_devices = lguest_map(max_pfn<<PAGE_SHIFT, 1);
+
+ scan_devices();
+ return 0;
+}
+/* We do this after core stuff, but before the drivers. */
+postcore_initcall(lguest_devices_init);
+
+/*D:150
+ * At this point in the journey we used to now wade through the lguest
+ * devices themselves: net, block and console. Since they're all now virtio
+ * devices rather than lguest-specific, I've decided to ignore them. Mostly,
+ * they're kind of boring. But this does mean you'll never experience the
+ * thrill of reading the forbidden love scene buried deep in the block driver.
+ *
+ * "make Launcher" beckons, where we answer questions like "Where do Guests
+ * come from?", and "What do you do when someone asks for optimization?".
+ */
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 80d1b58c769..4263f4cc8c5 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -1,124 +1,224 @@
-/*P:200 This contains all the /dev/lguest code, whereby the userspace launcher
- * controls and communicates with the Guest. For example, the first write will
- * tell us the memory size, pagetable, entry point and kernel address offset.
- * A read will run the Guest until a signal is pending (-EINTR), or the Guest
- * does a DMA out to the Launcher. Writes are also used to get a DMA buffer
- * registered by the Guest and to send the Guest an interrupt. :*/
+/*P:200 This contains all the /dev/lguest code, whereby the userspace
+ * launcher controls and communicates with the Guest. For example,
+ * the first write will tell us the Guest's memory layout and entry
+ * point. A read will run the Guest until something happens, such as
+ * a signal or the Guest doing a NOTIFY out to the Launcher. There is
+ * also a way for the Launcher to attach eventfds to particular NOTIFY
+ * values instead of returning from the read() call.
+:*/
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/eventfd.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/export.h>
#include "lg.h"
-/*L:030 setup_regs() doesn't really belong in this file, but it gives us an
- * early glimpse deeper into the Host so it's worth having here.
+/*L:056
+ * Before we move on, let's jump ahead and look at what the kernel does when
+ * it needs to look up the eventfds. That will complete our picture of how we
+ * use RCU.
*
- * Most of the Guest's registers are left alone: we used get_zeroed_page() to
- * allocate the structure, so they will be 0. */
-static void setup_regs(struct lguest_regs *regs, unsigned long start)
+ * The notification value is in cpu->pending_notify: we return true if it went
+ * to an eventfd.
+ */
+bool send_notify_to_eventfd(struct lg_cpu *cpu)
{
- /* There are four "segment" registers which the Guest needs to boot:
- * The "code segment" register (cs) refers to the kernel code segment
- * __KERNEL_CS, and the "data", "extra" and "stack" segment registers
- * refer to the kernel data segment __KERNEL_DS.
+ unsigned int i;
+ struct lg_eventfd_map *map;
+
+ /*
+ * This "rcu_read_lock()" helps track when someone is still looking at
+ * the (RCU-using) eventfds array. It's not actually a lock at all;
+ * indeed it's a noop in many configurations. (You didn't expect me to
+ * explain all the RCU secrets here, did you?)
+ */
+ rcu_read_lock();
+ /*
+ * rcu_dereference is the counter-side of rcu_assign_pointer(); it
+ * makes sure we don't access the memory pointed to by
+ * cpu->lg->eventfds before cpu->lg->eventfds is set. Sounds crazy,
+ * but Alpha allows this! Paul McKenney points out that a really
+ * aggressive compiler could have the same effect:
+ * http://lists.ozlabs.org/pipermail/lguest/2009-July/001560.html
*
- * The privilege level is packed into the lower bits. The Guest runs
- * at privilege level 1 (GUEST_PL).*/
- regs->ds = regs->es = regs->ss = __KERNEL_DS|GUEST_PL;
- regs->cs = __KERNEL_CS|GUEST_PL;
-
- /* The "eflags" register contains miscellaneous flags. Bit 1 (0x002)
- * is supposed to always be "1". Bit 9 (0x200) controls whether
- * interrupts are enabled. We always leave interrupts enabled while
- * running the Guest. */
- regs->eflags = 0x202;
-
- /* The "Extended Instruction Pointer" register says where the Guest is
- * running. */
- regs->eip = start;
-
- /* %esi points to our boot information, at physical address 0, so don't
- * touch it. */
+ * So play safe, use rcu_dereference to get the rcu-protected pointer:
+ */
+ map = rcu_dereference(cpu->lg->eventfds);
+ /*
+ * Simple array search: even if they add an eventfd while we do this,
+ * we'll continue to use the old array and just won't see the new one.
+ */
+ for (i = 0; i < map->num; i++) {
+ if (map->map[i].addr == cpu->pending_notify) {
+ eventfd_signal(map->map[i].event, 1);
+ cpu->pending_notify = 0;
+ break;
+ }
+ }
+ /* We're done with the rcu-protected variable cpu->lg->eventfds. */
+ rcu_read_unlock();
+
+ /* If we cleared the notification, it's because we found a match. */
+ return cpu->pending_notify == 0;
}
-/*L:310 To send DMA into the Guest, the Launcher needs to be able to ask for a
- * DMA buffer. This is done by writing LHREQ_GETDMA and the key to
- * /dev/lguest. */
-static long user_get_dma(struct lguest *lg, const u32 __user *input)
+/*L:055
+ * One of the more tricksy tricks in the Linux Kernel is a technique called
+ * Read Copy Update. Since one point of lguest is to teach lguest journeyers
+ * about kernel coding, I use it here. (In case you're curious, other purposes
+ * include learning about virtualization and instilling a deep appreciation for
+ * simplicity and puppies).
+ *
+ * We keep a simple array which maps LHCALL_NOTIFY values to eventfds, but we
+ * add new eventfds without ever blocking readers from accessing the array.
+ * The current Launcher only does this during boot, so that never happens. But
+ * Read Copy Update is cool, and adding a lock risks damaging even more puppies
+ * than this code does.
+ *
+ * We allocate a brand new one-larger array, copy the old one and add our new
+ * element. Then we make the lg eventfd pointer point to the new array.
+ * That's the easy part: now we need to free the old one, but we need to make
+ * sure no slow CPU somewhere is still looking at it. That's what
+ * synchronize_rcu does for us: waits until every CPU has indicated that it has
+ * moved on to know it's no longer using the old one.
+ *
+ * If that's unclear, see http://en.wikipedia.org/wiki/Read-copy-update.
+ */
+static int add_eventfd(struct lguest *lg, unsigned long addr, int fd)
{
- unsigned long key, udma, irq;
+ struct lg_eventfd_map *new, *old = lg->eventfds;
- /* Fetch the key they wrote to us. */
- if (get_user(key, input) != 0)
- return -EFAULT;
- /* Look for a free Guest DMA buffer bound to that key. */
- udma = get_dma_buffer(lg, key, &irq);
- if (!udma)
- return -ENOENT;
-
- /* We need to tell the Launcher what interrupt the Guest expects after
- * the buffer is filled. We stash it in udma->used_len. */
- lgwrite_u32(lg, udma + offsetof(struct lguest_dma, used_len), irq);
-
- /* The (guest-physical) address of the DMA buffer is returned from
- * the write(). */
- return udma;
+ /*
+ * We don't allow notifications on value 0 anyway (pending_notify of
+ * 0 means "nothing pending").
+ */
+ if (!addr)
+ return -EINVAL;
+
+ /*
+ * Replace the old array with the new one, carefully: others can
+ * be accessing it at the same time.
+ */
+ new = kmalloc(sizeof(*new) + sizeof(new->map[0]) * (old->num + 1),
+ GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+
+ /* First make identical copy. */
+ memcpy(new->map, old->map, sizeof(old->map[0]) * old->num);
+ new->num = old->num;
+
+ /* Now append new entry. */
+ new->map[new->num].addr = addr;
+ new->map[new->num].event = eventfd_ctx_fdget(fd);
+ if (IS_ERR(new->map[new->num].event)) {
+ int err = PTR_ERR(new->map[new->num].event);
+ kfree(new);
+ return err;
+ }
+ new->num++;
+
+ /*
+ * Now put new one in place: rcu_assign_pointer() is a fancy way of
+ * doing "lg->eventfds = new", but it uses memory barriers to make
+ * absolutely sure that the contents of "new" written above is nailed
+ * down before we actually do the assignment.
+ *
+ * We have to think about these kinds of things when we're operating on
+ * live data without locks.
+ */
+ rcu_assign_pointer(lg->eventfds, new);
+
+ /*
+ * We're not in a big hurry. Wait until no one's looking at old
+ * version, then free it.
+ */
+ synchronize_rcu();
+ kfree(old);
+
+ return 0;
}
-/*L:315 To force the Guest to stop running and return to the Launcher, the
- * Waker sets writes LHREQ_BREAK and the value "1" to /dev/lguest. The
- * Launcher then writes LHREQ_BREAK and "0" to release the Waker. */
-static int break_guest_out(struct lguest *lg, const u32 __user *input)
+/*L:052
+ * Receiving notifications from the Guest is usually done by attaching a
+ * particular LHCALL_NOTIFY value to an event filedescriptor. The eventfd will
+ * become readable when the Guest does an LHCALL_NOTIFY with that value.
+ *
+ * This is really convenient for processing each virtqueue in a separate
+ * thread.
+ */
+static int attach_eventfd(struct lguest *lg, const unsigned long __user *input)
{
- unsigned long on;
+ unsigned long addr, fd;
+ int err;
- /* Fetch whether they're turning break on or off.. */
- if (get_user(on, input) != 0)
+ if (get_user(addr, input) != 0)
+ return -EFAULT;
+ input++;
+ if (get_user(fd, input) != 0)
return -EFAULT;
- if (on) {
- lg->break_out = 1;
- /* Pop it out (may be running on different CPU) */
- wake_up_process(lg->tsk);
- /* Wait for them to reset it */
- return wait_event_interruptible(lg->break_wq, !lg->break_out);
- } else {
- lg->break_out = 0;
- wake_up(&lg->break_wq);
- return 0;
- }
+ /*
+ * Just make sure two callers don't add eventfds at once. We really
+ * only need to lock against callers adding to the same Guest, so using
+ * the Big Lguest Lock is overkill. But this is setup, not a fast path.
+ */
+ mutex_lock(&lguest_lock);
+ err = add_eventfd(lg, addr, fd);
+ mutex_unlock(&lguest_lock);
+
+ return err;
}
-/*L:050 Sending an interrupt is done by writing LHREQ_IRQ and an interrupt
- * number to /dev/lguest. */
-static int user_send_irq(struct lguest *lg, const u32 __user *input)
+/*L:050
+ * Sending an interrupt is done by writing LHREQ_IRQ and an interrupt
+ * number to /dev/lguest.
+ */
+static int user_send_irq(struct lg_cpu *cpu, const unsigned long __user *input)
{
- u32 irq;
+ unsigned long irq;
if (get_user(irq, input) != 0)
return -EFAULT;
if (irq >= LGUEST_IRQS)
return -EINVAL;
- /* Next time the Guest runs, the core code will see if it can deliver
- * this interrupt. */
- set_bit(irq, lg->irqs_pending);
+
+ /*
+ * Next time the Guest runs, the core code will see if it can deliver
+ * this interrupt.
+ */
+ set_interrupt(cpu, irq);
return 0;
}
-/*L:040 Once our Guest is initialized, the Launcher makes it run by reading
- * from /dev/lguest. */
+/*L:040
+ * Once our Guest is initialized, the Launcher makes it run by reading
+ * from /dev/lguest.
+ */
static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
{
struct lguest *lg = file->private_data;
+ struct lg_cpu *cpu;
+ unsigned int cpu_id = *o;
/* You must write LHREQ_INITIALIZE first! */
if (!lg)
return -EINVAL;
- /* If you're not the task which owns the guest, go away. */
- if (current != lg->tsk)
+ /* Watch out for arbitrary vcpu indexes! */
+ if (cpu_id >= lg->nr_cpus)
+ return -EINVAL;
+
+ cpu = &lg->cpus[cpu_id];
+
+ /* If you're not the task which owns the Guest, go away. */
+ if (current != cpu->tsk)
return -EPERM;
- /* If the guest is already dead, we indicate why */
+ /* If the Guest is already dead, we indicate why */
if (lg->dead) {
size_t len;
@@ -133,43 +233,98 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
return len;
}
- /* If we returned from read() last time because the Guest sent DMA,
- * clear the flag. */
- if (lg->dma_is_pending)
- lg->dma_is_pending = 0;
+ /*
+ * If we returned from read() last time because the Guest sent I/O,
+ * clear the flag.
+ */
+ if (cpu->pending_notify)
+ cpu->pending_notify = 0;
/* Run the Guest until something interesting happens. */
- return run_guest(lg, (unsigned long __user *)user);
+ return run_guest(cpu, (unsigned long __user *)user);
+}
+
+/*L:025
+ * This actually initializes a CPU. For the moment, a Guest is only
+ * uniprocessor, so "id" is always 0.
+ */
+static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
+{
+ /* We have a limited number of CPUs in the lguest struct. */
+ if (id >= ARRAY_SIZE(cpu->lg->cpus))
+ return -EINVAL;
+
+ /* Set up this CPU's id, and pointer back to the lguest struct. */
+ cpu->id = id;
+ cpu->lg = container_of(cpu, struct lguest, cpus[id]);
+ cpu->lg->nr_cpus++;
+
+ /* Each CPU has a timer it can set. */
+ init_clockdev(cpu);
+
+ /*
+ * We need a complete page for the Guest registers: they are accessible
+ * to the Guest and we can only grant it access to whole pages.
+ */
+ cpu->regs_page = get_zeroed_page(GFP_KERNEL);
+ if (!cpu->regs_page)
+ return -ENOMEM;
+
+ /* We actually put the registers at the end of the page. */
+ cpu->regs = (void *)cpu->regs_page + PAGE_SIZE - sizeof(*cpu->regs);
+
+ /*
+ * Now we initialize the Guest's registers, handing it the start
+ * address.
+ */
+ lguest_arch_setup_regs(cpu, start_ip);
+
+ /*
+ * We keep a pointer to the Launcher task (ie. current task) for when
+ * other Guests want to wake this one (eg. console input).
+ */
+ cpu->tsk = current;
+
+ /*
+ * We need to keep a pointer to the Launcher's memory map, because if
+ * the Launcher dies we need to clean it up. If we don't keep a
+ * reference, it is destroyed before close() is called.
+ */
+ cpu->mm = get_task_mm(cpu->tsk);
+
+ /*
+ * We remember which CPU's pages this Guest used last, for optimization
+ * when the same Guest runs on the same CPU twice.
+ */
+ cpu->last_pages = NULL;
+
+ /* No error == success. */
+ return 0;
}
-/*L:020 The initialization write supplies 4 32-bit values (in addition to the
- * 32-bit LHREQ_INITIALIZE value). These are:
+/*L:020
+ * The initialization write supplies 3 pointer sized (32 or 64 bit) values (in
+ * addition to the LHREQ_INITIALIZE value). These are:
*
- * pfnlimit: The highest (Guest-physical) page number the Guest should be
- * allowed to access. The Launcher has to live in Guest memory, so it sets
- * this to ensure the Guest can't reach it.
+ * base: The start of the Guest-physical memory inside the Launcher memory.
*
- * pgdir: The (Guest-physical) address of the top of the initial Guest
- * pagetables (which are set up by the Launcher).
+ * pfnlimit: The highest (Guest-physical) page number the Guest should be
+ * allowed to access. The Guest memory lives inside the Launcher, so it sets
+ * this to ensure the Guest can only reach its own memory.
*
* start: The first instruction to execute ("eip" in x86-speak).
- *
- * page_offset: The PAGE_OFFSET constant in the Guest kernel. We should
- * probably wean the code off this, but it's a very useful constant! Any
- * address above this is within the Guest kernel, and any kernel address can
- * quickly converted from physical to virtual by adding PAGE_OFFSET. It's
- * 0xC0000000 (3G) by default, but it's configurable at kernel build time.
*/
-static int initialize(struct file *file, const u32 __user *input)
+static int initialize(struct file *file, const unsigned long __user *input)
{
- /* "struct lguest" contains everything we (the Host) know about a
- * Guest. */
+ /* "struct lguest" contains all we (the Host) know about a Guest. */
struct lguest *lg;
- int err, i;
- u32 args[4];
+ int err;
+ unsigned long args[3];
- /* We grab the Big Lguest lock, which protects the global array
- * "lguests" and multiple simultaneous initializations. */
+ /*
+ * We grab the Big Lguest lock, which protects against multiple
+ * simultaneous initializations.
+ */
mutex_lock(&lguest_lock);
/* You can't initialize twice! Close the device and start again... */
if (file->private_data) {
@@ -182,63 +337,35 @@ static int initialize(struct file *file, const u32 __user *input)
goto unlock;
}
- /* Find an unused guest. */
- i = find_free_guest();
- if (i < 0) {
- err = -ENOSPC;
+ lg = kzalloc(sizeof(*lg), GFP_KERNEL);
+ if (!lg) {
+ err = -ENOMEM;
goto unlock;
}
- /* OK, we have an index into the "lguest" array: "lg" is a convenient
- * pointer. */
- lg = &lguests[i];
- /* Populate the easy fields of our "struct lguest" */
- lg->guestid = i;
- lg->pfn_limit = args[0];
- lg->page_offset = args[3];
-
- /* We need a complete page for the Guest registers: they are accessible
- * to the Guest and we can only grant it access to whole pages. */
- lg->regs_page = get_zeroed_page(GFP_KERNEL);
- if (!lg->regs_page) {
+ lg->eventfds = kmalloc(sizeof(*lg->eventfds), GFP_KERNEL);
+ if (!lg->eventfds) {
err = -ENOMEM;
- goto release_guest;
+ goto free_lg;
}
- /* We actually put the registers at the bottom of the page. */
- lg->regs = (void *)lg->regs_page + PAGE_SIZE - sizeof(*lg->regs);
-
- /* Initialize the Guest's shadow page tables, using the toplevel
- * address the Launcher gave us. This allocates memory, so can
- * fail. */
- err = init_guest_pagetable(lg, args[1]);
- if (err)
- goto free_regs;
-
- /* Now we initialize the Guest's registers, handing it the start
- * address. */
- setup_regs(lg->regs, args[2]);
+ lg->eventfds->num = 0;
- /* There are a couple of GDT entries the Guest expects when first
- * booting. */
- setup_guest_gdt(lg);
-
- /* The timer for lguest's clock needs initialization. */
- init_clockdev(lg);
-
- /* We keep a pointer to the Launcher task (ie. current task) for when
- * other Guests want to wake this one (inter-Guest I/O). */
- lg->tsk = current;
- /* We need to keep a pointer to the Launcher's memory map, because if
- * the Launcher dies we need to clean it up. If we don't keep a
- * reference, it is destroyed before close() is called. */
- lg->mm = get_task_mm(lg->tsk);
+ /* Populate the easy fields of our "struct lguest" */
+ lg->mem_base = (void __user *)args[0];
+ lg->pfn_limit = args[1];
- /* Initialize the queue for the waker to wait on */
- init_waitqueue_head(&lg->break_wq);
+ /* This is the first cpu (cpu 0) and it will start booting at args[2] */
+ err = lg_cpu_start(&lg->cpus[0], 0, args[2]);
+ if (err)
+ goto free_eventfds;
- /* We remember which CPU's pages this Guest used last, for optimization
- * when the same Guest runs on the same CPU twice. */
- lg->last_pages = NULL;
+ /*
+ * Initialize the Guest's shadow page tables. This allocates
+ * memory, so can fail.
+ */
+ err = init_guest_pagetable(lg);
+ if (err)
+ goto free_regs;
/* We keep our "struct lguest" in the file's private_data. */
file->private_data = lg;
@@ -249,92 +376,121 @@ static int initialize(struct file *file, const u32 __user *input)
return sizeof(args);
free_regs:
- free_page(lg->regs_page);
-release_guest:
- memset(lg, 0, sizeof(*lg));
+ /* FIXME: This should be in free_vcpu */
+ free_page(lg->cpus[0].regs_page);
+free_eventfds:
+ kfree(lg->eventfds);
+free_lg:
+ kfree(lg);
unlock:
mutex_unlock(&lguest_lock);
return err;
}
-/*L:010 The first operation the Launcher does must be a write. All writes
- * start with a 32 bit number: for the first write this must be
+/*L:010
+ * The first operation the Launcher does must be a write. All writes
+ * start with an unsigned long number: for the first write this must be
* LHREQ_INITIALIZE to set up the Guest. After that the Launcher can use
- * writes of other values to get DMA buffers and send interrupts. */
-static ssize_t write(struct file *file, const char __user *input,
+ * writes of other values to send interrupts or set up receipt of notifications.
+ *
+ * Note that we overload the "offset" in the /dev/lguest file to indicate what
+ * CPU number we're dealing with. Currently this is always 0 since we only
+ * support uniprocessor Guests, but you can see the beginnings of SMP support
+ * here.
+ */
+static ssize_t write(struct file *file, const char __user *in,
size_t size, loff_t *off)
{
- /* Once the guest is initialized, we hold the "struct lguest" in the
- * file private data. */
+ /*
+ * Once the Guest is initialized, we hold the "struct lguest" in the
+ * file private data.
+ */
struct lguest *lg = file->private_data;
- u32 req;
+ const unsigned long __user *input = (const unsigned long __user *)in;
+ unsigned long req;
+ struct lg_cpu *uninitialized_var(cpu);
+ unsigned int cpu_id = *off;
+ /* The first value tells us what this request is. */
if (get_user(req, input) != 0)
return -EFAULT;
- input += sizeof(req);
+ input++;
/* If you haven't initialized, you must do that first. */
- if (req != LHREQ_INITIALIZE && !lg)
- return -EINVAL;
-
- /* Once the Guest is dead, all you can do is read() why it died. */
- if (lg && lg->dead)
- return -ENOENT;
-
- /* If you're not the task which owns the Guest, you can only break */
- if (lg && current != lg->tsk && req != LHREQ_BREAK)
- return -EPERM;
+ if (req != LHREQ_INITIALIZE) {
+ if (!lg || (cpu_id >= lg->nr_cpus))
+ return -EINVAL;
+ cpu = &lg->cpus[cpu_id];
+
+ /* Once the Guest is dead, you can only read() why it died. */
+ if (lg->dead)
+ return -ENOENT;
+ }
switch (req) {
case LHREQ_INITIALIZE:
- return initialize(file, (const u32 __user *)input);
- case LHREQ_GETDMA:
- return user_get_dma(lg, (const u32 __user *)input);
+ return initialize(file, input);
case LHREQ_IRQ:
- return user_send_irq(lg, (const u32 __user *)input);
- case LHREQ_BREAK:
- return break_guest_out(lg, (const u32 __user *)input);
+ return user_send_irq(cpu, input);
+ case LHREQ_EVENTFD:
+ return attach_eventfd(lg, input);
default:
return -EINVAL;
}
}
-/*L:060 The final piece of interface code is the close() routine. It reverses
+/*L:060
+ * The final piece of interface code is the close() routine. It reverses
* everything done in initialize(). This is usually called because the
* Launcher exited.
*
* Note that the close routine returns 0 or a negative error number: it can't
* really fail, but it can whine. I blame Sun for this wart, and K&R C for
- * letting them do it. :*/
+ * letting them do it.
+:*/
static int close(struct inode *inode, struct file *file)
{
struct lguest *lg = file->private_data;
+ unsigned int i;
/* If we never successfully initialized, there's nothing to clean up */
if (!lg)
return 0;
- /* We need the big lock, to protect from inter-guest I/O and other
- * Launchers initializing guests. */
+ /*
+ * We need the big lock, to protect from inter-guest I/O and other
+ * Launchers initializing guests.
+ */
mutex_lock(&lguest_lock);
- /* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
- hrtimer_cancel(&lg->hrt);
- /* Free any DMA buffers the Guest had bound. */
- release_all_dma(lg);
+
/* Free up the shadow page tables for the Guest. */
free_guest_pagetable(lg);
- /* Now all the memory cleanups are done, it's safe to release the
- * Launcher's memory management structure. */
- mmput(lg->mm);
- /* If lg->dead doesn't contain an error code it will be NULL or a
- * kmalloc()ed string, either of which is ok to hand to kfree(). */
+
+ for (i = 0; i < lg->nr_cpus; i++) {
+ /* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
+ hrtimer_cancel(&lg->cpus[i].hrt);
+ /* We can free up the register page we allocated. */
+ free_page(lg->cpus[i].regs_page);
+ /*
+ * Now all the memory cleanups are done, it's safe to release
+ * the Launcher's memory management structure.
+ */
+ mmput(lg->cpus[i].mm);
+ }
+
+ /* Release any eventfds they registered. */
+ for (i = 0; i < lg->eventfds->num; i++)
+ eventfd_ctx_put(lg->eventfds->map[i].event);
+ kfree(lg->eventfds);
+
+ /*
+ * If lg->dead doesn't contain an error code it will be NULL or a
+ * kmalloc()ed string, either of which is ok to hand to kfree().
+ */
if (!IS_ERR(lg->dead))
kfree(lg->dead);
- /* We can free up the register page we allocated. */
- free_page(lg->regs_page);
- /* We clear the entire structure, which also marks it as free for the
- * next user. */
- memset(lg, 0, sizeof(*lg));
+ /* Free the memory allocated to the lguest_struct */
+ kfree(lg);
/* Release lock and exit. */
mutex_unlock(&lguest_lock);
@@ -347,24 +503,28 @@ static int close(struct inode *inode, struct file *file)
* The Launcher is the Host userspace program which sets up, runs and services
* the Guest. In fact, many comments in the Drivers which refer to "the Host"
* doing things are inaccurate: the Launcher does all the device handling for
- * the Guest. The Guest can't tell what's done by the the Launcher and what by
- * the Host.
+ * the Guest, but the Guest can't know that.
*
* Just to confuse you: to the Host kernel, the Launcher *is* the Guest and we
* shall see more of that later.
*
* We begin our understanding with the Host kernel interface which the Launcher
* uses: reading and writing a character device called /dev/lguest. All the
- * work happens in the read(), write() and close() routines: */
-static struct file_operations lguest_fops = {
+ * work happens in the read(), write() and close() routines:
+ */
+static const struct file_operations lguest_fops = {
.owner = THIS_MODULE,
.release = close,
.write = write,
.read = read,
+ .llseek = default_llseek,
};
+/*:*/
-/* This is a textbook example of a "misc" character device. Populate a "struct
- * miscdevice" and register it with misc_register(). */
+/*
+ * This is a textbook example of a "misc" character device. Populate a "struct
+ * miscdevice" and register it with misc_register().
+ */
static struct miscdevice lguest_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "lguest",
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index b7a924ace68..e8b55c3a617 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -1,31 +1,38 @@
-/*P:700 The pagetable code, on the other hand, still shows the scars of
+/*P:700
+ * The pagetable code, on the other hand, still shows the scars of
* previous encounters. It's functional, and as neat as it can be in the
* circumstances, but be wary, for these things are subtle and break easily.
* The Guest provides a virtual to physical mapping, but we can neither trust
- * it nor use it: we verify and convert it here to point the hardware to the
- * actual Guest pages when running the Guest. :*/
+ * it nor use it: we verify and convert it here then point the CPU to the
+ * converted Guest pages when running the Guest.
+:*/
-/* Copyright (C) Rusty Russell IBM Corporation 2006.
+/* Copyright (C) Rusty Russell IBM Corporation 2013.
* GPL v2 and any later version */
#include <linux/mm.h>
+#include <linux/gfp.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/random.h>
#include <linux/percpu.h>
#include <asm/tlbflush.h>
+#include <asm/uaccess.h>
#include "lg.h"
-/*M:008 We hold reference to pages, which prevents them from being swapped.
+/*M:008
+ * We hold reference to pages, which prevents them from being swapped.
* It'd be nice to have a callback in the "struct mm_struct" when Linux wants
* to swap out. If we had this, and a shrinker callback to trim PTE pages, we
- * could probably consider launching Guests as non-root. :*/
+ * could probably consider launching Guests as non-root.
+:*/
/*H:300
* The Page Table Code
*
- * We use two-level page tables for the Guest. If you're not entirely
- * comfortable with virtual addresses, physical addresses and page tables then
- * I recommend you review lguest.c's "Page Table Handling" (with diagrams!).
+ * We use two-level page tables for the Guest, or three-level with PAE. If
+ * you're not entirely comfortable with virtual addresses, physical addresses
+ * and page tables then I recommend you review arch/x86/lguest/boot.c's "Page
+ * Table Handling" (with diagrams!).
*
* The Guest keeps page tables, but we maintain the actual ones here: these are
* called "shadow" page tables. Which is a very Guest-centric name: these are
@@ -35,172 +42,330 @@
*
* Anyway, this is the most complicated part of the Host code. There are seven
* parts to this:
- * (i) Setting up a page table entry for the Guest when it faults,
- * (ii) Setting up the page table entry for the Guest stack,
- * (iii) Setting up a page table entry when the Guest tells us it has changed,
+ * (i) Looking up a page table entry when the Guest faults,
+ * (ii) Making sure the Guest stack is mapped,
+ * (iii) Setting up a page table entry when the Guest tells us one has changed,
* (iv) Switching page tables,
- * (v) Flushing (thowing away) page tables,
+ * (v) Flushing (throwing away) page tables,
* (vi) Mapping the Switcher when the Guest is about to run,
* (vii) Setting up the page tables initially.
- :*/
-
-/* Pages a 4k long, and each page table entry is 4 bytes long, giving us 1024
- * (or 2^10) entries per page. */
-#define PTES_PER_PAGE_SHIFT 10
-#define PTES_PER_PAGE (1 << PTES_PER_PAGE_SHIFT)
-
-/* 1024 entries in a page table page maps 1024 pages: 4MB. The Switcher is
- * conveniently placed at the top 4MB, so it uses a separate, complete PTE
- * page. */
-#define SWITCHER_PGD_INDEX (PTES_PER_PAGE - 1)
-
-/* We actually need a separate PTE page for each CPU. Remember that after the
- * Switcher code itself comes two pages for each CPU, and we don't want this
- * CPU's guest to see the pages of any other CPU. */
-static DEFINE_PER_CPU(spte_t *, switcher_pte_pages);
-#define switcher_pte_page(cpu) per_cpu(switcher_pte_pages, cpu)
-
-/*H:320 With our shadow and Guest types established, we need to deal with
- * them: the page table code is curly enough to need helper functions to keep
- * it clear and clean.
- *
- * The first helper takes a virtual address, and says which entry in the top
- * level page table deals with that address. Since each top level entry deals
- * with 4M, this effectively divides by 4M. */
-static unsigned vaddr_to_pgd_index(unsigned long vaddr)
-{
- return vaddr >> (PAGE_SHIFT + PTES_PER_PAGE_SHIFT);
-}
+:*/
-/* There are two functions which return pointers to the shadow (aka "real")
+/*
+ * The Switcher uses the complete top PTE page. That's 1024 PTE entries (4MB)
+ * or 512 PTE entries with PAE (2MB).
+ */
+#define SWITCHER_PGD_INDEX (PTRS_PER_PGD - 1)
+
+/*
+ * For PAE we need the PMD index as well. We use the last 2MB, so we
+ * will need the last pmd entry of the last pmd page.
+ */
+#ifdef CONFIG_X86_PAE
+#define CHECK_GPGD_MASK _PAGE_PRESENT
+#else
+#define CHECK_GPGD_MASK _PAGE_TABLE
+#endif
+
+/*H:320
+ * The page table code is curly enough to need helper functions to keep it
+ * clear and clean. The kernel itself provides many of them; one advantage
+ * of insisting that the Guest and Host use the same CONFIG_X86_PAE setting.
+ *
+ * There are two functions which return pointers to the shadow (aka "real")
* page tables.
*
* spgd_addr() takes the virtual address and returns a pointer to the top-level
- * page directory entry for that address. Since we keep track of several page
- * tables, the "i" argument tells us which one we're interested in (it's
- * usually the current one). */
-static spgd_t *spgd_addr(struct lguest *lg, u32 i, unsigned long vaddr)
+ * page directory entry (PGD) for that address. Since we keep track of several
+ * page tables, the "i" argument tells us which one we're interested in (it's
+ * usually the current one).
+ */
+static pgd_t *spgd_addr(struct lg_cpu *cpu, u32 i, unsigned long vaddr)
{
- unsigned int index = vaddr_to_pgd_index(vaddr);
+ unsigned int index = pgd_index(vaddr);
- /* We kill any Guest trying to touch the Switcher addresses. */
- if (index >= SWITCHER_PGD_INDEX) {
- kill_guest(lg, "attempt to access switcher pages");
- index = 0;
- }
/* Return a pointer index'th pgd entry for the i'th page table. */
- return &lg->pgdirs[i].pgdir[index];
+ return &cpu->lg->pgdirs[i].pgdir[index];
+}
+
+#ifdef CONFIG_X86_PAE
+/*
+ * This routine then takes the PGD entry given above, which contains the
+ * address of the PMD page. It then returns a pointer to the PMD entry for the
+ * given address.
+ */
+static pmd_t *spmd_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
+{
+ unsigned int index = pmd_index(vaddr);
+ pmd_t *page;
+
+ /* You should never call this if the PGD entry wasn't valid */
+ BUG_ON(!(pgd_flags(spgd) & _PAGE_PRESENT));
+ page = __va(pgd_pfn(spgd) << PAGE_SHIFT);
+
+ return &page[index];
}
+#endif
-/* This routine then takes the PGD entry given above, which contains the
- * address of the PTE page. It then returns a pointer to the PTE entry for the
- * given address. */
-static spte_t *spte_addr(struct lguest *lg, spgd_t spgd, unsigned long vaddr)
+/*
+ * This routine then takes the page directory entry returned above, which
+ * contains the address of the page table entry (PTE) page. It then returns a
+ * pointer to the PTE entry for the given address.
+ */
+static pte_t *spte_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
{
- spte_t *page = __va(spgd.pfn << PAGE_SHIFT);
+#ifdef CONFIG_X86_PAE
+ pmd_t *pmd = spmd_addr(cpu, spgd, vaddr);
+ pte_t *page = __va(pmd_pfn(*pmd) << PAGE_SHIFT);
+
+ /* You should never call this if the PMD entry wasn't valid */
+ BUG_ON(!(pmd_flags(*pmd) & _PAGE_PRESENT));
+#else
+ pte_t *page = __va(pgd_pfn(spgd) << PAGE_SHIFT);
/* You should never call this if the PGD entry wasn't valid */
- BUG_ON(!(spgd.flags & _PAGE_PRESENT));
- return &page[(vaddr >> PAGE_SHIFT) % PTES_PER_PAGE];
+ BUG_ON(!(pgd_flags(spgd) & _PAGE_PRESENT));
+#endif
+
+ return &page[pte_index(vaddr)];
}
-/* These two functions just like the above two, except they access the Guest
- * page tables. Hence they return a Guest address. */
-static unsigned long gpgd_addr(struct lguest *lg, unsigned long vaddr)
+/*
+ * These functions are just like the above, except they access the Guest
+ * page tables. Hence they return a Guest address.
+ */
+static unsigned long gpgd_addr(struct lg_cpu *cpu, unsigned long vaddr)
{
- unsigned int index = vaddr >> (PAGE_SHIFT + PTES_PER_PAGE_SHIFT);
- return lg->pgdirs[lg->pgdidx].cr3 + index * sizeof(gpgd_t);
+ unsigned int index = vaddr >> (PGDIR_SHIFT);
+ return cpu->lg->pgdirs[cpu->cpu_pgd].gpgdir + index * sizeof(pgd_t);
}
-static unsigned long gpte_addr(struct lguest *lg,
- gpgd_t gpgd, unsigned long vaddr)
+#ifdef CONFIG_X86_PAE
+/* Follow the PGD to the PMD. */
+static unsigned long gpmd_addr(pgd_t gpgd, unsigned long vaddr)
{
- unsigned long gpage = gpgd.pfn << PAGE_SHIFT;
- BUG_ON(!(gpgd.flags & _PAGE_PRESENT));
- return gpage + ((vaddr>>PAGE_SHIFT) % PTES_PER_PAGE) * sizeof(gpte_t);
+ unsigned long gpage = pgd_pfn(gpgd) << PAGE_SHIFT;
+ BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT));
+ return gpage + pmd_index(vaddr) * sizeof(pmd_t);
}
-/*H:350 This routine takes a page number given by the Guest and converts it to
+/* Follow the PMD to the PTE. */
+static unsigned long gpte_addr(struct lg_cpu *cpu,
+ pmd_t gpmd, unsigned long vaddr)
+{
+ unsigned long gpage = pmd_pfn(gpmd) << PAGE_SHIFT;
+
+ BUG_ON(!(pmd_flags(gpmd) & _PAGE_PRESENT));
+ return gpage + pte_index(vaddr) * sizeof(pte_t);
+}
+#else
+/* Follow the PGD to the PTE (no mid-level for !PAE). */
+static unsigned long gpte_addr(struct lg_cpu *cpu,
+ pgd_t gpgd, unsigned long vaddr)
+{
+ unsigned long gpage = pgd_pfn(gpgd) << PAGE_SHIFT;
+
+ BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT));
+ return gpage + pte_index(vaddr) * sizeof(pte_t);
+}
+#endif
+/*:*/
+
+/*M:007
+ * get_pfn is slow: we could probably try to grab batches of pages here as
+ * an optimization (ie. pre-faulting).
+:*/
+
+/*H:350
+ * This routine takes a page number given by the Guest and converts it to
* an actual, physical page number. It can fail for several reasons: the
* virtual address might not be mapped by the Launcher, the write flag is set
* and the page is read-only, or the write flag was set and the page was
* shared so had to be copied, but we ran out of memory.
*
- * This holds a reference to the page, so release_pte() is careful to
- * put that back. */
+ * This holds a reference to the page, so release_pte() is careful to put that
+ * back.
+ */
static unsigned long get_pfn(unsigned long virtpfn, int write)
{
struct page *page;
- /* This value indicates failure. */
- unsigned long ret = -1UL;
- /* get_user_pages() is a complex interface: it gets the "struct
- * vm_area_struct" and "struct page" assocated with a range of pages.
- * It also needs the task's mmap_sem held, and is not very quick.
- * It returns the number of pages it got. */
- down_read(&current->mm->mmap_sem);
- if (get_user_pages(current, current->mm, virtpfn << PAGE_SHIFT,
- 1, write, 1, &page, NULL) == 1)
- ret = page_to_pfn(page);
- up_read(&current->mm->mmap_sem);
- return ret;
+ /* gup me one page at this address please! */
+ if (get_user_pages_fast(virtpfn << PAGE_SHIFT, 1, write, &page) == 1)
+ return page_to_pfn(page);
+
+ /* This value indicates failure. */
+ return -1UL;
}
-/*H:340 Converting a Guest page table entry to a shadow (ie. real) page table
+/*H:340
+ * Converting a Guest page table entry to a shadow (ie. real) page table
* entry can be a little tricky. The flags are (almost) the same, but the
* Guest PTE contains a virtual page number: the CPU needs the real page
- * number. */
-static spte_t gpte_to_spte(struct lguest *lg, gpte_t gpte, int write)
+ * number.
+ */
+static pte_t gpte_to_spte(struct lg_cpu *cpu, pte_t gpte, int write)
{
- spte_t spte;
- unsigned long pfn;
+ unsigned long pfn, base, flags;
- /* The Guest sets the global flag, because it thinks that it is using
+ /*
+ * The Guest sets the global flag, because it thinks that it is using
* PGE. We only told it to use PGE so it would tell us whether it was
* flushing a kernel mapping or a userspace mapping. We don't actually
- * use the global bit, so throw it away. */
- spte.flags = (gpte.flags & ~_PAGE_GLOBAL);
+ * use the global bit, so throw it away.
+ */
+ flags = (pte_flags(gpte) & ~_PAGE_GLOBAL);
- /* We need a temporary "unsigned long" variable to hold the answer from
+ /* The Guest's pages are offset inside the Launcher. */
+ base = (unsigned long)cpu->lg->mem_base / PAGE_SIZE;
+
+ /*
+ * We need a temporary "unsigned long" variable to hold the answer from
* get_pfn(), because it returns 0xFFFFFFFF on failure, which wouldn't
* fit in spte.pfn. get_pfn() finds the real physical number of the
- * page, given the virtual number. */
- pfn = get_pfn(gpte.pfn, write);
+ * page, given the virtual number.
+ */
+ pfn = get_pfn(base + pte_pfn(gpte), write);
if (pfn == -1UL) {
- kill_guest(lg, "failed to get page %u", gpte.pfn);
- /* When we destroy the Guest, we'll go through the shadow page
+ kill_guest(cpu, "failed to get page %lu", pte_pfn(gpte));
+ /*
+ * When we destroy the Guest, we'll go through the shadow page
* tables and release_pte() them. Make sure we don't think
- * this one is valid! */
- spte.flags = 0;
+ * this one is valid!
+ */
+ flags = 0;
}
- /* Now we assign the page number, and our shadow PTE is complete. */
- spte.pfn = pfn;
- return spte;
+ /* Now we assemble our shadow PTE from the page number and flags. */
+ return pfn_pte(pfn, __pgprot(flags));
}
/*H:460 And to complete the chain, release_pte() looks like this: */
-static void release_pte(spte_t pte)
+static void release_pte(pte_t pte)
{
- /* Remember that get_user_pages() took a reference to the page, in
- * get_pfn()? We have to put it back now. */
- if (pte.flags & _PAGE_PRESENT)
- put_page(pfn_to_page(pte.pfn));
+ /*
+ * Remember that get_user_pages_fast() took a reference to the page, in
+ * get_pfn()? We have to put it back now.
+ */
+ if (pte_flags(pte) & _PAGE_PRESENT)
+ put_page(pte_page(pte));
}
/*:*/
-static void check_gpte(struct lguest *lg, gpte_t gpte)
+static bool check_gpte(struct lg_cpu *cpu, pte_t gpte)
+{
+ if ((pte_flags(gpte) & _PAGE_PSE) ||
+ pte_pfn(gpte) >= cpu->lg->pfn_limit) {
+ kill_guest(cpu, "bad page table entry");
+ return false;
+ }
+ return true;
+}
+
+static bool check_gpgd(struct lg_cpu *cpu, pgd_t gpgd)
{
- if ((gpte.flags & (_PAGE_PWT|_PAGE_PSE)) || gpte.pfn >= lg->pfn_limit)
- kill_guest(lg, "bad page table entry");
+ if ((pgd_flags(gpgd) & ~CHECK_GPGD_MASK) ||
+ (pgd_pfn(gpgd) >= cpu->lg->pfn_limit)) {
+ kill_guest(cpu, "bad page directory entry");
+ return false;
+ }
+ return true;
}
-static void check_gpgd(struct lguest *lg, gpgd_t gpgd)
+#ifdef CONFIG_X86_PAE
+static bool check_gpmd(struct lg_cpu *cpu, pmd_t gpmd)
{
- if ((gpgd.flags & ~_PAGE_TABLE) || gpgd.pfn >= lg->pfn_limit)
- kill_guest(lg, "bad page directory entry");
+ if ((pmd_flags(gpmd) & ~_PAGE_TABLE) ||
+ (pmd_pfn(gpmd) >= cpu->lg->pfn_limit)) {
+ kill_guest(cpu, "bad page middle directory entry");
+ return false;
+ }
+ return true;
+}
+#endif
+
+/*H:331
+ * This is the core routine to walk the shadow page tables and find the page
+ * table entry for a specific address.
+ *
+ * If allocate is set, then we allocate any missing levels, setting the flags
+ * on the new page directory and mid-level directories using the arguments
+ * (which are copied from the Guest's page table entries).
+ */
+static pte_t *find_spte(struct lg_cpu *cpu, unsigned long vaddr, bool allocate,
+ int pgd_flags, int pmd_flags)
+{
+ pgd_t *spgd;
+ /* Mid level for PAE. */
+#ifdef CONFIG_X86_PAE
+ pmd_t *spmd;
+#endif
+
+ /* Get top level entry. */
+ spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr);
+ if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) {
+ /* No shadow entry: allocate a new shadow PTE page. */
+ unsigned long ptepage;
+
+ /* If they didn't want us to allocate anything, stop. */
+ if (!allocate)
+ return NULL;
+
+ ptepage = get_zeroed_page(GFP_KERNEL);
+ /*
+ * This is not really the Guest's fault, but killing it is
+ * simple for this corner case.
+ */
+ if (!ptepage) {
+ kill_guest(cpu, "out of memory allocating pte page");
+ return NULL;
+ }
+ /*
+ * And we copy the flags to the shadow PGD entry. The page
+ * number in the shadow PGD is the page we just allocated.
+ */
+ set_pgd(spgd, __pgd(__pa(ptepage) | pgd_flags));
+ }
+
+ /*
+ * Intel's Physical Address Extension actually uses three levels of
+ * page tables, so we need to look in the mid-level.
+ */
+#ifdef CONFIG_X86_PAE
+ /* Now look at the mid-level shadow entry. */
+ spmd = spmd_addr(cpu, *spgd, vaddr);
+
+ if (!(pmd_flags(*spmd) & _PAGE_PRESENT)) {
+ /* No shadow entry: allocate a new shadow PTE page. */
+ unsigned long ptepage;
+
+ /* If they didn't want us to allocate anything, stop. */
+ if (!allocate)
+ return NULL;
+
+ ptepage = get_zeroed_page(GFP_KERNEL);
+
+ /*
+ * This is not really the Guest's fault, but killing it is
+ * simple for this corner case.
+ */
+ if (!ptepage) {
+ kill_guest(cpu, "out of memory allocating pmd page");
+ return NULL;
+ }
+
+ /*
+ * And we copy the flags to the shadow PMD entry. The page
+ * number in the shadow PMD is the page we just allocated.
+ */
+ set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags));
+ }
+#endif
+
+ /* Get the pointer to the shadow PTE entry we're going to set. */
+ return spte_addr(cpu, *spgd, vaddr);
}
/*H:330
- * (i) Setting up a page table entry for the Guest when it faults
+ * (i) Looking up a page table entry when the Guest faults.
*
* We saw this call in run_guest(): when we see a page fault in the Guest, we
* come here. That's because we only set up the shadow page tables lazily as
@@ -208,256 +373,507 @@ static void check_gpgd(struct lguest *lg, gpgd_t gpgd)
* and return to the Guest without it knowing.
*
* If we fixed up the fault (ie. we mapped the address), this routine returns
- * true. */
-int demand_page(struct lguest *lg, unsigned long vaddr, int errcode)
+ * true. Otherwise, it was a real fault and we need to tell the Guest.
+ */
+bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
{
- gpgd_t gpgd;
- spgd_t *spgd;
unsigned long gpte_ptr;
- gpte_t gpte;
- spte_t *spte;
+ pte_t gpte;
+ pte_t *spte;
+ pmd_t gpmd;
+ pgd_t gpgd;
+
+ /* We never demand page the Switcher, so trying is a mistake. */
+ if (vaddr >= switcher_addr)
+ return false;
/* First step: get the top-level Guest page table entry. */
- gpgd = mkgpgd(lgread_u32(lg, gpgd_addr(lg, vaddr)));
- /* Toplevel not present? We can't map it in. */
- if (!(gpgd.flags & _PAGE_PRESENT))
- return 0;
+ if (unlikely(cpu->linear_pages)) {
+ /* Faking up a linear mapping. */
+ gpgd = __pgd(CHECK_GPGD_MASK);
+ } else {
+ gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
+ /* Toplevel not present? We can't map it in. */
+ if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
+ return false;
+
+ /*
+ * This kills the Guest if it has weird flags or tries to
+ * refer to a "physical" address outside the bounds.
+ */
+ if (!check_gpgd(cpu, gpgd))
+ return false;
+ }
- /* Now look at the matching shadow entry. */
- spgd = spgd_addr(lg, lg->pgdidx, vaddr);
- if (!(spgd->flags & _PAGE_PRESENT)) {
- /* No shadow entry: allocate a new shadow PTE page. */
- unsigned long ptepage = get_zeroed_page(GFP_KERNEL);
- /* This is not really the Guest's fault, but killing it is
- * simple for this corner case. */
- if (!ptepage) {
- kill_guest(lg, "out of memory allocating pte page");
- return 0;
- }
- /* We check that the Guest pgd is OK. */
- check_gpgd(lg, gpgd);
- /* And we copy the flags to the shadow PGD entry. The page
- * number in the shadow PGD is the page we just allocated. */
- spgd->raw.val = (__pa(ptepage) | gpgd.flags);
+ /* This "mid-level" entry is only used for non-linear, PAE mode. */
+ gpmd = __pmd(_PAGE_TABLE);
+
+#ifdef CONFIG_X86_PAE
+ if (likely(!cpu->linear_pages)) {
+ gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
+ /* Middle level not present? We can't map it in. */
+ if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
+ return false;
+
+ /*
+ * This kills the Guest if it has weird flags or tries to
+ * refer to a "physical" address outside the bounds.
+ */
+ if (!check_gpmd(cpu, gpmd))
+ return false;
}
- /* OK, now we look at the lower level in the Guest page table: keep its
- * address, because we might update it later. */
- gpte_ptr = gpte_addr(lg, gpgd, vaddr);
- gpte = mkgpte(lgread_u32(lg, gpte_ptr));
+ /*
+ * OK, now we look at the lower level in the Guest page table: keep its
+ * address, because we might update it later.
+ */
+ gpte_ptr = gpte_addr(cpu, gpmd, vaddr);
+#else
+ /*
+ * OK, now we look at the lower level in the Guest page table: keep its
+ * address, because we might update it later.
+ */
+ gpte_ptr = gpte_addr(cpu, gpgd, vaddr);
+#endif
+
+ if (unlikely(cpu->linear_pages)) {
+ /* Linear? Make up a PTE which points to same page. */
+ gpte = __pte((vaddr & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT);
+ } else {
+ /* Read the actual PTE value. */
+ gpte = lgread(cpu, gpte_ptr, pte_t);
+ }
/* If this page isn't in the Guest page tables, we can't page it in. */
- if (!(gpte.flags & _PAGE_PRESENT))
- return 0;
-
- /* Check they're not trying to write to a page the Guest wants
- * read-only (bit 2 of errcode == write). */
- if ((errcode & 2) && !(gpte.flags & _PAGE_RW))
- return 0;
+ if (!(pte_flags(gpte) & _PAGE_PRESENT))
+ return false;
+
+ /*
+ * Check they're not trying to write to a page the Guest wants
+ * read-only (bit 2 of errcode == write).
+ */
+ if ((errcode & 2) && !(pte_flags(gpte) & _PAGE_RW))
+ return false;
+
+ /* User access to a kernel-only page? (bit 3 == user access) */
+ if ((errcode & 4) && !(pte_flags(gpte) & _PAGE_USER))
+ return false;
+
+ /*
+ * Check that the Guest PTE flags are OK, and the page number is below
+ * the pfn_limit (ie. not mapping the Launcher binary).
+ */
+ if (!check_gpte(cpu, gpte))
+ return false;
- /* User access to a kernel page? (bit 3 == user access) */
- if ((errcode & 4) && !(gpte.flags & _PAGE_USER))
- return 0;
-
- /* Check that the Guest PTE flags are OK, and the page number is below
- * the pfn_limit (ie. not mapping the Launcher binary). */
- check_gpte(lg, gpte);
/* Add the _PAGE_ACCESSED and (for a write) _PAGE_DIRTY flag */
- gpte.flags |= _PAGE_ACCESSED;
+ gpte = pte_mkyoung(gpte);
if (errcode & 2)
- gpte.flags |= _PAGE_DIRTY;
+ gpte = pte_mkdirty(gpte);
/* Get the pointer to the shadow PTE entry we're going to set. */
- spte = spte_addr(lg, *spgd, vaddr);
- /* If there was a valid shadow PTE entry here before, we release it.
- * This can happen with a write to a previously read-only entry. */
+ spte = find_spte(cpu, vaddr, true, pgd_flags(gpgd), pmd_flags(gpmd));
+ if (!spte)
+ return false;
+
+ /*
+ * If there was a valid shadow PTE entry here before, we release it.
+ * This can happen with a write to a previously read-only entry.
+ */
release_pte(*spte);
- /* If this is a write, we insist that the Guest page is writable (the
- * final arg to gpte_to_spte()). */
- if (gpte.flags & _PAGE_DIRTY)
- *spte = gpte_to_spte(lg, gpte, 1);
- else {
- /* If this is a read, don't set the "writable" bit in the page
+ /*
+ * If this is a write, we insist that the Guest page is writable (the
+ * final arg to gpte_to_spte()).
+ */
+ if (pte_dirty(gpte))
+ *spte = gpte_to_spte(cpu, gpte, 1);
+ else
+ /*
+ * If this is a read, don't set the "writable" bit in the page
* table entry, even if the Guest says it's writable. That way
- * we come back here when a write does actually ocur, so we can
- * update the Guest's _PAGE_DIRTY flag. */
- gpte_t ro_gpte = gpte;
- ro_gpte.flags &= ~_PAGE_RW;
- *spte = gpte_to_spte(lg, ro_gpte, 0);
- }
-
- /* Finally, we write the Guest PTE entry back: we've set the
- * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags. */
- lgwrite_u32(lg, gpte_ptr, gpte.raw.val);
-
- /* We succeeded in mapping the page! */
- return 1;
+ * we will come back here when a write does actually occur, so
+ * we can update the Guest's _PAGE_DIRTY flag.
+ */
+ set_pte(spte, gpte_to_spte(cpu, pte_wrprotect(gpte), 0));
+
+ /*
+ * Finally, we write the Guest PTE entry back: we've set the
+ * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags.
+ */
+ if (likely(!cpu->linear_pages))
+ lgwrite(cpu, gpte_ptr, pte_t, gpte);
+
+ /*
+ * The fault is fixed, the page table is populated, the mapping
+ * manipulated, the result returned and the code complete. A small
+ * delay and a trace of alliteration are the only indications the Guest
+ * has that a page fault occurred at all.
+ */
+ return true;
}
-/*H:360 (ii) Setting up the page table entry for the Guest stack.
+/*H:360
+ * (ii) Making sure the Guest stack is mapped.
*
- * Remember pin_stack_pages() which makes sure the stack is mapped? It could
- * simply call demand_page(), but as we've seen that logic is quite long, and
- * usually the stack pages are already mapped anyway, so it's not required.
+ * Remember that direct traps into the Guest need a mapped Guest kernel stack.
+ * pin_stack_pages() calls us here: we could simply call demand_page(), but as
+ * we've seen that logic is quite long, and usually the stack pages are already
+ * mapped, so it's overkill.
*
* This is a quick version which answers the question: is this virtual address
- * mapped by the shadow page tables, and is it writable? */
-static int page_writable(struct lguest *lg, unsigned long vaddr)
+ * mapped by the shadow page tables, and is it writable?
+ */
+static bool page_writable(struct lg_cpu *cpu, unsigned long vaddr)
{
- spgd_t *spgd;
+ pte_t *spte;
unsigned long flags;
- /* Look at the top level entry: is it present? */
- spgd = spgd_addr(lg, lg->pgdidx, vaddr);
- if (!(spgd->flags & _PAGE_PRESENT))
- return 0;
+ /* You can't put your stack in the Switcher! */
+ if (vaddr >= switcher_addr)
+ return false;
- /* Check the flags on the pte entry itself: it must be present and
- * writable. */
- flags = spte_addr(lg, *spgd, vaddr)->flags;
+ /* If there's no shadow PTE, it's not writable. */
+ spte = find_spte(cpu, vaddr, false, 0, 0);
+ if (!spte)
+ return false;
+
+ /*
+ * Check the flags on the pte entry itself: it must be present and
+ * writable.
+ */
+ flags = pte_flags(*spte);
return (flags & (_PAGE_PRESENT|_PAGE_RW)) == (_PAGE_PRESENT|_PAGE_RW);
}
-/* So, when pin_stack_pages() asks us to pin a page, we check if it's already
+/*
+ * So, when pin_stack_pages() asks us to pin a page, we check if it's already
* in the page tables, and if not, we call demand_page() with error code 2
- * (meaning "write"). */
-void pin_page(struct lguest *lg, unsigned long vaddr)
+ * (meaning "write").
+ */
+void pin_page(struct lg_cpu *cpu, unsigned long vaddr)
{
- if (!page_writable(lg, vaddr) && !demand_page(lg, vaddr, 2))
- kill_guest(lg, "bad stack page %#lx", vaddr);
+ if (!page_writable(cpu, vaddr) && !demand_page(cpu, vaddr, 2))
+ kill_guest(cpu, "bad stack page %#lx", vaddr);
}
+/*:*/
-/*H:450 If we chase down the release_pgd() code, it looks like this: */
-static void release_pgd(struct lguest *lg, spgd_t *spgd)
+#ifdef CONFIG_X86_PAE
+static void release_pmd(pmd_t *spmd)
{
/* If the entry's not present, there's nothing to release. */
- if (spgd->flags & _PAGE_PRESENT) {
+ if (pmd_flags(*spmd) & _PAGE_PRESENT) {
unsigned int i;
- /* Converting the pfn to find the actual PTE page is easy: turn
+ pte_t *ptepage = __va(pmd_pfn(*spmd) << PAGE_SHIFT);
+ /* For each entry in the page, we might need to release it. */
+ for (i = 0; i < PTRS_PER_PTE; i++)
+ release_pte(ptepage[i]);
+ /* Now we can free the page of PTEs */
+ free_page((long)ptepage);
+ /* And zero out the PMD entry so we never release it twice. */
+ set_pmd(spmd, __pmd(0));
+ }
+}
+
+static void release_pgd(pgd_t *spgd)
+{
+ /* If the entry's not present, there's nothing to release. */
+ if (pgd_flags(*spgd) & _PAGE_PRESENT) {
+ unsigned int i;
+ pmd_t *pmdpage = __va(pgd_pfn(*spgd) << PAGE_SHIFT);
+
+ for (i = 0; i < PTRS_PER_PMD; i++)
+ release_pmd(&pmdpage[i]);
+
+ /* Now we can free the page of PMDs */
+ free_page((long)pmdpage);
+ /* And zero out the PGD entry so we never release it twice. */
+ set_pgd(spgd, __pgd(0));
+ }
+}
+
+#else /* !CONFIG_X86_PAE */
+/*H:450
+ * If we chase down the release_pgd() code, the non-PAE version looks like
+ * this. The PAE version is almost identical, but instead of calling
+ * release_pte it calls release_pmd(), which looks much like this.
+ */
+static void release_pgd(pgd_t *spgd)
+{
+ /* If the entry's not present, there's nothing to release. */
+ if (pgd_flags(*spgd) & _PAGE_PRESENT) {
+ unsigned int i;
+ /*
+ * Converting the pfn to find the actual PTE page is easy: turn
* the page number into a physical address, then convert to a
- * virtual address (easy for kernel pages like this one). */
- spte_t *ptepage = __va(spgd->pfn << PAGE_SHIFT);
+ * virtual address (easy for kernel pages like this one).
+ */
+ pte_t *ptepage = __va(pgd_pfn(*spgd) << PAGE_SHIFT);
/* For each entry in the page, we might need to release it. */
- for (i = 0; i < PTES_PER_PAGE; i++)
+ for (i = 0; i < PTRS_PER_PTE; i++)
release_pte(ptepage[i]);
/* Now we can free the page of PTEs */
free_page((long)ptepage);
- /* And zero out the PGD entry we we never release it twice. */
- spgd->raw.val = 0;
+ /* And zero out the PGD entry so we never release it twice. */
+ *spgd = __pgd(0);
}
}
+#endif
-/*H:440 (v) Flushing (thowing away) page tables,
- *
- * We saw flush_user_mappings() called when we re-used a top-level pgdir page.
- * It simply releases every PTE page from 0 up to the kernel address. */
+/*H:445
+ * We saw flush_user_mappings() twice: once from the flush_user_mappings()
+ * hypercall and once in new_pgdir() when we re-used a top-level pgdir page.
+ * It simply releases every PTE page from 0 up to the Guest's kernel address.
+ */
static void flush_user_mappings(struct lguest *lg, int idx)
{
unsigned int i;
/* Release every pgd entry up to the kernel's address. */
- for (i = 0; i < vaddr_to_pgd_index(lg->page_offset); i++)
- release_pgd(lg, lg->pgdirs[idx].pgdir + i);
+ for (i = 0; i < pgd_index(lg->kernel_address); i++)
+ release_pgd(lg->pgdirs[idx].pgdir + i);
}
-/* The Guest also has a hypercall to do this manually: it's used when a large
- * number of mappings have been changed. */
-void guest_pagetable_flush_user(struct lguest *lg)
+/*H:440
+ * (v) Flushing (throwing away) page tables,
+ *
+ * The Guest has a hypercall to throw away the page tables: it's used when a
+ * large number of mappings have been changed.
+ */
+void guest_pagetable_flush_user(struct lg_cpu *cpu)
{
/* Drop the userspace part of the current page table. */
- flush_user_mappings(lg, lg->pgdidx);
+ flush_user_mappings(cpu->lg, cpu->cpu_pgd);
}
/*:*/
-/* We keep several page tables. This is a simple routine to find the page
+/* We walk down the guest page tables to get a guest-physical address */
+unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr)
+{
+ pgd_t gpgd;
+ pte_t gpte;
+#ifdef CONFIG_X86_PAE
+ pmd_t gpmd;
+#endif
+
+ /* Still not set up? Just map 1:1. */
+ if (unlikely(cpu->linear_pages))
+ return vaddr;
+
+ /* First step: get the top-level Guest page table entry. */
+ gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
+ /* Toplevel not present? We can't map it in. */
+ if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) {
+ kill_guest(cpu, "Bad address %#lx", vaddr);
+ return -1UL;
+ }
+
+#ifdef CONFIG_X86_PAE
+ gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
+ if (!(pmd_flags(gpmd) & _PAGE_PRESENT)) {
+ kill_guest(cpu, "Bad address %#lx", vaddr);
+ return -1UL;
+ }
+ gpte = lgread(cpu, gpte_addr(cpu, gpmd, vaddr), pte_t);
+#else
+ gpte = lgread(cpu, gpte_addr(cpu, gpgd, vaddr), pte_t);
+#endif
+ if (!(pte_flags(gpte) & _PAGE_PRESENT))
+ kill_guest(cpu, "Bad address %#lx", vaddr);
+
+ return pte_pfn(gpte) * PAGE_SIZE | (vaddr & ~PAGE_MASK);
+}
+
+/*
+ * We keep several page tables. This is a simple routine to find the page
* table (if any) corresponding to this top-level address the Guest has given
- * us. */
+ * us.
+ */
static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++)
- if (lg->pgdirs[i].cr3 == pgtable)
+ if (lg->pgdirs[i].pgdir && lg->pgdirs[i].gpgdir == pgtable)
break;
return i;
}
-/*H:435 And this is us, creating the new page directory. If we really do
+/*H:435
+ * And this is us, creating the new page directory. If we really do
* allocate a new one (and so the kernel parts are not there), we set
- * blank_pgdir. */
-static unsigned int new_pgdir(struct lguest *lg,
- unsigned long cr3,
+ * blank_pgdir.
+ */
+static unsigned int new_pgdir(struct lg_cpu *cpu,
+ unsigned long gpgdir,
int *blank_pgdir)
{
unsigned int next;
- /* We pick one entry at random to throw out. Choosing the Least
- * Recently Used might be better, but this is easy. */
- next = random32() % ARRAY_SIZE(lg->pgdirs);
+ /*
+ * We pick one entry at random to throw out. Choosing the Least
+ * Recently Used might be better, but this is easy.
+ */
+ next = prandom_u32() % ARRAY_SIZE(cpu->lg->pgdirs);
/* If it's never been allocated at all before, try now. */
- if (!lg->pgdirs[next].pgdir) {
- lg->pgdirs[next].pgdir = (spgd_t *)get_zeroed_page(GFP_KERNEL);
+ if (!cpu->lg->pgdirs[next].pgdir) {
+ cpu->lg->pgdirs[next].pgdir =
+ (pgd_t *)get_zeroed_page(GFP_KERNEL);
/* If the allocation fails, just keep using the one we have */
- if (!lg->pgdirs[next].pgdir)
- next = lg->pgdidx;
- else
- /* This is a blank page, so there are no kernel
- * mappings: caller must map the stack! */
+ if (!cpu->lg->pgdirs[next].pgdir)
+ next = cpu->cpu_pgd;
+ else {
+ /*
+ * This is a blank page, so there are no kernel
+ * mappings: caller must map the stack!
+ */
*blank_pgdir = 1;
+ }
}
/* Record which Guest toplevel this shadows. */
- lg->pgdirs[next].cr3 = cr3;
+ cpu->lg->pgdirs[next].gpgdir = gpgdir;
/* Release all the non-kernel mappings. */
- flush_user_mappings(lg, next);
+ flush_user_mappings(cpu->lg, next);
+
+ /* This hasn't run on any CPU at all. */
+ cpu->lg->pgdirs[next].last_host_cpu = -1;
return next;
}
-/*H:430 (iv) Switching page tables
+/*H:501
+ * We do need the Switcher code mapped at all times, so we allocate that
+ * part of the Guest page table here. We map the Switcher code immediately,
+ * but defer mapping of the guest register page and IDT/LDT etc page until
+ * just before we run the guest in map_switcher_in_guest().
*
- * This is what happens when the Guest changes page tables (ie. changes the
- * top-level pgdir). This happens on almost every context switch. */
-void guest_new_pagetable(struct lguest *lg, unsigned long pgtable)
+ * We *could* do this setup in map_switcher_in_guest(), but at that point
+ * we've interrupts disabled, and allocating pages like that is fraught: we
+ * can't sleep if we need to free up some memory.
+ */
+static bool allocate_switcher_mapping(struct lg_cpu *cpu)
{
- int newpgdir, repin = 0;
-
- /* Look to see if we have this one already. */
- newpgdir = find_pgdir(lg, pgtable);
- /* If not, we allocate or mug an existing one: if it's a fresh one,
- * repin gets set to 1. */
- if (newpgdir == ARRAY_SIZE(lg->pgdirs))
- newpgdir = new_pgdir(lg, pgtable, &repin);
- /* Change the current pgd index to the new one. */
- lg->pgdidx = newpgdir;
- /* If it was completely blank, we map in the Guest kernel stack */
- if (repin)
- pin_stack_pages(lg);
+ int i;
+
+ for (i = 0; i < TOTAL_SWITCHER_PAGES; i++) {
+ pte_t *pte = find_spte(cpu, switcher_addr + i * PAGE_SIZE, true,
+ CHECK_GPGD_MASK, _PAGE_TABLE);
+ if (!pte)
+ return false;
+
+ /*
+ * Map the switcher page if not already there. It might
+ * already be there because we call allocate_switcher_mapping()
+ * in guest_set_pgd() just in case it did discard our Switcher
+ * mapping, but it probably didn't.
+ */
+ if (i == 0 && !(pte_flags(*pte) & _PAGE_PRESENT)) {
+ /* Get a reference to the Switcher page. */
+ get_page(lg_switcher_pages[0]);
+ /* Create a read-only, exectuable, kernel-style PTE */
+ set_pte(pte,
+ mk_pte(lg_switcher_pages[0], PAGE_KERNEL_RX));
+ }
+ }
+ cpu->lg->pgdirs[cpu->cpu_pgd].switcher_mapped = true;
+ return true;
}
-/*H:470 Finally, a routine which throws away everything: all PGD entries in all
- * the shadow page tables. This is used when we destroy the Guest. */
+/*H:470
+ * Finally, a routine which throws away everything: all PGD entries in all
+ * the shadow page tables, including the Guest's kernel mappings. This is used
+ * when we destroy the Guest.
+ */
static void release_all_pagetables(struct lguest *lg)
{
unsigned int i, j;
/* Every shadow pagetable this Guest has */
- for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++)
- if (lg->pgdirs[i].pgdir)
- /* Every PGD entry except the Switcher at the top */
- for (j = 0; j < SWITCHER_PGD_INDEX; j++)
- release_pgd(lg, lg->pgdirs[i].pgdir + j);
+ for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++) {
+ if (!lg->pgdirs[i].pgdir)
+ continue;
+
+ /* Every PGD entry. */
+ for (j = 0; j < PTRS_PER_PGD; j++)
+ release_pgd(lg->pgdirs[i].pgdir + j);
+ lg->pgdirs[i].switcher_mapped = false;
+ lg->pgdirs[i].last_host_cpu = -1;
+ }
}
-/* We also throw away everything when a Guest tells us it's changed a kernel
+/*
+ * We also throw away everything when a Guest tells us it's changed a kernel
* mapping. Since kernel mappings are in every page table, it's easiest to
- * throw them all away. This is amazingly slow, but thankfully rare. */
-void guest_pagetable_clear_all(struct lguest *lg)
+ * throw them all away. This traps the Guest in amber for a while as
+ * everything faults back in, but it's rare.
+ */
+void guest_pagetable_clear_all(struct lg_cpu *cpu)
{
- release_all_pagetables(lg);
+ release_all_pagetables(cpu->lg);
/* We need the Guest kernel stack mapped again. */
- pin_stack_pages(lg);
+ pin_stack_pages(cpu);
+ /* And we need Switcher allocated. */
+ if (!allocate_switcher_mapping(cpu))
+ kill_guest(cpu, "Cannot populate switcher mapping");
}
-/*H:420 This is the routine which actually sets the page table entry for then
+/*H:430
+ * (iv) Switching page tables
+ *
+ * Now we've seen all the page table setting and manipulation, let's see
+ * what happens when the Guest changes page tables (ie. changes the top-level
+ * pgdir). This occurs on almost every context switch.
+ */
+void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
+{
+ int newpgdir, repin = 0;
+
+ /*
+ * The very first time they call this, we're actually running without
+ * any page tables; we've been making it up. Throw them away now.
+ */
+ if (unlikely(cpu->linear_pages)) {
+ release_all_pagetables(cpu->lg);
+ cpu->linear_pages = false;
+ /* Force allocation of a new pgdir. */
+ newpgdir = ARRAY_SIZE(cpu->lg->pgdirs);
+ } else {
+ /* Look to see if we have this one already. */
+ newpgdir = find_pgdir(cpu->lg, pgtable);
+ }
+
+ /*
+ * If not, we allocate or mug an existing one: if it's a fresh one,
+ * repin gets set to 1.
+ */
+ if (newpgdir == ARRAY_SIZE(cpu->lg->pgdirs))
+ newpgdir = new_pgdir(cpu, pgtable, &repin);
+ /* Change the current pgd index to the new one. */
+ cpu->cpu_pgd = newpgdir;
+ /*
+ * If it was completely blank, we map in the Guest kernel stack and
+ * the Switcher.
+ */
+ if (repin)
+ pin_stack_pages(cpu);
+
+ if (!cpu->lg->pgdirs[cpu->cpu_pgd].switcher_mapped) {
+ if (!allocate_switcher_mapping(cpu))
+ kill_guest(cpu, "Cannot populate switcher mapping");
+ }
+}
+/*:*/
+
+/*M:009
+ * Since we throw away all mappings when a kernel mapping changes, our
+ * performance sucks for guests using highmem. In fact, a guest with
+ * PAGE_OFFSET 0xc0000000 (the default) and more than about 700MB of RAM is
+ * usually slower than a Guest with less memory.
+ *
+ * This, of course, cannot be fixed. It would take some kind of... well, I
+ * don't know, but the term "puissant code-fu" comes to mind.
+:*/
+
+/*H:420
+ * This is the routine which actually sets the page table entry for then
* "idx"'th shadow page table.
*
* Normally, we can just throw out the old entry and replace it with 0: if they
@@ -471,31 +887,52 @@ void guest_pagetable_clear_all(struct lguest *lg)
* _PAGE_ACCESSED then we can put a read-only PTE entry in immediately, and if
* they set _PAGE_DIRTY then we can put a writable PTE entry in immediately.
*/
-static void do_set_pte(struct lguest *lg, int idx,
- unsigned long vaddr, gpte_t gpte)
+static void __guest_set_pte(struct lg_cpu *cpu, int idx,
+ unsigned long vaddr, pte_t gpte)
{
- /* Look up the matching shadow page directot entry. */
- spgd_t *spgd = spgd_addr(lg, idx, vaddr);
+ /* Look up the matching shadow page directory entry. */
+ pgd_t *spgd = spgd_addr(cpu, idx, vaddr);
+#ifdef CONFIG_X86_PAE
+ pmd_t *spmd;
+#endif
/* If the top level isn't present, there's no entry to update. */
- if (spgd->flags & _PAGE_PRESENT) {
- /* Otherwise, we start by releasing the existing entry. */
- spte_t *spte = spte_addr(lg, *spgd, vaddr);
- release_pte(*spte);
-
- /* If they're setting this entry as dirty or accessed, we might
- * as well put that entry they've given us in now. This shaves
- * 10% off a copy-on-write micro-benchmark. */
- if (gpte.flags & (_PAGE_DIRTY | _PAGE_ACCESSED)) {
- check_gpte(lg, gpte);
- *spte = gpte_to_spte(lg, gpte, gpte.flags&_PAGE_DIRTY);
- } else
- /* Otherwise we can demand_page() it in later. */
- spte->raw.val = 0;
+ if (pgd_flags(*spgd) & _PAGE_PRESENT) {
+#ifdef CONFIG_X86_PAE
+ spmd = spmd_addr(cpu, *spgd, vaddr);
+ if (pmd_flags(*spmd) & _PAGE_PRESENT) {
+#endif
+ /* Otherwise, start by releasing the existing entry. */
+ pte_t *spte = spte_addr(cpu, *spgd, vaddr);
+ release_pte(*spte);
+
+ /*
+ * If they're setting this entry as dirty or accessed,
+ * we might as well put that entry they've given us in
+ * now. This shaves 10% off a copy-on-write
+ * micro-benchmark.
+ */
+ if (pte_flags(gpte) & (_PAGE_DIRTY | _PAGE_ACCESSED)) {
+ if (!check_gpte(cpu, gpte))
+ return;
+ set_pte(spte,
+ gpte_to_spte(cpu, gpte,
+ pte_flags(gpte) & _PAGE_DIRTY));
+ } else {
+ /*
+ * Otherwise kill it and we can demand_page()
+ * it in later.
+ */
+ set_pte(spte, __pte(0));
+ }
+#ifdef CONFIG_X86_PAE
+ }
+#endif
}
}
-/*H:410 Updating a PTE entry is a little trickier.
+/*H:410
+ * Updating a PTE entry is a little trickier.
*
* We keep track of several different page tables (the Guest uses one for each
* process, so it makes sense to cache at least a few). Each of these have
@@ -503,29 +940,38 @@ static void do_set_pte(struct lguest *lg, int idx,
* all processes. So when the page table above that address changes, we update
* all the page tables, not just the current one. This is rare.
*
- * The benefit is that when we have to track a new page table, we can copy keep
- * all the kernel mappings. This speeds up context switch immensely. */
-void guest_set_pte(struct lguest *lg,
- unsigned long cr3, unsigned long vaddr, gpte_t gpte)
-{
- /* Kernel mappings must be changed on all top levels. Slow, but
- * doesn't happen often. */
- if (vaddr >= lg->page_offset) {
+ * The benefit is that when we have to track a new page table, we can keep all
+ * the kernel mappings. This speeds up context switch immensely.
+ */
+void guest_set_pte(struct lg_cpu *cpu,
+ unsigned long gpgdir, unsigned long vaddr, pte_t gpte)
+{
+ /* We don't let you remap the Switcher; we need it to get back! */
+ if (vaddr >= switcher_addr) {
+ kill_guest(cpu, "attempt to set pte into Switcher pages");
+ return;
+ }
+
+ /*
+ * Kernel mappings must be changed on all top levels. Slow, but doesn't
+ * happen often.
+ */
+ if (vaddr >= cpu->lg->kernel_address) {
unsigned int i;
- for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++)
- if (lg->pgdirs[i].pgdir)
- do_set_pte(lg, i, vaddr, gpte);
+ for (i = 0; i < ARRAY_SIZE(cpu->lg->pgdirs); i++)
+ if (cpu->lg->pgdirs[i].pgdir)
+ __guest_set_pte(cpu, i, vaddr, gpte);
} else {
/* Is this page table one we have a shadow for? */
- int pgdir = find_pgdir(lg, cr3);
- if (pgdir != ARRAY_SIZE(lg->pgdirs))
+ int pgdir = find_pgdir(cpu->lg, gpgdir);
+ if (pgdir != ARRAY_SIZE(cpu->lg->pgdirs))
/* If so, do the update. */
- do_set_pte(lg, pgdir, vaddr, gpte);
+ __guest_set_pte(cpu, pgdir, vaddr, gpte);
}
}
/*H:400
- * (iii) Setting up a page table entry when the Guest tells us it has changed.
+ * (iii) Setting up a page table entry when the Guest tells us one has changed.
*
* Just like we did in interrupts_and_traps.c, it makes sense for us to deal
* with the other side of page tables while we're here: what happens when the
@@ -536,45 +982,105 @@ void guest_set_pte(struct lguest *lg,
* tells us they've changed. When the Guest tries to use the new entry it will
* fault and demand_page() will fix it up.
*
- * So with that in mind here's our code to to update a (top-level) PGD entry:
+ * So with that in mind here's our code to update a (top-level) PGD entry:
*/
-void guest_set_pmd(struct lguest *lg, unsigned long cr3, u32 idx)
+void guest_set_pgd(struct lguest *lg, unsigned long gpgdir, u32 idx)
{
int pgdir;
- /* The kernel seems to try to initialize this early on: we ignore its
- * attempts to map over the Switcher. */
- if (idx >= SWITCHER_PGD_INDEX)
+ if (idx > PTRS_PER_PGD) {
+ kill_guest(&lg->cpus[0], "Attempt to set pgd %u/%u",
+ idx, PTRS_PER_PGD);
return;
+ }
/* If they're talking about a page table we have a shadow for... */
- pgdir = find_pgdir(lg, cr3);
- if (pgdir < ARRAY_SIZE(lg->pgdirs))
+ pgdir = find_pgdir(lg, gpgdir);
+ if (pgdir < ARRAY_SIZE(lg->pgdirs)) {
/* ... throw it away. */
- release_pgd(lg, lg->pgdirs[pgdir].pgdir + idx);
+ release_pgd(lg->pgdirs[pgdir].pgdir + idx);
+ /* That might have been the Switcher mapping, remap it. */
+ if (!allocate_switcher_mapping(&lg->cpus[0])) {
+ kill_guest(&lg->cpus[0],
+ "Cannot populate switcher mapping");
+ }
+ lg->pgdirs[pgdir].last_host_cpu = -1;
+ }
+}
+
+#ifdef CONFIG_X86_PAE
+/* For setting a mid-level, we just throw everything away. It's easy. */
+void guest_set_pmd(struct lguest *lg, unsigned long pmdp, u32 idx)
+{
+ guest_pagetable_clear_all(&lg->cpus[0]);
}
+#endif
-/*H:500 (vii) Setting up the page tables initially.
+/*H:500
+ * (vii) Setting up the page tables initially.
*
- * When a Guest is first created, the Launcher tells us where the toplevel of
- * its first page table is. We set some things up here: */
-int init_guest_pagetable(struct lguest *lg, unsigned long pgtable)
-{
- /* In flush_user_mappings() we loop from 0 to
- * "vaddr_to_pgd_index(lg->page_offset)". This assumes it won't hit
- * the Switcher mappings, so check that now. */
- if (vaddr_to_pgd_index(lg->page_offset) >= SWITCHER_PGD_INDEX)
- return -EINVAL;
- /* We start on the first shadow page table, and give it a blank PGD
- * page. */
- lg->pgdidx = 0;
- lg->pgdirs[lg->pgdidx].cr3 = pgtable;
- lg->pgdirs[lg->pgdidx].pgdir = (spgd_t*)get_zeroed_page(GFP_KERNEL);
- if (!lg->pgdirs[lg->pgdidx].pgdir)
+ * When a Guest is first created, set initialize a shadow page table which
+ * we will populate on future faults. The Guest doesn't have any actual
+ * pagetables yet, so we set linear_pages to tell demand_page() to fake it
+ * for the moment.
+ *
+ * We do need the Switcher to be mapped at all times, so we allocate that
+ * part of the Guest page table here.
+ */
+int init_guest_pagetable(struct lguest *lg)
+{
+ struct lg_cpu *cpu = &lg->cpus[0];
+ int allocated = 0;
+
+ /* lg (and lg->cpus[]) starts zeroed: this allocates a new pgdir */
+ cpu->cpu_pgd = new_pgdir(cpu, 0, &allocated);
+ if (!allocated)
return -ENOMEM;
+
+ /* We start with a linear mapping until the initialize. */
+ cpu->linear_pages = true;
+
+ /* Allocate the page tables for the Switcher. */
+ if (!allocate_switcher_mapping(cpu)) {
+ release_all_pagetables(lg);
+ return -ENOMEM;
+ }
+
return 0;
}
+/*H:508 When the Guest calls LHCALL_LGUEST_INIT we do more setup. */
+void page_table_guest_data_init(struct lg_cpu *cpu)
+{
+ /*
+ * We tell the Guest that it can't use the virtual addresses
+ * used by the Switcher. This trick is equivalent to 4GB -
+ * switcher_addr.
+ */
+ u32 top = ~switcher_addr + 1;
+
+ /* We get the kernel address: above this is all kernel memory. */
+ if (get_user(cpu->lg->kernel_address,
+ &cpu->lg->lguest_data->kernel_address)
+ /*
+ * We tell the Guest that it can't use the top virtual
+ * addresses (used by the Switcher).
+ */
+ || put_user(top, &cpu->lg->lguest_data->reserve_mem)) {
+ kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
+ return;
+ }
+
+ /*
+ * In flush_user_mappings() we loop from 0 to
+ * "pgd_index(lg->kernel_address)". This assumes it won't hit the
+ * Switcher mappings, so check that now.
+ */
+ if (cpu->lg->kernel_address >= switcher_addr)
+ kill_guest(cpu, "bad kernel address %#lx",
+ cpu->lg->kernel_address);
+}
+
/* When a Guest dies, our cleanup is fairly simple. */
void free_guest_pagetable(struct lguest *lg)
{
@@ -587,94 +1093,104 @@ void free_guest_pagetable(struct lguest *lg)
free_page((long)lg->pgdirs[i].pgdir);
}
-/*H:480 (vi) Mapping the Switcher when the Guest is about to run.
- *
- * The Switcher and the two pages for this CPU need to be available to the
- * Guest (and not the pages for other CPUs). We have the appropriate PTE pages
- * for each CPU already set up, we just need to hook them in. */
-void map_switcher_in_guest(struct lguest *lg, struct lguest_pages *pages)
-{
- spte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages);
- spgd_t switcher_pgd;
- spte_t regs_pte;
-
- /* Make the last PGD entry for this Guest point to the Switcher's PTE
- * page for this CPU (with appropriate flags). */
- switcher_pgd.pfn = __pa(switcher_pte_page) >> PAGE_SHIFT;
- switcher_pgd.flags = _PAGE_KERNEL;
- lg->pgdirs[lg->pgdidx].pgdir[SWITCHER_PGD_INDEX] = switcher_pgd;
-
- /* We also change the Switcher PTE page. When we're running the Guest,
- * we want the Guest's "regs" page to appear where the first Switcher
- * page for this CPU is. This is an optimization: when the Switcher
- * saves the Guest registers, it saves them into the first page of this
- * CPU's "struct lguest_pages": if we make sure the Guest's register
- * page is already mapped there, we don't have to copy them out
- * again. */
- regs_pte.pfn = __pa(lg->regs_page) >> PAGE_SHIFT;
- regs_pte.flags = _PAGE_KERNEL;
- switcher_pte_page[(unsigned long)pages/PAGE_SIZE%PTES_PER_PAGE]
- = regs_pte;
-}
-/*:*/
-
-static void free_switcher_pte_pages(void)
+/*H:481
+ * This clears the Switcher mappings for cpu #i.
+ */
+static void remove_switcher_percpu_map(struct lg_cpu *cpu, unsigned int i)
{
- unsigned int i;
+ unsigned long base = switcher_addr + PAGE_SIZE + i * PAGE_SIZE*2;
+ pte_t *pte;
+
+ /* Clear the mappings for both pages. */
+ pte = find_spte(cpu, base, false, 0, 0);
+ release_pte(*pte);
+ set_pte(pte, __pte(0));
- for_each_possible_cpu(i)
- free_page((long)switcher_pte_page(i));
+ pte = find_spte(cpu, base + PAGE_SIZE, false, 0, 0);
+ release_pte(*pte);
+ set_pte(pte, __pte(0));
}
-/*H:520 Setting up the Switcher PTE page for given CPU is fairly easy, given
- * the CPU number and the "struct page"s for the Switcher code itself.
+/*H:480
+ * (vi) Mapping the Switcher when the Guest is about to run.
*
- * Currently the Switcher is less than a page long, so "pages" is always 1. */
-static __init void populate_switcher_pte_page(unsigned int cpu,
- struct page *switcher_page[],
- unsigned int pages)
+ * The Switcher and the two pages for this CPU need to be visible in the Guest
+ * (and not the pages for other CPUs).
+ *
+ * The pages for the pagetables have all been allocated before: we just need
+ * to make sure the actual PTEs are up-to-date for the CPU we're about to run
+ * on.
+ */
+void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages)
{
- unsigned int i;
- spte_t *pte = switcher_pte_page(cpu);
+ unsigned long base;
+ struct page *percpu_switcher_page, *regs_page;
+ pte_t *pte;
+ struct pgdir *pgdir = &cpu->lg->pgdirs[cpu->cpu_pgd];
+
+ /* Switcher page should always be mapped by now! */
+ BUG_ON(!pgdir->switcher_mapped);
+
+ /*
+ * Remember that we have two pages for each Host CPU, so we can run a
+ * Guest on each CPU without them interfering. We need to make sure
+ * those pages are mapped correctly in the Guest, but since we usually
+ * run on the same CPU, we cache that, and only update the mappings
+ * when we move.
+ */
+ if (pgdir->last_host_cpu == raw_smp_processor_id())
+ return;
- /* The first entries are easy: they map the Switcher code. */
- for (i = 0; i < pages; i++) {
- pte[i].pfn = page_to_pfn(switcher_page[i]);
- pte[i].flags = _PAGE_PRESENT|_PAGE_ACCESSED;
+ /* -1 means unknown so we remove everything. */
+ if (pgdir->last_host_cpu == -1) {
+ unsigned int i;
+ for_each_possible_cpu(i)
+ remove_switcher_percpu_map(cpu, i);
+ } else {
+ /* We know exactly what CPU mapping to remove. */
+ remove_switcher_percpu_map(cpu, pgdir->last_host_cpu);
}
- /* The only other thing we map is this CPU's pair of pages. */
- i = pages + cpu*2;
-
- /* First page (Guest registers) is writable from the Guest */
- pte[i].pfn = page_to_pfn(switcher_page[i]);
- pte[i].flags = _PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW;
- /* The second page contains the "struct lguest_ro_state", and is
- * read-only. */
- pte[i+1].pfn = page_to_pfn(switcher_page[i+1]);
- pte[i+1].flags = _PAGE_PRESENT|_PAGE_ACCESSED;
+ /*
+ * When we're running the Guest, we want the Guest's "regs" page to
+ * appear where the first Switcher page for this CPU is. This is an
+ * optimization: when the Switcher saves the Guest registers, it saves
+ * them into the first page of this CPU's "struct lguest_pages": if we
+ * make sure the Guest's register page is already mapped there, we
+ * don't have to copy them out again.
+ */
+ /* Find the shadow PTE for this regs page. */
+ base = switcher_addr + PAGE_SIZE
+ + raw_smp_processor_id() * sizeof(struct lguest_pages);
+ pte = find_spte(cpu, base, false, 0, 0);
+ regs_page = pfn_to_page(__pa(cpu->regs_page) >> PAGE_SHIFT);
+ get_page(regs_page);
+ set_pte(pte, mk_pte(regs_page, __pgprot(__PAGE_KERNEL & ~_PAGE_GLOBAL)));
+
+ /*
+ * We map the second page of the struct lguest_pages read-only in
+ * the Guest: the IDT, GDT and other things it's not supposed to
+ * change.
+ */
+ pte = find_spte(cpu, base + PAGE_SIZE, false, 0, 0);
+ percpu_switcher_page
+ = lg_switcher_pages[1 + raw_smp_processor_id()*2 + 1];
+ get_page(percpu_switcher_page);
+ set_pte(pte, mk_pte(percpu_switcher_page,
+ __pgprot(__PAGE_KERNEL_RO & ~_PAGE_GLOBAL)));
+
+ pgdir->last_host_cpu = raw_smp_processor_id();
}
-/*H:510 At boot or module load time, init_pagetables() allocates and populates
- * the Switcher PTE page for each CPU. */
-__init int init_pagetables(struct page **switcher_page, unsigned int pages)
-{
- unsigned int i;
-
- for_each_possible_cpu(i) {
- switcher_pte_page(i) = (spte_t *)get_zeroed_page(GFP_KERNEL);
- if (!switcher_pte_page(i)) {
- free_switcher_pte_pages();
- return -ENOMEM;
- }
- populate_switcher_pte_page(i, switcher_page, pages);
- }
- return 0;
-}
-/*:*/
-
-/* Cleaning up simply involves freeing the PTE page for each CPU. */
-void free_pagetables(void)
-{
- free_switcher_pte_pages();
-}
+/*H:490
+ * We've made it through the page table code. Perhaps our tired brains are
+ * still processing the details, or perhaps we're simply glad it's over.
+ *
+ * If nothing else, note that all this complexity in juggling shadow page tables
+ * in sync with the Guest's page tables is for one reason: for most Guests this
+ * page table dance determines how bad performance will be. This is why Xen
+ * uses exotic direct Guest pagetable manipulation, and why both Intel and AMD
+ * have implemented shadow page table support directly into hardware.
+ *
+ * There is just one file remaining in the Host.
+ */
diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c
index 9b81119f46e..c4fb424dfdd 100644
--- a/drivers/lguest/segments.c
+++ b/drivers/lguest/segments.c
@@ -1,4 +1,5 @@
-/*P:600 The x86 architecture has segments, which involve a table of descriptors
+/*P:600
+ * The x86 architecture has segments, which involve a table of descriptors
* which can be used to do funky things with virtual address interpretation.
* We originally used to use segments so the Guest couldn't alter the
* Guest<->Host Switcher, and then we had to trim Guest segments, and restore
@@ -8,12 +9,11 @@
*
* In these modern times, the segment handling code consists of simple sanity
* checks, and the worst you'll experience reading this code is butterfly-rash
- * from frolicking through its parklike serenity. :*/
+ * from frolicking through its parklike serenity.
+:*/
#include "lg.h"
/*H:600
- * We've almost completed the Host; there's just one file to go!
- *
* Segments & The Global Descriptor Table
*
* (That title sounds like a bad Nerdcore group. Not to suggest that there are
@@ -43,11 +43,13 @@
* begin.
*/
-/* There are several entries we don't let the Guest set. The TSS entry is the
+/*
+ * There are several entries we don't let the Guest set. The TSS entry is the
* "Task State Segment" which controls all kinds of delicate things. The
* LGUEST_CS and LGUEST_DS entries are reserved for the Switcher, and the
- * the Guest can't be trusted to deal with double faults. */
-static int ignored_gdt(unsigned int num)
+ * the Guest can't be trusted to deal with double faults.
+ */
+static bool ignored_gdt(unsigned int num)
{
return (num == GDT_ENTRY_TSS
|| num == GDT_ENTRY_LGUEST_CS
@@ -55,118 +57,167 @@ static int ignored_gdt(unsigned int num)
|| num == GDT_ENTRY_DOUBLEFAULT_TSS);
}
-/*H:610 Once the GDT has been changed, we fix the new entries up a little. We
+/*H:630
+ * Once the Guest gave us new GDT entries, we fix them up a little. We
* don't care if they're invalid: the worst that can happen is a General
* Protection Fault in the Switcher when it restores a Guest segment register
* which tries to use that entry. Then we kill the Guest for causing such a
- * mess: the message will be "unhandled trap 256". */
-static void fixup_gdt_table(struct lguest *lg, unsigned start, unsigned end)
+ * mess: the message will be "unhandled trap 256".
+ */
+static void fixup_gdt_table(struct lg_cpu *cpu, unsigned start, unsigned end)
{
unsigned int i;
for (i = start; i < end; i++) {
- /* We never copy these ones to real GDT, so we don't care what
- * they say */
+ /*
+ * We never copy these ones to real GDT, so we don't care what
+ * they say
+ */
if (ignored_gdt(i))
continue;
- /* Segment descriptors contain a privilege level: the Guest is
+ /*
+ * Segment descriptors contain a privilege level: the Guest is
* sometimes careless and leaves this as 0, even though it's
- * running at privilege level 1. If so, we fix it here. */
- if ((lg->gdt[i].b & 0x00006000) == 0)
- lg->gdt[i].b |= (GUEST_PL << 13);
+ * running at privilege level 1. If so, we fix it here.
+ */
+ if (cpu->arch.gdt[i].dpl == 0)
+ cpu->arch.gdt[i].dpl |= GUEST_PL;
- /* Each descriptor has an "accessed" bit. If we don't set it
+ /*
+ * Each descriptor has an "accessed" bit. If we don't set it
* now, the CPU will try to set it when the Guest first loads
* that entry into a segment register. But the GDT isn't
- * writable by the Guest, so bad things can happen. */
- lg->gdt[i].b |= 0x00000100;
+ * writable by the Guest, so bad things can happen.
+ */
+ cpu->arch.gdt[i].type |= 0x1;
}
}
-/* This routine is called at boot or modprobe time for each CPU to set up the
- * "constant" GDT entries for Guests running on that CPU. */
+/*H:610
+ * Like the IDT, we never simply use the GDT the Guest gives us. We keep
+ * a GDT for each CPU, and copy across the Guest's entries each time we want to
+ * run the Guest on that CPU.
+ *
+ * This routine is called at boot or modprobe time for each CPU to set up the
+ * constant GDT entries: the ones which are the same no matter what Guest we're
+ * running.
+ */
void setup_default_gdt_entries(struct lguest_ro_state *state)
{
struct desc_struct *gdt = state->guest_gdt;
unsigned long tss = (unsigned long)&state->guest_tss;
- /* The hypervisor segments are full 0-4G segments, privilege level 0 */
+ /* The Switcher segments are full 0-4G segments, privilege level 0 */
gdt[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
gdt[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
- /* The TSS segment refers to the TSS entry for this CPU, so we cannot
- * copy it from the Guest. Forgive the magic flags */
- gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16);
- gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000)
- | ((tss >> 16) & 0x000000FF);
+ /*
+ * The TSS segment refers to the TSS entry for this particular CPU.
+ */
+ gdt[GDT_ENTRY_TSS].a = 0;
+ gdt[GDT_ENTRY_TSS].b = 0;
+
+ gdt[GDT_ENTRY_TSS].limit0 = 0x67;
+ gdt[GDT_ENTRY_TSS].base0 = tss & 0xFFFF;
+ gdt[GDT_ENTRY_TSS].base1 = (tss >> 16) & 0xFF;
+ gdt[GDT_ENTRY_TSS].base2 = tss >> 24;
+ gdt[GDT_ENTRY_TSS].type = 0x9; /* 32-bit TSS (available) */
+ gdt[GDT_ENTRY_TSS].p = 0x1; /* Entry is present */
+ gdt[GDT_ENTRY_TSS].dpl = 0x0; /* Privilege level 0 */
+ gdt[GDT_ENTRY_TSS].s = 0x0; /* system segment */
+
}
-/* This routine is called before the Guest is run for the first time. */
-void setup_guest_gdt(struct lguest *lg)
+/*
+ * This routine sets up the initial Guest GDT for booting. All entries start
+ * as 0 (unusable).
+ */
+void setup_guest_gdt(struct lg_cpu *cpu)
{
- /* Start with full 0-4G segments... */
- lg->gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
- lg->gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
- /* ...except the Guest is allowed to use them, so set the privilege
- * level appropriately in the flags. */
- lg->gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13);
- lg->gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
+ /*
+ * Start with full 0-4G segments...except the Guest is allowed to use
+ * them, so set the privilege level appropriately in the flags.
+ */
+ cpu->arch.gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
+ cpu->arch.gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
+ cpu->arch.gdt[GDT_ENTRY_KERNEL_CS].dpl |= GUEST_PL;
+ cpu->arch.gdt[GDT_ENTRY_KERNEL_DS].dpl |= GUEST_PL;
}
-/* Like the IDT, we never simply use the GDT the Guest gives us. We set up the
- * GDTs for each CPU, then we copy across the entries each time we want to run
- * a different Guest on that CPU. */
-
-/* A partial GDT load, for the three "thead-local storage" entries. Otherwise
- * it's just like load_guest_gdt(). So much, in fact, it would probably be
- * neater to have a single hypercall to cover both. */
-void copy_gdt_tls(const struct lguest *lg, struct desc_struct *gdt)
+/*H:650
+ * An optimization of copy_gdt(), for just the three "thead-local storage"
+ * entries.
+ */
+void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt)
{
unsigned int i;
for (i = GDT_ENTRY_TLS_MIN; i <= GDT_ENTRY_TLS_MAX; i++)
- gdt[i] = lg->gdt[i];
+ gdt[i] = cpu->arch.gdt[i];
}
-/* This is the full version */
-void copy_gdt(const struct lguest *lg, struct desc_struct *gdt)
+/*H:640
+ * When the Guest is run on a different CPU, or the GDT entries have changed,
+ * copy_gdt() is called to copy the Guest's GDT entries across to this CPU's
+ * GDT.
+ */
+void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt)
{
unsigned int i;
- /* The default entries from setup_default_gdt_entries() are not
- * replaced. See ignored_gdt() above. */
+ /*
+ * The default entries from setup_default_gdt_entries() are not
+ * replaced. See ignored_gdt() above.
+ */
for (i = 0; i < GDT_ENTRIES; i++)
if (!ignored_gdt(i))
- gdt[i] = lg->gdt[i];
+ gdt[i] = cpu->arch.gdt[i];
}
-/* This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT). */
-void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num)
+/*H:620
+ * This is where the Guest asks us to load a new GDT entry
+ * (LHCALL_LOAD_GDT_ENTRY). We tweak the entry and copy it in.
+ */
+void load_guest_gdt_entry(struct lg_cpu *cpu, u32 num, u32 lo, u32 hi)
{
- /* We assume the Guest has the same number of GDT entries as the
- * Host, otherwise we'd have to dynamically allocate the Guest GDT. */
- if (num > ARRAY_SIZE(lg->gdt))
- kill_guest(lg, "too many gdt entries %i", num);
-
- /* We read the whole thing in, then fix it up. */
- lgread(lg, lg->gdt, table, num * sizeof(lg->gdt[0]));
- fixup_gdt_table(lg, 0, ARRAY_SIZE(lg->gdt));
- /* Mark that the GDT changed so the core knows it has to copy it again,
- * even if the Guest is run on the same CPU. */
- lg->changed |= CHANGED_GDT;
+ /*
+ * We assume the Guest has the same number of GDT entries as the
+ * Host, otherwise we'd have to dynamically allocate the Guest GDT.
+ */
+ if (num >= ARRAY_SIZE(cpu->arch.gdt)) {
+ kill_guest(cpu, "too many gdt entries %i", num);
+ return;
+ }
+
+ /* Set it up, then fix it. */
+ cpu->arch.gdt[num].a = lo;
+ cpu->arch.gdt[num].b = hi;
+ fixup_gdt_table(cpu, num, num+1);
+ /*
+ * Mark that the GDT changed so the core knows it has to copy it again,
+ * even if the Guest is run on the same CPU.
+ */
+ cpu->changed |= CHANGED_GDT;
}
-void guest_load_tls(struct lguest *lg, unsigned long gtls)
+/*
+ * This is the fast-track version for just changing the three TLS entries.
+ * Remember that this happens on every context switch, so it's worth
+ * optimizing. But wouldn't it be neater to have a single hypercall to cover
+ * both cases?
+ */
+void guest_load_tls(struct lg_cpu *cpu, unsigned long gtls)
{
- struct desc_struct *tls = &lg->gdt[GDT_ENTRY_TLS_MIN];
+ struct desc_struct *tls = &cpu->arch.gdt[GDT_ENTRY_TLS_MIN];
- lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES);
- fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1);
- lg->changed |= CHANGED_GDT_TLS;
+ __lgread(cpu, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES);
+ fixup_gdt_table(cpu, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1);
+ /* Note that just the TLS entries have changed. */
+ cpu->changed |= CHANGED_GDT_TLS;
}
-/*
+/*H:660
* With this, we have finished the Host.
*
* Five of the seven parts of our task are complete. You have made it through
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
new file mode 100644
index 00000000000..922a1acbf65
--- /dev/null
+++ b/drivers/lguest/x86/core.c
@@ -0,0 +1,720 @@
+/*
+ * Copyright (C) 2006, Rusty Russell <rusty@rustcorp.com.au> IBM Corporation.
+ * Copyright (C) 2007, Jes Sorensen <jes@sgi.com> SGI.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*P:450
+ * This file contains the x86-specific lguest code. It used to be all
+ * mixed in with drivers/lguest/core.c but several foolhardy code slashers
+ * wrestled most of the dependencies out to here in preparation for porting
+ * lguest to other architectures (see what I mean by foolhardy?).
+ *
+ * This also contains a couple of non-obvious setup and teardown pieces which
+ * were implemented after days of debugging pain.
+:*/
+#include <linux/kernel.h>
+#include <linux/start_kernel.h>
+#include <linux/string.h>
+#include <linux/console.h>
+#include <linux/screen_info.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/cpu.h>
+#include <linux/lguest.h>
+#include <linux/lguest_launcher.h>
+#include <asm/paravirt.h>
+#include <asm/param.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/desc.h>
+#include <asm/setup.h>
+#include <asm/lguest.h>
+#include <asm/uaccess.h>
+#include <asm/i387.h>
+#include "../lg.h"
+
+static int cpu_had_pge;
+
+static struct {
+ unsigned long offset;
+ unsigned short segment;
+} lguest_entry;
+
+/* Offset from where switcher.S was compiled to where we've copied it */
+static unsigned long switcher_offset(void)
+{
+ return switcher_addr - (unsigned long)start_switcher_text;
+}
+
+/* This cpu's struct lguest_pages (after the Switcher text page) */
+static struct lguest_pages *lguest_pages(unsigned int cpu)
+{
+ return &(((struct lguest_pages *)(switcher_addr + PAGE_SIZE))[cpu]);
+}
+
+static DEFINE_PER_CPU(struct lg_cpu *, lg_last_cpu);
+
+/*S:010
+ * We approach the Switcher.
+ *
+ * Remember that each CPU has two pages which are visible to the Guest when it
+ * runs on that CPU. This has to contain the state for that Guest: we copy the
+ * state in just before we run the Guest.
+ *
+ * Each Guest has "changed" flags which indicate what has changed in the Guest
+ * since it last ran. We saw this set in interrupts_and_traps.c and
+ * segments.c.
+ */
+static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages)
+{
+ /*
+ * Copying all this data can be quite expensive. We usually run the
+ * same Guest we ran last time (and that Guest hasn't run anywhere else
+ * meanwhile). If that's not the case, we pretend everything in the
+ * Guest has changed.
+ */
+ if (__this_cpu_read(lg_last_cpu) != cpu || cpu->last_pages != pages) {
+ __this_cpu_write(lg_last_cpu, cpu);
+ cpu->last_pages = pages;
+ cpu->changed = CHANGED_ALL;
+ }
+
+ /*
+ * These copies are pretty cheap, so we do them unconditionally: */
+ /* Save the current Host top-level page directory.
+ */
+ pages->state.host_cr3 = __pa(current->mm->pgd);
+ /*
+ * Set up the Guest's page tables to see this CPU's pages (and no
+ * other CPU's pages).
+ */
+ map_switcher_in_guest(cpu, pages);
+ /*
+ * Set up the two "TSS" members which tell the CPU what stack to use
+ * for traps which do directly into the Guest (ie. traps at privilege
+ * level 1).
+ */
+ pages->state.guest_tss.sp1 = cpu->esp1;
+ pages->state.guest_tss.ss1 = cpu->ss1;
+
+ /* Copy direct-to-Guest trap entries. */
+ if (cpu->changed & CHANGED_IDT)
+ copy_traps(cpu, pages->state.guest_idt, default_idt_entries);
+
+ /* Copy all GDT entries which the Guest can change. */
+ if (cpu->changed & CHANGED_GDT)
+ copy_gdt(cpu, pages->state.guest_gdt);
+ /* If only the TLS entries have changed, copy them. */
+ else if (cpu->changed & CHANGED_GDT_TLS)
+ copy_gdt_tls(cpu, pages->state.guest_gdt);
+
+ /* Mark the Guest as unchanged for next time. */
+ cpu->changed = 0;
+}
+
+/* Finally: the code to actually call into the Switcher to run the Guest. */
+static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages)
+{
+ /* This is a dummy value we need for GCC's sake. */
+ unsigned int clobber;
+
+ /*
+ * Copy the guest-specific information into this CPU's "struct
+ * lguest_pages".
+ */
+ copy_in_guest_info(cpu, pages);
+
+ /*
+ * Set the trap number to 256 (impossible value). If we fault while
+ * switching to the Guest (bad segment registers or bug), this will
+ * cause us to abort the Guest.
+ */
+ cpu->regs->trapnum = 256;
+
+ /*
+ * Now: we push the "eflags" register on the stack, then do an "lcall".
+ * This is how we change from using the kernel code segment to using
+ * the dedicated lguest code segment, as well as jumping into the
+ * Switcher.
+ *
+ * The lcall also pushes the old code segment (KERNEL_CS) onto the
+ * stack, then the address of this call. This stack layout happens to
+ * exactly match the stack layout created by an interrupt...
+ */
+ asm volatile("pushf; lcall *%4"
+ /*
+ * This is how we tell GCC that %eax ("a") and %ebx ("b")
+ * are changed by this routine. The "=" means output.
+ */
+ : "=a"(clobber), "=b"(clobber)
+ /*
+ * %eax contains the pages pointer. ("0" refers to the
+ * 0-th argument above, ie "a"). %ebx contains the
+ * physical address of the Guest's top-level page
+ * directory.
+ */
+ : "0"(pages),
+ "1"(__pa(cpu->lg->pgdirs[cpu->cpu_pgd].pgdir)),
+ "m"(lguest_entry)
+ /*
+ * We tell gcc that all these registers could change,
+ * which means we don't have to save and restore them in
+ * the Switcher.
+ */
+ : "memory", "%edx", "%ecx", "%edi", "%esi");
+}
+/*:*/
+
+/*M:002
+ * There are hooks in the scheduler which we can register to tell when we
+ * get kicked off the CPU (preempt_notifier_register()). This would allow us
+ * to lazily disable SYSENTER which would regain some performance, and should
+ * also simplify copy_in_guest_info(). Note that we'd still need to restore
+ * things when we exit to Launcher userspace, but that's fairly easy.
+ *
+ * We could also try using these hooks for PGE, but that might be too expensive.
+ *
+ * The hooks were designed for KVM, but we can also put them to good use.
+:*/
+
+/*H:040
+ * This is the i386-specific code to setup and run the Guest. Interrupts
+ * are disabled: we own the CPU.
+ */
+void lguest_arch_run_guest(struct lg_cpu *cpu)
+{
+ /*
+ * Remember the awfully-named TS bit? If the Guest has asked to set it
+ * we set it now, so we can trap and pass that trap to the Guest if it
+ * uses the FPU.
+ */
+ if (cpu->ts && user_has_fpu())
+ stts();
+
+ /*
+ * SYSENTER is an optimized way of doing system calls. We can't allow
+ * it because it always jumps to privilege level 0. A normal Guest
+ * won't try it because we don't advertise it in CPUID, but a malicious
+ * Guest (or malicious Guest userspace program) could, so we tell the
+ * CPU to disable it before running the Guest.
+ */
+ if (boot_cpu_has(X86_FEATURE_SEP))
+ wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
+
+ /*
+ * Now we actually run the Guest. It will return when something
+ * interesting happens, and we can examine its registers to see what it
+ * was doing.
+ */
+ run_guest_once(cpu, lguest_pages(raw_smp_processor_id()));
+
+ /*
+ * Note that the "regs" structure contains two extra entries which are
+ * not really registers: a trap number which says what interrupt or
+ * trap made the switcher code come back, and an error code which some
+ * traps set.
+ */
+
+ /* Restore SYSENTER if it's supposed to be on. */
+ if (boot_cpu_has(X86_FEATURE_SEP))
+ wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
+
+ /* Clear the host TS bit if it was set above. */
+ if (cpu->ts && user_has_fpu())
+ clts();
+
+ /*
+ * If the Guest page faulted, then the cr2 register will tell us the
+ * bad virtual address. We have to grab this now, because once we
+ * re-enable interrupts an interrupt could fault and thus overwrite
+ * cr2, or we could even move off to a different CPU.
+ */
+ if (cpu->regs->trapnum == 14)
+ cpu->arch.last_pagefault = read_cr2();
+ /*
+ * Similarly, if we took a trap because the Guest used the FPU,
+ * we have to restore the FPU it expects to see.
+ * math_state_restore() may sleep and we may even move off to
+ * a different CPU. So all the critical stuff should be done
+ * before this.
+ */
+ else if (cpu->regs->trapnum == 7 && !user_has_fpu())
+ math_state_restore();
+}
+
+/*H:130
+ * Now we've examined the hypercall code; our Guest can make requests.
+ * Our Guest is usually so well behaved; it never tries to do things it isn't
+ * allowed to, and uses hypercalls instead. Unfortunately, Linux's paravirtual
+ * infrastructure isn't quite complete, because it doesn't contain replacements
+ * for the Intel I/O instructions. As a result, the Guest sometimes fumbles
+ * across one during the boot process as it probes for various things which are
+ * usually attached to a PC.
+ *
+ * When the Guest uses one of these instructions, we get a trap (General
+ * Protection Fault) and come here. We see if it's one of those troublesome
+ * instructions and skip over it. We return true if we did.
+ */
+static int emulate_insn(struct lg_cpu *cpu)
+{
+ u8 insn;
+ unsigned int insnlen = 0, in = 0, small_operand = 0;
+ /*
+ * The eip contains the *virtual* address of the Guest's instruction:
+ * walk the Guest's page tables to find the "physical" address.
+ */
+ unsigned long physaddr = guest_pa(cpu, cpu->regs->eip);
+
+ /*
+ * This must be the Guest kernel trying to do something, not userspace!
+ * The bottom two bits of the CS segment register are the privilege
+ * level.
+ */
+ if ((cpu->regs->cs & 3) != GUEST_PL)
+ return 0;
+
+ /* Decoding x86 instructions is icky. */
+ insn = lgread(cpu, physaddr, u8);
+
+ /*
+ * Around 2.6.33, the kernel started using an emulation for the
+ * cmpxchg8b instruction in early boot on many configurations. This
+ * code isn't paravirtualized, and it tries to disable interrupts.
+ * Ignore it, which will Mostly Work.
+ */
+ if (insn == 0xfa) {
+ /* "cli", or Clear Interrupt Enable instruction. Skip it. */
+ cpu->regs->eip++;
+ return 1;
+ }
+
+ /*
+ * 0x66 is an "operand prefix". It means a 16, not 32 bit in/out.
+ */
+ if (insn == 0x66) {
+ small_operand = 1;
+ /* The instruction is 1 byte so far, read the next byte. */
+ insnlen = 1;
+ insn = lgread(cpu, physaddr + insnlen, u8);
+ }
+
+ /*
+ * We can ignore the lower bit for the moment and decode the 4 opcodes
+ * we need to emulate.
+ */
+ switch (insn & 0xFE) {
+ case 0xE4: /* in <next byte>,%al */
+ insnlen += 2;
+ in = 1;
+ break;
+ case 0xEC: /* in (%dx),%al */
+ insnlen += 1;
+ in = 1;
+ break;
+ case 0xE6: /* out %al,<next byte> */
+ insnlen += 2;
+ break;
+ case 0xEE: /* out %al,(%dx) */
+ insnlen += 1;
+ break;
+ default:
+ /* OK, we don't know what this is, can't emulate. */
+ return 0;
+ }
+
+ /*
+ * If it was an "IN" instruction, they expect the result to be read
+ * into %eax, so we change %eax. We always return all-ones, which
+ * traditionally means "there's nothing there".
+ */
+ if (in) {
+ /* Lower bit tells means it's a 32/16 bit access */
+ if (insn & 0x1) {
+ if (small_operand)
+ cpu->regs->eax |= 0xFFFF;
+ else
+ cpu->regs->eax = 0xFFFFFFFF;
+ } else
+ cpu->regs->eax |= 0xFF;
+ }
+ /* Finally, we've "done" the instruction, so move past it. */
+ cpu->regs->eip += insnlen;
+ /* Success! */
+ return 1;
+}
+
+/*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */
+void lguest_arch_handle_trap(struct lg_cpu *cpu)
+{
+ switch (cpu->regs->trapnum) {
+ case 13: /* We've intercepted a General Protection Fault. */
+ /*
+ * Check if this was one of those annoying IN or OUT
+ * instructions which we need to emulate. If so, we just go
+ * back into the Guest after we've done it.
+ */
+ if (cpu->regs->errcode == 0) {
+ if (emulate_insn(cpu))
+ return;
+ }
+ break;
+ case 14: /* We've intercepted a Page Fault. */
+ /*
+ * The Guest accessed a virtual address that wasn't mapped.
+ * This happens a lot: we don't actually set up most of the page
+ * tables for the Guest at all when we start: as it runs it asks
+ * for more and more, and we set them up as required. In this
+ * case, we don't even tell the Guest that the fault happened.
+ *
+ * The errcode tells whether this was a read or a write, and
+ * whether kernel or userspace code.
+ */
+ if (demand_page(cpu, cpu->arch.last_pagefault,
+ cpu->regs->errcode))
+ return;
+
+ /*
+ * OK, it's really not there (or not OK): the Guest needs to
+ * know. We write out the cr2 value so it knows where the
+ * fault occurred.
+ *
+ * Note that if the Guest were really messed up, this could
+ * happen before it's done the LHCALL_LGUEST_INIT hypercall, so
+ * lg->lguest_data could be NULL
+ */
+ if (cpu->lg->lguest_data &&
+ put_user(cpu->arch.last_pagefault,
+ &cpu->lg->lguest_data->cr2))
+ kill_guest(cpu, "Writing cr2");
+ break;
+ case 7: /* We've intercepted a Device Not Available fault. */
+ /*
+ * If the Guest doesn't want to know, we already restored the
+ * Floating Point Unit, so we just continue without telling it.
+ */
+ if (!cpu->ts)
+ return;
+ break;
+ case 32 ... 255:
+ /*
+ * These values mean a real interrupt occurred, in which case
+ * the Host handler has already been run. We just do a
+ * friendly check if another process should now be run, then
+ * return to run the Guest again.
+ */
+ cond_resched();
+ return;
+ case LGUEST_TRAP_ENTRY:
+ /*
+ * Our 'struct hcall_args' maps directly over our regs: we set
+ * up the pointer now to indicate a hypercall is pending.
+ */
+ cpu->hcall = (struct hcall_args *)cpu->regs;
+ return;
+ }
+
+ /* We didn't handle the trap, so it needs to go to the Guest. */
+ if (!deliver_trap(cpu, cpu->regs->trapnum))
+ /*
+ * If the Guest doesn't have a handler (either it hasn't
+ * registered any yet, or it's one of the faults we don't let
+ * it handle), it dies with this cryptic error message.
+ */
+ kill_guest(cpu, "unhandled trap %li at %#lx (%#lx)",
+ cpu->regs->trapnum, cpu->regs->eip,
+ cpu->regs->trapnum == 14 ? cpu->arch.last_pagefault
+ : cpu->regs->errcode);
+}
+
+/*
+ * Now we can look at each of the routines this calls, in increasing order of
+ * complexity: do_hypercalls(), emulate_insn(), maybe_do_interrupt(),
+ * deliver_trap() and demand_page(). After all those, we'll be ready to
+ * examine the Switcher, and our philosophical understanding of the Host/Guest
+ * duality will be complete.
+:*/
+static void adjust_pge(void *on)
+{
+ if (on)
+ write_cr4(read_cr4() | X86_CR4_PGE);
+ else
+ write_cr4(read_cr4() & ~X86_CR4_PGE);
+}
+
+/*H:020
+ * Now the Switcher is mapped and every thing else is ready, we need to do
+ * some more i386-specific initialization.
+ */
+void __init lguest_arch_host_init(void)
+{
+ int i;
+
+ /*
+ * Most of the x86/switcher_32.S doesn't care that it's been moved; on
+ * Intel, jumps are relative, and it doesn't access any references to
+ * external code or data.
+ *
+ * The only exception is the interrupt handlers in switcher.S: their
+ * addresses are placed in a table (default_idt_entries), so we need to
+ * update the table with the new addresses. switcher_offset() is a
+ * convenience function which returns the distance between the
+ * compiled-in switcher code and the high-mapped copy we just made.
+ */
+ for (i = 0; i < IDT_ENTRIES; i++)
+ default_idt_entries[i] += switcher_offset();
+
+ /*
+ * Set up the Switcher's per-cpu areas.
+ *
+ * Each CPU gets two pages of its own within the high-mapped region
+ * (aka. "struct lguest_pages"). Much of this can be initialized now,
+ * but some depends on what Guest we are running (which is set up in
+ * copy_in_guest_info()).
+ */
+ for_each_possible_cpu(i) {
+ /* lguest_pages() returns this CPU's two pages. */
+ struct lguest_pages *pages = lguest_pages(i);
+ /* This is a convenience pointer to make the code neater. */
+ struct lguest_ro_state *state = &pages->state;
+
+ /*
+ * The Global Descriptor Table: the Host has a different one
+ * for each CPU. We keep a descriptor for the GDT which says
+ * where it is and how big it is (the size is actually the last
+ * byte, not the size, hence the "-1").
+ */
+ state->host_gdt_desc.size = GDT_SIZE-1;
+ state->host_gdt_desc.address = (long)get_cpu_gdt_table(i);
+
+ /*
+ * All CPUs on the Host use the same Interrupt Descriptor
+ * Table, so we just use store_idt(), which gets this CPU's IDT
+ * descriptor.
+ */
+ store_idt(&state->host_idt_desc);
+
+ /*
+ * The descriptors for the Guest's GDT and IDT can be filled
+ * out now, too. We copy the GDT & IDT into ->guest_gdt and
+ * ->guest_idt before actually running the Guest.
+ */
+ state->guest_idt_desc.size = sizeof(state->guest_idt)-1;
+ state->guest_idt_desc.address = (long)&state->guest_idt;
+ state->guest_gdt_desc.size = sizeof(state->guest_gdt)-1;
+ state->guest_gdt_desc.address = (long)&state->guest_gdt;
+
+ /*
+ * We know where we want the stack to be when the Guest enters
+ * the Switcher: in pages->regs. The stack grows upwards, so
+ * we start it at the end of that structure.
+ */
+ state->guest_tss.sp0 = (long)(&pages->regs + 1);
+ /*
+ * And this is the GDT entry to use for the stack: we keep a
+ * couple of special LGUEST entries.
+ */
+ state->guest_tss.ss0 = LGUEST_DS;
+
+ /*
+ * x86 can have a finegrained bitmap which indicates what I/O
+ * ports the process can use. We set it to the end of our
+ * structure, meaning "none".
+ */
+ state->guest_tss.io_bitmap_base = sizeof(state->guest_tss);
+
+ /*
+ * Some GDT entries are the same across all Guests, so we can
+ * set them up now.
+ */
+ setup_default_gdt_entries(state);
+ /* Most IDT entries are the same for all Guests, too.*/
+ setup_default_idt_entries(state, default_idt_entries);
+
+ /*
+ * The Host needs to be able to use the LGUEST segments on this
+ * CPU, too, so put them in the Host GDT.
+ */
+ get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
+ get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
+ }
+
+ /*
+ * In the Switcher, we want the %cs segment register to use the
+ * LGUEST_CS GDT entry: we've put that in the Host and Guest GDTs, so
+ * it will be undisturbed when we switch. To change %cs and jump we
+ * need this structure to feed to Intel's "lcall" instruction.
+ */
+ lguest_entry.offset = (long)switch_to_guest + switcher_offset();
+ lguest_entry.segment = LGUEST_CS;
+
+ /*
+ * Finally, we need to turn off "Page Global Enable". PGE is an
+ * optimization where page table entries are specially marked to show
+ * they never change. The Host kernel marks all the kernel pages this
+ * way because it's always present, even when userspace is running.
+ *
+ * Lguest breaks this: unbeknownst to the rest of the Host kernel, we
+ * switch to the Guest kernel. If you don't disable this on all CPUs,
+ * you'll get really weird bugs that you'll chase for two days.
+ *
+ * I used to turn PGE off every time we switched to the Guest and back
+ * on when we return, but that slowed the Switcher down noticibly.
+ */
+
+ /*
+ * We don't need the complexity of CPUs coming and going while we're
+ * doing this.
+ */
+ get_online_cpus();
+ if (cpu_has_pge) { /* We have a broader idea of "global". */
+ /* Remember that this was originally set (for cleanup). */
+ cpu_had_pge = 1;
+ /*
+ * adjust_pge is a helper function which sets or unsets the PGE
+ * bit on its CPU, depending on the argument (0 == unset).
+ */
+ on_each_cpu(adjust_pge, (void *)0, 1);
+ /* Turn off the feature in the global feature set. */
+ clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
+ }
+ put_online_cpus();
+}
+/*:*/
+
+void __exit lguest_arch_host_fini(void)
+{
+ /* If we had PGE before we started, turn it back on now. */
+ get_online_cpus();
+ if (cpu_had_pge) {
+ set_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
+ /* adjust_pge's argument "1" means set PGE. */
+ on_each_cpu(adjust_pge, (void *)1, 1);
+ }
+ put_online_cpus();
+}
+
+
+/*H:122 The i386-specific hypercalls simply farm out to the right functions. */
+int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
+{
+ switch (args->arg0) {
+ case LHCALL_LOAD_GDT_ENTRY:
+ load_guest_gdt_entry(cpu, args->arg1, args->arg2, args->arg3);
+ break;
+ case LHCALL_LOAD_IDT_ENTRY:
+ load_guest_idt_entry(cpu, args->arg1, args->arg2, args->arg3);
+ break;
+ case LHCALL_LOAD_TLS:
+ guest_load_tls(cpu, args->arg1);
+ break;
+ default:
+ /* Bad Guest. Bad! */
+ return -EIO;
+ }
+ return 0;
+}
+
+/*H:126 i386-specific hypercall initialization: */
+int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
+{
+ u32 tsc_speed;
+
+ /*
+ * The pointer to the Guest's "struct lguest_data" is the only argument.
+ * We check that address now.
+ */
+ if (!lguest_address_ok(cpu->lg, cpu->hcall->arg1,
+ sizeof(*cpu->lg->lguest_data)))
+ return -EFAULT;
+
+ /*
+ * Having checked it, we simply set lg->lguest_data to point straight
+ * into the Launcher's memory at the right place and then use
+ * copy_to_user/from_user from now on, instead of lgread/write. I put
+ * this in to show that I'm not immune to writing stupid
+ * optimizations.
+ */
+ cpu->lg->lguest_data = cpu->lg->mem_base + cpu->hcall->arg1;
+
+ /*
+ * We insist that the Time Stamp Counter exist and doesn't change with
+ * cpu frequency. Some devious chip manufacturers decided that TSC
+ * changes could be handled in software. I decided that time going
+ * backwards might be good for benchmarks, but it's bad for users.
+ *
+ * We also insist that the TSC be stable: the kernel detects unreliable
+ * TSCs for its own purposes, and we use that here.
+ */
+ if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable())
+ tsc_speed = tsc_khz;
+ else
+ tsc_speed = 0;
+ if (put_user(tsc_speed, &cpu->lg->lguest_data->tsc_khz))
+ return -EFAULT;
+
+ /* The interrupt code might not like the system call vector. */
+ if (!check_syscall_vector(cpu->lg))
+ kill_guest(cpu, "bad syscall vector");
+
+ return 0;
+}
+/*:*/
+
+/*L:030
+ * Most of the Guest's registers are left alone: we used get_zeroed_page() to
+ * allocate the structure, so they will be 0.
+ */
+void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start)
+{
+ struct lguest_regs *regs = cpu->regs;
+
+ /*
+ * There are four "segment" registers which the Guest needs to boot:
+ * The "code segment" register (cs) refers to the kernel code segment
+ * __KERNEL_CS, and the "data", "extra" and "stack" segment registers
+ * refer to the kernel data segment __KERNEL_DS.
+ *
+ * The privilege level is packed into the lower bits. The Guest runs
+ * at privilege level 1 (GUEST_PL).
+ */
+ regs->ds = regs->es = regs->ss = __KERNEL_DS|GUEST_PL;
+ regs->cs = __KERNEL_CS|GUEST_PL;
+
+ /*
+ * The "eflags" register contains miscellaneous flags. Bit 1 (0x002)
+ * is supposed to always be "1". Bit 9 (0x200) controls whether
+ * interrupts are enabled. We always leave interrupts enabled while
+ * running the Guest.
+ */
+ regs->eflags = X86_EFLAGS_IF | X86_EFLAGS_FIXED;
+
+ /*
+ * The "Extended Instruction Pointer" register says where the Guest is
+ * running.
+ */
+ regs->eip = start;
+
+ /*
+ * %esi points to our boot information, at physical address 0, so don't
+ * touch it.
+ */
+
+ /* There are a couple of GDT entries the Guest expects at boot. */
+ setup_guest_gdt(cpu);
+}
diff --git a/drivers/lguest/switcher.S b/drivers/lguest/x86/switcher_32.S
index 7c9c230cc84..40634b0db9f 100644
--- a/drivers/lguest/switcher.S
+++ b/drivers/lguest/x86/switcher_32.S
@@ -1,10 +1,47 @@
-/*P:900 This is the Switcher: code which sits at 0xFFC00000 to do the low-level
- * Guest<->Host switch. It is as simple as it can be made, but it's naturally
- * very specific to x86.
+/*P:900
+ * This is the Switcher: code which sits at 0xFFC00000 (or 0xFFE00000) astride
+ * both the Host and Guest to do the low-level Guest<->Host switch. It is as
+ * simple as it can be made, but it's naturally very specific to x86.
*
* You have now completed Preparation. If this has whet your appetite; if you
* are feeling invigorated and refreshed then the next, more challenging stage
- * can be found in "make Guest". :*/
+ * can be found in "make Guest".
+ :*/
+
+/*M:012
+ * Lguest is meant to be simple: my rule of thumb is that 1% more LOC must
+ * gain at least 1% more performance. Since neither LOC nor performance can be
+ * measured beforehand, it generally means implementing a feature then deciding
+ * if it's worth it. And once it's implemented, who can say no?
+ *
+ * This is why I haven't implemented this idea myself. I want to, but I
+ * haven't. You could, though.
+ *
+ * The main place where lguest performance sucks is Guest page faulting. When
+ * a Guest userspace process hits an unmapped page we switch back to the Host,
+ * walk the page tables, find it's not mapped, switch back to the Guest page
+ * fault handler, which calls a hypercall to set the page table entry, then
+ * finally returns to userspace. That's two round-trips.
+ *
+ * If we had a small walker in the Switcher, we could quickly check the Guest
+ * page table and if the page isn't mapped, immediately reflect the fault back
+ * into the Guest. This means the Switcher would have to know the top of the
+ * Guest page table and the page fault handler address.
+ *
+ * For simplicity, the Guest should only handle the case where the privilege
+ * level of the fault is 3 and probably only not present or write faults. It
+ * should also detect recursive faults, and hand the original fault to the
+ * Host (which is actually really easy).
+ *
+ * Two questions remain. Would the performance gain outweigh the complexity?
+ * And who would write the verse documenting it?
+:*/
+
+/*M:011
+ * Lguest64 handles NMI. This gave me NMI envy (until I looked at their
+ * code). It's worth doing though, since it would let us use oprofile in the
+ * Host when a Guest is running.
+:*/
/*S:100
* Welcome to the Switcher itself!
@@ -48,7 +85,8 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/page.h>
-#include "lg.h"
+#include <asm/segment.h>
+#include <asm/lguest.h>
// We mark the start of the code to copy
// It's placed in .text tho it's never run here
@@ -87,7 +125,7 @@ ENTRY(switch_to_guest)
// All saved and there's now five steps before us:
// Stack, GDT, IDT, TSS
- // And last of all the page tables are flipped.
+ // Then last of all the page tables are flipped.
// Yet beware that our stack pointer must be
// Always valid lest an NMI hits
@@ -102,25 +140,25 @@ ENTRY(switch_to_guest)
lgdt LGUEST_PAGES_guest_gdt_desc(%eax)
// The Guest's IDT we did partially
- // Move to the "struct lguest_pages" as well.
+ // Copy to "struct lguest_pages" as well.
lidt LGUEST_PAGES_guest_idt_desc(%eax)
// The TSS entry which controls traps
// Must be loaded up with "ltr" now:
+ // The GDT entry that TSS uses
+ // Changes type when we load it: damn Intel!
// For after we switch over our page tables
- // It (as the rest) will be writable no more.
- // (The GDT entry TSS needs
- // Changes type when we load it: damn Intel!)
+ // That entry will be read-only: we'd crash.
movl $(GDT_ENTRY_TSS*8), %edx
ltr %dx
// Look back now, before we take this last step!
// The Host's TSS entry was also marked used;
- // Let's clear it again, ere we return.
+ // Let's clear it again for our return.
// The GDT descriptor of the Host
// Points to the table after two "size" bytes
movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %edx
- // Clear the type field of "used" (byte 5, bit 2)
+ // Clear "used" from type field (byte 5, bit 2)
andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%edx)
// Once our page table's switched, the Guest is live!
@@ -130,8 +168,9 @@ ENTRY(switch_to_guest)
// The page table change did one tricky thing:
// The Guest's register page has been mapped
- // Writable onto our %esp (stack) --
+ // Writable under our %esp (stack) --
// We can simply pop off all Guest regs.
+ popl %eax
popl %ebx
popl %ecx
popl %edx
@@ -139,7 +178,6 @@ ENTRY(switch_to_guest)
popl %edi
popl %ebp
popl %gs
- popl %eax
popl %fs
popl %ds
popl %es
@@ -151,23 +189,21 @@ ENTRY(switch_to_guest)
addl $8, %esp
// The last five stack slots hold return address
- // And everything needed to change privilege
- // Into the Guest privilege level of 1,
+ // And everything needed to switch privilege
+ // From Switcher's level 0 to Guest's 1,
// And the stack where the Guest had last left it.
// Interrupts are turned back on: we are Guest.
iret
-// There are two paths where we switch to the Host
+// We tread two paths to switch back to the Host
+// Yet both must save Guest state and restore Host
// So we put the routine in a macro.
-// We are on our way home, back to the Host
-// Interrupted out of the Guest, we come here.
#define SWITCH_TO_HOST \
/* We save the Guest state: all registers first \
* Laid out just as "struct lguest_regs" defines */ \
pushl %es; \
pushl %ds; \
pushl %fs; \
- pushl %eax; \
pushl %gs; \
pushl %ebp; \
pushl %edi; \
@@ -175,6 +211,7 @@ ENTRY(switch_to_guest)
pushl %edx; \
pushl %ecx; \
pushl %ebx; \
+ pushl %eax; \
/* Our stack and our code are using segments \
* Set in the TSS and IDT \
* Yet if we were to touch data we'd use \
@@ -193,7 +230,7 @@ ENTRY(switch_to_guest)
movl %esp, %eax; \
andl $(~(1 << PAGE_SHIFT - 1)), %eax; \
/* Save our trap number: the switch will obscure it \
- * (The Guest regs are not mapped here in the Host) \
+ * (In the Host the Guest regs are not mapped here) \
* %ebx holds it safe for deliver_to_host */ \
movl LGUEST_PAGES_regs_trapnum(%eax), %ebx; \
/* The Host GDT, IDT and stack! \
@@ -209,9 +246,9 @@ ENTRY(switch_to_guest)
/* Switch to Host's GDT, IDT. */ \
lgdt LGUEST_PAGES_host_gdt_desc(%eax); \
lidt LGUEST_PAGES_host_idt_desc(%eax); \
- /* Restore the Host's stack where it's saved regs lie */ \
+ /* Restore the Host's stack where its saved regs lie */ \
movl LGUEST_PAGES_host_sp(%eax), %esp; \
- /* Last the TSS: our Host is complete */ \
+ /* Last the TSS: our Host is returned */ \
movl $(GDT_ENTRY_TSS*8), %edx; \
ltr %dx; \
/* Restore now the regs saved right at the first. */ \
@@ -221,14 +258,15 @@ ENTRY(switch_to_guest)
popl %ds; \
popl %es
-// Here's where we come when the Guest has just trapped:
-// (Which trap we'll see has been pushed on the stack).
+// The first path is trod when the Guest has trapped:
+// (Which trap it was has been pushed on the stack).
// We need only switch back, and the Host will decode
// Why we came home, and what needs to be done.
return_to_host:
SWITCH_TO_HOST
iret
+// We are lead to the second path like so:
// An interrupt, with some cause external
// Has ajerked us rudely from the Guest's code
// Again we must return home to the Host
@@ -237,7 +275,7 @@ deliver_to_host:
// But now we must go home via that place
// Where that interrupt was supposed to go
// Had we not been ensconced, running the Guest.
- // Here we see the cleverness of our stack:
+ // Here we see the trickness of run_guest_once():
// The Host stack is formed like an interrupt
// With EIP, CS and EFLAGS layered.
// Interrupt handlers end with "iret"
@@ -262,7 +300,7 @@ deliver_to_host:
xorw %ax, %ax
orl %eax, %edx
// Now the address of the handler's in %edx
- // We call it now: its "iret" takes us home.
+ // We call it now: its "iret" drops us home.
jmp *%edx
// Every interrupt can come to us here