aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/lguest/interrupts_and_traps.c49
-rw-r--r--drivers/lguest/lg.h3
2 files changed, 20 insertions, 32 deletions
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index 39731232d827..0dfb0903aa69 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -218,10 +218,9 @@ int deliver_trap(struct lguest *lg, unsigned int num)
218 * system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all 218 * system calls down from 1750ns to 270ns. Plus, if lguest didn't do it, all
219 * the other hypervisors would tease it. 219 * the other hypervisors would tease it.
220 * 220 *
221 * This routine determines if a trap can be delivered directly. */ 221 * This routine indicates if a particular trap number could be delivered
222static int direct_trap(const struct lguest *lg, 222 * directly. */
223 const struct desc_struct *trap, 223static int direct_trap(unsigned int num)
224 unsigned int num)
225{ 224{
226 /* Hardware interrupts don't go to the Guest at all (except system 225 /* Hardware interrupts don't go to the Guest at all (except system
227 * call). */ 226 * call). */
@@ -232,14 +231,7 @@ static int direct_trap(const struct lguest *lg,
232 * fault address), general protection faults (in/out emulation) and 231 * fault address), general protection faults (in/out emulation) and
233 * device not available (TS handling), and of course, the hypercall 232 * device not available (TS handling), and of course, the hypercall
234 * trap. */ 233 * trap. */
235 if (num == 14 || num == 13 || num == 7 || num == LGUEST_TRAP_ENTRY) 234 return num != 14 && num != 13 && num != 7 && num != LGUEST_TRAP_ENTRY;
236 return 0;
237
238 /* Only trap gates (type 15) can go direct to the Guest. Interrupt
239 * gates (type 14) disable interrupts as they are entered, which we
240 * never let the Guest do. Not present entries (type 0x0) also can't
241 * go direct, of course 8) */
242 return idt_type(trap->a, trap->b) == 0xF;
243} 235}
244/*:*/ 236/*:*/
245 237
@@ -348,15 +340,11 @@ void load_guest_idt_entry(struct lguest *lg, unsigned int num, u32 lo, u32 hi)
348 * to copy this again. */ 340 * to copy this again. */
349 lg->changed |= CHANGED_IDT; 341 lg->changed |= CHANGED_IDT;
350 342
351 /* The IDT which we keep in "struct lguest" only contains 32 entries 343 /* Check that the Guest doesn't try to step outside the bounds. */
352 * for the traps and LGUEST_IRQS (32) entries for interrupts. We 344 if (num >= ARRAY_SIZE(lg->idt))
353 * ignore attempts to set handlers for higher interrupt numbers, except 345 kill_guest(lg, "Setting idt entry %u", num);
354 * for the system call "interrupt" at 128: we have a special IDT entry 346 else
355 * for that. */
356 if (num < ARRAY_SIZE(lg->idt))
357 set_trap(lg, &lg->idt[num], num, lo, hi); 347 set_trap(lg, &lg->idt[num], num, lo, hi);
358 else if (num == SYSCALL_VECTOR)
359 set_trap(lg, &lg->syscall_idt, num, lo, hi);
360} 348}
361 349
362/* The default entry for each interrupt points into the Switcher routines which 350/* 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,
399 387
400 /* We can simply copy the direct traps, otherwise we use the default 388 /* We can simply copy the direct traps, otherwise we use the default
401 * ones in the Switcher: they will return to the Host. */ 389 * ones in the Switcher: they will return to the Host. */
402 for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) { 390 for (i = 0; i < ARRAY_SIZE(lg->idt); i++) {
403 if (direct_trap(lg, &lg->idt[i], i)) 391 /* If no Guest can ever override this trap, leave it alone. */
392 if (!direct_trap(i))
393 continue;
394
395 /* Only trap gates (type 15) can go direct to the Guest.
396 * Interrupt gates (type 14) disable interrupts as they are
397 * entered, which we never let the Guest do. Not present
398 * entries (type 0x0) also can't go direct, of course. */
399 if (idt_type(lg->idt[i].a, lg->idt[i].b) == 0xF)
404 idt[i] = lg->idt[i]; 400 idt[i] = lg->idt[i];
405 else 401 else
402 /* Reset it to the default. */
406 default_idt_entry(&idt[i], i, def[i]); 403 default_idt_entry(&idt[i], i, def[i]);
407 } 404 }
408
409 /* Don't forget the system call trap! The IDT entries for other
410 * interupts never change, so no need to copy them. */
411 i = SYSCALL_VECTOR;
412 if (direct_trap(lg, &lg->syscall_idt, i))
413 idt[i] = lg->syscall_idt;
414 else
415 default_idt_entry(&idt[i], i, def[i]);
416} 405}
417 406
418void guest_set_clockevent(struct lguest *lg, unsigned long delta) 407void guest_set_clockevent(struct lguest *lg, unsigned long delta)
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index c9d1dc29490d..c1ca127ddece 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -184,8 +184,7 @@ struct lguest
184 struct desc_struct gdt[GDT_ENTRIES]; 184 struct desc_struct gdt[GDT_ENTRIES];
185 185
186 /* The IDT entries: some copied into lguest_ro_state when running. */ 186 /* The IDT entries: some copied into lguest_ro_state when running. */
187 struct desc_struct idt[FIRST_EXTERNAL_VECTOR+LGUEST_IRQS]; 187 struct desc_struct idt[IDT_ENTRIES];
188 struct desc_struct syscall_idt;
189 188
190 /* Virtual clock device */ 189 /* Virtual clock device */
191 struct hrtimer hrt; 190 struct hrtimer hrt;