]> err.no Git - linux-2.6/commitdiff
lguest: make registers per-vcpu
authorGlauber de Oliveira Costa <gcosta@redhat.com>
Mon, 7 Jan 2008 13:05:32 +0000 (11:05 -0200)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 30 Jan 2008 11:50:11 +0000 (22:50 +1100)
This is the most obvious per-vcpu field: registers.

So this patch moves it from struct lguest to struct vcpu,
and patch the places in which they are used, accordingly

Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
drivers/lguest/interrupts_and_traps.c
drivers/lguest/lg.h
drivers/lguest/lguest_user.c
drivers/lguest/page_tables.c
drivers/lguest/x86/core.c

index 8f59232f458b0484bf1e14612e1643f80c0f779f..468faf8233d631077a747d6686ce72741e89e318 100644 (file)
@@ -70,7 +70,7 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
        /* There are two cases for interrupts: one where the Guest is already
         * in the kernel, and a more complex one where the Guest is in
         * userspace.  We check the privilege level to find out. */
-       if ((lg->regs->ss&0x3) != GUEST_PL) {
+       if ((cpu->regs->ss&0x3) != GUEST_PL) {
                /* The Guest told us their kernel stack with the SET_STACK
                 * hypercall: both the virtual address and the segment */
                virtstack = lg->esp1;
@@ -81,12 +81,12 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
                 * stack: when the Guest does an "iret" back from the interrupt
                 * handler the CPU will notice they're dropping privilege
                 * levels and expect these here. */
-               push_guest_stack(lg, &gstack, lg->regs->ss);
-               push_guest_stack(lg, &gstack, lg->regs->esp);
+               push_guest_stack(lg, &gstack, cpu->regs->ss);
+               push_guest_stack(lg, &gstack, cpu->regs->esp);
        } else {
                /* We're staying on the same Guest (kernel) stack. */
-               virtstack = lg->regs->esp;
-               ss = lg->regs->ss;
+               virtstack = cpu->regs->esp;
+               ss = cpu->regs->ss;
 
                origstack = gstack = guest_pa(lg, virtstack);
        }
@@ -95,7 +95,7 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
         * 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". */
-       eflags = lg->regs->eflags;
+       eflags = cpu->regs->eflags;
        if (get_user(irq_enable, &lg->lguest_data->irq_enabled) == 0
            && !(irq_enable & X86_EFLAGS_IF))
                eflags &= ~X86_EFLAGS_IF;
@@ -104,19 +104,19 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
         * "eflags" word, the old code segment, and the old instruction
         * pointer. */
        push_guest_stack(lg, &gstack, eflags);
-       push_guest_stack(lg, &gstack, lg->regs->cs);
-       push_guest_stack(lg, &gstack, lg->regs->eip);
+       push_guest_stack(lg, &gstack, cpu->regs->cs);
+       push_guest_stack(lg, &gstack, cpu->regs->eip);
 
        /* For the six traps which supply an error code, we push that, too. */
        if (has_err)
-               push_guest_stack(lg, &gstack, lg->regs->errcode);
+               push_guest_stack(lg, &gstack, cpu->regs->errcode);
 
        /* Now we've pushed all the old state, we change the stack, the code
         * segment and the address to execute. */
-       lg->regs->ss = ss;
-       lg->regs->esp = virtstack + (gstack - origstack);
-       lg->regs->cs = (__KERNEL_CS|GUEST_PL);
-       lg->regs->eip = idt_address(lo, hi);
+       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. */
@@ -157,7 +157,7 @@ void maybe_do_interrupt(struct lg_cpu *cpu)
 
        /* They may be in the middle of an iret, where they asked us never to
         * deliver interrupts. */
-       if (lg->regs->eip >= lg->noirq_start && lg->regs->eip < lg->noirq_end)
+       if (cpu->regs->eip >= lg->noirq_start && cpu->regs->eip < lg->noirq_end)
                return;
 
        /* If they're halted, interrupts restart them. */
index 072d0d4fd0b9e63d076657d37b19dd32c2b2b90d..35b331230c557d73914a117101887f83e4ecc343 100644 (file)
@@ -44,6 +44,10 @@ struct lg_cpu {
        unsigned int id;
        struct lguest *lg;
 
+       /* At end of a page shared mapped over lguest_pages in guest.  */
+       unsigned long regs_page;
+       struct lguest_regs *regs;
+
        /* If a hypercall was asked for, this points to the arguments. */
        struct hcall_args *hcall;
        u32 next_hcall;
@@ -58,9 +62,6 @@ struct lg_cpu {
 /* The private info the thread maintains about the guest. */
 struct lguest
 {
-       /* At end of a page shared mapped over lguest_pages in guest.  */
-       unsigned long regs_page;
-       struct lguest_regs *regs;
        struct lguest_data __user *lguest_data;
        struct task_struct *tsk;
        struct mm_struct *mm;   /* == tsk->mm, but that becomes NULL on exit */
@@ -181,7 +182,7 @@ void lguest_arch_run_guest(struct lg_cpu *cpu);
 void lguest_arch_handle_trap(struct lg_cpu *cpu);
 int lguest_arch_init_hypercalls(struct lg_cpu *cpu);
 int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args);
-void lguest_arch_setup_regs(struct lguest *lg, unsigned long start);
+void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start);
 
 /* <arch>/switcher.S: */
 extern char start_switcher_text[], end_switcher_text[], switch_to_guest[];
index 605db5c49e7fdb7ac2154718b7ded80d6cfcd956..d21d95b2b1fcdeb20d7c581d79721dddfaa78878 100644 (file)
@@ -106,6 +106,19 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
        cpu->lg->nr_cpus++;
        init_clockdev(cpu);
 
+       /* We need a complete page for the Guest registers: they are accessible
+        * to the Guest and we can only grant it access to whole pages. */
+       cpu->regs_page = get_zeroed_page(GFP_KERNEL);
+       if (!cpu->regs_page)
+               return -ENOMEM;
+
+       /* We actually put the registers at the bottom of the page. */
+       cpu->regs = (void *)cpu->regs_page + PAGE_SIZE - sizeof(*cpu->regs);
+
+       /* Now we initialize the Guest's registers, handing it the start
+        * address. */
+       lguest_arch_setup_regs(cpu, start_ip);
+
        return 0;
 }
 
@@ -160,16 +173,6 @@ static int initialize(struct file *file, const unsigned long __user *input)
        if (err)
                goto release_guest;
 
-       /* We need a complete page for the Guest registers: they are accessible
-        * to the Guest and we can only grant it access to whole pages. */
-       lg->regs_page = get_zeroed_page(GFP_KERNEL);
-       if (!lg->regs_page) {
-               err = -ENOMEM;
-               goto release_guest;
-       }
-       /* We actually put the registers at the bottom of the page. */
-       lg->regs = (void *)lg->regs_page + PAGE_SIZE - sizeof(*lg->regs);
-
        /* Initialize the Guest's shadow page tables, using the toplevel
         * address the Launcher gave us.  This allocates memory, so can
         * fail. */
@@ -177,10 +180,6 @@ static int initialize(struct file *file, const unsigned long __user *input)
        if (err)
                goto free_regs;
 
-       /* Now we initialize the Guest's registers, handing it the start
-        * address. */
-       lguest_arch_setup_regs(lg, args[3]);
-
        /* We keep a pointer to the Launcher task (ie. current task) for when
         * other Guests want to wake this one (inter-Guest I/O). */
        lg->tsk = current;
@@ -205,7 +204,8 @@ static int initialize(struct file *file, const unsigned long __user *input)
        return sizeof(args);
 
 free_regs:
-       free_page(lg->regs_page);
+       /* FIXME: This should be in free_vcpu */
+       free_page(lg->cpus[0].regs_page);
 release_guest:
        kfree(lg);
 unlock:
@@ -280,9 +280,12 @@ static int close(struct inode *inode, struct file *file)
        /* We need the big lock, to protect from inter-guest I/O and other
         * Launchers initializing guests. */
        mutex_lock(&lguest_lock);
-       for (i = 0; i < lg->nr_cpus; i++)
+       for (i = 0; i < lg->nr_cpus; i++) {
                /* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
                hrtimer_cancel(&lg->cpus[i].hrt);
+               /* We can free up the register page we allocated. */
+               free_page(lg->cpus[i].regs_page);
+       }
        /* Free up the shadow page tables for the Guest. */
        free_guest_pagetable(lg);
        /* Now all the memory cleanups are done, it's safe to release the
@@ -292,8 +295,6 @@ static int close(struct inode *inode, struct file *file)
         * kmalloc()ed string, either of which is ok to hand to kfree(). */
        if (!IS_ERR(lg->dead))
                kfree(lg->dead);
-       /* We can free up the register page we allocated. */
-       free_page(lg->regs_page);
        /* We clear the entire structure, which also marks it as free for the
         * next user. */
        memset(lg, 0, sizeof(*lg));
index 17d3329e34c2178dde0d159d890dc842db8a8d19..f19add4699440114af688ffcebac25541a34699b 100644 (file)
@@ -640,6 +640,7 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages)
        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). */
@@ -654,7 +655,8 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages)
         * CPU's "struct lguest_pages": if we make sure the Guest's register
         * page is already mapped there, we don't have to copy them out
         * again. */
-       regs_pte = pfn_pte (__pa(lg->regs_page) >> PAGE_SHIFT, __pgprot(_PAGE_KERNEL));
+       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;
 }
 /*:*/
index ae46c6b1f2f96d448c16f87df56ae925d5078ce8..d96a93d95aea588b020b199b940a7e984201245a 100644 (file)
@@ -127,7 +127,7 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *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
@@ -195,11 +195,11 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
         * 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. */
@@ -225,12 +225,12 @@ static int emulate_insn(struct lg_cpu *cpu)
        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. */
@@ -273,12 +273,12 @@ static int emulate_insn(struct lg_cpu *cpu)
        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;
 }
@@ -287,12 +287,12 @@ static int emulate_insn(struct lg_cpu *cpu)
 void lguest_arch_handle_trap(struct lg_cpu *cpu)
 {
        struct lguest *lg = cpu->lg;
-       switch (lg->regs->trapnum) {
+       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 (cpu->regs->errcode == 0) {
                        if (emulate_insn(cpu))
                                return;
                }
@@ -307,7 +307,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
                 *
                 * 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
@@ -338,19 +338,19 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
        case LGUEST_TRAP_ENTRY:
                /* Our 'struct hcall_args' maps directly over our regs: we set
                 * up the pointer now to indicate a hypercall is pending. */
-               cpu->hcall = (struct hcall_args *)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(cpu, 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
@@ -557,9 +557,9 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
  *
  * 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
@@ -586,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);
 }