Mercurial > hvf > hvf-old
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; +}