aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/x86
diff options
context:
space:
mode:
authorMatias Zabaljauregui <zabaljauregui@gmail.com>2009-04-08 16:58:39 -0400
committerRusty Russell <rusty@rustcorp.com.au>2009-04-19 09:44:00 -0400
commit88df781afb788fa588dbf2e77f205214022a8893 (patch)
treeb73e2b470a959e60fb5332737c1fca04bb629ba7 /drivers/lguest/x86
parentff54250a0ebab7f90a5f848a0ba63f999830c872 (diff)
lguest: fix crash on vmlinux images
Typical message: 'lguest: unhandled trap 6 at 0x418726 (0x0)' vmlinux guests were broken by 4cd8b5e2a159f18a1507f1187b44a1acbfa6341b 'lguest: use KVM hypercalls', which rewrites guest text from kvm hypercalls to trap 31. The Launcher mmaps the kernel image. The Guest executes and immediately faults in the first text page (read-only). Then it hits a hypercall, and we rewrite that hypercall, causing a copy-on-write. But the Guest pagetables still refer to the old page: we fault again, but as Host we see the hypercall already rewritten, and pass the fault back to the Guest. The Guest hasn't set up an IDT yet, so we kill it. This doesn't happen with bzImages: they unpack themselves and so the text pages are already read-write. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Tested-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'drivers/lguest/x86')
-rw-r--r--drivers/lguest/x86/core.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index a6b717644be0..d6d7ac0982ab 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -324,6 +324,11 @@ static void rewrite_hypercall(struct lg_cpu *cpu)
324 u8 insn[3] = {0xcd, 0x1f, 0x90}; 324 u8 insn[3] = {0xcd, 0x1f, 0x90};
325 325
326 __lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn)); 326 __lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn));
327 /* The above write might have caused a copy of that page to be made
328 * (if it was read-only). We need to make sure the Guest has
329 * up-to-date pagetables. As this doesn't happen often, we can just
330 * drop them all. */
331 guest_pagetable_clear_all(cpu);
327} 332}
328 333
329static bool is_hypercall(struct lg_cpu *cpu) 334static bool is_hypercall(struct lg_cpu *cpu)