diff options
| -rw-r--r-- | drivers/lguest/interrupts_and_traps.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 0414ddf87587..a1039068f95c 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c | |||
| @@ -406,7 +406,8 @@ void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int num, u32 lo, u32 hi) | |||
| 406 | * deliver_trap() to bounce it back into the Guest. */ | 406 | * deliver_trap() to bounce it back into the Guest. */ |
| 407 | static void default_idt_entry(struct desc_struct *idt, | 407 | static void default_idt_entry(struct desc_struct *idt, |
| 408 | int trap, | 408 | int trap, |
| 409 | const unsigned long handler) | 409 | const unsigned long handler, |
| 410 | const struct desc_struct *base) | ||
| 410 | { | 411 | { |
| 411 | /* A present interrupt gate. */ | 412 | /* A present interrupt gate. */ |
| 412 | u32 flags = 0x8e00; | 413 | u32 flags = 0x8e00; |
| @@ -415,6 +416,10 @@ static void default_idt_entry(struct desc_struct *idt, | |||
| 415 | * the Guest to use the "int" instruction to trigger it. */ | 416 | * the Guest to use the "int" instruction to trigger it. */ |
| 416 | if (trap == LGUEST_TRAP_ENTRY) | 417 | if (trap == LGUEST_TRAP_ENTRY) |
| 417 | flags |= (GUEST_PL << 13); | 418 | flags |= (GUEST_PL << 13); |
| 419 | else if (base) | ||
| 420 | /* Copy priv. level from what Guest asked for. This allows | ||
| 421 | * debug (int 3) traps from Guest userspace, for example. */ | ||
| 422 | flags |= (base->b & 0x6000); | ||
| 418 | 423 | ||
| 419 | /* Now pack it into the IDT entry in its weird format. */ | 424 | /* Now pack it into the IDT entry in its weird format. */ |
| 420 | idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF); | 425 | idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF); |
| @@ -428,7 +433,7 @@ void setup_default_idt_entries(struct lguest_ro_state *state, | |||
| 428 | unsigned int i; | 433 | unsigned int i; |
| 429 | 434 | ||
| 430 | for (i = 0; i < ARRAY_SIZE(state->guest_idt); i++) | 435 | for (i = 0; i < ARRAY_SIZE(state->guest_idt); i++) |
| 431 | default_idt_entry(&state->guest_idt[i], i, def[i]); | 436 | default_idt_entry(&state->guest_idt[i], i, def[i], NULL); |
| 432 | } | 437 | } |
| 433 | 438 | ||
| 434 | /*H:240 We don't use the IDT entries in the "struct lguest" directly, instead | 439 | /*H:240 We don't use the IDT entries in the "struct lguest" directly, instead |
| @@ -442,6 +447,8 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt, | |||
| 442 | /* We can simply copy the direct traps, otherwise we use the default | 447 | /* We can simply copy the direct traps, otherwise we use the default |
| 443 | * ones in the Switcher: they will return to the Host. */ | 448 | * ones in the Switcher: they will return to the Host. */ |
| 444 | for (i = 0; i < ARRAY_SIZE(cpu->arch.idt); i++) { | 449 | for (i = 0; i < ARRAY_SIZE(cpu->arch.idt); i++) { |
| 450 | const struct desc_struct *gidt = &cpu->arch.idt[i]; | ||
| 451 | |||
| 445 | /* If no Guest can ever override this trap, leave it alone. */ | 452 | /* If no Guest can ever override this trap, leave it alone. */ |
| 446 | if (!direct_trap(i)) | 453 | if (!direct_trap(i)) |
| 447 | continue; | 454 | continue; |
| @@ -449,12 +456,15 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt, | |||
| 449 | /* Only trap gates (type 15) can go direct to the Guest. | 456 | /* Only trap gates (type 15) can go direct to the Guest. |
| 450 | * Interrupt gates (type 14) disable interrupts as they are | 457 | * Interrupt gates (type 14) disable interrupts as they are |
| 451 | * entered, which we never let the Guest do. Not present | 458 | * entered, which we never let the Guest do. Not present |
| 452 | * entries (type 0x0) also can't go direct, of course. */ | 459 | * entries (type 0x0) also can't go direct, of course. |
| 453 | if (idt_type(cpu->arch.idt[i].a, cpu->arch.idt[i].b) == 0xF) | 460 | * |
| 454 | idt[i] = cpu->arch.idt[i]; | 461 | * If it can't go direct, we still need to copy the priv. level: |
| 462 | * they might want to give userspace access to a software | ||
| 463 | * interrupt. */ | ||
| 464 | if (idt_type(gidt->a, gidt->b) == 0xF) | ||
| 465 | idt[i] = *gidt; | ||
| 455 | else | 466 | else |
| 456 | /* Reset it to the default. */ | 467 | default_idt_entry(&idt[i], i, def[i], gidt); |
| 457 | default_idt_entry(&idt[i], i, def[i]); | ||
| 458 | } | 468 | } |
| 459 | } | 469 | } |
| 460 | 470 | ||
