[PATCH 1/3] Implement emulator_write_phys()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Since a hypercall may span two pages and is a gva, we need a function to write
to a gva that may span multiple pages.  emulator_write_phys() seems like the
logical choice for this.

Signed-off-by: Anthony Liguori <[email protected]>

diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index d154487..ebcc5c9 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -962,8 +962,35 @@ static int emulator_write_std(unsigned long addr,
 			      unsigned int bytes,
 			      struct kvm_vcpu *vcpu)
 {
-	pr_unimpl(vcpu, "emulator_write_std: addr %lx n %d\n", addr, bytes);
-	return X86EMUL_UNHANDLEABLE;
+	const void *data = val;
+
+	while (bytes) {
+		gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
+		unsigned offset = addr & (PAGE_SIZE-1);
+		unsigned tocopy = min(bytes, (unsigned)PAGE_SIZE - offset);
+		unsigned long pfn;
+		struct page *page;
+		void *page_virt;
+
+		if (gpa == UNMAPPED_GVA)
+			return X86EMUL_PROPAGATE_FAULT;
+		pfn = gpa >> PAGE_SHIFT;
+		page = gfn_to_page(vcpu->kvm, pfn);
+		if (!page)
+			return X86EMUL_UNHANDLEABLE;
+		page_virt = kmap_atomic(page, KM_USER0);
+
+		memcpy(page_virt + offset, data, tocopy);
+
+		kunmap_atomic(page_virt, KM_USER0);
+		mark_page_dirty(vcpu->kvm, addr >> PAGE_SHIFT);
+
+		bytes -= tocopy;
+		data += tocopy;
+		addr += tocopy;
+	}
+
+	return X86EMUL_CONTINUE;
 }
 
 static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux