aboutsummaryrefslogtreecommitdiff
path: root/drivers/lguest
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest')
-rw-r--r--drivers/lguest/Kconfig7
-rw-r--r--drivers/lguest/Makefile2
-rw-r--r--drivers/lguest/core.c217
-rw-r--r--drivers/lguest/hypercalls.c155
-rw-r--r--drivers/lguest/interrupts_and_traps.c393
-rw-r--r--drivers/lguest/lg.h86
-rw-r--r--drivers/lguest/lguest_device.c335
-rw-r--r--drivers/lguest/lguest_user.c381
-rw-r--r--drivers/lguest/page_tables.c1086
-rw-r--r--drivers/lguest/segments.c147
-rw-r--r--drivers/lguest/x86/core.c425
-rw-r--r--drivers/lguest/x86/switcher_32.S22
12 files changed, 2236 insertions, 1020 deletions
diff --git a/drivers/lguest/Kconfig b/drivers/lguest/Kconfig
index 6b8dbb9ba73..ee035ec4526 100644
--- a/drivers/lguest/Kconfig
+++ b/drivers/lguest/Kconfig
@@ -1,12 +1,13 @@
config LGUEST
tristate "Linux hypervisor example code"
- depends on X86_32 && EXPERIMENTAL && !X86_PAE && FUTEX && !(X86_VISWS || X86_VOYAGER)
+ 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.
diff --git a/drivers/lguest/Makefile b/drivers/lguest/Makefile
index 7d463c26124..c4197503900 100644
--- a/drivers/lguest/Makefile
+++ b/drivers/lguest/Makefile
@@ -18,7 +18,7 @@ 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"
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 5eea4356d70..0bf1e4edf04 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -1,6 +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. :*/
+ * Host to do something. This file also contains useful helper routines.
+:*/
#include <linux/module.h>
#include <linux/stringify.h>
#include <linux/stddef.h>
@@ -10,6 +12,7 @@
#include <linux/cpu.h>
#include <linux/freezer.h>
#include <linux/highmem.h>
+#include <linux/slab.h>
#include <asm/paravirt.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -17,14 +20,15 @@
#include <asm/asm-offsets.h>
#include "lg.h"
-
+unsigned long switcher_addr;
+struct page **lg_switcher_pages;
static struct vm_struct *switcher_vma;
-static struct page **switcher_page;
/* This One Big lock protects all inter-guest data structures. */
DEFINE_MUTEX(lguest_lock);
-/*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.
@@ -33,7 +37,8 @@ DEFINE_MUTEX(lguest_lock);
* 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. */
+ * it's not a simple one-liner.
+ */
static __init int map_switcher(void)
{
int i, err;
@@ -47,41 +52,53 @@ static __init int map_switcher(void)
* easy.
*/
- /* We allocate an array of struct page pointers. map_vm_area() wants
- * this, rather than just an array of pages. */
- 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);
}
- /* First we check that the Switcher won't overlap the fixmap area at
- * the top of memory. It's currently nowhere near, but it could have
- * very strange effects if it ever happened. */
- if (SWITCHER_ADDR + (TOTAL_SWITCHER_PAGES+1)*PAGE_SIZE > FIXADDR_START){
- err = -ENOMEM;
- printk("lguest: mapping switcher would thwack fixmap\n");
- goto free_pages;
- }
+ /*
+ * 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: 0xFFC00000
- * (SWITCHER_ADDR). 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. */
+ /*
+ * 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, SWITCHER_ADDR
+ VM_ALLOC, switcher_addr, switcher_addr
+ (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
if (!switcher_vma) {
err = -ENOMEM;
@@ -89,20 +106,24 @@ static __init int map_switcher(void)
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 <arch>_switcher.S). */
+ /*
+ * 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).
+ */
memcpy(switcher_vma->addr, start_switcher_text,
end_switcher_text - start_switcher_text);
@@ -117,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;
@@ -134,7 +154,8 @@ 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:032
@@ -150,16 +171,19 @@ static void unmap_switcher(void)
* 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 routine copies memory from the Guest. Here we can see how useful the
+/*
+ * 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. */
+ * 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(cpu->lg, addr, bytes)
@@ -180,58 +204,87 @@ void __lgwrite(struct lg_cpu *cpu, unsigned long addr, const void *b,
}
/*:*/
-/*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. */
+ * 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 (!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, in which case we return from the read() now. */
+ /*
+ * It's possible the Guest did a NOTIFY hypercall to the
+ * Launcher.
+ */
if (cpu->pending_notify) {
- if (put_user(cpu->pending_notify, user))
- return -EFAULT;
- return sizeof(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 (cpu->break_out)
- return -EAGAIN;
-
- /* Check if there are any interrupts which can be delivered now:
+ /*
+ * 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(cpu);
-
- /* 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. */
+ * 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 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();
/* Actually run the Guest until something happens. */
@@ -265,7 +318,7 @@ static int __init init(void)
int err;
/* Lguest can't run under Xen, VMI or itself. It does Tricky Stuff. */
- if (paravirt_enabled()) {
+ if (get_kernel_rpl() != 0) {
printk("lguest is afraid of being a guest\n");
return -EPERM;
}
@@ -275,15 +328,10 @@ static int __init init(void)
if (err)
goto out;
- /* Now we set up the pagetable implementation for the Guests. */
- err = init_pagetables(switcher_page, SHARED_SWITCHER_PAGES);
- if (err)
- goto unmap;
-
/* We might need to reserve an interrupt vector. */
err = init_interrupts();
if (err)
- goto free_pgtables;
+ goto unmap;
/* /dev/lguest needs to be registered. */
err = lguest_device_init();
@@ -298,8 +346,6 @@ static int __init init(void)
free_interrupts:
free_interrupts();
-free_pgtables:
- free_pagetables();
unmap:
unmap_switcher();
out:
@@ -311,15 +357,16 @@ static void __exit fini(void)
{
lguest_device_remove();
free_interrupts();
- free_pagetables();
unmap_switcher();
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 54d66f05fef..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
@@ -28,26 +30,41 @@
#include <asm/pgtable.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_SHUTDOWN, both. */
+/*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 (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. */
+ /*
+ * You can't get here unless you're already initialized. Don't
+ * do that.
+ */
kill_guest(cpu, "already have lguest_data");
break;
case LHCALL_SHUTDOWN: {
- /* Shutdown is such a trivial hypercall that we do it in four
- * lines right here. */
char msg[128];
- /* If the lgread fails, it will call kill_guest() itself; the
- * kill_guest() with the message will be ignored. */
+ /*
+ * 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(cpu, "CRASH: %s", msg);
@@ -56,16 +73,17 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
break;
}
case LHCALL_FLUSH_TLB:
- /* FLUSH_TLB comes in two flavors, depending on the
- * argument: */
+ /* FLUSH_TLB comes in two flavors, depending on the argument: */
if (args->arg1)
guest_pagetable_clear_all(cpu);
else
guest_pagetable_flush_user(cpu);
break;
- /* All these calls simply pass the arguments through to the right
- * routines. */
+ /*
+ * All these calls simply pass the arguments through to the right
+ * routines.
+ */
case LHCALL_NEW_PGTABLE:
guest_new_pagetable(cpu, args->arg1);
break;
@@ -73,11 +91,21 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
guest_set_stack(cpu, args->arg1, args->arg2, args->arg3);
break;
case LHCALL_SET_PTE:
+#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_PGD:
+ guest_set_pgd(cpu->lg, args->arg1, args->arg2);
+ break;
+#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(cpu, args->arg1);
break;
@@ -98,15 +126,16 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
kill_guest(cpu, "Bad hypercall %li\n", args->arg0);
}
}
-/*:*/
-/*H:124 Asynchronous hypercalls are easy: we just look in the array in the
+/*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). */
+ * checking for a normal hcall).
+ */
static void do_async_hcalls(struct lg_cpu *cpu)
{
unsigned int i;
@@ -119,22 +148,28 @@ static void do_async_hcalls(struct lg_cpu *cpu)
/* We process "struct lguest_data"s hcalls[] ring once. */
for (i = 0; i < ARRAY_SIZE(st); i++) {
struct hcall_args args;
- /* We remember where we were up to from last time. This makes
+ /*
+ * 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. */
+ * 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. */
+ /*
+ * 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;
- /* Copy the hypercall arguments into a local copy of
- * the hcall_args struct. */
+ /*
+ * 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");
@@ -150,19 +185,25 @@ static void do_async_hcalls(struct lg_cpu *cpu)
break;
}
- /* Stop doing hypercalls if they want to notify the Launcher:
- * it needs to service this first. */
+ /*
+ * 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: */
+/*
+ * 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)
{
- /* You can't do anything until you're initialized. The Guest knows the
- * rules, so we're unforgiving here. */
+ /*
+ * 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;
@@ -171,32 +212,44 @@ static void initialize(struct lg_cpu *cpu)
if (lguest_arch_init_hypercalls(cpu))
kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
- /* The Guest tells us where we're not to deliver interrupts by putting
- * the range of addresses into "struct 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 so it can
- * set its clock. */
+ /*
+ * We write the current time into the Guest's data page once so it can
+ * set its clock.
+ */
write_timestamp(cpu);
/* 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
+ /*
+ * 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 old page might be (read-only) in the Guest
- * pagetable. */
+ * pagetable.
+ */
guest_pagetable_clear_all(cpu);
}
/*:*/
-/*M:013 If a Guest reads from a page (so creates a mapping) that it has never
+/*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. :*/
+ * a similar scenario might one day bite us, so it's worth mentioning.
+ *
+ * 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
@@ -215,17 +268,22 @@ void do_hypercalls(struct lg_cpu *cpu)
return;
}
- /* The Guest has initialized.
+ /*
+ * The Guest has initialized.
*
- * Look in the hypercall ring for the async hypercalls: */
+ * 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
+ /*
+ * 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. */
+ * the hypercall.
+ */
if (!cpu->pending_notify) {
do_hcall(cpu, cpu->hcall);
- /* Tricky point: we reset the hcall pointer to mark the
+ /*
+ * 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
@@ -234,13 +292,16 @@ void do_hypercalls(struct lg_cpu *cpu)
* 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. */
+ * 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. */
+/*
+ * 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;
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index 0414ddf8758..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,10 +11,12 @@
* 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. */
@@ -26,21 +29,25 @@ 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. */
+/*
+ * 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. */
@@ -48,7 +55,8 @@ static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 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.
@@ -59,27 +67,35 @@ static void push_guest_stack(struct lg_cpu *cpu, 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 lg_cpu *cpu, 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, 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. */
+ * 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 */
+ /*
+ * 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
+ /*
+ * 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. */
+ * levels and expect these here.
+ */
push_guest_stack(cpu, &gstack, cpu->regs->ss);
push_guest_stack(cpu, &gstack, cpu->regs->esp);
} else {
@@ -90,18 +106,22 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
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: we saw the Guest
- * copy it back in "lguest_iret". */
+ * 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. */
+ * pointer.
+ */
push_guest_stack(cpu, &gstack, eflags);
push_guest_stack(cpu, &gstack, cpu->regs->cs);
push_guest_stack(cpu, &gstack, cpu->regs->eip);
@@ -110,15 +130,29 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
if (has_err)
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. */
+ /*
+ * 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);
- /* There are two kinds of interrupt handlers: 0xE is an "interrupt
- * gate" which expects interrupts to be disabled on entry. */
+ /*
+ * 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, &cpu->lg->lguest_data->irq_enabled))
kill_guest(cpu, "Disabling interrupts");
@@ -127,33 +161,49 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
/*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 lg_cpu *cpu)
+ * 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 (!cpu->lg->lguest_data)
- return;
+ return LGUEST_IRQS;
- /* Take our "irqs_pending" array and remove any interrupts the Guest
- * wants blocked: the result ends up in "blk". */
+ /*
+ * 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;
+ 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. */
+ /*
+ * 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;
@@ -169,39 +219,75 @@ void maybe_do_interrupt(struct lg_cpu *cpu)
u32 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. */
+ * 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, cpu->irqs_pending);
- /* set_guest_interrupt() takes the interrupt descriptor and a
+ /*
+ * 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(cpu, 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. */
+ * 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);
}
/*:*/
-/* Linux uses trap 128 for system calls. Plan9 uses 64, and Ron Minnich sent
+/*
+ * 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. */
+ * userbase. Oh well.
+ */
static bool could_be_syscall(unsigned int num)
{
/* Normal Linux SYSCALL_VECTOR or reserved vector? */
@@ -222,11 +308,16 @@ bool check_syscall_vector(struct lguest *lg)
int init_interrupts(void)
{
/* If they want some strange system call vector, reserve it now */
- if (syscall_vector != SYSCALL_VECTOR
- && test_and_set_bit(syscall_vector, used_vectors)) {
- printk("lg: couldn't reserve syscall %u\n", syscall_vector);
- return -EBUSY;
+ 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;
}
@@ -236,32 +327,39 @@ void free_interrupts(void)
clear_bit(syscall_vector, used_vectors);
}
-/*H:220 Now we've got the routines to deliver interrupts, delivering traps like
+/*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)
+ * 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 lg_cpu *cpu, 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. */
+ /*
+ * 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 0;
+ 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. */
+ /*
+ * 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 0;
+ return false;
set_guest_interrupt(cpu, cpu->arch.idt[num].a,
cpu->arch.idt[num].b, has_err(num));
- return 1;
+ 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 (usually trap
* 128).
@@ -273,68 +371,85 @@ int deliver_trap(struct lg_cpu *cpu, unsigned int num)
* the other hypervisors would beat it up at lunchtime.
*
* This routine indicates if a particular trap number could be delivered
- * directly. */
-static int direct_trap(unsigned int num)
+ * directly.
+ */
+static bool direct_trap(unsigned int num)
{
- /* Hardware interrupts don't go to the Guest at all (except system
- * call). */
+ /*
+ * Hardware interrupts don't go to the Guest at all (except system
+ * call).
+ */
if (num >= FIRST_EXTERNAL_VECTOR && !could_be_syscall(num))
- return 0;
+ return false;
- /* The Host needs to see page faults (for shadow paging and to save the
+ /*
+ * 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. */
+ * 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. */
+ * 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. */
+ /*
+ * 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
+ /*
+ * 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. */
+ * 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. */
+ * change stacks on each context switch.
+ */
void guest_set_stack(struct lg_cpu *cpu, u32 seg, u32 esp, unsigned int pages)
{
- /* You are not allowed 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(cpu, "bad stack segment %i", seg);
/* We only expect one or two stack pages. */
@@ -348,11 +463,15 @@ void guest_set_stack(struct lg_cpu *cpu, u32 seg, u32 esp, unsigned int pages)
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 the entry in "struct lguest": */
+/*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)
{
@@ -368,30 +487,38 @@ static void set_trap(struct lg_cpu *cpu, struct desc_struct *trap,
if (type != 0xE && type != 0xF)
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. */
+ * 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. */
+ /*
+ * 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. */
@@ -401,20 +528,31 @@ void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int num, u32 lo, u32 hi)
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);
@@ -428,33 +566,44 @@ 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. */
+ * 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. */
+ /*
+ * 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.
+ /*
+ * 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 (idt_type(cpu->arch.idt[i].a, cpu->arch.idt[i].b) == 0xF)
- idt[i] = cpu->arch.idt[i];
+ * 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
- /* Reset it to the default. */
- default_idt_entry(&idt[i], i, def[i]);
+ default_idt_entry(&idt[i], i, def[i], gidt);
}
}
@@ -469,7 +618,8 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
* 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". */
+ * 0 means "turn off the clock".
+ */
void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta)
{
ktime_t expires;
@@ -480,9 +630,11 @@ void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta)
return;
}
- /* We use wallclock time here, so the Guest might not be running for
+ /*
+ * 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. */
+ * is almost always the right thing to do.
+ */
expires = ktime_add_ns(ktime_get_real(), delta);
hrtimer_start(&cpu->hrt, expires, HRTIMER_MODE_ABS);
}
@@ -493,10 +645,7 @@ static enum hrtimer_restart clockdev_fn(struct hrtimer *timer)
struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt);
/* Remember the first interrupt is the timer interrupt. */
- set_bit(0, cpu->irqs_pending);
- /* If the Guest is actually stopped, we need to wake it up. */
- if (cpu->halted)
- wake_up_process(cpu->tsk);
+ set_interrupt(cpu, 0);
return HRTIMER_NORESTART;
}
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 2337e1a06f0..2eef40be4c0 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -10,22 +10,19 @@
#include <linux/wait.h>
#include <linux/hrtimer.h>
#include <linux/err.h>
-#include <asm/semaphore.h>
+#include <linux/slab.h>
#include <asm/lguest.h>
-void free_pagetables(void);
-int init_pagetables(struct page **switcher_page, unsigned int pages);
-
-struct pgdir
-{
+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;
@@ -39,8 +36,6 @@ struct lguest_pages
#define CHANGED_GDT_TLS 4 /* Actually a subset of CHANGED_GDT */
#define CHANGED_ALL 3
-struct lguest;
-
struct lg_cpu {
unsigned int id;
struct lguest *lg;
@@ -50,20 +45,22 @@ struct lg_cpu {
u32 cr2;
int ts;
u32 esp1;
- u8 ss1;
+ 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. */
+ /* 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;
- int cpu_pgd; /* which pgd this cpu is currently using */
+ /* 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;
@@ -72,9 +69,7 @@ struct lg_cpu {
/* Virtual clock device */
struct hrtimer hrt;
- /* Do we need to stop what we're doing and return to userspace? */
- int break_out;
- wait_queue_head_t break_wq;
+ /* Did the Guest tell us to halt? */
int halted;
/* Pending virtual interrupts */
@@ -83,16 +78,28 @@ struct lg_cpu {
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 {
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. */
+
+ /*
+ * This provides the offset to the base of guest-physical memory in the
+ * Launcher.
+ */
void __user *mem_base;
unsigned long kernel_address;
@@ -103,6 +110,8 @@ struct lguest
unsigned int stack_pages;
u32 tsc_khz;
+ struct lg_eventfd_map *eventfds;
+
/* Dead? */
const char *dead;
};
@@ -110,16 +119,19 @@ struct lguest
extern struct mutex lguest_lock;
/* core.c: */
-int lguest_address_ok(const struct lguest *lg,
- unsigned long addr, unsigned long len);
+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
+/*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. */
+ * 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; })
@@ -133,16 +145,21 @@ void __lgwrite(struct lg_cpu *, unsigned long, const void *, unsigned);
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
+/*
+ * 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. */
+ * in the kernel.
+ */
#define pgd_flags(x) (pgd_val(x) & ~PAGE_MASK)
-#define pte_flags(x) (pte_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 lg_cpu *cpu);
-int deliver_trap(struct lg_cpu *cpu, unsigned int num);
+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);
@@ -152,6 +169,7 @@ void setup_default_idt_entries(struct lguest_ro_state *state,
void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
const unsigned long *def);
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);
@@ -160,22 +178,26 @@ void free_interrupts(void);
/* segments.c: */
void setup_default_gdt_entries(struct lguest_ro_state *state);
void setup_guest_gdt(struct lg_cpu *cpu);
-void load_guest_gdt(struct lg_cpu *cpu, unsigned long table, u32 num);
+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 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);
-int demand_page(struct lg_cpu *cpu, unsigned long cr2, int errcode);
+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);
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 2bc9bf7e88e..d0a1d8a45c8 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -1,10 +1,12 @@
-/*P:050 Lguest guests use a very simple method to describe devices. It's a
+/*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. :*/
+ * information and a "virtqueue" or two to send and receive data.
+:*/
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/lguest_launcher.h>
@@ -13,6 +15,8 @@
#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>
@@ -20,14 +24,13 @@
/* The pointer to our (page) of device descriptions. */
static void *lguest_devices;
-/* Unique numbering for lguest devices. */
-static unsigned int dev_index;
-
-/* For Guests, device memory can be used as normal memory, so we cast away the
- * __iomem to quieten sparse. */
+/*
+ * 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(phys_addr, PAGE_SIZE*pages);
+ return (__force void *)ioremap_cache(phys_addr, PAGE_SIZE*pages);
}
static inline void lguest_unmap(void *addr)
@@ -35,8 +38,10 @@ 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. */
+/*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;
@@ -44,9 +49,11 @@ struct lguest_device {
struct lguest_device_desc *desc;
};
-/* Since the virtio infrastructure hands us a pointer to the virtio_device all
+/*
+ * 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. */
+ * lguest_device it's enclosed in.
+ */
#define to_lgdev(vd) container_of(vd, struct lguest_device, vdev)
/*D:130
@@ -58,7 +65,8 @@ struct lguest_device {
* the driver will look at them during setup.
*
* A convenient routine to return the device's virtqueue config array:
- * immediately after the descriptor. */
+ * immediately after the descriptor.
+ */
static struct lguest_vqconfig *lg_vq(const struct lguest_device_desc *desc)
{
return (void *)(desc + 1);
@@ -85,27 +93,63 @@ static unsigned desc_size(const struct lguest_device_desc *desc)
+ desc->config_len;
}
-/* This tests (and acknowleges) a feature bit. */
-static bool lg_feature(struct virtio_device *vdev, unsigned fbit)
+/* 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 *features;
-
- /* Obviously if they ask for a feature off the end of our feature
- * bitmap, it's not set. */
- if (fbit / 8 > desc->feature_len)
- return false;
-
- /* The feature bitmap comes after the virtqueues. */
- features = lg_features(desc);
- if (!(features[fbit / 8] & (1 << (fbit % 8))))
- return false;
-
- /* We set the matching bit in the other half of the bitmap to tell the
- * Host we want to use this feature. We don't use this yet, but we
- * could in future. */
- features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8));
- return true;
+ 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. */
@@ -130,8 +174,10 @@ static void lg_set(struct virtio_device *vdev, unsigned int offset,
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. */
+/*
+ * 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;
@@ -141,16 +187,17 @@ 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);
}
-/* To reset the device, we (ab)use the NOTIFY hypercall, with the descriptor
- * address of the device. The Host will zero the status and all the
- * features. */
static void lg_reset(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 status means "reset" */
+ to_lgdev(vdev)->desc->status = 0;
+ status_notify(vdev);
}
/*
@@ -169,8 +216,7 @@ static void lg_reset(struct virtio_device *vdev)
*/
/*D:140 This is the information we remember about each virtqueue. */
-struct lguest_vq_info
-{
+struct lguest_vq_info {
/* A copy of the information contained in the device config. */
struct lguest_vqconfig config;
@@ -178,19 +224,28 @@ struct lguest_vq_info
void *pages;
};
-/* When the virtio_ring code wants to prod the Host, it calls us here and we
+/*
+ * 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 void lg_notify(struct virtqueue *vq)
+ * 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. */
+ /*
+ * 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);
+ hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0);
+ return true;
}
-/* This routine finds the first virtqueue described in the configuration of
+/* 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
@@ -198,18 +253,20 @@ static void lg_notify(struct virtqueue *vq)
* 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.
- *
- * So we provide drivers with a "find the Nth virtqueue and set it up"
- * function. */
+ */
static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
unsigned index,
- void (*callback)(struct virtqueue *vq))
+ 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);
@@ -218,9 +275,11 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
if (!lvq)
return ERR_PTR(-ENOMEM);
- /* Make a copy of the "struct lguest_vqconfig" entry, which sits after
+ /*
+ * 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. */
+ * be aligned correctly.
+ */
memcpy(&lvq->config, lg_vq(ldev->desc)+index, sizeof(lvq->config));
printk("Mapping virtqueue %i addr %lx\n", index,
@@ -228,37 +287,53 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
/* 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,
- PAGE_SIZE),
+ 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. */
- vq = vring_new_virtqueue(lvq->config.num, vdev, lvq->pages,
- lg_notify, callback);
+ /*
+ * 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;
}
- /* 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
+ /* 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.. */
+ * back.
+ */
err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED,
- vdev->dev.bus_id, vq);
+ dev_name(&vdev->dev), vq);
if (err)
- goto destroy_vring;
+ goto free_desc;
- /* Last of all we hook up our 'struct lguest_vq_info" to the
- * virtqueue's priv pointer. */
+ /*
+ * 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:
@@ -284,26 +359,65 @@ static void lg_del_vq(struct virtqueue *vq)
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 struct virtio_config_ops lguest_config_ops = {
- .feature = lg_feature,
+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_vq = lg_find_vq,
- .del_vq = lg_del_vq,
+ .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 = {
- .parent = NULL,
- .bus_id = "lguest",
-};
+/*
+ * 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.
+/*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.
@@ -311,46 +425,54 @@ static struct device lguest_root = {
* 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. */
-static void add_lguest_device(struct lguest_device_desc *d)
+ * 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 seems to count on
- * it. */
+ /* 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\n",
- dev_index++);
+ 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;
- /* We have a unique device index thanks to the dev_index counter. */
- ldev->vdev.index = dev_index++;
- /* The device type comes straight from the descriptor. There's also a
+ 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. */
+ * 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. */
+ /*
+ * 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
+ /*
+ * 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. */
+ * infrastructure look for a matching driver.
+ */
if (register_virtio_device(&ldev->vdev) != 0) {
- printk(KERN_ERR "Failed to register lguest device %u\n",
- ldev->vdev.index);
+ 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". */
+/*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;
@@ -365,11 +487,12 @@ static void scan_devices(void)
break;
printk("Device at %i has size %u\n", i, desc_size(d));
- add_lguest_device(d);
+ add_lguest_device(d, i);
}
}
-/*D:105 Fairly early in boot, lguest_devices_init() is called to set up the
+/*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.
@@ -380,13 +503,15 @@ static void scan_devices(void)
* correct sysfs incantation).
*
* Finally we call scan_devices() which adds all the devices found in the
- * lguest_devices page. */
+ * lguest_devices page.
+ */
static int __init lguest_devices_init(void)
{
if (strcmp(pv_info.name, "lguest") != 0)
return 0;
- if (device_register(&lguest_root) != 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 */
@@ -398,11 +523,13 @@ static int __init lguest_devices_init(void)
/* 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
+/*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?". */
+ * 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 645e6e040bf..4263f4cc8c5 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -1,42 +1,182 @@
-/*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, pagetable, entry point and kernel address
- * offset. A read will run the Guest until something happens, such as a signal
- * or the Guest doing a NOTIFY out to the Launcher. :*/
+/*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:055 When something happens, the Waker process needs a way to stop the
- * kernel running the Guest and return to the Launcher. So the Waker writes
- * LHREQ_BREAK and the value "1" to /dev/lguest to do this. Once the Launcher
- * has done whatever needs attention, it writes LHREQ_BREAK and "0" to release
- * the Waker. */
-static int break_guest_out(struct lg_cpu *cpu, const unsigned long __user*input)
+/*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.
+ *
+ * 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)
{
- unsigned long on;
+ 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
+ *
+ * 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();
- /* Fetch whether they're turning break on or off. */
- if (get_user(on, input) != 0)
- return -EFAULT;
+ /* If we cleared the notification, it's because we found a match. */
+ return cpu->pending_notify == 0;
+}
- if (on) {
- cpu->break_out = 1;
- /* Pop it out of the Guest (may be running on different CPU) */
- wake_up_process(cpu->tsk);
- /* Wait for them to reset it */
- return wait_event_interruptible(cpu->break_wq, !cpu->break_out);
- } else {
- cpu->break_out = 0;
- wake_up(&cpu->break_wq);
- return 0;
+/*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)
+{
+ struct lg_eventfd_map *new, *old = lg->eventfds;
+
+ /*
+ * 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:050 Sending an interrupt is done by writing LHREQ_IRQ and an interrupt
- * number to /dev/lguest. */
+/*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 addr, fd;
+ int err;
+
+ if (get_user(addr, input) != 0)
+ return -EFAULT;
+ input++;
+ if (get_user(fd, input) != 0)
+ return -EFAULT;
+
+ /*
+ * 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 lg_cpu *cpu, const unsigned long __user *input)
{
unsigned long irq;
@@ -45,14 +185,19 @@ static int user_send_irq(struct lg_cpu *cpu, const unsigned long __user *input)
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, cpu->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;
@@ -88,8 +233,10 @@ 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 I/O,
- * clear the flag. */
+ /*
+ * If we returned from read() last time because the Guest sent I/O,
+ * clear the flag.
+ */
if (cpu->pending_notify)
cpu->pending_notify = 0;
@@ -97,57 +244,67 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
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. */
+/*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 the number of CPUs in the lguest struct. */
- if (id >= NR_CPUS)
+ /* 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 - id), struct lguest, cpus[0]);
+ 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. */
+ /*
+ * 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 bottom of the page. */
+ /* 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. */
+ /*
+ * Now we initialize the Guest's registers, handing it the start
+ * address.
+ */
lguest_arch_setup_regs(cpu, start_ip);
- /* Initialize the queue for the Waker to wait on */
- init_waitqueue_head(&cpu->break_wq);
-
- /* We keep a pointer to the Launcher task (ie. current task) for when
- * other Guests want to wake this one (eg. console input). */
+ /*
+ * 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
+ /*
+ * 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. */
+ * 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. */
+ /*
+ * 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 pointer sized (32 or 64 bit)
- * values (in addition to the 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:
*
* base: The start of the Guest-physical memory inside the Launcher memory.
*
@@ -155,21 +312,19 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
* allowed to access. The Guest memory lives inside the Launcher, so it sets
* this to ensure the Guest can only reach its own memory.
*
- * pgdir: The (Guest-physical) address of the top of the initial Guest
- * pagetables (which are set up by the Launcher).
- *
* start: The first instruction to execute ("eip" in x86-speak).
*/
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;
- unsigned long args[4];
+ unsigned long args[3];
- /* We grab the Big Lguest lock, which protects against 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) {
@@ -188,18 +343,27 @@ static int initialize(struct file *file, const unsigned long __user *input)
goto unlock;
}
+ lg->eventfds = kmalloc(sizeof(*lg->eventfds), GFP_KERNEL);
+ if (!lg->eventfds) {
+ err = -ENOMEM;
+ goto free_lg;
+ }
+ lg->eventfds->num = 0;
+
/* Populate the easy fields of our "struct lguest" */
lg->mem_base = (void __user *)args[0];
lg->pfn_limit = args[1];
- /* This is the first cpu (cpu 0) and it will start booting at args[3] */
- err = lg_cpu_start(&lg->cpus[0], 0, args[3]);
+ /* 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 release_guest;
+ goto free_eventfds;
- /* 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[2]);
+ /*
+ * Initialize the Guest's shadow page tables. This allocates
+ * memory, so can fail.
+ */
+ err = init_guest_pagetable(lg);
if (err)
goto free_regs;
@@ -214,27 +378,33 @@ static int initialize(struct file *file, const unsigned long __user *input)
free_regs:
/* FIXME: This should be in free_vcpu */
free_page(lg->cpus[0].regs_page);
-release_guest:
+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
+/*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 send interrupts.
+ * 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
+ * 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. */
+ * 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;
const unsigned long __user *input = (const unsigned long __user *)in;
unsigned long req;
@@ -251,17 +421,10 @@ static ssize_t write(struct file *file, const char __user *in,
if (!lg || (cpu_id >= lg->nr_cpus))
return -EINVAL;
cpu = &lg->cpus[cpu_id];
- if (!cpu)
- return -EINVAL;
/* Once the Guest is dead, you can only read() why it died. */
if (lg->dead)
return -ENOENT;
-
- /* If you're not the task which owns the Guest, all you can do
- * is break the Launcher out of running the Guest. */
- if (current != cpu->tsk && req != LHREQ_BREAK)
- return -EPERM;
}
switch (req) {
@@ -269,20 +432,22 @@ static ssize_t write(struct file *file, const char __user *in,
return initialize(file, input);
case LHREQ_IRQ:
return user_send_irq(cpu, input);
- case LHREQ_BREAK:
- return break_guest_out(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;
@@ -292,8 +457,10 @@ static int close(struct inode *inode, struct file *file)
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);
/* Free up the shadow page tables for the Guest. */
@@ -304,17 +471,26 @@ static int close(struct inode *inode, struct file *file)
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. */
+ /*
+ * Now all the memory cleanups are done, it's safe to release
+ * the Launcher's memory management structure.
+ */
mmput(lg->cpus[i].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(). */
+
+ /* 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 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);
@@ -334,16 +510,21 @@ static int close(struct inode *inode, struct file *file)
*
* 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 d93500f24fb..e8b55c3a617 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -1,13 +1,16 @@
-/*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 then point the CPU to the
- * converted Guest pages when running the Guest. :*/
+ * 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>
@@ -16,18 +19,20 @@
#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 arch/x86/lguest/boot.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
@@ -44,22 +49,28 @@
* (v) Flushing (throwing away) page tables,
* (vi) Mapping the Switcher when the Guest is about to run,
* (vii) Setting up the page tables initially.
- :*/
+:*/
-
-/* 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. */
+/*
+ * 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)
-/* 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(pte_t *, switcher_pte_pages);
-#define switcher_pte_page(cpu) per_cpu(switcher_pte_pages, cpu)
-
-/*H:320 The page table code is curly enough to need helper functions to keep it
- * clear and clean.
+/*
+ * 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.
@@ -67,104 +78,160 @@ static DEFINE_PER_CPU(pte_t *, switcher_pte_pages);
* spgd_addr() takes the virtual address and returns a pointer to the top-level
* 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). */
+ * usually the current one).
+ */
static pgd_t *spgd_addr(struct lg_cpu *cpu, u32 i, unsigned long vaddr)
{
unsigned int index = pgd_index(vaddr);
- /* We kill any Guest trying to touch the Switcher addresses. */
- if (index >= SWITCHER_PGD_INDEX) {
- kill_guest(cpu, "attempt to access switcher pages");
- index = 0;
- }
/* Return a pointer index'th pgd entry for the i'th page table. */
return &cpu->lg->pgdirs[i].pgdir[index];
}
-/* This routine then takes the page directory entry returned above, which
+#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 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(pgd_t spgd, unsigned long vaddr)
+ * pointer to the PTE entry for the given address.
+ */
+static pte_t *spte_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
{
+#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(!(pgd_flags(spgd) & _PAGE_PRESENT));
- return &page[(vaddr >> PAGE_SHIFT) % PTRS_PER_PTE];
+#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. */
+/*
+ * 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 >> (PGDIR_SHIFT);
return cpu->lg->pgdirs[cpu->cpu_pgd].gpgdir + index * sizeof(pgd_t);
}
-static unsigned long gpte_addr(pgd_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 = pgd_pfn(gpgd) << PAGE_SHIFT;
BUG_ON(!(pgd_flags(gpgd) & _PAGE_PRESENT));
- return gpage + ((vaddr>>PAGE_SHIFT) % PTRS_PER_PTE) * sizeof(pte_t);
+ return gpage + pmd_index(vaddr) * sizeof(pmd_t);
+}
+
+/* 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:014 get_pfn is slow; it takes the mmap sem and calls get_user_pages. We
- * could probably try to grab batches of pages here as an optimization
- * (ie. pre-faulting). :*/
+/*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
+/*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. */
+ * 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. */
+ * number.
+ */
static pte_t gpte_to_spte(struct lg_cpu *cpu, pte_t gpte, int write)
{
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. */
+ * use the global bit, so throw it away.
+ */
flags = (pte_flags(gpte) & ~_PAGE_GLOBAL);
/* 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
+ /*
+ * 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. */
+ * page, given the virtual number.
+ */
pfn = get_pfn(base + pte_pfn(gpte), write);
if (pfn == -1UL) {
kill_guest(cpu, "failed to get page %lu", pte_pfn(gpte));
- /* When we destroy the Guest, we'll go through the shadow page
+ /*
+ * 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! */
+ * this one is valid!
+ */
flags = 0;
}
/* Now we assemble our shadow PTE from the page number and flags. */
@@ -174,25 +241,127 @@ static pte_t gpte_to_spte(struct lg_cpu *cpu, pte_t gpte, int write)
/*H:460 And to complete the chain, release_pte() looks like this: */
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. */
+ /*
+ * 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(pfn_to_page(pte_pfn(pte)));
+ put_page(pte_page(pte));
}
/*:*/
-static void check_gpte(struct lg_cpu *cpu, pte_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)
+ pte_pfn(gpte) >= cpu->lg->pfn_limit) {
kill_guest(cpu, "bad page table entry");
+ return false;
+ }
+ return true;
}
-static void check_gpgd(struct lg_cpu *cpu, pgd_t gpgd)
+static bool check_gpgd(struct lg_cpu *cpu, pgd_t gpgd)
{
- if ((pgd_flags(gpgd) & ~_PAGE_TABLE) ||
- (pgd_pfn(gpgd) >= cpu->lg->pfn_limit))
+ 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;
+}
+
+#ifdef CONFIG_X86_PAE
+static bool check_gpmd(struct lg_cpu *cpu, pmd_t gpmd)
+{
+ 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
@@ -204,60 +373,98 @@ static void check_gpgd(struct lg_cpu *cpu, pgd_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. Otherwise, it was a real fault and we need to tell the Guest. */
-int demand_page(struct lg_cpu *cpu, 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)
{
- pgd_t gpgd;
- pgd_t *spgd;
unsigned long gpte_ptr;
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 = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
- /* Toplevel not present? We can't map it in. */
- if (!(pgd_flags(gpgd) & _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(cpu, cpu->cpu_pgd, vaddr);
- if (!(pgd_flags(*spgd) & _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(cpu, "out of memory allocating pte page");
- return 0;
- }
- /* We check that the Guest pgd is OK. */
- check_gpgd(cpu, 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 = __pgd(__pa(ptepage) | pgd_flags(gpgd));
+ /* 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(gpgd, vaddr);
- gpte = lgread(cpu, gpte_ptr, pte_t);
+ /*
+ * 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 (!(pte_flags(gpte) & _PAGE_PRESENT))
- return 0;
+ return false;
- /* Check they're not trying to write to a page the Guest wants
- * read-only (bit 2 of errcode == write). */
+ /*
+ * 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 0;
+ return false;
/* User access to a kernel-only page? (bit 3 == user access) */
if ((errcode & 4) && !(pte_flags(gpte) & _PAGE_USER))
- return 0;
+ 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). */
- check_gpte(cpu, gpte);
+ /*
+ * 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;
/* Add the _PAGE_ACCESSED and (for a write) _PAGE_DIRTY flag */
gpte = pte_mkyoung(gpte);
@@ -265,31 +472,45 @@ int demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
gpte = pte_mkdirty(gpte);
/* Get the pointer to the shadow PTE entry we're going to set. */
- spte = spte_addr(*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 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
+ /*
+ * 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 will come back here when a write does actually occur, so
- * we can update the Guest's _PAGE_DIRTY flag. */
- *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. */
- lgwrite(cpu, gpte_ptr, pte_t, gpte);
-
- /* The fault is fixed, the page table is populated, the mapping
+ * 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 1;
+ * has that a page fault occurred at all.
+ */
+ return true;
}
/*H:360
@@ -301,42 +522,92 @@ int demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
* 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 lg_cpu *cpu, unsigned long vaddr)
+ * mapped by the shadow page tables, and is it writable?
+ */
+static bool page_writable(struct lg_cpu *cpu, unsigned long vaddr)
{
- pgd_t *spgd;
+ pte_t *spte;
unsigned long flags;
- /* Look at the current top level entry: is it present? */
- spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr);
- if (!(pgd_flags(*spgd) & _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 = pte_flags(*(spte_addr(*spgd, vaddr)));
+ /* 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"). */
+ * (meaning "write").
+ */
void pin_page(struct lg_cpu *cpu, unsigned long vaddr)
{
if (!page_writable(cpu, vaddr) && !demand_page(cpu, vaddr, 2))
kill_guest(cpu, "bad stack page %#lx", vaddr);
}
+/*:*/
+
+#ifdef CONFIG_X86_PAE
+static void release_pmd(pmd_t *spmd)
+{
+ /* If the entry's not present, there's nothing to release. */
+ if (pmd_flags(*spmd) & _PAGE_PRESENT) {
+ unsigned int i;
+ 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));
+ }
+}
-/*H:450 If we chase down the release_pgd() code, it looks like this: */
-static void release_pgd(struct lguest *lg, pgd_t *spgd)
+#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
+ /*
+ * 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). */
+ * 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 < PTRS_PER_PTE; i++)
@@ -347,22 +618,27 @@ static void release_pgd(struct lguest *lg, pgd_t *spgd)
*spgd = __pgd(0);
}
}
+#endif
-/*H:445 We saw flush_user_mappings() twice: once from the flush_user_mappings()
+/*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. */
+ * 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 < pgd_index(lg->kernel_address); i++)
- release_pgd(lg, lg->pgdirs[idx].pgdir + i);
+ release_pgd(lg->pgdirs[idx].pgdir + i);
}
-/*H:440 (v) Flushing (throwing away) page tables,
+/*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. */
+ * 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. */
@@ -375,23 +651,43 @@ 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))
+ if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) {
kill_guest(cpu, "Bad address %#lx", vaddr);
+ return -1UL;
+ }
- gpte = lgread(cpu, gpte_addr(gpgd, vaddr), pte_t);
+#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
+/*
+ * 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;
@@ -401,18 +697,22 @@ static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable)
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. */
+ * 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(cpu->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 (!cpu->lg->pgdirs[next].pgdir) {
cpu->lg->pgdirs[next].pgdir =
@@ -420,76 +720,160 @@ static unsigned int new_pgdir(struct lg_cpu *cpu,
/* If the allocation fails, just keep using the one we have */
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! */
+ 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. */
cpu->lg->pgdirs[next].gpgdir = gpgdir;
/* Release all the non-kernel mappings. */
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().
*
- * Now we've seen all the page table setting and manipulation, let's see what
- * 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)
+ * 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(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 */
- if (repin)
- pin_stack_pages(cpu);
+ 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
+/*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. */
+ * 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 traps the Guest in amber for a while as
- * everything faults back in, but it's rare. */
+ * everything faults back in, but it's rare.
+ */
void guest_pagetable_clear_all(struct lg_cpu *cpu)
{
release_all_pagetables(cpu->lg);
/* We need the Guest kernel stack mapped again. */
pin_stack_pages(cpu);
+ /* And we need Switcher allocated. */
+ if (!allocate_switcher_mapping(cpu))
+ kill_guest(cpu, "Cannot populate switcher mapping");
+}
+
+/*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
+
+/*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. :*/
+ * 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
+/*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
@@ -503,33 +887,52 @@ void guest_pagetable_clear_all(struct lg_cpu *cpu)
* _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 lg_cpu *cpu, int idx,
+static void __guest_set_pte(struct lg_cpu *cpu, int idx,
unsigned long vaddr, pte_t gpte)
{
/* 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 (pgd_flags(*spgd) & _PAGE_PRESENT) {
- /* Otherwise, we start by releasing the existing entry. */
- pte_t *spte = spte_addr(*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)) {
- check_gpte(cpu, gpte);
- *spte = gpte_to_spte(cpu, gpte,
- pte_flags(gpte) & _PAGE_DIRTY);
- } else
- /* Otherwise kill it and we can demand_page() it in
- * later. */
- *spte = __pte(0);
+#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
@@ -538,23 +941,32 @@ static void do_set_pte(struct lg_cpu *cpu, int idx,
* 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 keep all
- * the kernel mappings. This speeds up context switch immensely. */
+ * 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)
{
- /* Kernel mappings must be changed on all top levels. Slow, but doesn't
- * happen often. */
+ /* 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(cpu->lg->pgdirs); i++)
if (cpu->lg->pgdirs[i].pgdir)
- do_set_pte(cpu, i, vaddr, gpte);
+ __guest_set_pte(cpu, i, vaddr, gpte);
} else {
/* Is this page table one we have a shadow for? */
int pgdir = find_pgdir(cpu->lg, gpgdir);
if (pgdir != ARRAY_SIZE(cpu->lg->pgdirs))
/* If so, do the update. */
- do_set_pte(cpu, pgdir, vaddr, gpte);
+ __guest_set_pte(cpu, pgdir, vaddr, gpte);
}
}
@@ -570,56 +982,101 @@ void guest_set_pte(struct lg_cpu *cpu,
* 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 gpgdir, 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, gpgdir);
- if (pgdir < ARRAY_SIZE(lg->pgdirs))
+ 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;
+ }
}
-/*H:500 (vii) Setting up the page tables initially.
+#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.
+ *
+ * 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.
*
- * 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)
-{
- /* We start on the first shadow page table, and give it a blank PGD
- * page. */
- lg->pgdirs[0].gpgdir = pgtable;
- lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL);
- if (!lg->pgdirs[0].pgdir)
+ * 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;
- lg->cpus[0].cpu_pgd = 0;
+
+ /* 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;
}
-/* When the Guest calls LHCALL_LGUEST_INIT we do more setup. */
+/*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 4MB of virtual
- * addresses used by the Switcher. */
- || put_user(4U*1024*1024, &cpu->lg->lguest_data->reserve_mem)
- || put_user(cpu->lg->pgdirs[0].gpgdir, &cpu->lg->lguest_data->pgdir))
+ /*
+ * 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
+ /*
+ * 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 (pgd_index(cpu->lg->kernel_address) >= SWITCHER_PGD_INDEX)
+ * Switcher mappings, so check that now.
+ */
+ if (cpu->lg->kernel_address >= switcher_addr)
kill_guest(cpu, "bad kernel address %#lx",
cpu->lg->kernel_address);
}
@@ -636,77 +1093,97 @@ 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 visible in 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 now we know which
- * Guest is about to run on this CPU. */
-void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages)
+/*H:481
+ * This clears the Switcher mappings for cpu #i.
+ */
+static void remove_switcher_percpu_map(struct lg_cpu *cpu, unsigned int i)
{
- pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages);
- pgd_t switcher_pgd;
- pte_t regs_pte;
- unsigned long pfn;
-
- /* Make the last PGD entry for this Guest point to the Switcher's PTE
- * page for this CPU (with appropriate flags). */
- switcher_pgd = __pgd(__pa(switcher_pte_page) | __PAGE_KERNEL);
-
- cpu->lg->pgdirs[cpu->cpu_pgd].pgdir[SWITCHER_PGD_INDEX] = switcher_pgd;
+ unsigned long base = switcher_addr + PAGE_SIZE + i * PAGE_SIZE*2;
+ pte_t *pte;
- /* 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. */
- pfn = __pa(cpu->regs_page) >> PAGE_SHIFT;
- regs_pte = pfn_pte(pfn, __pgprot(__PAGE_KERNEL));
- switcher_pte_page[(unsigned long)pages/PAGE_SIZE%PTRS_PER_PTE] = regs_pte;
-}
-/*:*/
+ /* Clear the mappings for both pages. */
+ pte = find_spte(cpu, base, false, 0, 0);
+ release_pte(*pte);
+ set_pte(pte, __pte(0));
-static void free_switcher_pte_pages(void)
-{
- unsigned int i;
-
- 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.
+ *
+ * The Switcher and the two pages for this CPU need to be visible in the Guest
+ * (and not the pages for other CPUs).
*
- * 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 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;
- pte_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] = mk_pte(switcher_page[i],
- __pgprot(_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_pte(page_to_pfn(switcher_page[i]),
- __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW));
-
- /* The second page contains the "struct lguest_ro_state", and is
- * read-only. */
- pte[i+1] = pfn_pte(page_to_pfn(switcher_page[i+1]),
- __pgprot(_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();
}
-/* We've made it through the page table code. Perhaps our tired brains are
+/*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
@@ -715,28 +1192,5 @@ static __init void populate_switcher_pte_page(unsigned int cpu,
* 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. */
-
-/*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) = (pte_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();
-}
+ * There is just one file remaining in the Host.
+ */
diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c
index ec6aa3f1c36..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,7 +9,8 @@
*
* 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
@@ -41,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
@@ -53,42 +57,52 @@ static int ignored_gdt(unsigned int num)
|| num == GDT_ENTRY_DOUBLEFAULT_TSS);
}
-/*H:630 Once the Guest gave us new GDT entries, we fix them 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". */
+ * 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 ((cpu->arch.gdt[i].b & 0x00006000) == 0)
- cpu->arch.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. */
- cpu->arch.gdt[i].b |= 0x00000100;
+ * writable by the Guest, so bad things can happen.
+ */
+ cpu->arch.gdt[i].type |= 0x1;
}
}
-/*H:610 Like the IDT, we never simply use the GDT the Guest gives us. We keep
+/*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. */
+ * running.
+ */
void setup_default_gdt_entries(struct lguest_ro_state *state)
{
struct desc_struct *gdt = state->guest_gdt;
@@ -98,30 +112,43 @@ void setup_default_gdt_entries(struct lguest_ro_state *state)
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 particular CPU.
- * Forgive the magic flags: the 0x8900 means the entry is Present, it's
- * privilege level 0 Available 386 TSS system segment, and the 0x67
- * means Saturn is eclipsed by Mercury in the twelfth house. */
- 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 sets up the initial Guest GDT for booting. All entries start
- * as 0 (unusable). */
+/*
+ * 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... */
+ /*
+ * 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;
- /* ...except the Guest is allowed to use them, so set the privilege
- * level appropriately in the flags. */
- cpu->arch.gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13);
- cpu->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
+ cpu->arch.gdt[GDT_ENTRY_KERNEL_CS].dpl |= GUEST_PL;
+ cpu->arch.gdt[GDT_ENTRY_KERNEL_DS].dpl |= GUEST_PL;
}
-/*H:650 An optimization of copy_gdt(), for just the three "thead-local storage"
- * entries. */
+/*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;
@@ -130,41 +157,56 @@ void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt)
gdt[i] = cpu->arch.gdt[i];
}
-/*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. */
+/*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] = cpu->arch.gdt[i];
}
-/*H:620 This is where the Guest asks us to load a new GDT (LHCALL_LOAD_GDT).
- * We copy it from the Guest and tweak the entries. */
-void load_guest_gdt(struct lg_cpu *cpu, 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(cpu->arch.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;
+ }
- /* We read the whole thing in, then fix it up. */
- __lgread(cpu, cpu->arch.gdt, table, num * sizeof(cpu->arch.gdt[0]));
- fixup_gdt_table(cpu, 0, ARRAY_SIZE(cpu->arch.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. */
+ /* 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;
}
-/* This is the fast-track version for just changing the three TLS entries.
+/*
+ * 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? */
+ * both cases?
+ */
void guest_load_tls(struct lg_cpu *cpu, unsigned long gtls)
{
struct desc_struct *tls = &cpu->arch.gdt[GDT_ENTRY_TLS_MIN];
@@ -174,7 +216,6 @@ void guest_load_tls(struct lg_cpu *cpu, unsigned long gtls)
/* Note that just the TLS entries have changed. */
cpu->changed |= CHANGED_GDT_TLS;
}
-/*:*/
/*H:660
* With this, we have finished the Host.
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 5126d5d9ea0..922a1acbf65 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -17,13 +17,15 @@
* 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
+/*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. :*/
+ * were implemented after days of debugging pain.
+:*/
#include <linux/kernel.h>
#include <linux/start_kernel.h>
#include <linux/string.h>
@@ -57,17 +59,16 @@ static struct {
/* 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;
+ return switcher_addr - (unsigned long)start_switcher_text;
}
-/* This cpu's struct lguest_pages. */
+/* 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 + SHARED_SWITCHER_PAGES*PAGE_SIZE))[cpu]);
+ return &(((struct lguest_pages *)(switcher_addr + PAGE_SIZE))[cpu]);
}
-static DEFINE_PER_CPU(struct lg_cpu *, last_cpu);
+static DEFINE_PER_CPU(struct lg_cpu *, lg_last_cpu);
/*S:010
* We approach the Switcher.
@@ -82,25 +83,33 @@ static DEFINE_PER_CPU(struct lg_cpu *, last_cpu);
*/
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
+ /*
+ * 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_cpu) != cpu || cpu->last_pages != pages) {
- __get_cpu_var(last_cpu) = cpu;
+ * 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. */
+ /*
+ * 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). */
+ /*
+ * 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
+ /*
+ * 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). */
+ * level 1).
+ */
pages->state.guest_tss.sp1 = cpu->esp1;
pages->state.guest_tss.ss1 = cpu->ss1;
@@ -125,94 +134,132 @@ 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 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
+ /*
+ * 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. */
+ * cause us to abort the Guest.
+ */
cpu->regs->trapnum = 256;
- /* Now: we push the "eflags" register on the stack, then do an "lcall".
+ /*
+ * 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 *lguest_entry"
- /* This is how we tell GCC that %eax ("a") and %ebx ("b")
- * are changed by this routine. The "=" means output. */
+ * 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
+ /*
+ * %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))
- /* We tell gcc that all these registers could change,
+ * 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. */
+ * the Switcher.
+ */
: "memory", "%edx", "%ecx", "%edi", "%esi");
}
/*:*/
-/*M:002 There are hooks in the scheduler which we can register to tell when we
+/*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 this hooks for PGE, but that might be too expensive.
+ * 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. :*/
+ * 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. */
+/*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
+ /*
+ * 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)
- lguest_set_ts();
+ * uses the FPU.
+ */
+ if (cpu->ts && user_has_fpu())
+ stts();
- /* SYSENTER is an optimized way of doing system calls. We can't allow
+ /*
+ * 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. */
+ * 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
+ /*
+ * 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. */
+ * was doing.
+ */
run_guest_once(cpu, lguest_pages(raw_smp_processor_id()));
- /* Note that the "regs" structure contains two extra entries which are
+ /*
+ * 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. */
+ * 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
+ /*
+ * 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. */
+ * 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. */
- else if (cpu->regs->trapnum == 7)
+ /*
+ * 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();
-
- /* Restore SYSENTER if it's supposed to be on. */
- if (boot_cpu_has(X86_FEATURE_SEP))
- wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
}
-/*H:130 Now we've examined the hypercall code; our Guest can make requests.
+/*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
@@ -222,35 +269,55 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
*
* 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. */
+ * 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, shift = 0;
- /* The eip contains the *virtual* address of the Guest's instruction:
- * guest_pa just subtracts the Guest's page_offset. */
+ 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!
+ /*
+ * 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. */
+ * level.
+ */
if ((cpu->regs->cs & 3) != GUEST_PL)
return 0;
/* Decoding x86 instructions is icky. */
insn = lgread(cpu, physaddr, u8);
- /* 0x66 is an "operand prefix". It means it's using the upper 16 bits
- of the eax register. */
+ /*
+ * 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) {
- shift = 16;
+ 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. */
+ /*
+ * 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;
@@ -271,15 +338,20 @@ static int emulate_insn(struct lg_cpu *cpu)
return 0;
}
- /* If it was an "IN" instruction, they expect the result to be read
+ /*
+ * 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". */
+ * traditionally means "there's nothing there".
+ */
if (in) {
- /* Lower bit tells is whether it's a 16 or 32 bit access */
- if (insn & 0x1)
- cpu->regs->eax = 0xFFFFFFFF;
- else
- cpu->regs->eax |= (0xFFFF << shift);
+ /* 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;
@@ -292,76 +364,91 @@ 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
+ /*
+ * 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. */
+ * 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.
+ /*
+ * 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. */
+ * 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
+ /*
+ * 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 */
+ * 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 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
+ /*
+ * 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 */
+ * 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. */
+ /*
+ * 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
+ /*
+ * 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. */
+ * 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
+/*
+ * 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. :*/
+ * duality will be complete.
+:*/
static void adjust_pge(void *on)
{
if (on)
@@ -370,13 +457,16 @@ static void adjust_pge(void *on)
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. */
+/*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 i386/switcher.S doesn't care that it's been moved; on
+ /*
+ * 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.
*
@@ -384,7 +474,8 @@ void __init lguest_arch_host_init(void)
* 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. */
+ * 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();
@@ -399,63 +490,81 @@ void __init lguest_arch_host_init(void)
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. */
+ /* 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
+ /*
+ * 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"). */
+ * 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
+ /*
+ * All CPUs on the Host use the same Interrupt Descriptor
* Table, so we just use store_idt(), which gets this CPU's IDT
- * descriptor. */
+ * descriptor.
+ */
store_idt(&state->host_idt_desc);
- /* The descriptors for the Guest's GDT and IDT can be filled
+ /*
+ * 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. */
+ * ->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
+ /*
+ * 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. */
+ * 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. */
+ /*
+ * 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
+ /*
+ * 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". */
+ * 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. */
+ /*
+ * 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. */
+ /*
+ * 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
+ /*
+ * 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. */
+ * 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
+ /*
+ * 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.
@@ -465,22 +574,27 @@ void __init lguest_arch_host_init(void)
* 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. */
+ * 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. */
+ /*
+ * 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, 0, 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_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
+ clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
}
put_online_cpus();
-};
+}
/*:*/
void __exit lguest_arch_host_fini(void)
@@ -488,9 +602,9 @@ 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_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
+ set_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
/* adjust_pge's argument "1" means set PGE. */
- on_each_cpu(adjust_pge, (void *)1, 0, 1);
+ on_each_cpu(adjust_pge, (void *)1, 1);
}
put_online_cpus();
}
@@ -500,8 +614,8 @@ void __exit lguest_arch_host_fini(void)
int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
{
switch (args->arg0) {
- case LHCALL_LOAD_GDT:
- load_guest_gdt(cpu, args->arg1, args->arg2);
+ 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);
@@ -521,26 +635,32 @@ 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. */
+ /*
+ * 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
+ /*
+ * 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. */
+ * 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
+ /*
+ * 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. */
+ * 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
@@ -556,38 +676,45 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
}
/*:*/
-/*L:030 lguest_arch_setup_regs()
- *
+/*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. */
+ * 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:
+ /*
+ * 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).*/
+ * 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)
+ /*
+ * 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 | 0x2;
+ * running the Guest.
+ */
+ regs->eflags = X86_EFLAGS_IF | X86_EFLAGS_FIXED;
- /* The "Extended Instruction Pointer" register says where the Guest is
- * running. */
+ /*
+ * 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. */
+ /*
+ * %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 when first
- * booting. */
+ /* There are a couple of GDT entries the Guest expects at boot. */
setup_guest_gdt(cpu);
}
diff --git a/drivers/lguest/x86/switcher_32.S b/drivers/lguest/x86/switcher_32.S
index 3fc15318a80..40634b0db9f 100644
--- a/drivers/lguest/x86/switcher_32.S
+++ b/drivers/lguest/x86/switcher_32.S
@@ -1,12 +1,15 @@
-/*P:900 This is the Switcher: code which sits at 0xFFC00000 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.
+/*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
+/*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?
@@ -31,11 +34,14 @@
* Host (which is actually really easy).
*
* Two questions remain. Would the performance gain outweigh the complexity?
- * And who would write the verse documenting it? :*/
+ * And who would write the verse documenting it?
+:*/
-/*M:011 Lguest64 handles NMI. This gave me NMI envy (until I looked at their
+/*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. :*/
+ * Host when a Guest is running.
+:*/
/*S:100
* Welcome to the Switcher itself!