| 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 | #ifndef SEMIHOSTING_UACCESS_H |
| 11 | #define SEMIHOSTING_UACCESS_H |
| 12 | |
| 13 | #ifdef CONFIG_USER_ONLY |
| 14 | #error Cannot include semihosting/uaccess.h from user emulation |
| 15 | #endif |
| 16 | |
| 17 | #include "exec/cpu-common.h" |
| 18 | #include "exec/tswap.h" |
| 19 | #include "exec/page-protection.h" |
| 20 | #include "exec/vaddr.h" |
| 21 | |
| 22 | /** |
| 23 | * get_user_u64: |
| 24 | * |
| 25 | * Returns: 0 on success, -1 on error. |
| 26 | */ |
| 27 | #define get_user_u64(val, addr) \ |
| 28 | ({ uint64_t val_ = 0; \ |
| 29 | int ret_ = cpu_memory_rw_debug(env_cpu(env), (addr), \ |
| 30 | &val_, sizeof(val_), 0); \ |
| 31 | (val) = cpu_internal_tswap64(cs, val_); ret_; }) |
| 32 | |
| 33 | /** |
| 34 | * get_user_u32: |
| 35 | * |
| 36 | * Returns: 0 on success, -1 on error. |
| 37 | */ |
| 38 | #define get_user_u32(val, addr) \ |
| 39 | ({ uint32_t val_ = 0; \ |
| 40 | int ret_ = cpu_memory_rw_debug(env_cpu(env), (addr), \ |
| 41 | &val_, sizeof(val_), 0); \ |
| 42 | (val) = cpu_internal_tswap32(cs, val_); ret_; }) |
| 43 | |
| 44 | /** |
| 45 | * get_user_u8: |
| 46 | * |
| 47 | * Returns: 0 on success, -1 on error. |
| 48 | */ |
| 49 | #define get_user_u8(val, addr) \ |
| 50 | ({ uint8_t val_ = 0; \ |
| 51 | int ret_ = cpu_memory_rw_debug(env_cpu(env), (addr), \ |
| 52 | &val_, sizeof(val_), 0); \ |
| 53 | (val) = val_; ret_; }) |
| 54 | |
| 55 | /** |
| 56 | * get_user_ual: |
| 57 | * |
| 58 | * Returns: 0 on success, -1 on error. |
| 59 | */ |
| 60 | #define get_user_ual(arg, p) get_user_u32(arg, p) |
| 61 | |
| 62 | /** |
| 63 | * put_user_u64: |
| 64 | * |
| 65 | * Returns: 0 on success, -1 on error. |
| 66 | */ |
| 67 | #define put_user_u64(val, addr) \ |
| 68 | ({ uint64_t val_ = cpu_internal_tswap64(cs, val); \ |
| 69 | cpu_memory_rw_debug(env_cpu(env), (addr), &val_, sizeof(val_), 1); }) |
| 70 | |
| 71 | /** |
| 72 | * put_user_u32: |
| 73 | * |
| 74 | * Returns: 0 on success, -1 on error. |
| 75 | */ |
| 76 | #define put_user_u32(val, addr) \ |
| 77 | ({ uint32_t val_ = cpu_internal_tswap32(cs, val); \ |
| 78 | cpu_memory_rw_debug(env_cpu(env), (addr), &val_, sizeof(val_), 1); }) |
| 79 | |
| 80 | /** |
| 81 | * put_user_ual: |
| 82 | * |
| 83 | * Returns: 0 on success, -1 on error. |
| 84 | */ |
| 85 | #define put_user_ual(arg, p) put_user_u32(arg, p) |
| 86 | |
| 87 | /** |
| 88 | * uaccess_lock_user: |
| 89 | * |
| 90 | * The returned pointer should be freed using uaccess_unlock_user(). |
| 91 | */ |
| 92 | void *uaccess_lock_user(CPUArchState *env, vaddr addr, |
| 93 | size_t len, bool copy); |
| 94 | /** |
| 95 | * lock_user: |
| 96 | * |
| 97 | * The returned pointer should be freed using unlock_user(). |
| 98 | */ |
| 99 | #define lock_user(type, p, len, copy) uaccess_lock_user(env, p, len, copy) |
| 100 | |
| 101 | /** |
| 102 | * uaccess_lock_user_string: |
| 103 | * |
| 104 | * The returned string should be freed using uaccess_unlock_user(). |
| 105 | */ |
| 106 | char *uaccess_lock_user_string(CPUArchState *env, vaddr addr); |
| 107 | /** |
| 108 | * uaccess_lock_user_string: |
| 109 | * |
| 110 | * The returned string should be freed using unlock_user(). |
| 111 | */ |
| 112 | #define lock_user_string(p) uaccess_lock_user_string(env, p) |
| 113 | |
| 114 | void uaccess_unlock_user(CPUArchState *env, void *p, |
| 115 | vaddr addr, size_t len); |
| 116 | #define unlock_user(s, args, len) uaccess_unlock_user(env, s, args, len) |
| 117 | |
| 118 | ssize_t uaccess_strlen_user(CPUArchState *env, vaddr addr); |
| 119 | #define target_strlen(p) uaccess_strlen_user(env, p) |
| 120 | |
| 121 | #endif /* SEMIHOSTING_SOFTMMU_UACCESS_H */ |