diff options
author | Avi Kivity <avi@qumranet.com> | 2007-01-05 16:36:44 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2007-01-05 23:55:25 -0800 |
commit | da4a00f002239f72b0d7d0eeaa3b60100e2b1438 (patch) | |
tree | 7c7e72ea1fd48025c029429b413e127a3a580c10 /drivers/kvm/kvm_main.c | |
parent | 815af8d42ee3f844c0ceaf2104bd9c6a0bb1e26c (diff) | |
download | op-kernel-dev-da4a00f002239f72b0d7d0eeaa3b60100e2b1438.zip op-kernel-dev-da4a00f002239f72b0d7d0eeaa3b60100e2b1438.tar.gz |
[PATCH] KVM: MMU: Support emulated writes into RAM
As the mmu write protects guest page table, we emulate those writes. Since
they are not mmio, there is no need to go to userspace to perform them.
So, perform the writes in the kernel if possible, and notify the mmu about
them so it can take the approriate action.
Signed-off-by: Avi Kivity <avi@qumranet.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r-- | drivers/kvm/kvm_main.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 68e121e..047f6f6 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -877,6 +877,27 @@ static int emulator_read_emulated(unsigned long addr, } } +static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, + unsigned long val, int bytes) +{ + struct kvm_memory_slot *m; + struct page *page; + void *virt; + + if (((gpa + bytes - 1) >> PAGE_SHIFT) != (gpa >> PAGE_SHIFT)) + return 0; + m = gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT); + if (!m) + return 0; + page = gfn_to_page(m, gpa >> PAGE_SHIFT); + kvm_mmu_pre_write(vcpu, gpa, bytes); + virt = kmap_atomic(page, KM_USER0); + memcpy(virt + offset_in_page(gpa), &val, bytes); + kunmap_atomic(virt, KM_USER0); + kvm_mmu_post_write(vcpu, gpa, bytes); + return 1; +} + static int emulator_write_emulated(unsigned long addr, unsigned long val, unsigned int bytes, @@ -888,6 +909,9 @@ static int emulator_write_emulated(unsigned long addr, if (gpa == UNMAPPED_GVA) return X86EMUL_PROPAGATE_FAULT; + if (emulator_write_phys(vcpu, gpa, val, bytes)) + return X86EMUL_CONTINUE; + vcpu->mmio_needed = 1; vcpu->mmio_phys_addr = gpa; vcpu->mmio_size = bytes; |