rendered paste body---
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()
*/