diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2015-02-11 15:15:10 +1030 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2015-02-11 16:47:33 +1030 |
commit | 7313d5217e6b9817897172d6a6ff477bdc415ed6 (patch) | |
tree | 448fc79d9048af296aeb6c6fbbf5da84dc6f7046 /drivers/lguest/x86 | |
parent | d1c29465b8a52d8fc5a59aac92c6b206b69fe631 (diff) | |
download | linux-7313d5217e6b9817897172d6a6ff477bdc415ed6.tar.bz2 |
lguest: add iomem region, where guest page faults get sent to userspace.
This lets us implement PCI.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/lguest/x86')
-rw-r--r-- | drivers/lguest/x86/core.c | 19 |
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 |