184778508Sblueswir1 /* User memory access */
22231197cSPeter Maydell #include "qemu/osdep.h"
3abd4556aSEd Maste #include "qemu/cutils.h"
484778508Sblueswir1
584778508Sblueswir1 #include "qemu.h"
684778508Sblueswir1
784778508Sblueswir1 /* copy_from_user() and copy_to_user() are usually used to copy data
884778508Sblueswir1 * buffers between the target and host. These internally perform
984778508Sblueswir1 * locking/unlocking of the memory.
1084778508Sblueswir1 */
copy_from_user(void * hptr,abi_ulong gaddr,size_t len)1184778508Sblueswir1 abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len)
1284778508Sblueswir1 {
1384778508Sblueswir1 abi_long ret = 0;
1484778508Sblueswir1 void *ghptr;
1584778508Sblueswir1
1684778508Sblueswir1 if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) {
1784778508Sblueswir1 memcpy(hptr, ghptr, len);
1884778508Sblueswir1 unlock_user(ghptr, gaddr, 0);
1984778508Sblueswir1 } else
2084778508Sblueswir1 ret = -TARGET_EFAULT;
2184778508Sblueswir1
2284778508Sblueswir1 return ret;
2384778508Sblueswir1 }
2484778508Sblueswir1
2584778508Sblueswir1
copy_to_user(abi_ulong gaddr,void * hptr,size_t len)2684778508Sblueswir1 abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len)
2784778508Sblueswir1 {
2884778508Sblueswir1 abi_long ret = 0;
2984778508Sblueswir1 void *ghptr;
3084778508Sblueswir1
3184778508Sblueswir1 if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) {
3284778508Sblueswir1 memcpy(ghptr, hptr, len);
3384778508Sblueswir1 unlock_user(ghptr, gaddr, len);
3484778508Sblueswir1 } else
3584778508Sblueswir1 ret = -TARGET_EFAULT;
3684778508Sblueswir1
3784778508Sblueswir1 return ret;
3884778508Sblueswir1 }
3984778508Sblueswir1
4084778508Sblueswir1 /* Return the length of a string in target memory or -TARGET_EFAULT if
4184778508Sblueswir1 access error */
target_strlen(abi_ulong guest_addr1)4284778508Sblueswir1 abi_long target_strlen(abi_ulong guest_addr1)
4384778508Sblueswir1 {
4484778508Sblueswir1 uint8_t *ptr;
4584778508Sblueswir1 abi_ulong guest_addr;
4684778508Sblueswir1 int max_len, len;
4784778508Sblueswir1
4884778508Sblueswir1 guest_addr = guest_addr1;
4984778508Sblueswir1 for (;;) {
5084778508Sblueswir1 max_len = TARGET_PAGE_SIZE - (guest_addr & ~TARGET_PAGE_MASK);
5184778508Sblueswir1 ptr = lock_user(VERIFY_READ, guest_addr, max_len, 1);
5284778508Sblueswir1 if (!ptr)
5384778508Sblueswir1 return -TARGET_EFAULT;
54*43b0ea1aSEd Maste len = qemu_strnlen((const char *)ptr, max_len);
5584778508Sblueswir1 unlock_user(ptr, guest_addr, 0);
5684778508Sblueswir1 guest_addr += len;
5784778508Sblueswir1 /* we don't allow wrapping or integer overflow */
5884778508Sblueswir1 if (guest_addr == 0 ||
5984778508Sblueswir1 (guest_addr - guest_addr1) > 0x7fffffff)
6084778508Sblueswir1 return -TARGET_EFAULT;
6184778508Sblueswir1 if (len != max_len)
6284778508Sblueswir1 break;
6384778508Sblueswir1 }
6484778508Sblueswir1 return guest_addr - guest_addr1;
6584778508Sblueswir1 }
66