]> err.no Git - linux-2.6/blobdiff - drivers/lguest/core.c
Remove fixed limit on number of guests, and lguests array.
[linux-2.6] / drivers / lguest / core.c
index 0a46e8837d9a01629d708db246953a4af3f4600b..ca581ef591e89970669b26f0ff50045354f8aab5 100644 (file)
@@ -47,10 +47,6 @@ static struct {
 DEFINE_MUTEX(lguest_lock);
 static DEFINE_PER_CPU(struct lguest *, last_guest);
 
-/* FIXME: Make dynamic. */
-#define MAX_LGUEST_GUESTS 16
-struct lguest lguests[MAX_LGUEST_GUESTS];
-
 /* Offset from where switcher.S was compiled to where we've copied it */
 static unsigned long switcher_offset(void)
 {
@@ -248,8 +244,8 @@ static void unmap_switcher(void)
 }
 
 /*H:130 Our Guest is usually so well behaved; it never tries to do things it
- * isn't allowed to.  Unfortunately, "struct paravirt_ops" isn't quite
- * complete, because it doesn't contain replacements for the Intel I/O
+ * isn't allowed to.  Unfortunately, Linux's paravirtual infrastructure isn't
+ * quite complete, because it doesn't contain replacements for the Intel I/O
  * instructions.  As a result, the Guest sometimes fumbles across one during
  * the boot process as it probes for various things which are usually attached
  * to a PC.
@@ -325,8 +321,8 @@ static int emulate_insn(struct lguest *lg)
  * Dealing With Guest Memory.
  *
  * When the Guest gives us (what it thinks is) a physical address, we can use
- * the normal copy_from_user() & copy_to_user() on that address: remember,
- * Guest physical == Launcher virtual.
+ * the normal copy_from_user() & copy_to_user() on the corresponding place in
+ * the memory region allocated by the Launcher.
  *
  * But we can't trust the Guest: it might be trying to access the Launcher
  * code.  We have to check that the range is below the pfn_limit the Launcher
@@ -348,8 +344,8 @@ u32 lgread_u32(struct lguest *lg, unsigned long addr)
 
        /* Don't let them access lguest binary. */
        if (!lguest_address_ok(lg, addr, sizeof(val))
-           || get_user(val, (u32 __user *)addr) != 0)
-               kill_guest(lg, "bad read address %#lx", addr);
+           || get_user(val, (u32 *)(lg->mem_base + addr)) != 0)
+               kill_guest(lg, "bad read address %#lx: pfn_limit=%u membase=%p", addr, lg->pfn_limit, lg->mem_base);
        return val;
 }
 
@@ -357,7 +353,7 @@ u32 lgread_u32(struct lguest *lg, unsigned long addr)
 void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val)
 {
        if (!lguest_address_ok(lg, addr, sizeof(val))
-           || put_user(val, (u32 __user *)addr) != 0)
+           || put_user(val, (u32 *)(lg->mem_base + addr)) != 0)
                kill_guest(lg, "bad write address %#lx", addr);
 }
 
@@ -367,7 +363,7 @@ void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val)
 void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
 {
        if (!lguest_address_ok(lg, addr, bytes)
-           || copy_from_user(b, (void __user *)addr, bytes) != 0) {
+           || copy_from_user(b, lg->mem_base + addr, bytes) != 0) {
                /* copy_from_user should do this, but as we rely on it... */
                memset(b, 0, bytes);
                kill_guest(lg, "bad read address %#lx len %u", addr, bytes);
@@ -379,7 +375,7 @@ void lgwrite(struct lguest *lg, unsigned long addr, const void *b,
             unsigned bytes)
 {
        if (!lguest_address_ok(lg, addr, bytes)
-           || copy_to_user((void __user *)addr, b, bytes) != 0)
+           || copy_to_user(lg->mem_base + addr, b, bytes) != 0)
                kill_guest(lg, "bad write address %#lx len %u", addr, bytes);
 }
 /* (end of memory access helper routines) :*/
@@ -453,6 +449,11 @@ static void run_guest_once(struct lguest *lg, struct lguest_pages *pages)
         * lguest_pages". */
        copy_in_guest_info(lg, pages);
 
+       /* Set the trap number to 256 (impossible value).  If we fault while
+        * switching to the Guest (bad segment registers or bug), this will
+        * cause us to abort the Guest. */
+       lg->regs->trapnum = 256;
+
        /* Now: we push the "eflags" register on the stack, then do an "lcall".
         * This is how we change from using the kernel code segment to using
         * the dedicated lguest code segment, as well as jumping into the
@@ -611,11 +612,9 @@ int run_guest(struct lguest *lg, unsigned long __user *user)
                         *
                         * Note that if the Guest were really messed up, this
                         * could happen before it's done the INITIALIZE
-                        * hypercall, so lg->lguest_data will be NULL, so
-                        * &lg->lguest_data->cr2 will be address 8.  Writing
-                        * into that address won't hurt the Host at all,
-                        * though. */
-                       if (put_user(cr2, &lg->lguest_data->cr2))
+                        * hypercall, so lg->lguest_data will be NULL */
+                       if (lg->lguest_data
+                           && put_user(cr2, &lg->lguest_data->cr2))
                                kill_guest(lg, "Writing cr2");
                        break;
                case 7: /* We've intercepted a Device Not Available fault. */
@@ -657,16 +656,6 @@ int run_guest(struct lguest *lg, unsigned long __user *user)
  * deliver_trap() and demand_page().  After all those, we'll be ready to
  * examine the Switcher, and our philosophical understanding of the Host/Guest
  * duality will be complete. :*/
-
-int find_free_guest(void)
-{
-       unsigned int i;
-       for (i = 0; i < MAX_LGUEST_GUESTS; i++)
-               if (!lguests[i].tsk)
-                       return i;
-       return -1;
-}
-
 static void adjust_pge(void *on)
 {
        if (on)
@@ -689,7 +678,7 @@ static int __init init(void)
 
        /* Lguest can't run under Xen, VMI or itself.  It does Tricky Stuff. */
        if (paravirt_enabled()) {
-               printk("lguest is afraid of %s\n", paravirt_ops.name);
+               printk("lguest is afraid of %s\n", pv_info.name);
                return -EPERM;
        }