1 /* 2 * Helper routines to provide target memory access for semihosting 3 * syscalls in system emulation mode. 4 * 5 * Copyright (c) 2007 CodeSourcery. 6 * 7 * This code is licensed under the GPL 8 */ 9 10 #include "qemu/osdep.h" 11 #include "exec/exec-all.h" 12 #include "semihosting/uaccess.h" 13 14 void *uaccess_lock_user(CPUArchState *env, target_ulong addr, 15 target_ulong len, bool copy) 16 { 17 void *p = malloc(len); 18 if (p && copy) { 19 if (cpu_memory_rw_debug(env_cpu(env), addr, p, len, 0)) { 20 free(p); 21 p = NULL; 22 } 23 } 24 return p; 25 } 26 27 ssize_t uaccess_strlen_user(CPUArchState *env, target_ulong addr) 28 { 29 int mmu_idx = cpu_mmu_index(env_cpu(env), false); 30 size_t len = 0; 31 32 while (1) { 33 size_t left_in_page; 34 int flags; 35 void *h; 36 37 /* Find the number of bytes remaining in the page. */ 38 left_in_page = TARGET_PAGE_SIZE - (addr & ~TARGET_PAGE_MASK); 39 40 flags = probe_access_flags(env, addr, 0, MMU_DATA_LOAD, 41 mmu_idx, true, &h, 0); 42 if (flags & TLB_INVALID_MASK) { 43 return -1; 44 } 45 if (flags & TLB_MMIO) { 46 do { 47 uint8_t c; 48 if (cpu_memory_rw_debug(env_cpu(env), addr, &c, 1, 0)) { 49 return -1; 50 } 51 if (c == 0) { 52 return len; 53 } 54 addr++; 55 len++; 56 if (len > INT32_MAX) { 57 return -1; 58 } 59 } while (--left_in_page != 0); 60 } else { 61 char *p = memchr(h, 0, left_in_page); 62 if (p) { 63 len += p - (char *)h; 64 return len <= INT32_MAX ? (ssize_t)len : -1; 65 } 66 addr += left_in_page; 67 len += left_in_page; 68 if (len > INT32_MAX) { 69 return -1; 70 } 71 } 72 } 73 } 74 75 char *uaccess_lock_user_string(CPUArchState *env, target_ulong addr) 76 { 77 ssize_t len = uaccess_strlen_user(env, addr); 78 if (len < 0) { 79 return NULL; 80 } 81 return uaccess_lock_user(env, addr, len + 1, true); 82 } 83 84 void uaccess_unlock_user(CPUArchState *env, void *p, 85 target_ulong addr, target_ulong len) 86 { 87 if (len) { 88 cpu_memory_rw_debug(env_cpu(env), addr, p, len, 1); 89 } 90 free(p); 91 } 92