/* 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. */
- idt = &lg->idt[FIRST_EXTERNAL_VECTOR+irq];
+ idt = &lg->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. */
* the stack as well: virtual interrupts never do. */
set_guest_interrupt(lg, idt->a, idt->b, 0);
}
+
+ /* 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. */
+ write_timestamp(lg);
}
/*H:220 Now we've got the routines to deliver interrupts, delivering traps
/* deliver_trap() returns true if it could deliver the trap. */
int deliver_trap(struct lguest *lg, unsigned int num)
{
- u32 lo = lg->idt[num].a, hi = lg->idt[num].b;
+ /* 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))
+ 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(lo, hi))
+ if (!idt_present(lg->arch.idt[num].a, lg->arch.idt[num].b))
return 0;
- set_guest_interrupt(lg, lo, hi, has_err(num));
+ set_guest_interrupt(lg, lg->arch.idt[num].a, lg->arch.idt[num].b, has_err(num));
return 1;
}
* system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all
* the other hypervisors would tease it.
*
- * This routine determines if a trap can be delivered directly. */
-static int direct_trap(const struct lguest *lg,
- const struct desc_struct *trap,
- unsigned int num)
+ * This routine indicates if a particular trap number could be delivered
+ * directly. */
+static int direct_trap(unsigned int num)
{
/* Hardware interrupts don't go to the Guest at all (except system
* call). */
* fault address), general protection faults (in/out emulation) and
* device not available (TS handling), and of course, the hypercall
* trap. */
- if (num == 14 || num == 13 || num == 7 || num == LGUEST_TRAP_ENTRY)
- return 0;
-
- /* 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 8) */
- return idt_type(trap->a, trap->b) == 0xF;
+ return num != 14 && num != 13 && num != 7 && num != LGUEST_TRAP_ENTRY;
}
/*:*/
/* Depending on the CONFIG_4KSTACKS option, the Guest can have one or
* two pages of stack space. */
for (i = 0; i < lg->stack_pages; i++)
- /* The stack grows *upwards*, hence the subtraction */
- pin_page(lg, lg->esp1 - i * PAGE_SIZE);
+ /* 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. */
+ pin_page(lg, lg->esp1 - 1 - i * PAGE_SIZE);
}
/* Direct traps also mean that we need to know whenever the Guest wants to use
* to copy this again. */
lg->changed |= CHANGED_IDT;
- /* The IDT which we keep in "struct lguest" only contains 32 entries
- * for the traps and LGUEST_IRQS (32) entries for interrupts. We
- * ignore attempts to set handlers for higher interrupt numbers, except
- * for the system call "interrupt" at 128: we have a special IDT entry
- * for that. */
- if (num < ARRAY_SIZE(lg->idt))
- set_trap(lg, &lg->idt[num], num, lo, hi);
- else if (num == SYSCALL_VECTOR)
- set_trap(lg, &lg->syscall_idt, num, lo, hi);
+ /* Check that the Guest doesn't try to step outside the bounds. */
+ if (num >= ARRAY_SIZE(lg->arch.idt))
+ kill_guest(lg, "Setting idt entry %u", num);
+ else
+ set_trap(lg, &lg->arch.idt[num], num, lo, hi);
}
/* The default entry for each interrupt points into the Switcher routines which
/* 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 < FIRST_EXTERNAL_VECTOR; i++) {
- if (direct_trap(lg, &lg->idt[i], i))
- idt[i] = lg->idt[i];
+ for (i = 0; i < ARRAY_SIZE(lg->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.
+ * 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(lg->arch.idt[i].a, lg->arch.idt[i].b) == 0xF)
+ idt[i] = lg->arch.idt[i];
else
+ /* Reset it to the default. */
default_idt_entry(&idt[i], i, def[i]);
}
-
- /* Don't forget the system call trap! The IDT entries for other
- * interupts never change, so no need to copy them. */
- i = SYSCALL_VECTOR;
- if (direct_trap(lg, &lg->syscall_idt, i))
- idt[i] = lg->syscall_idt;
- else
- default_idt_entry(&idt[i], i, def[i]);
}
void guest_set_clockevent(struct lguest *lg, unsigned long delta)