Make shadow IDT a complete IDT with 256 entries.
This simplifies the code a little, in preparation for allowing alternate system call vectors in guests (Plan 9 uses 0x40). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Родитель
48245cc070
Коммит
56adbe9ddc
|
@ -218,10 +218,9 @@ int deliver_trap(struct lguest *lg, unsigned int num)
|
||||||
* system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all
|
* system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all
|
||||||
* the other hypervisors would tease it.
|
* the other hypervisors would tease it.
|
||||||
*
|
*
|
||||||
* This routine determines if a trap can be delivered directly. */
|
* This routine indicates if a particular trap number could be delivered
|
||||||
static int direct_trap(const struct lguest *lg,
|
* directly. */
|
||||||
const struct desc_struct *trap,
|
static int direct_trap(unsigned int num)
|
||||||
unsigned int num)
|
|
||||||
{
|
{
|
||||||
/* Hardware interrupts don't go to the Guest at all (except system
|
/* Hardware interrupts don't go to the Guest at all (except system
|
||||||
* call). */
|
* call). */
|
||||||
|
@ -232,14 +231,7 @@ static int direct_trap(const struct lguest *lg,
|
||||||
* fault address), general protection faults (in/out emulation) and
|
* fault address), general protection faults (in/out emulation) and
|
||||||
* device not available (TS handling), and of course, the hypercall
|
* device not available (TS handling), and of course, the hypercall
|
||||||
* trap. */
|
* trap. */
|
||||||
if (num == 14 || num == 13 || num == 7 || num == LGUEST_TRAP_ENTRY)
|
return 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;
|
|
||||||
}
|
}
|
||||||
/*:*/
|
/*:*/
|
||||||
|
|
||||||
|
@ -348,15 +340,11 @@ void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi)
|
||||||
* to copy this again. */
|
* to copy this again. */
|
||||||
lg->changed |= CHANGED_IDT;
|
lg->changed |= CHANGED_IDT;
|
||||||
|
|
||||||
/* The IDT which we keep in "struct lguest" only contains 32 entries
|
/* Check that the Guest doesn't try to step outside the bounds. */
|
||||||
* for the traps and LGUEST_IRQS (32) entries for interrupts. We
|
if (num >= ARRAY_SIZE(lg->idt))
|
||||||
* ignore attempts to set handlers for higher interrupt numbers, except
|
kill_guest(lg, "Setting idt entry %u", num);
|
||||||
* for the system call "interrupt" at 128: we have a special IDT entry
|
else
|
||||||
* for that. */
|
|
||||||
if (num < ARRAY_SIZE(lg->idt))
|
|
||||||
set_trap(lg, &lg->idt[num], num, lo, hi);
|
set_trap(lg, &lg->idt[num], num, lo, hi);
|
||||||
else if (num == SYSCALL_VECTOR)
|
|
||||||
set_trap(lg, &lg->syscall_idt, num, lo, hi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The default entry for each interrupt points into the Switcher routines which
|
/* The default entry for each interrupt points into the Switcher routines which
|
||||||
|
@ -399,20 +387,21 @@ void copy_traps(const struct lguest *lg, struct desc_struct *idt,
|
||||||
|
|
||||||
/* We can simply copy the direct traps, otherwise we use the default
|
/* We can simply copy the direct traps, otherwise we use the default
|
||||||
* ones in the Switcher: they will return to the Host. */
|
* ones in the Switcher: they will return to the Host. */
|
||||||
for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) {
|
for (i = 0; i < ARRAY_SIZE(lg->idt); i++) {
|
||||||
if (direct_trap(lg, &lg->idt[i], 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->idt[i].a, lg->idt[i].b) == 0xF)
|
||||||
idt[i] = lg->idt[i];
|
idt[i] = lg->idt[i];
|
||||||
else
|
else
|
||||||
|
/* Reset it to the default. */
|
||||||
default_idt_entry(&idt[i], i, def[i]);
|
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)
|
void guest_set_clockevent(struct lguest *lg, unsigned long delta)
|
||||||
|
|
|
@ -184,8 +184,7 @@ struct lguest
|
||||||
struct desc_struct gdt[GDT_ENTRIES];
|
struct desc_struct gdt[GDT_ENTRIES];
|
||||||
|
|
||||||
/* The IDT entries: some copied into lguest_ro_state when running. */
|
/* The IDT entries: some copied into lguest_ro_state when running. */
|
||||||
struct desc_struct idt[FIRST_EXTERNAL_VECTOR+LGUEST_IRQS];
|
struct desc_struct idt[IDT_ENTRIES];
|
||||||
struct desc_struct syscall_idt;
|
|
||||||
|
|
||||||
/* Virtual clock device */
|
/* Virtual clock device */
|
||||||
struct hrtimer hrt;
|
struct hrtimer hrt;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче