summary refs log tree commit diff
path: root/drivers/lguest/x86/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest/x86/core.c')
-rw-r--r--drivers/lguest/x86/core.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 42e87bf14113..18d841e738bc 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -362,9 +362,19 @@ static void setup_emulate_insn(struct lg_cpu *cpu)
 			sizeof(cpu->pending.insn));
 }
 
+static void setup_iomem_insn(struct lg_cpu *cpu, unsigned long iomem_addr)
+{
+	cpu->pending.trap = 14;
+	cpu->pending.addr = iomem_addr;
+	copy_from_guest(cpu, cpu->pending.insn, cpu->regs->eip,
+			sizeof(cpu->pending.insn));
+}
+
 /*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */
 void lguest_arch_handle_trap(struct lg_cpu *cpu)
 {
+	unsigned long iomem_addr;
+
 	switch (cpu->regs->trapnum) {
 	case 13: /* We've intercepted a General Protection Fault. */
 		/* Hand to Launcher to emulate those pesky IN and OUT insns */
@@ -385,8 +395,15 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
 		 * whether kernel or userspace code.
 		 */
 		if (demand_page(cpu, cpu->arch.last_pagefault,
-				cpu->regs->errcode))
+				cpu->regs->errcode, &iomem_addr))
+			return;
+
+		/* Was this an access to memory mapped IO? */
+		if (iomem_addr) {
+			/* Tell Launcher, let it handle it. */
+			setup_iomem_insn(cpu, iomem_addr);
 			return;
+		}
 
 		/*
 		 * OK, it's really not there (or not OK): the Guest needs to