hw/intc/arm_gic.c: Implement GICv2 GICC_DIR
[qemu.git] / linux-user / uaccess.c
blob75d890dfef74a748a17a1f1f88a14703db87b470
1 /* User memory access */
2 #include "qemu/osdep.h"
4 #include "qemu.h"
6 /* copy_from_user() and copy_to_user() are usually used to copy data
7 * buffers between the target and host. These internally perform
8 * locking/unlocking of the memory.
9 */
10 abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len)
12 abi_long ret = 0;
13 void *ghptr;
15 if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) {
16 memcpy(hptr, ghptr, len);
17 unlock_user(ghptr, gaddr, 0);
18 } else
19 ret = -TARGET_EFAULT;
21 return ret;
25 abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len)
27 abi_long ret = 0;
28 void *ghptr;
30 if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) {
31 memcpy(ghptr, hptr, len);
32 unlock_user(ghptr, gaddr, len);
33 } else
34 ret = -TARGET_EFAULT;
36 return ret;
39 /* Return the length of a string in target memory or -TARGET_EFAULT if
40 access error */
41 abi_long target_strlen(abi_ulong guest_addr1)
43 uint8_t *ptr;
44 abi_ulong guest_addr;
45 int max_len, len;
47 guest_addr = guest_addr1;
48 for(;;) {
49 max_len = TARGET_PAGE_SIZE - (guest_addr & ~TARGET_PAGE_MASK);
50 ptr = lock_user(VERIFY_READ, guest_addr, max_len, 1);
51 if (!ptr)
52 return -TARGET_EFAULT;
53 len = qemu_strnlen((const char *)ptr, max_len);
54 unlock_user(ptr, guest_addr, 0);
55 guest_addr += len;
56 /* we don't allow wrapping or integer overflow */
57 if (guest_addr == 0 ||
58 (guest_addr - guest_addr1) > 0x7fffffff)
59 return -TARGET_EFAULT;
60 if (len != max_len)
61 break;
63 return guest_addr - guest_addr1;