bellard | e88de09 | 2005-02-07 12:35:39 +0000 | [diff] [blame] | 1 | #ifndef QEMU_H |
| 2 | #define QEMU_H |
bellard | 31e31b8 | 2003-02-18 22:55:36 +0000 | [diff] [blame] | 3 | |
bellard | 6180a18 | 2003-09-30 21:04:53 +0000 | [diff] [blame] | 4 | #include "cpu.h" |
Paolo Bonzini | f08b617 | 2014-03-28 19:42:10 +0100 | [diff] [blame] | 5 | #include "exec/cpu_ldst.h" |
blueswir1 | 992f48a | 2007-10-14 16:27:31 +0000 | [diff] [blame] | 6 | |
balrog | 06177d3 | 2007-12-24 13:47:52 +0000 | [diff] [blame] | 7 | #undef DEBUG_REMAP |
balrog | 06177d3 | 2007-12-24 13:47:52 +0000 | [diff] [blame] | 8 | |
Paolo Bonzini | 022c62c | 2012-12-17 18:19:49 +0100 | [diff] [blame] | 9 | #include "exec/user/abitypes.h" |
blueswir1 | 992f48a | 2007-10-14 16:27:31 +0000 | [diff] [blame] | 10 | |
blueswir1 | 992f48a | 2007-10-14 16:27:31 +0000 | [diff] [blame] | 11 | #include "syscall_defs.h" |
LluĂs Vilanova | 460c579 | 2016-02-01 19:38:42 +0100 | [diff] [blame] | 12 | #include "target_syscall.h" |
bellard | 66fb976 | 2003-03-23 01:06:05 +0000 | [diff] [blame] | 13 | |
Peter Maydell | 400b7f6 | 2021-09-08 16:43:57 +0100 | [diff] [blame] | 14 | /* |
| 15 | * This is the size of the host kernel's sigset_t, needed where we make |
Peter Maydell | 1d48fdd | 2016-06-14 12:49:18 +0100 | [diff] [blame] | 16 | * direct system calls that take a sigset_t pointer and a size. |
| 17 | */ |
| 18 | #define SIGSET_T_SIZE (_NSIG / 8) |
| 19 | |
Peter Maydell | 400b7f6 | 2021-09-08 16:43:57 +0100 | [diff] [blame] | 20 | /* |
| 21 | * This struct is used to hold certain information about the image. |
bellard | 31e31b8 | 2003-02-18 22:55:36 +0000 | [diff] [blame] | 22 | * Basically, it replicates in user space what would be certain |
| 23 | * task_struct fields in the kernel |
| 24 | */ |
| 25 | struct image_info { |
Richard Henderson | 9955ffa | 2010-07-27 10:25:30 -0700 | [diff] [blame] | 26 | abi_ulong load_bias; |
blueswir1 | 992f48a | 2007-10-14 16:27:31 +0000 | [diff] [blame] | 27 | abi_ulong load_addr; |
| 28 | abi_ulong start_code; |
| 29 | abi_ulong end_code; |
| 30 | abi_ulong start_data; |
| 31 | abi_ulong end_data; |
blueswir1 | 992f48a | 2007-10-14 16:27:31 +0000 | [diff] [blame] | 32 | abi_ulong brk; |
blueswir1 | 992f48a | 2007-10-14 16:27:31 +0000 | [diff] [blame] | 33 | abi_ulong start_stack; |
Paul Brook | 97374d3 | 2010-06-16 13:03:51 +0100 | [diff] [blame] | 34 | abi_ulong stack_limit; |
Richard Henderson | 5d94c2f | 2023-08-16 10:54:57 -0700 | [diff] [blame] | 35 | abi_ulong vdso; |
blueswir1 | 992f48a | 2007-10-14 16:27:31 +0000 | [diff] [blame] | 36 | abi_ulong entry; |
| 37 | abi_ulong code_offset; |
| 38 | abi_ulong data_offset; |
Mika Westerberg | edf8e2a | 2009-04-07 09:57:11 +0300 | [diff] [blame] | 39 | abi_ulong saved_auxv; |
Alexander Graf | 125b0f5 | 2012-01-28 21:12:14 +0200 | [diff] [blame] | 40 | abi_ulong auxv_len; |
Richard Henderson | 60f1c80 | 2022-04-26 19:51:29 -0700 | [diff] [blame] | 41 | abi_ulong argc; |
| 42 | abi_ulong argv; |
| 43 | abi_ulong envc; |
| 44 | abi_ulong envp; |
Richard Henderson | 7c4ee5b | 2016-12-15 09:38:11 -0800 | [diff] [blame] | 45 | abi_ulong file_string; |
Paul Brook | d8fd295 | 2012-03-30 18:02:50 +0100 | [diff] [blame] | 46 | uint32_t elf_flags; |
Peter Maydell | 400b7f6 | 2021-09-08 16:43:57 +0100 | [diff] [blame] | 47 | int personality; |
Laurent Vivier | 33143c4 | 2018-07-16 21:53:49 +0200 | [diff] [blame] | 48 | abi_ulong alignment; |
Richard Henderson | 872f3d0 | 2022-08-10 23:00:52 -0700 | [diff] [blame] | 49 | bool exec_stack; |
Christophe Lyon | a99856c | 2018-04-30 10:03:41 +0200 | [diff] [blame] | 50 | |
Richard Henderson | 60f1c80 | 2022-04-26 19:51:29 -0700 | [diff] [blame] | 51 | /* Generic semihosting knows about these pointers. */ |
| 52 | abi_ulong arg_strings; /* strings for argv */ |
| 53 | abi_ulong env_strings; /* strings for envp; ends arg_strings */ |
| 54 | |
Christophe Lyon | a99856c | 2018-04-30 10:03:41 +0200 | [diff] [blame] | 55 | /* The fields below are used in FDPIC mode. */ |
Mike Frysinger | 1af02e8 | 2011-02-07 01:05:50 -0500 | [diff] [blame] | 56 | abi_ulong loadmap_addr; |
| 57 | uint16_t nsegs; |
Peter Maydell | 400b7f6 | 2021-09-08 16:43:57 +0100 | [diff] [blame] | 58 | void *loadsegs; |
Mike Frysinger | 1af02e8 | 2011-02-07 01:05:50 -0500 | [diff] [blame] | 59 | abi_ulong pt_dynamic_addr; |
Christophe Lyon | 3cb10cf | 2018-04-30 10:03:43 +0200 | [diff] [blame] | 60 | abi_ulong interpreter_loadmap_addr; |
| 61 | abi_ulong interpreter_pt_dynamic_addr; |
Mike Frysinger | 1af02e8 | 2011-02-07 01:05:50 -0500 | [diff] [blame] | 62 | struct image_info *other_info; |
Richard Henderson | 83f990e | 2020-10-21 10:37:47 -0700 | [diff] [blame] | 63 | |
| 64 | /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */ |
| 65 | uint32_t note_flags; |
| 66 | |
Stefan Markovic | 74cfc70 | 2018-10-22 16:43:40 +0200 | [diff] [blame] | 67 | #ifdef TARGET_MIPS |
| 68 | int fp_abi; |
| 69 | int interp_fp_abi; |
| 70 | #endif |
bellard | 31e31b8 | 2003-02-18 22:55:36 +0000 | [diff] [blame] | 71 | }; |
| 72 | |
bellard | b346ff4 | 2003-06-15 20:05:50 +0000 | [diff] [blame] | 73 | #ifdef TARGET_I386 |
bellard | 851e67a | 2003-03-29 16:53:14 +0000 | [diff] [blame] | 74 | /* Information about the current linux thread */ |
| 75 | struct vm86_saved_state { |
| 76 | uint32_t eax; /* return code */ |
| 77 | uint32_t ebx; |
| 78 | uint32_t ecx; |
| 79 | uint32_t edx; |
| 80 | uint32_t esi; |
| 81 | uint32_t edi; |
| 82 | uint32_t ebp; |
| 83 | uint32_t esp; |
| 84 | uint32_t eflags; |
| 85 | uint32_t eip; |
| 86 | uint16_t cs, ss, ds, es, fs, gs; |
| 87 | }; |
bellard | b346ff4 | 2003-06-15 20:05:50 +0000 | [diff] [blame] | 88 | #endif |
bellard | 851e67a | 2003-03-29 16:53:14 +0000 | [diff] [blame] | 89 | |
Peter Maydell | 848d72c | 2013-09-03 20:12:17 +0100 | [diff] [blame] | 90 | #if defined(TARGET_ARM) && defined(TARGET_ABI32) |
bellard | 28c4f36 | 2004-02-16 21:47:43 +0000 | [diff] [blame] | 91 | /* FPU emulator */ |
| 92 | #include "nwfpe/fpa11.h" |
bellard | 28c4f36 | 2004-02-16 21:47:43 +0000 | [diff] [blame] | 93 | #endif |
| 94 | |
pbrook | 624f797 | 2008-05-31 16:11:38 +0000 | [diff] [blame] | 95 | struct emulated_sigtable { |
| 96 | int pending; /* true if signal is pending */ |
Timothy E Baldwin | 907f5fd | 2016-05-27 15:51:52 +0100 | [diff] [blame] | 97 | target_siginfo_t info; |
pbrook | 624f797 | 2008-05-31 16:11:38 +0000 | [diff] [blame] | 98 | }; |
| 99 | |
bellard | 851e67a | 2003-03-29 16:53:14 +0000 | [diff] [blame] | 100 | typedef struct TaskState { |
Mika Westerberg | edf8e2a | 2009-04-07 09:57:11 +0300 | [diff] [blame] | 101 | pid_t ts_tid; /* tid (or pid) of this task */ |
bellard | 28c4f36 | 2004-02-16 21:47:43 +0000 | [diff] [blame] | 102 | #ifdef TARGET_ARM |
Peter Maydell | 848d72c | 2013-09-03 20:12:17 +0100 | [diff] [blame] | 103 | # ifdef TARGET_ABI32 |
bellard | 28c4f36 | 2004-02-16 21:47:43 +0000 | [diff] [blame] | 104 | /* FPA state */ |
| 105 | FPA11 fpa; |
Peter Maydell | 848d72c | 2013-09-03 20:12:17 +0100 | [diff] [blame] | 106 | # endif |
Keith Packard | a10b9d9 | 2021-01-08 22:42:52 +0000 | [diff] [blame] | 107 | #endif |
| 108 | #if defined(TARGET_ARM) || defined(TARGET_RISCV) |
bellard | a4f8197 | 2005-04-23 18:25:41 +0000 | [diff] [blame] | 109 | int swi_errno; |
bellard | 28c4f36 | 2004-02-16 21:47:43 +0000 | [diff] [blame] | 110 | #endif |
j_mayer | 84409dd | 2007-04-06 08:56:50 +0000 | [diff] [blame] | 111 | #if defined(TARGET_I386) && !defined(TARGET_X86_64) |
blueswir1 | 992f48a | 2007-10-14 16:27:31 +0000 | [diff] [blame] | 112 | abi_ulong target_v86; |
bellard | 851e67a | 2003-03-29 16:53:14 +0000 | [diff] [blame] | 113 | struct vm86_saved_state vm86_saved_regs; |
bellard | b333af0 | 2003-05-14 21:48:51 +0000 | [diff] [blame] | 114 | struct target_vm86plus_struct vm86plus; |
bellard | 631271d | 2003-05-10 13:14:52 +0000 | [diff] [blame] | 115 | uint32_t v86flags; |
| 116 | uint32_t v86mask; |
bellard | b346ff4 | 2003-06-15 20:05:50 +0000 | [diff] [blame] | 117 | #endif |
pbrook | c276471 | 2009-03-07 15:24:59 +0000 | [diff] [blame] | 118 | abi_ulong child_tidptr; |
pbrook | e6e5906 | 2006-10-22 00:18:54 +0000 | [diff] [blame] | 119 | #ifdef TARGET_M68K |
Peter Maydell | 1ccd937 | 2013-07-16 18:44:55 +0100 | [diff] [blame] | 120 | abi_ulong tp_value; |
pbrook | e6e5906 | 2006-10-22 00:18:54 +0000 | [diff] [blame] | 121 | #endif |
Keith Packard | a10b9d9 | 2021-01-08 22:42:52 +0000 | [diff] [blame] | 122 | #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_RISCV) |
pbrook | a87295e | 2007-05-26 15:09:38 +0000 | [diff] [blame] | 123 | /* Extra fields for semihosted binaries. */ |
Peter Maydell | d317091 | 2016-07-04 13:06:35 +0100 | [diff] [blame] | 124 | abi_ulong heap_base; |
| 125 | abi_ulong heap_limit; |
pbrook | a87295e | 2007-05-26 15:09:38 +0000 | [diff] [blame] | 126 | #endif |
Peter Maydell | d317091 | 2016-07-04 13:06:35 +0100 | [diff] [blame] | 127 | abi_ulong stack_base; |
bellard | 851e67a | 2003-03-29 16:53:14 +0000 | [diff] [blame] | 128 | int used; /* non zero if used */ |
pbrook | 978efd6 | 2006-06-17 18:30:42 +0000 | [diff] [blame] | 129 | struct image_info *info; |
Mika Westerberg | edf8e2a | 2009-04-07 09:57:11 +0300 | [diff] [blame] | 130 | struct linux_binprm *bprm; |
pbrook | 624f797 | 2008-05-31 16:11:38 +0000 | [diff] [blame] | 131 | |
Timothy E Baldwin | 655ed67 | 2016-05-27 15:51:53 +0100 | [diff] [blame] | 132 | struct emulated_sigtable sync_signal; |
pbrook | 624f797 | 2008-05-31 16:11:38 +0000 | [diff] [blame] | 133 | struct emulated_sigtable sigtab[TARGET_NSIG]; |
Peter Maydell | 400b7f6 | 2021-09-08 16:43:57 +0100 | [diff] [blame] | 134 | /* |
| 135 | * This thread's signal mask, as requested by the guest program. |
Peter Maydell | 3d3efba | 2016-05-27 15:51:49 +0100 | [diff] [blame] | 136 | * The actual signal mask of this thread may differ: |
| 137 | * + we don't let SIGSEGV and SIGBUS be blocked while running guest code |
| 138 | * + sometimes we block all signals to avoid races |
| 139 | */ |
| 140 | sigset_t signal_mask; |
Peter Maydell | 400b7f6 | 2021-09-08 16:43:57 +0100 | [diff] [blame] | 141 | /* |
| 142 | * The signal mask imposed by a guest sigsuspend syscall, if we are |
Peter Maydell | 3d3efba | 2016-05-27 15:51:49 +0100 | [diff] [blame] | 143 | * currently in the middle of such a syscall |
| 144 | */ |
| 145 | sigset_t sigsuspend_mask; |
| 146 | /* Nonzero if we're leaving a sigsuspend and sigsuspend_mask is valid. */ |
| 147 | int in_sigsuspend; |
| 148 | |
Peter Maydell | 400b7f6 | 2021-09-08 16:43:57 +0100 | [diff] [blame] | 149 | /* |
| 150 | * Nonzero if process_pending_signals() needs to do something (either |
Peter Maydell | 3d3efba | 2016-05-27 15:51:49 +0100 | [diff] [blame] | 151 | * handle a pending signal or unblock signals). |
| 152 | * This flag is written from a signal handler so should be accessed via |
Stefan Hajnoczi | d73415a | 2020-09-23 11:56:46 +0100 | [diff] [blame] | 153 | * the qatomic_read() and qatomic_set() functions. (It is not accessed |
Peter Maydell | 3d3efba | 2016-05-27 15:51:49 +0100 | [diff] [blame] | 154 | * from multiple threads.) |
| 155 | */ |
| 156 | int signal_pending; |
| 157 | |
Peter Maydell | 5bfce0b | 2019-07-25 14:16:45 +0100 | [diff] [blame] | 158 | /* This thread's sigaltstack, if it has one */ |
| 159 | struct target_sigaltstack sigaltstack_used; |
Cameron Esfahani | eb33cda | 2022-01-27 16:12:51 -0800 | [diff] [blame] | 160 | |
| 161 | /* Start time of task after system boot in clock ticks */ |
| 162 | uint64_t start_boottime; |
Peter Maydell | b1b2138 | 2022-01-14 15:37:30 +0000 | [diff] [blame] | 163 | } TaskState; |
bellard | 851e67a | 2003-03-29 16:53:14 +0000 | [diff] [blame] | 164 | |
Peter Maydell | 3b249d2 | 2021-09-08 16:44:03 +0100 | [diff] [blame] | 165 | abi_long do_brk(abi_ulong new_brk); |
Ilya Leoshkevich | a4dab0a | 2023-06-30 19:04:16 +0100 | [diff] [blame] | 166 | int do_guest_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, |
Ilya Leoshkevich | 35be898 | 2023-06-30 19:04:17 +0100 | [diff] [blame] | 167 | int flags, mode_t mode, bool safe); |
Ilya Leoshkevich | a4dab0a | 2023-06-30 19:04:16 +0100 | [diff] [blame] | 168 | ssize_t do_guest_readlink(const char *pathname, char *buf, size_t bufsiz); |
bellard | 631271d | 2003-05-10 13:14:52 +0000 | [diff] [blame] | 169 | |
bellard | edf779f | 2004-02-22 13:40:13 +0000 | [diff] [blame] | 170 | /* user access */ |
| 171 | |
Thomas WeiĂźschuh | 64d0601 | 2023-04-22 12:03:13 +0200 | [diff] [blame] | 172 | #define VERIFY_NONE 0 |
Richard Henderson | 68f7766 | 2021-02-12 10:48:38 -0800 | [diff] [blame] | 173 | #define VERIFY_READ PAGE_READ |
| 174 | #define VERIFY_WRITE (PAGE_READ | PAGE_WRITE) |
bellard | edf779f | 2004-02-22 13:40:13 +0000 | [diff] [blame] | 175 | |
Richard Henderson | c7169b0 | 2021-02-12 10:48:47 -0800 | [diff] [blame] | 176 | static inline bool access_ok_untagged(int type, abi_ulong addr, abi_ulong size) |
bellard | dae3270 | 2007-11-14 10:51:00 +0000 | [diff] [blame] | 177 | { |
Richard Henderson | 114556c | 2021-02-12 10:48:45 -0800 | [diff] [blame] | 178 | if (size == 0 |
Richard Henderson | 46b12f4 | 2021-02-12 10:48:46 -0800 | [diff] [blame] | 179 | ? !guest_addr_valid_untagged(addr) |
| 180 | : !guest_range_valid_untagged(addr, size)) { |
Richard Henderson | 4feac83 | 2021-02-12 10:48:37 -0800 | [diff] [blame] | 181 | return false; |
| 182 | } |
Richard Henderson | bef6f00 | 2023-07-07 21:40:52 +0100 | [diff] [blame] | 183 | return page_check_range((target_ulong)addr, size, type); |
bellard | dae3270 | 2007-11-14 10:51:00 +0000 | [diff] [blame] | 184 | } |
bellard | edf779f | 2004-02-22 13:40:13 +0000 | [diff] [blame] | 185 | |
Richard Henderson | c7169b0 | 2021-02-12 10:48:47 -0800 | [diff] [blame] | 186 | static inline bool access_ok(CPUState *cpu, int type, |
| 187 | abi_ulong addr, abi_ulong size) |
| 188 | { |
| 189 | return access_ok_untagged(type, cpu_untagged_addr(cpu, addr), size); |
| 190 | } |
| 191 | |
Richard Henderson | 658f2dc | 2013-01-04 16:39:31 -0800 | [diff] [blame] | 192 | /* NOTE __get_user and __put_user use host pointers and don't check access. |
| 193 | These are usually used to access struct data members once the struct has |
| 194 | been locked - usually with lock_user_struct. */ |
bellard | edf779f | 2004-02-22 13:40:13 +0000 | [diff] [blame] | 195 | |
Peter Maydell | 850d5e3 | 2018-10-09 17:18:14 +0100 | [diff] [blame] | 196 | /* |
| 197 | * Tricky points: |
| 198 | * - Use __builtin_choose_expr to avoid type promotion from ?:, |
| 199 | * - Invalid sizes result in a compile time error stemming from |
| 200 | * the fact that abort has no parameters. |
| 201 | * - It's easier to use the endian-specific unaligned load/store |
| 202 | * functions than host-endian unaligned load/store plus tswapN. |
| 203 | * - The pragmas are necessary only to silence a clang false-positive |
| 204 | * warning: see https://bugs.llvm.org/show_bug.cgi?id=39113 . |
Peter Maydell | 850d5e3 | 2018-10-09 17:18:14 +0100 | [diff] [blame] | 205 | * - gcc has bugs in its _Pragma() support in some versions, eg |
| 206 | * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83256 -- so we only |
| 207 | * include the warning-suppression pragmas for clang |
| 208 | */ |
Thomas Huth | 798b858 | 2018-11-30 09:23:16 +0100 | [diff] [blame] | 209 | #if defined(__clang__) && __has_warning("-Waddress-of-packed-member") |
Peter Maydell | 850d5e3 | 2018-10-09 17:18:14 +0100 | [diff] [blame] | 210 | #define PRAGMA_DISABLE_PACKED_WARNING \ |
| 211 | _Pragma("GCC diagnostic push"); \ |
Peter Maydell | 850d5e3 | 2018-10-09 17:18:14 +0100 | [diff] [blame] | 212 | _Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\"") |
Richard Henderson | 658f2dc | 2013-01-04 16:39:31 -0800 | [diff] [blame] | 213 | |
Peter Maydell | 850d5e3 | 2018-10-09 17:18:14 +0100 | [diff] [blame] | 214 | #define PRAGMA_REENABLE_PACKED_WARNING \ |
| 215 | _Pragma("GCC diagnostic pop") |
Richard Henderson | 658f2dc | 2013-01-04 16:39:31 -0800 | [diff] [blame] | 216 | |
Peter Maydell | 850d5e3 | 2018-10-09 17:18:14 +0100 | [diff] [blame] | 217 | #else |
| 218 | #define PRAGMA_DISABLE_PACKED_WARNING |
| 219 | #define PRAGMA_REENABLE_PACKED_WARNING |
| 220 | #endif |
| 221 | |
| 222 | #define __put_user_e(x, hptr, e) \ |
| 223 | do { \ |
| 224 | PRAGMA_DISABLE_PACKED_WARNING; \ |
| 225 | (__builtin_choose_expr(sizeof(*(hptr)) == 1, stb_p, \ |
| 226 | __builtin_choose_expr(sizeof(*(hptr)) == 2, stw_##e##_p, \ |
| 227 | __builtin_choose_expr(sizeof(*(hptr)) == 4, stl_##e##_p, \ |
| 228 | __builtin_choose_expr(sizeof(*(hptr)) == 8, stq_##e##_p, abort)))) \ |
| 229 | ((hptr), (x)), (void)0); \ |
| 230 | PRAGMA_REENABLE_PACKED_WARNING; \ |
| 231 | } while (0) |
| 232 | |
| 233 | #define __get_user_e(x, hptr, e) \ |
| 234 | do { \ |
| 235 | PRAGMA_DISABLE_PACKED_WARNING; \ |
| 236 | ((x) = (typeof(*hptr))( \ |
| 237 | __builtin_choose_expr(sizeof(*(hptr)) == 1, ldub_p, \ |
| 238 | __builtin_choose_expr(sizeof(*(hptr)) == 2, lduw_##e##_p, \ |
| 239 | __builtin_choose_expr(sizeof(*(hptr)) == 4, ldl_##e##_p, \ |
| 240 | __builtin_choose_expr(sizeof(*(hptr)) == 8, ldq_##e##_p, abort)))) \ |
| 241 | (hptr)), (void)0); \ |
| 242 | PRAGMA_REENABLE_PACKED_WARNING; \ |
| 243 | } while (0) |
| 244 | |
Richard Henderson | 658f2dc | 2013-01-04 16:39:31 -0800 | [diff] [blame] | 245 | |
Marc-André Lureau | ee3eb3a | 2022-03-23 19:57:18 +0400 | [diff] [blame] | 246 | #if TARGET_BIG_ENDIAN |
Richard Henderson | 658f2dc | 2013-01-04 16:39:31 -0800 | [diff] [blame] | 247 | # define __put_user(x, hptr) __put_user_e(x, hptr, be) |
| 248 | # define __get_user(x, hptr) __get_user_e(x, hptr, be) |
| 249 | #else |
| 250 | # define __put_user(x, hptr) __put_user_e(x, hptr, le) |
| 251 | # define __get_user(x, hptr) __get_user_e(x, hptr, le) |
| 252 | #endif |
bellard | edf779f | 2004-02-22 13:40:13 +0000 | [diff] [blame] | 253 | |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 254 | /* put_user()/get_user() take a guest address and check access */ |
| 255 | /* These are usually used to access an atomic data type, such as an int, |
| 256 | * that has been passed by address. These internally perform locking |
| 257 | * and unlocking on the data type. |
| 258 | */ |
| 259 | #define put_user(x, gaddr, target_type) \ |
| 260 | ({ \ |
| 261 | abi_ulong __gaddr = (gaddr); \ |
| 262 | target_type *__hptr; \ |
Riku Voipio | a42267e | 2014-04-22 15:40:50 +0300 | [diff] [blame] | 263 | abi_long __ret = 0; \ |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 264 | if ((__hptr = lock_user(VERIFY_WRITE, __gaddr, sizeof(target_type), 0))) { \ |
Riku Voipio | a42267e | 2014-04-22 15:40:50 +0300 | [diff] [blame] | 265 | __put_user((x), __hptr); \ |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 266 | unlock_user(__hptr, __gaddr, sizeof(target_type)); \ |
| 267 | } else \ |
| 268 | __ret = -TARGET_EFAULT; \ |
| 269 | __ret; \ |
bellard | edf779f | 2004-02-22 13:40:13 +0000 | [diff] [blame] | 270 | }) |
| 271 | |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 272 | #define get_user(x, gaddr, target_type) \ |
| 273 | ({ \ |
| 274 | abi_ulong __gaddr = (gaddr); \ |
| 275 | target_type *__hptr; \ |
Riku Voipio | a42267e | 2014-04-22 15:40:50 +0300 | [diff] [blame] | 276 | abi_long __ret = 0; \ |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 277 | if ((__hptr = lock_user(VERIFY_READ, __gaddr, sizeof(target_type), 1))) { \ |
Riku Voipio | a42267e | 2014-04-22 15:40:50 +0300 | [diff] [blame] | 278 | __get_user((x), __hptr); \ |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 279 | unlock_user(__hptr, __gaddr, 0); \ |
bellard | 2f61969 | 2007-11-16 10:46:05 +0000 | [diff] [blame] | 280 | } else { \ |
| 281 | /* avoid warning */ \ |
| 282 | (x) = 0; \ |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 283 | __ret = -TARGET_EFAULT; \ |
bellard | 2f61969 | 2007-11-16 10:46:05 +0000 | [diff] [blame] | 284 | } \ |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 285 | __ret; \ |
bellard | edf779f | 2004-02-22 13:40:13 +0000 | [diff] [blame] | 286 | }) |
| 287 | |
bellard | 2f61969 | 2007-11-16 10:46:05 +0000 | [diff] [blame] | 288 | #define put_user_ual(x, gaddr) put_user((x), (gaddr), abi_ulong) |
| 289 | #define put_user_sal(x, gaddr) put_user((x), (gaddr), abi_long) |
| 290 | #define put_user_u64(x, gaddr) put_user((x), (gaddr), uint64_t) |
| 291 | #define put_user_s64(x, gaddr) put_user((x), (gaddr), int64_t) |
| 292 | #define put_user_u32(x, gaddr) put_user((x), (gaddr), uint32_t) |
| 293 | #define put_user_s32(x, gaddr) put_user((x), (gaddr), int32_t) |
| 294 | #define put_user_u16(x, gaddr) put_user((x), (gaddr), uint16_t) |
| 295 | #define put_user_s16(x, gaddr) put_user((x), (gaddr), int16_t) |
| 296 | #define put_user_u8(x, gaddr) put_user((x), (gaddr), uint8_t) |
| 297 | #define put_user_s8(x, gaddr) put_user((x), (gaddr), int8_t) |
| 298 | |
| 299 | #define get_user_ual(x, gaddr) get_user((x), (gaddr), abi_ulong) |
| 300 | #define get_user_sal(x, gaddr) get_user((x), (gaddr), abi_long) |
| 301 | #define get_user_u64(x, gaddr) get_user((x), (gaddr), uint64_t) |
| 302 | #define get_user_s64(x, gaddr) get_user((x), (gaddr), int64_t) |
| 303 | #define get_user_u32(x, gaddr) get_user((x), (gaddr), uint32_t) |
| 304 | #define get_user_s32(x, gaddr) get_user((x), (gaddr), int32_t) |
| 305 | #define get_user_u16(x, gaddr) get_user((x), (gaddr), uint16_t) |
| 306 | #define get_user_s16(x, gaddr) get_user((x), (gaddr), int16_t) |
| 307 | #define get_user_u8(x, gaddr) get_user((x), (gaddr), uint8_t) |
| 308 | #define get_user_s8(x, gaddr) get_user((x), (gaddr), int8_t) |
| 309 | |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 310 | /* copy_from_user() and copy_to_user() are usually used to copy data |
| 311 | * buffers between the target and host. These internally perform |
| 312 | * locking/unlocking of the memory. |
| 313 | */ |
Richard Henderson | 360f0ab | 2021-03-15 14:40:04 -0600 | [diff] [blame] | 314 | int copy_from_user(void *hptr, abi_ulong gaddr, ssize_t len); |
| 315 | int copy_to_user(abi_ulong gaddr, void *hptr, ssize_t len); |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 316 | |
pbrook | 53a5960 | 2006-03-25 19:31:22 +0000 | [diff] [blame] | 317 | /* Functions for accessing guest memory. The tget and tput functions |
Stefan Weil | 6f20f55 | 2013-09-12 19:57:15 +0200 | [diff] [blame] | 318 | read/write single values, byteswapping as necessary. The lock_user function |
pbrook | 53a5960 | 2006-03-25 19:31:22 +0000 | [diff] [blame] | 319 | gets a pointer to a contiguous area of guest memory, but does not perform |
Stefan Weil | 6f20f55 | 2013-09-12 19:57:15 +0200 | [diff] [blame] | 320 | any byteswapping. lock_user may return either a pointer to the guest |
pbrook | 53a5960 | 2006-03-25 19:31:22 +0000 | [diff] [blame] | 321 | memory, or a temporary buffer. */ |
| 322 | |
| 323 | /* Lock an area of guest memory into the host. If copy is true then the |
| 324 | host area will have the same contents as the guest. */ |
Richard Henderson | 360f0ab | 2021-03-15 14:40:04 -0600 | [diff] [blame] | 325 | void *lock_user(int type, abi_ulong guest_addr, ssize_t len, bool copy); |
bellard | edf779f | 2004-02-22 13:40:13 +0000 | [diff] [blame] | 326 | |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 327 | /* Unlock an area of guest memory. The first LEN bytes must be |
ths | 1235fc0 | 2008-06-03 19:51:57 +0000 | [diff] [blame] | 328 | flushed back to guest memory. host_ptr = NULL is explicitly |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 329 | allowed and does nothing. */ |
Richard Henderson | 687ca79 | 2021-02-12 10:48:48 -0800 | [diff] [blame] | 330 | #ifndef DEBUG_REMAP |
Richard Henderson | 360f0ab | 2021-03-15 14:40:04 -0600 | [diff] [blame] | 331 | static inline void unlock_user(void *host_ptr, abi_ulong guest_addr, |
| 332 | ssize_t len) |
| 333 | { |
| 334 | /* no-op */ |
| 335 | } |
Richard Henderson | 687ca79 | 2021-02-12 10:48:48 -0800 | [diff] [blame] | 336 | #else |
Richard Henderson | 360f0ab | 2021-03-15 14:40:04 -0600 | [diff] [blame] | 337 | void unlock_user(void *host_ptr, abi_ulong guest_addr, ssize_t len); |
pbrook | 53a5960 | 2006-03-25 19:31:22 +0000 | [diff] [blame] | 338 | #endif |
bellard | edf779f | 2004-02-22 13:40:13 +0000 | [diff] [blame] | 339 | |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 340 | /* Return the length of a string in target memory or -TARGET_EFAULT if |
| 341 | access error. */ |
Richard Henderson | 09f679b | 2021-02-12 10:48:49 -0800 | [diff] [blame] | 342 | ssize_t target_strlen(abi_ulong gaddr); |
bellard | edf779f | 2004-02-22 13:40:13 +0000 | [diff] [blame] | 343 | |
pbrook | 53a5960 | 2006-03-25 19:31:22 +0000 | [diff] [blame] | 344 | /* Like lock_user but for null terminated strings. */ |
Richard Henderson | 687ca79 | 2021-02-12 10:48:48 -0800 | [diff] [blame] | 345 | void *lock_user_string(abi_ulong guest_addr); |
pbrook | 53a5960 | 2006-03-25 19:31:22 +0000 | [diff] [blame] | 346 | |
Stefan Weil | 41d1af4 | 2013-09-12 19:57:41 +0200 | [diff] [blame] | 347 | /* Helper macros for locking/unlocking a target struct. */ |
bellard | 579a97f | 2007-11-11 14:26:47 +0000 | [diff] [blame] | 348 | #define lock_user_struct(type, host_ptr, guest_addr, copy) \ |
| 349 | (host_ptr = lock_user(type, guest_addr, sizeof(*host_ptr), copy)) |
| 350 | #define unlock_user_struct(host_ptr, guest_addr, copy) \ |
pbrook | 53a5960 | 2006-03-25 19:31:22 +0000 | [diff] [blame] | 351 | unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) |
| 352 | |
bellard | e88de09 | 2005-02-07 12:35:39 +0000 | [diff] [blame] | 353 | #endif /* QEMU_H */ |