lguest: make registers per-vcpu
[deliverable/linux.git] / drivers / lguest / interrupts_and_traps.c
index 2b66f79c208b519d19937af625ae64a8b8fc70a5..468faf8233d631077a747d6686ce72741e89e318 100644 (file)
@@ -60,16 +60,17 @@ static void push_guest_stack(struct lguest *lg, unsigned long *gstack, u32 val)
  * We set up the stack just like the CPU does for a real interrupt, so it's
  * identical for the Guest (and the standard "iret" instruction will undo
  * it). */
-static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
+static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err)
 {
        unsigned long gstack, origstack;
        u32 eflags, ss, irq_enable;
        unsigned long virtstack;
+       struct lguest *lg = cpu->lg;
 
        /* 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;
@@ -80,12 +81,12 @@ static void set_guest_interrupt(struct lguest *lg, 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);
        }
@@ -94,7 +95,7 @@ static void set_guest_interrupt(struct lguest *lg, 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;
@@ -103,19 +104,19 @@ static void set_guest_interrupt(struct lguest *lg, 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. */
@@ -129,9 +130,10 @@ static void set_guest_interrupt(struct lguest *lg, u32 lo, u32 hi, int has_err)
  *
  * maybe_do_interrupt() gets called before every entry to the Guest, to see if
  * we should divert the Guest to running an interrupt handler. */
-void maybe_do_interrupt(struct lguest *lg)
+void maybe_do_interrupt(struct lg_cpu *cpu)
 {
        unsigned int irq;
+       struct lguest *lg = cpu->lg;
        DECLARE_BITMAP(blk, LGUEST_IRQS);
        struct desc_struct *idt;
 
@@ -145,7 +147,7 @@ void maybe_do_interrupt(struct lguest *lg)
                           sizeof(blk)))
                return;
 
-       bitmap_andnot(blk, lg->irqs_pending, blk, LGUEST_IRQS);
+       bitmap_andnot(blk, cpu->irqs_pending, blk, LGUEST_IRQS);
 
        /* Find the first interrupt. */
        irq = find_first_bit(blk, LGUEST_IRQS);
@@ -155,7 +157,7 @@ void maybe_do_interrupt(struct lguest *lg)
 
        /* 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. */
@@ -180,11 +182,11 @@ void maybe_do_interrupt(struct lguest *lg)
        /* If they don't have a handler (yet?), we just ignore it */
        if (idt_present(idt->a, idt->b)) {
                /* OK, mark it no longer pending and deliver it. */
-               clear_bit(irq, lg->irqs_pending);
+               clear_bit(irq, cpu->irqs_pending);
                /* set_guest_interrupt() takes the interrupt descriptor and a
                 * flag to say whether this interrupt pushes an error code onto
                 * the stack as well: virtual interrupts never do. */
-               set_guest_interrupt(lg, idt->a, idt->b, 0);
+               set_guest_interrupt(cpu, idt->a, idt->b, 0);
        }
 
        /* Every time we deliver an interrupt, we update the timestamp in the
@@ -245,19 +247,19 @@ static int has_err(unsigned int trap)
 }
 
 /* deliver_trap() returns true if it could deliver the trap. */
-int deliver_trap(struct lguest *lg, unsigned int num)
+int deliver_trap(struct lg_cpu *cpu, unsigned int num)
 {
        /* Trap numbers are always 8 bit, but we set an impossible trap number
         * for traps inside the Switcher, so check that here. */
-       if (num >= ARRAY_SIZE(lg->arch.idt))
+       if (num >= ARRAY_SIZE(cpu->lg->arch.idt))
                return 0;
 
        /* Early on the Guest hasn't set the IDT entries (or maybe it put a
         * bogus one in): if we fail here, the Guest will be killed. */
-       if (!idt_present(lg->arch.idt[num].a, lg->arch.idt[num].b))
+       if (!idt_present(cpu->lg->arch.idt[num].a, cpu->lg->arch.idt[num].b))
                return 0;
-       set_guest_interrupt(lg, lg->arch.idt[num].a, lg->arch.idt[num].b,
-                           has_err(num));
+       set_guest_interrupt(cpu, cpu->lg->arch.idt[num].a,
+                           cpu->lg->arch.idt[num].b, has_err(num));
        return 1;
 }
 
@@ -470,13 +472,13 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt,
  * infrastructure to set a callback at that time.
  *
  * 0 means "turn off the clock". */
-void guest_set_clockevent(struct lguest *lg, unsigned long delta)
+void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta)
 {
        ktime_t expires;
 
        if (unlikely(delta == 0)) {
                /* Clock event device is shutting down. */
-               hrtimer_cancel(&lg->hrt);
+               hrtimer_cancel(&cpu->hrt);
                return;
        }
 
@@ -484,25 +486,25 @@ void guest_set_clockevent(struct lguest *lg, unsigned long delta)
         * all the time between now and the timer interrupt it asked for.  This
         * is almost always the right thing to do. */
        expires = ktime_add_ns(ktime_get_real(), delta);
-       hrtimer_start(&lg->hrt, expires, HRTIMER_MODE_ABS);
+       hrtimer_start(&cpu->hrt, expires, HRTIMER_MODE_ABS);
 }
 
 /* This is the function called when the Guest's timer expires. */
 static enum hrtimer_restart clockdev_fn(struct hrtimer *timer)
 {
-       struct lguest *lg = container_of(timer, struct lguest, hrt);
+       struct lg_cpu *cpu = container_of(timer, struct lg_cpu, hrt);
 
        /* Remember the first interrupt is the timer interrupt. */
-       set_bit(0, lg->irqs_pending);
+       set_bit(0, cpu->irqs_pending);
        /* If the Guest is actually stopped, we need to wake it up. */
-       if (lg->halted)
-               wake_up_process(lg->tsk);
+       if (cpu->lg->halted)
+               wake_up_process(cpu->lg->tsk);
        return HRTIMER_NORESTART;
 }
 
 /* This sets up the timer for this Guest. */
-void init_clockdev(struct lguest *lg)
+void init_clockdev(struct lg_cpu *cpu)
 {
-       hrtimer_init(&lg->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS);
-       lg->hrt.function = clockdev_fn;
+       hrtimer_init(&cpu->hrt, CLOCK_REALTIME, HRTIMER_MODE_ABS);
+       cpu->hrt.function = clockdev_fn;
 }
This page took 0.027326 seconds and 5 git commands to generate.