Kernel KVM-PPC virtualization development
 help / color / mirror / Atom feed
* [PATCH 1/2] KVM: Implement kvm_copy_guest() to perform copy of guest memory in place
@ 2019-03-06  6:00 Suraj Jitindar Singh
  2019-03-06 14:12 ` kbuild test robot
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Suraj Jitindar Singh @ 2019-03-06  6:00 UTC (permalink / raw)
  To: kvm-ppc

Implement the function kvm_copy_guest() to be used to perform a memory
copy from one guest physical address to another of a variable length.

This performs similar functionality as the kvm_read_guest() and
kvm_write_guest() functions, except both addresses point to guest memory.
This performs a copy in place using raw_copy_in_user() to avoid having to
buffer the data.

The guest memory can reside in different memslots and the copy length
can span memslots.

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>

---

I suspect additional checking may be required around the raw_copy_in_user()
call.

---
 include/linux/kvm_host.h |  1 +
 virt/kvm/kvm_main.c      | 69 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c38cc5eb7e73..53b266c04041 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -697,6 +697,7 @@ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 				  void *data, unsigned int offset,
 				  unsigned long len);
+int kvm_copy_guest(struct kvm *kvm, gpa_t to, gpa_t from, unsigned long len);
 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
 			      gpa_t gpa, unsigned long len);
 int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 076bc38963bf..0922d45baf72 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1999,6 +1999,75 @@ int kvm_vcpu_write_guest(struct kvm_vcpu *vcpu, gpa_t gpa, const void *data,
 }
 EXPORT_SYMBOL_GPL(kvm_vcpu_write_guest);
 
+static int __kvm_copy_guest_page(struct kvm_memory_slot *to_memslot,
+				 gfn_t to_gfn, int to_offset,
+				 struct kvm_memory_slot *from_memslot,
+				 gfn_t from_gfn, int from_offset, int len)
+{
+	int r;
+	unsigned long to_addr, from_addr;
+
+	to_addr = gfn_to_hva_memslot(to_memslot, to_gfn);
+	if (kvm_is_error_hva(to_addr))
+		return -EFAULT;
+	from_addr = gfn_to_hva_memslot(from_memslot, from_gfn);
+	if (kvm_is_error_hva(from_addr))
+		return -EFAULT;
+	r = raw_copy_in_user((void __user *)to_addr + to_offset,
+			     (void __user *)from_addr + from_offset, len);
+	if (r)
+		return -EFAULT;
+	mark_page_dirty_in_slot(to_memslot, to_gfn);
+	return 0;
+}
+
+static int next_segment_many(unsigned long len, int offset1, int offset2)
+{
+	int size = min(PAGE_SIZE - offset1, PAGE_SIZE - offset2);
+
+	if (len > size)
+		return size;
+	else
+		return len;
+}
+
+int kvm_copy_guest(struct kvm *kvm, gpa_t to, gpa_t from, unsigned long len)
+{
+	struct kvm_memory_slot *to_memslot = NULL;
+	struct kvm_memory_slot *from_memslot = NULL;
+	gfn_t to_gfn = to >> PAGE_SHIFT;
+	gfn_t from_gfn = from >> PAGE_SHIFT;
+	int seg;
+	int to_offset = offset_in_page(to);
+	int from_offset = offset_in_page(from);
+	int ret;
+
+	while ((seg = next_segment_many(len, to_offset, from_offset)) != 0) {
+		if (!to_memslot || (to_gfn >= (to_memslot->base_gfn +
+					       to_memslot->npages)))
+			to_memslot = gfn_to_memslot(kvm, to_gfn);
+		if (!from_memslot || (from_gfn >= (from_memslot->base_gfn +
+						   from_memslot->npages)))
+			from_memslot = gfn_to_memslot(kvm, from_gfn);
+
+		ret = __kvm_copy_guest_page(to_memslot, to_gfn, to_offset,
+					    from_memslot, from_gfn, from_offset,
+					    seg);
+		if (ret < 0)
+			return ret;
+
+		to_offset = (to_offset + seg) & (PAGE_SIZE - 1);
+		from_offset = (from_offset + seg) & (PAGE_SIZE - 1);
+		len -= seg;
+		if (!to_offset)
+			to_gfn += 1;
+		if (!from_offset)
+			from_gfn += 1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_copy_guest);
+
 static int __kvm_gfn_to_hva_cache_init(struct kvm_memslots *slots,
 				       struct gfn_to_hva_cache *ghc,
 				       gpa_t gpa, unsigned long len)
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-03-22  2:33 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-03-06  6:00 [PATCH 1/2] KVM: Implement kvm_copy_guest() to perform copy of guest memory in place Suraj Jitindar Singh
2019-03-06 14:12 ` kbuild test robot
2019-03-06 17:21 ` Sean Christopherson
2019-03-06 18:28 ` kbuild test robot
2019-03-06 23:18 ` Suraj Jitindar Singh
2019-03-21 14:34 ` Sean Christopherson
2019-03-22  2:33 ` Suraj Jitindar Singh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox