--- drivers/kvm/kvm.h | 10 +++++++ drivers/kvm/kvm_main.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) Index: linux/drivers/kvm/kvm.h =================================================================== --- linux.orig/drivers/kvm/kvm.h +++ linux/drivers/kvm/kvm.h @@ -484,11 +484,21 @@ int kvm_read_guest(struct kvm_vcpu *vcpu unsigned long size, void *dest); +int kvm_read_guest_gpa(struct kvm_vcpu *vcpu, + gpa_t addr, + unsigned long size, + void *dest); + int kvm_write_guest(struct kvm_vcpu *vcpu, gva_t addr, unsigned long size, void *data); +int kvm_write_guest_gpa(struct kvm_vcpu *vcpu, + gpa_t addr, + unsigned long size, + void *data); + unsigned long segment_base(u16 selector); void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes); Index: linux/drivers/kvm/kvm_main.c =================================================================== --- linux.orig/drivers/kvm/kvm_main.c +++ linux/drivers/kvm/kvm_main.c @@ -217,6 +217,41 @@ int kvm_read_guest(struct kvm_vcpu *vcpu } EXPORT_SYMBOL_GPL(kvm_read_guest); +int kvm_read_guest_gpa(struct kvm_vcpu *vcpu, + gpa_t addr, + unsigned long size, + void *dest) +{ + unsigned char *host_buf = dest; + unsigned long req_size = size; + + while (size) { + hpa_t paddr; + unsigned now; + unsigned offset; + hva_t guest_buf; + + paddr = gpa_to_hpa(vcpu, addr); + + if (is_error_hpa(paddr)) + break; + + guest_buf = (hva_t)kmap_atomic( + pfn_to_page(paddr >> PAGE_SHIFT), + KM_USER0); + offset = addr & ~PAGE_MASK; + guest_buf |= offset; + now = min(size, PAGE_SIZE - offset); + memcpy(host_buf, (void*)guest_buf, now); + host_buf += now; + addr += now; + size -= now; + kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0); + } + return req_size - size; +} +EXPORT_SYMBOL_GPL(kvm_read_guest_gpa); + int kvm_write_guest(struct kvm_vcpu *vcpu, gva_t addr, unsigned long size, void *data) { @@ -252,6 +287,41 @@ int kvm_write_guest(struct kvm_vcpu *vcp } EXPORT_SYMBOL_GPL(kvm_write_guest); +int kvm_write_guest_gpa(struct kvm_vcpu *vcpu, + gpa_t addr, + unsigned long size, + void *data) +{ + unsigned char *host_buf = data; + unsigned long req_size = size; + + while (size) { + hpa_t paddr; + unsigned now; + unsigned offset; + hva_t guest_buf; + + paddr = gpa_to_hpa(vcpu, addr); + if (is_error_hpa(paddr)) { + printk("hm, couldnt look up gpa: %08Lx\n", addr); + break; + } + + guest_buf = (hva_t)kmap_atomic( + pfn_to_page(paddr >> PAGE_SHIFT), KM_USER0); + offset = addr & ~PAGE_MASK; + guest_buf |= offset; + now = min(size, PAGE_SIZE - offset); + memcpy((void*)guest_buf, host_buf, now); + host_buf += now; + addr += now; + size -= now; + kunmap_atomic((void *)(guest_buf & PAGE_MASK), KM_USER0); + } + return req_size - size; +} +EXPORT_SYMBOL_GPL(kvm_write_guest_gpa); + /* * Switches to specified vcpu, until a matching vcpu_put() */