changeset 492:bf04161a8f5c

cp/dat: create a memcpy to/from guest storage Currently unused. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Thu, 21 Apr 2011 17:37:41 -0400
parents 0bb9a9b527cd
children ef4c3a01d9d5
files cp/include/dat.h cp/mm/dat.c
diffstat 2 files changed, 41 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/cp/include/dat.h	Thu Apr 21 15:52:52 2011 -0400
+++ b/cp/include/dat.h	Thu Apr 21 17:37:41 2011 -0400
@@ -140,4 +140,9 @@
 	return 0;
 }
 
+#define memcpy_to_guest(gaddr, ptr, len)	__memcpy_tofrom_guest((gaddr), (ptr), (len), 0)
+#define memcpy_from_guest(gaddr, ptr, len)	__memcpy_tofrom_guest((gaddr), (ptr), (len), 1)
+
+extern int __memcpy_tofrom_guest(u64 guest_addr, void *data, u64 *len, int from);
+
 #endif
--- a/cp/mm/dat.c	Thu Apr 21 15:52:52 2011 -0400
+++ b/cp/mm/dat.c	Thu Apr 21 17:37:41 2011 -0400
@@ -132,3 +132,39 @@
 	  "m" (cr1)
 	);
 }
+
+/* memcpy that pays attention to page boundary crossing; *len contains the
+ * number of bytes to copy on entry, and at return, the number of bytes
+ * copied */
+int __memcpy_tofrom_guest(u64 guest_addr, void *data, u64 *len, int from)
+{
+	u8 *_data = data;
+	u64 host_addr;
+	u64 copy_len;
+	u64 copied;
+	int ret = 0;
+
+	for(copied = 0; *len; ) {
+		/* walk the page tables to find the real page frame */
+		ret = virt2phy_current(guest_addr, &host_addr);
+		if (ret)
+			break;
+
+		/* copy this much this time around... until the end of the page, or
+		 * the while thing that's left
+		 */
+		copy_len = min(PAGE_SIZE - (host_addr & PAGE_MASK), *len);
+
+		/* COPY! */
+		if (from)
+			memcpy(_data + copied, (void*)host_addr, copy_len);
+		else
+			memcpy((void*)host_addr, _data + copied, copy_len);
+
+		copied += copy_len;
+		*len -= copy_len;
+	}
+
+	*len = copied;
+	return ret;
+}