]> err.no Git - linux-2.6/blobdiff - drivers/lguest/x86/core.c
lguest: make registers per-vcpu
[linux-2.6] / drivers / lguest / x86 / core.c
index 482aec2a96318e854aede3a385cf34eedc1da95f..d96a93d95aea588b020b199b940a7e984201245a 100644 (file)
@@ -73,8 +73,9 @@ static DEFINE_PER_CPU(struct lguest *, last_guest);
  * since it last ran.  We saw this set in interrupts_and_traps.c and
  * segments.c.
  */
-static void copy_in_guest_info(struct lguest *lg, struct lguest_pages *pages)
+static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages)
 {
+       struct lguest *lg = cpu->lg;
        /* 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
@@ -90,7 +91,7 @@ static void copy_in_guest_info(struct lguest *lg, struct lguest_pages *pages)
        pages->state.host_cr3 = __pa(current->mm->pgd);
        /* Set up the Guest's page tables to see this CPU's pages (and no
         * other CPU's pages). */
-       map_switcher_in_guest(lg, pages);
+       map_switcher_in_guest(cpu, pages);
        /* Set up the two "TSS" members which tell the CPU what stack to use
         * for traps which do directly into the Guest (ie. traps at privilege
         * level 1). */
@@ -113,19 +114,20 @@ static void copy_in_guest_info(struct lguest *lg, struct lguest_pages *pages)
 }
 
 /* Finally: the code to actually call into the Switcher to run the Guest. */
-static void run_guest_once(struct lguest *lg, struct lguest_pages *pages)
+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;
+       struct lguest *lg = cpu->lg;
 
        /* Copy the guest-specific information into this CPU's "struct
         * lguest_pages". */
-       copy_in_guest_info(lg, pages);
+       copy_in_guest_info(cpu, pages);
 
        /* Set the trap number to 256 (impossible value).  If we fault while
         * switching to the Guest (bad segment registers or bug), this will
         * cause us to abort the Guest. */
-       lg->regs->trapnum = 256;
+       cpu->regs->trapnum = 256;
 
        /* Now: we push the "eflags" register on the stack, then do an "lcall".
         * This is how we change from using the kernel code segment to using
@@ -161,8 +163,10 @@ static void run_guest_once(struct lguest *lg, struct lguest_pages *pages)
 
 /*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 lguest *lg)
+void lguest_arch_run_guest(struct lg_cpu *cpu)
 {
+       struct lguest *lg = cpu->lg;
+
        /* 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. */
@@ -180,7 +184,7 @@ void lguest_arch_run_guest(struct lguest *lg)
        /* Now we actually run the Guest.  It will return when something
         * interesting happens, and we can examine its registers to see what it
         * was doing. */
-       run_guest_once(lg, lguest_pages(raw_smp_processor_id()));
+       run_guest_once(cpu, lguest_pages(raw_smp_processor_id()));
 
        /* Note that the "regs" pointer contains two extra entries which are
         * not really registers: a trap number which says what interrupt or
@@ -191,11 +195,11 @@ void lguest_arch_run_guest(struct lguest *lg)
         * bad virtual address.  We have to grab this now, because once we
         * re-enable interrupts an interrupt could fault and thus overwrite
         * cr2, or we could even move off to a different CPU. */
-       if (lg->regs->trapnum == 14)
+       if (cpu->regs->trapnum == 14)
                lg->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 (lg->regs->trapnum == 7)
+       else if (cpu->regs->trapnum == 7)
                math_state_restore();
 
        /* Restore SYSENTER if it's supposed to be on. */
@@ -214,18 +218,19 @@ void lguest_arch_run_guest(struct lguest *lg)
  * When the Guest uses one of these instructions, we get a trap (General
  * Protection Fault) and come here.  We see if it's one of those troublesome
  * instructions and skip over it.  We return true if we did. */
-static int emulate_insn(struct lguest *lg)
+static int emulate_insn(struct lg_cpu *cpu)
 {
+       struct lguest *lg = cpu->lg;
        u8 insn;
        unsigned int insnlen = 0, in = 0, shift = 0;
        /* The eip contains the *virtual* address of the Guest's instruction:
         * guest_pa just subtracts the Guest's page_offset. */
-       unsigned long physaddr = guest_pa(lg, lg->regs->eip);
+       unsigned long physaddr = guest_pa(lg, cpu->regs->eip);
 
        /* This must be the Guest kernel trying to do something, not userspace!
         * The bottom two bits of the CS segment register are the privilege
         * level. */
-       if ((lg->regs->cs & 3) != GUEST_PL)
+       if ((cpu->regs->cs & 3) != GUEST_PL)
                return 0;
 
        /* Decoding x86 instructions is icky. */
@@ -268,26 +273,27 @@ static int emulate_insn(struct lguest *lg)
        if (in) {
                /* Lower bit tells is whether it's a 16 or 32 bit access */
                if (insn & 0x1)
-                       lg->regs->eax = 0xFFFFFFFF;
+                       cpu->regs->eax = 0xFFFFFFFF;
                else
-                       lg->regs->eax |= (0xFFFF << shift);
+                       cpu->regs->eax |= (0xFFFF << shift);
        }
        /* Finally, we've "done" the instruction, so move past it. */
-       lg->regs->eip += insnlen;
+       cpu->regs->eip += insnlen;
        /* Success! */
        return 1;
 }
 
 /*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */
-void lguest_arch_handle_trap(struct lguest *lg)
+void lguest_arch_handle_trap(struct lg_cpu *cpu)
 {
-       switch (lg->regs->trapnum) {
+       struct lguest *lg = cpu->lg;
+       switch (cpu->regs->trapnum) {
        case 13: /* We've intercepted a General Protection Fault. */
                /* Check if this was one of those annoying IN or OUT
                 * instructions which we need to emulate.  If so, we just go
                 * back into the Guest after we've done it. */
-               if (lg->regs->errcode == 0) {
-                       if (emulate_insn(lg))
+               if (cpu->regs->errcode == 0) {
+                       if (emulate_insn(cpu))
                                return;
                }
                break;
@@ -301,7 +307,7 @@ void lguest_arch_handle_trap(struct lguest *lg)
                 *
                 * The errcode tells whether this was a read or a write, and
                 * whether kernel or userspace code. */
-               if (demand_page(lg, lg->arch.last_pagefault, lg->regs->errcode))
+               if (demand_page(lg, lg->arch.last_pagefault, cpu->regs->errcode))
                        return;
 
                /* OK, it's really not there (or not OK): the Guest needs to
@@ -332,19 +338,19 @@ void lguest_arch_handle_trap(struct lguest *lg)
        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. */
-               lg->hcall = (struct hcall_args *)lg->regs;
+               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(lg, lg->regs->trapnum))
+       if (!deliver_trap(cpu, cpu->regs->trapnum))
                /* If the Guest doesn't have a handler (either it hasn't
                 * registered any yet, or it's one of the faults we don't let
                 * it handle), it dies with a cryptic error message. */
                kill_guest(lg, "unhandled trap %li at %#lx (%#lx)",
-                          lg->regs->trapnum, lg->regs->eip,
-                          lg->regs->trapnum == 14 ? lg->arch.last_pagefault
-                          : lg->regs->errcode);
+                          cpu->regs->trapnum, cpu->regs->eip,
+                          cpu->regs->trapnum == 14 ? lg->arch.last_pagefault
+                          : cpu->regs->errcode);
 }
 
 /* Now we can look at each of the routines this calls, in increasing order of
@@ -459,7 +465,7 @@ void __init lguest_arch_host_init(void)
 
        /* We don't need the complexity of CPUs coming and going while we're
         * doing this. */
-       lock_cpu_hotplug();
+       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;
@@ -469,26 +475,28 @@ void __init lguest_arch_host_init(void)
                /* Turn off the feature in the global feature set. */
                clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
        }
-       unlock_cpu_hotplug();
+       put_online_cpus();
 };
 /*:*/
 
 void __exit lguest_arch_host_fini(void)
 {
        /* If we had PGE before we started, turn it back on now. */
-       lock_cpu_hotplug();
+       get_online_cpus();
        if (cpu_had_pge) {
                set_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
                /* adjust_pge's argument "1" means set PGE. */
                on_each_cpu(adjust_pge, (void *)1, 0, 1);
        }
-       unlock_cpu_hotplug();
+       put_online_cpus();
 }
 
 
 /*H:122 The i386-specific hypercalls simply farm out to the right functions. */
-int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args)
+int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
 {
+       struct lguest *lg = cpu->lg;
+
        switch (args->arg0) {
        case LHCALL_LOAD_GDT:
                load_guest_gdt(lg, args->arg1, args->arg2);
@@ -507,13 +515,14 @@ int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args)
 }
 
 /*H:126 i386-specific hypercall initialization: */
-int lguest_arch_init_hypercalls(struct lguest *lg)
+int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
 {
        u32 tsc_speed;
+       struct lguest *lg = cpu->lg;
 
        /* The pointer to the Guest's "struct lguest_data" is the only
         * argument.  We check that address now. */
-       if (!lguest_address_ok(lg, lg->hcall->arg1, sizeof(*lg->lguest_data)))
+       if (!lguest_address_ok(lg, cpu->hcall->arg1, sizeof(*lg->lguest_data)))
                return -EFAULT;
 
        /* Having checked it, we simply set lg->lguest_data to point straight
@@ -521,7 +530,7 @@ int lguest_arch_init_hypercalls(struct lguest *lg)
         * 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. */
-       lg->lguest_data = lg->mem_base + lg->hcall->arg1;
+       lg->lguest_data = lg->mem_base + cpu->hcall->arg1;
 
        /* We insist that the Time Stamp Counter exist and doesn't change with
         * cpu frequency.  Some devious chip manufacturers decided that TSC
@@ -548,9 +557,9 @@ int lguest_arch_init_hypercalls(struct lguest *lg)
  *
  * Most of the Guest's registers are left alone: we used get_zeroed_page() to
  * allocate the structure, so they will be 0. */
-void lguest_arch_setup_regs(struct lguest *lg, unsigned long start)
+void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start)
 {
-       struct lguest_regs *regs = lg->regs;
+       struct lguest_regs *regs = cpu->regs;
 
        /* There are four "segment" registers which the Guest needs to boot:
         * The "code segment" register (cs) refers to the kernel code segment
@@ -577,5 +586,5 @@ void lguest_arch_setup_regs(struct lguest *lg, unsigned long start)
 
        /* There are a couple of GDT entries the Guest expects when first
         * booting. */
-       setup_guest_gdt(lg);
+       setup_guest_gdt(cpu->lg);
 }