188dae46dSSean Bruno /*
288dae46dSSean Bruno * qemu bsd user mode definition
388dae46dSSean Bruno *
488dae46dSSean Bruno * This program is free software; you can redistribute it and/or modify
588dae46dSSean Bruno * it under the terms of the GNU General Public License as published by
688dae46dSSean Bruno * the Free Software Foundation; either version 2 of the License, or
788dae46dSSean Bruno * (at your option) any later version.
888dae46dSSean Bruno *
988dae46dSSean Bruno * This program is distributed in the hope that it will be useful,
1088dae46dSSean Bruno * but WITHOUT ANY WARRANTY; without even the implied warranty of
1188dae46dSSean Bruno * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1288dae46dSSean Bruno * GNU General Public License for more details.
1388dae46dSSean Bruno *
1488dae46dSSean Bruno * You should have received a copy of the GNU General Public License
1588dae46dSSean Bruno * along with this program; if not, see <http://www.gnu.org/licenses/>.
1688dae46dSSean Bruno */
1784778508Sblueswir1 #ifndef QEMU_H
1884778508Sblueswir1 #define QEMU_H
1984778508Sblueswir1
20*ce6c541dSStacey Son #include <sys/param.h>
21*ce6c541dSStacey Son
22*ce6c541dSStacey Son #include "qemu/int128.h"
2384778508Sblueswir1 #include "cpu.h"
24e5e44263SWarner Losh #include "qemu/units.h"
25f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h"
26ab77bd84SWarner Losh #include "exec/exec-all.h"
2784778508Sblueswir1
2822879b66SPhilippe Mathieu-Daudé #include "user/abitypes.h"
2984778508Sblueswir1
304b599848SWarner Losh extern char **environ;
314b599848SWarner Losh
324e111653SPhilippe Mathieu-Daudé #include "user/thunk.h"
33ab77bd84SWarner Losh #include "target_arch.h"
3484778508Sblueswir1 #include "syscall_defs.h"
350c6940d0SLluís Vilanova #include "target_syscall.h"
3682792244SWarner Losh #include "target_os_vmparam.h"
37790baaccSWarner Losh #include "target_os_signal.h"
38647afdf1SWarner Losh #include "target.h"
39022c62cbSPaolo Bonzini #include "exec/gdbstub.h"
4074781c08SPhilippe Mathieu-Daudé #include "exec/page-protection.h"
41e022d9caSEmanuele Giuseppe Esposito #include "qemu/clang-tsa.h"
4280196013SPhilippe Mathieu-Daudé #include "accel/tcg/vcpu-state.h"
4384778508Sblueswir1
449b4a902dSStacey Son #include "qemu-os.h"
45c2bdd9a1SWarner Losh /*
468c45039fSRichard Henderson * TODO: Remove these and rely only on qemu_real_host_page_size().
478c45039fSRichard Henderson */
488c45039fSRichard Henderson extern uintptr_t qemu_host_page_size;
498c45039fSRichard Henderson extern intptr_t qemu_host_page_mask;
508c45039fSRichard Henderson #define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
518c45039fSRichard Henderson
528c45039fSRichard Henderson /*
53c2bdd9a1SWarner Losh * This struct is used to hold certain information about the image. Basically,
54c2bdd9a1SWarner Losh * it replicates in user space what would be certain task_struct fields in the
55c2bdd9a1SWarner Losh * kernel
5684778508Sblueswir1 */
5784778508Sblueswir1 struct image_info {
580475f8faSWarner Losh abi_ulong load_bias;
5984778508Sblueswir1 abi_ulong load_addr;
6084778508Sblueswir1 abi_ulong start_code;
6184778508Sblueswir1 abi_ulong end_code;
6284778508Sblueswir1 abi_ulong start_data;
6384778508Sblueswir1 abi_ulong end_data;
6484778508Sblueswir1 abi_ulong brk;
6584778508Sblueswir1 abi_ulong rss;
6684778508Sblueswir1 abi_ulong start_stack;
6784778508Sblueswir1 abi_ulong entry;
6884778508Sblueswir1 abi_ulong code_offset;
6984778508Sblueswir1 abi_ulong data_offset;
700475f8faSWarner Losh abi_ulong arg_start;
710475f8faSWarner Losh abi_ulong arg_end;
720475f8faSWarner Losh uint32_t elf_flags;
7384778508Sblueswir1 };
7484778508Sblueswir1
7584778508Sblueswir1 struct emulated_sigtable {
7684778508Sblueswir1 int pending; /* true if signal is pending */
77b46d4ad7SWarner Losh target_siginfo_t info;
7884778508Sblueswir1 };
7984778508Sblueswir1
80c2bdd9a1SWarner Losh /*
81c2bdd9a1SWarner Losh * NOTE: we force a big alignment so that the stack stored after is aligned too
82c2bdd9a1SWarner Losh */
83ef932e21SPhilippe Mathieu-Daudé struct TaskState {
84bd88c780SAlex Bennée pid_t ts_tid; /* tid (or pid) of this task */
85bd88c780SAlex Bennée
8684778508Sblueswir1 struct TaskState *next;
87031fe7afSWarner Losh struct bsd_binprm *bprm;
8884778508Sblueswir1 struct image_info *info;
8984778508Sblueswir1
9038be620cSWarner Losh struct emulated_sigtable sync_signal;
9138be620cSWarner Losh /*
9238be620cSWarner Losh * TODO: Since we block all signals while returning to the main CPU
9338be620cSWarner Losh * loop, this needn't be an array
9438be620cSWarner Losh */
9584778508Sblueswir1 struct emulated_sigtable sigtab[TARGET_NSIG];
9648047225SWarner Losh /*
9748047225SWarner Losh * Nonzero if process_pending_signals() needs to do something (either
9848047225SWarner Losh * handle a pending signal or unblock signals).
9948047225SWarner Losh * This flag is written from a signal handler so should be accessed via
10048047225SWarner Losh * the qatomic_read() and qatomic_set() functions. (It is not accessed
10148047225SWarner Losh * from multiple threads.)
10248047225SWarner Losh */
10348047225SWarner Losh int signal_pending;
1046c6d4b56SWarner Losh /* True if we're leaving a sigsuspend and sigsuspend_mask is valid. */
1056c6d4b56SWarner Losh bool in_sigsuspend;
106149076adSWarner Losh /*
107149076adSWarner Losh * This thread's signal mask, as requested by the guest program.
108149076adSWarner Losh * The actual signal mask of this thread may differ:
109149076adSWarner Losh * + we don't let SIGSEGV and SIGBUS be blocked while running guest code
110149076adSWarner Losh * + sometimes we block all signals to avoid races
111149076adSWarner Losh */
112149076adSWarner Losh sigset_t signal_mask;
1136c6d4b56SWarner Losh /*
1146c6d4b56SWarner Losh * The signal mask imposed by a guest sigsuspend syscall, if we are
1156c6d4b56SWarner Losh * currently in the middle of such a syscall
1166c6d4b56SWarner Losh */
1176c6d4b56SWarner Losh sigset_t sigsuspend_mask;
11884778508Sblueswir1
11946f4f76dSWarner Losh /* This thread's sigaltstack, if it has one */
12046f4f76dSWarner Losh struct target_sigaltstack sigaltstack_used;
121ef932e21SPhilippe Mathieu-Daudé } __attribute__((aligned(16)));
12284778508Sblueswir1
123653ccec2SWarner Losh void stop_all_tasks(void);
12486327290SStacey Son extern const char *interp_prefix;
12584778508Sblueswir1 extern const char *qemu_uname_release;
12684778508Sblueswir1
12784778508Sblueswir1 /*
128e5e44263SWarner Losh * TARGET_ARG_MAX defines the number of bytes allocated for arguments
129e5e44263SWarner Losh * and envelope for the new program. 256k should suffice for a reasonable
130944399ffSMichael Tokarev * maximum env+arg in 32-bit environments, bump it up to 512k for !ILP32
131e5e44263SWarner Losh * platforms.
13284778508Sblueswir1 */
133e5e44263SWarner Losh #if TARGET_ABI_BITS > 32
134e5e44263SWarner Losh #define TARGET_ARG_MAX (512 * KiB)
135e5e44263SWarner Losh #else
136e5e44263SWarner Losh #define TARGET_ARG_MAX (256 * KiB)
137e5e44263SWarner Losh #endif
138e5e44263SWarner Losh #define MAX_ARG_PAGES (TARGET_ARG_MAX / TARGET_PAGE_SIZE)
13984778508Sblueswir1
14084778508Sblueswir1 /*
14184778508Sblueswir1 * This structure is used to hold the arguments that are
14284778508Sblueswir1 * used when loading binaries.
14384778508Sblueswir1 */
144afcbcff8SWarner Losh struct bsd_binprm {
14584778508Sblueswir1 char buf[128];
14684778508Sblueswir1 void *page[MAX_ARG_PAGES];
14784778508Sblueswir1 abi_ulong p;
14898b34d35SWarner Losh abi_ulong stringp;
14984778508Sblueswir1 int fd;
15084778508Sblueswir1 int e_uid, e_gid;
15184778508Sblueswir1 int argc, envc;
15284778508Sblueswir1 char **argv;
15384778508Sblueswir1 char **envp;
1541b50ff64SWarner Losh char *filename; /* (Given) Name of binary */
1551b50ff64SWarner Losh char *fullpath; /* Full path of binary */
1560475f8faSWarner Losh int (*core_dump)(int, CPUArchState *);
15784778508Sblueswir1 };
15884778508Sblueswir1
15984778508Sblueswir1 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
16084778508Sblueswir1 abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
161ffa03665SWarner Losh abi_ulong stringp);
16284778508Sblueswir1 int loader_exec(const char *filename, char **argv, char **envp,
163d37853f9SWarner Losh struct target_pt_regs *regs, struct image_info *infop,
164d37853f9SWarner Losh struct bsd_binprm *bprm);
16584778508Sblueswir1
166afcbcff8SWarner Losh int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
16784778508Sblueswir1 struct image_info *info);
168afcbcff8SWarner Losh int load_flt_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
16984778508Sblueswir1 struct image_info *info);
1700475f8faSWarner Losh int is_target_elf_binary(int fd);
17184778508Sblueswir1
17284778508Sblueswir1 abi_long memcpy_to_target(abi_ulong dest, const void *src,
17384778508Sblueswir1 unsigned long len);
17484778508Sblueswir1 void target_set_brk(abi_ulong new_brk);
17584778508Sblueswir1 abi_long do_brk(abi_ulong new_brk);
17684778508Sblueswir1 void syscall_init(void);
17784778508Sblueswir1 abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
17884778508Sblueswir1 abi_long arg2, abi_long arg3, abi_long arg4,
17978cfb07fSJuergen Lock abi_long arg5, abi_long arg6, abi_long arg7,
18078cfb07fSJuergen Lock abi_long arg8);
18184778508Sblueswir1 abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
18284778508Sblueswir1 abi_long arg2, abi_long arg3, abi_long arg4,
18384778508Sblueswir1 abi_long arg5, abi_long arg6);
18484778508Sblueswir1 abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
18584778508Sblueswir1 abi_long arg2, abi_long arg3, abi_long arg4,
18684778508Sblueswir1 abi_long arg5, abi_long arg6);
1879edc6313SMarc-André Lureau void gemu_log(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
188d42df502SWarner Losh extern __thread CPUState *thread_cpu;
1899349b4f9SAndreas Färber void cpu_loop(CPUArchState *env);
19084778508Sblueswir1 char *target_strerror(int err);
19184778508Sblueswir1 int get_osversion(void);
19284778508Sblueswir1 void fork_start(void);
1934edc98fcSIlya Leoshkevich void fork_end(pid_t pid);
19484778508Sblueswir1
1951de7afc9SPaolo Bonzini #include "qemu/log.h"
19684778508Sblueswir1
19784778508Sblueswir1 /* strace.c */
19888dae46dSSean Bruno struct syscallname {
19988dae46dSSean Bruno int nr;
20088dae46dSSean Bruno const char *name;
20188dae46dSSean Bruno const char *format;
20288dae46dSSean Bruno void (*call)(const struct syscallname *,
20388dae46dSSean Bruno abi_long, abi_long, abi_long,
20488dae46dSSean Bruno abi_long, abi_long, abi_long);
20588dae46dSSean Bruno void (*result)(const struct syscallname *, abi_long);
20688dae46dSSean Bruno };
20788dae46dSSean Bruno
20884778508Sblueswir1 void
20984778508Sblueswir1 print_freebsd_syscall(int num,
21084778508Sblueswir1 abi_long arg1, abi_long arg2, abi_long arg3,
21184778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6);
21284778508Sblueswir1 void print_freebsd_syscall_ret(int num, abi_long ret);
21384778508Sblueswir1 void
21484778508Sblueswir1 print_netbsd_syscall(int num,
21584778508Sblueswir1 abi_long arg1, abi_long arg2, abi_long arg3,
21684778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6);
21784778508Sblueswir1 void print_netbsd_syscall_ret(int num, abi_long ret);
21884778508Sblueswir1 void
21984778508Sblueswir1 print_openbsd_syscall(int num,
22084778508Sblueswir1 abi_long arg1, abi_long arg2, abi_long arg3,
22184778508Sblueswir1 abi_long arg4, abi_long arg5, abi_long arg6);
22284778508Sblueswir1 void print_openbsd_syscall_ret(int num, abi_long ret);
223fd5bec9aSWarner Losh /**
224fd5bec9aSWarner Losh * print_taken_signal:
225fd5bec9aSWarner Losh * @target_signum: target signal being taken
226fd5bec9aSWarner Losh * @tinfo: target_siginfo_t which will be passed to the guest for the signal
227fd5bec9aSWarner Losh *
228fd5bec9aSWarner Losh * Print strace output indicating that this signal is being taken by the guest,
229fd5bec9aSWarner Losh * in a format similar to:
230fd5bec9aSWarner Losh * --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
231fd5bec9aSWarner Losh */
232fd5bec9aSWarner Losh void print_taken_signal(int target_signum, const target_siginfo_t *tinfo);
23384778508Sblueswir1 extern int do_strace;
23484778508Sblueswir1
23584778508Sblueswir1 /* mmap.c */
23684778508Sblueswir1 int target_mprotect(abi_ulong start, abi_ulong len, int prot);
23784778508Sblueswir1 abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
238be04f210SWarner Losh int flags, int fd, off_t offset);
23984778508Sblueswir1 int target_munmap(abi_ulong start, abi_ulong len);
24084778508Sblueswir1 abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
24184778508Sblueswir1 abi_ulong new_size, unsigned long flags,
24284778508Sblueswir1 abi_ulong new_addr);
24384778508Sblueswir1 int target_msync(abi_ulong start, abi_ulong len, int flags);
244be04f210SWarner Losh extern abi_ulong mmap_next_start;
245be04f210SWarner Losh abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
2464e00b7d8SStacey Son void mmap_reserve(abi_ulong start, abi_ulong size);
247e022d9caSEmanuele Giuseppe Esposito void TSA_NO_TSA mmap_fork_start(void);
248e022d9caSEmanuele Giuseppe Esposito void TSA_NO_TSA mmap_fork_end(int child);
24984778508Sblueswir1
25028e738dcSBlue Swirl /* main.c */
25101a298a5SWarner Losh extern char qemu_proc_pathname[];
252312a0b1cSWarner Losh extern unsigned long target_maxtsiz;
253312a0b1cSWarner Losh extern unsigned long target_dfldsiz;
254312a0b1cSWarner Losh extern unsigned long target_maxdsiz;
255312a0b1cSWarner Losh extern unsigned long target_dflssiz;
256312a0b1cSWarner Losh extern unsigned long target_maxssiz;
257312a0b1cSWarner Losh extern unsigned long target_sgrowsiz;
25828e738dcSBlue Swirl
259deeff83bSWarner Losh /* os-syscall.c */
260e5f674f0SWarner Losh abi_long get_errno(abi_long ret);
261e5f674f0SWarner Losh bool is_error(abi_long ret);
262deeff83bSWarner Losh int host_to_target_errno(int err);
263e5f674f0SWarner Losh
264cc47390cSStacey Son /* os-proc.c */
265cc47390cSStacey Son abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
266cc47390cSStacey Son abi_ulong guest_envp, int do_fexec);
267cc47390cSStacey Son abi_long do_freebsd_procctl(void *cpu_env, int idtype, abi_ulong arg2,
268cc47390cSStacey Son abi_ulong arg3, abi_ulong arg4, abi_ulong arg5, abi_ulong arg6);
269cc47390cSStacey Son
270da07e694SWarner Losh /* os-sys.c */
2717adda6deSKyle Evans abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen,
2727adda6deSKyle Evans abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen);
2736da777e2SKyle Evans abi_long do_freebsd_sysctlbyname(CPUArchState *env, abi_ulong namep,
2746da777e2SKyle Evans int32_t namelen, abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp,
2756da777e2SKyle Evans abi_ulong newlen);
276da07e694SWarner Losh abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2);
277da07e694SWarner Losh
27884778508Sblueswir1 /* user access */
27984778508Sblueswir1
2801720751fSRichard Henderson #define VERIFY_READ PAGE_READ
2811720751fSRichard Henderson #define VERIFY_WRITE (PAGE_READ | PAGE_WRITE)
28284778508Sblueswir1
access_ok(int type,abi_ulong addr,abi_ulong size)2831720751fSRichard Henderson static inline bool access_ok(int type, abi_ulong addr, abi_ulong size)
28484778508Sblueswir1 {
285bef6f008SRichard Henderson return page_check_range((target_ulong)addr, size, type);
28684778508Sblueswir1 }
28784778508Sblueswir1
288c2bdd9a1SWarner Losh /*
289c2bdd9a1SWarner Losh * NOTE __get_user and __put_user use host pointers and don't check access.
290c2bdd9a1SWarner Losh *
291c2bdd9a1SWarner Losh * These are usually used to access struct data members once the struct has been
292c2bdd9a1SWarner Losh * locked - usually with lock_user_struct().
29384778508Sblueswir1 */
2948a45962bSWarner Losh
2958a45962bSWarner Losh /*
2968a45962bSWarner Losh * Tricky points:
2978a45962bSWarner Losh * - Use __builtin_choose_expr to avoid type promotion from ?:,
2988a45962bSWarner Losh * - Invalid sizes result in a compile time error stemming from
2998a45962bSWarner Losh * the fact that abort has no parameters.
3008a45962bSWarner Losh * - It's easier to use the endian-specific unaligned load/store
3018a45962bSWarner Losh * functions than host-endian unaligned load/store plus tswapN.
3028a45962bSWarner Losh * - The pragmas are necessary only to silence a clang false-positive
3038a45962bSWarner Losh * warning: see https://bugs.llvm.org/show_bug.cgi?id=39113 .
3048a45962bSWarner Losh * - gcc has bugs in its _Pragma() support in some versions, eg
3058a45962bSWarner Losh * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83256 -- so we only
3068a45962bSWarner Losh * include the warning-suppression pragmas for clang
3078a45962bSWarner Losh */
3088a45962bSWarner Losh #if defined(__clang__) && __has_warning("-Waddress-of-packed-member")
3098a45962bSWarner Losh #define PRAGMA_DISABLE_PACKED_WARNING \
3108a45962bSWarner Losh _Pragma("GCC diagnostic push"); \
3118a45962bSWarner Losh _Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\"")
3128a45962bSWarner Losh
3138a45962bSWarner Losh #define PRAGMA_REENABLE_PACKED_WARNING \
3148a45962bSWarner Losh _Pragma("GCC diagnostic pop")
3158a45962bSWarner Losh
3168a45962bSWarner Losh #else
3178a45962bSWarner Losh #define PRAGMA_DISABLE_PACKED_WARNING
3188a45962bSWarner Losh #define PRAGMA_REENABLE_PACKED_WARNING
3198a45962bSWarner Losh #endif
3208a45962bSWarner Losh
3216538c682SWarner Losh #define __put_user_e(x, hptr, e) \
3226538c682SWarner Losh do { \
3236538c682SWarner Losh PRAGMA_DISABLE_PACKED_WARNING; \
3246538c682SWarner Losh (__builtin_choose_expr(sizeof(*(hptr)) == 1, stb_p, \
3256538c682SWarner Losh __builtin_choose_expr(sizeof(*(hptr)) == 2, stw_##e##_p, \
3266538c682SWarner Losh __builtin_choose_expr(sizeof(*(hptr)) == 4, stl_##e##_p, \
3276538c682SWarner Losh __builtin_choose_expr(sizeof(*(hptr)) == 8, stq_##e##_p, abort)))) \
3286538c682SWarner Losh ((hptr), (x)), (void)0); \
3296538c682SWarner Losh PRAGMA_REENABLE_PACKED_WARNING; \
3306538c682SWarner Losh } while (0)
33184778508Sblueswir1
3326538c682SWarner Losh #define __get_user_e(x, hptr, e) \
3336538c682SWarner Losh do { \
3346538c682SWarner Losh PRAGMA_DISABLE_PACKED_WARNING; \
3356538c682SWarner Losh ((x) = (typeof(*hptr))( \
3366538c682SWarner Losh __builtin_choose_expr(sizeof(*(hptr)) == 1, ldub_p, \
3376538c682SWarner Losh __builtin_choose_expr(sizeof(*(hptr)) == 2, lduw_##e##_p, \
3386538c682SWarner Losh __builtin_choose_expr(sizeof(*(hptr)) == 4, ldl_##e##_p, \
3396538c682SWarner Losh __builtin_choose_expr(sizeof(*(hptr)) == 8, ldq_##e##_p, abort)))) \
3406538c682SWarner Losh (hptr)), (void)0); \
3416538c682SWarner Losh PRAGMA_REENABLE_PACKED_WARNING; \
3426538c682SWarner Losh } while (0)
3436538c682SWarner Losh
3446538c682SWarner Losh
3456538c682SWarner Losh #if TARGET_BIG_ENDIAN
3466538c682SWarner Losh # define __put_user(x, hptr) __put_user_e(x, hptr, be)
3476538c682SWarner Losh # define __get_user(x, hptr) __get_user_e(x, hptr, be)
3486538c682SWarner Losh #else
3496538c682SWarner Losh # define __put_user(x, hptr) __put_user_e(x, hptr, le)
3506538c682SWarner Losh # define __get_user(x, hptr) __get_user_e(x, hptr, le)
3516538c682SWarner Losh #endif
35284778508Sblueswir1
353c2bdd9a1SWarner Losh /*
354c2bdd9a1SWarner Losh * put_user()/get_user() take a guest address and check access
355c2bdd9a1SWarner Losh *
356c2bdd9a1SWarner Losh * These are usually used to access an atomic data type, such as an int, that
357c2bdd9a1SWarner Losh * has been passed by address. These internally perform locking and unlocking
358c2bdd9a1SWarner Losh * on the data type.
35984778508Sblueswir1 */
36084778508Sblueswir1 #define put_user(x, gaddr, target_type) \
36184778508Sblueswir1 ({ \
36284778508Sblueswir1 abi_ulong __gaddr = (gaddr); \
36384778508Sblueswir1 target_type *__hptr; \
3646538c682SWarner Losh abi_long __ret = 0; \
36533066934SWarner Losh __hptr = lock_user(VERIFY_WRITE, __gaddr, sizeof(target_type), 0); \
36633066934SWarner Losh if (__hptr) { \
3676538c682SWarner Losh __put_user((x), __hptr); \
36884778508Sblueswir1 unlock_user(__hptr, __gaddr, sizeof(target_type)); \
36984778508Sblueswir1 } else \
37084778508Sblueswir1 __ret = -TARGET_EFAULT; \
37184778508Sblueswir1 __ret; \
37284778508Sblueswir1 })
37384778508Sblueswir1
37484778508Sblueswir1 #define get_user(x, gaddr, target_type) \
37584778508Sblueswir1 ({ \
37684778508Sblueswir1 abi_ulong __gaddr = (gaddr); \
37784778508Sblueswir1 target_type *__hptr; \
3786538c682SWarner Losh abi_long __ret = 0; \
37933066934SWarner Losh __hptr = lock_user(VERIFY_READ, __gaddr, sizeof(target_type), 1); \
38033066934SWarner Losh if (__hptr) { \
3816538c682SWarner Losh __get_user((x), __hptr); \
38284778508Sblueswir1 unlock_user(__hptr, __gaddr, 0); \
38384778508Sblueswir1 } else { \
38484778508Sblueswir1 (x) = 0; \
38584778508Sblueswir1 __ret = -TARGET_EFAULT; \
38684778508Sblueswir1 } \
38784778508Sblueswir1 __ret; \
38884778508Sblueswir1 })
38984778508Sblueswir1
39084778508Sblueswir1 #define put_user_ual(x, gaddr) put_user((x), (gaddr), abi_ulong)
39184778508Sblueswir1 #define put_user_sal(x, gaddr) put_user((x), (gaddr), abi_long)
39284778508Sblueswir1 #define put_user_u64(x, gaddr) put_user((x), (gaddr), uint64_t)
39384778508Sblueswir1 #define put_user_s64(x, gaddr) put_user((x), (gaddr), int64_t)
39484778508Sblueswir1 #define put_user_u32(x, gaddr) put_user((x), (gaddr), uint32_t)
39584778508Sblueswir1 #define put_user_s32(x, gaddr) put_user((x), (gaddr), int32_t)
39684778508Sblueswir1 #define put_user_u16(x, gaddr) put_user((x), (gaddr), uint16_t)
39784778508Sblueswir1 #define put_user_s16(x, gaddr) put_user((x), (gaddr), int16_t)
39884778508Sblueswir1 #define put_user_u8(x, gaddr) put_user((x), (gaddr), uint8_t)
39984778508Sblueswir1 #define put_user_s8(x, gaddr) put_user((x), (gaddr), int8_t)
40084778508Sblueswir1
40184778508Sblueswir1 #define get_user_ual(x, gaddr) get_user((x), (gaddr), abi_ulong)
40284778508Sblueswir1 #define get_user_sal(x, gaddr) get_user((x), (gaddr), abi_long)
40384778508Sblueswir1 #define get_user_u64(x, gaddr) get_user((x), (gaddr), uint64_t)
40484778508Sblueswir1 #define get_user_s64(x, gaddr) get_user((x), (gaddr), int64_t)
40584778508Sblueswir1 #define get_user_u32(x, gaddr) get_user((x), (gaddr), uint32_t)
40684778508Sblueswir1 #define get_user_s32(x, gaddr) get_user((x), (gaddr), int32_t)
40784778508Sblueswir1 #define get_user_u16(x, gaddr) get_user((x), (gaddr), uint16_t)
40884778508Sblueswir1 #define get_user_s16(x, gaddr) get_user((x), (gaddr), int16_t)
40984778508Sblueswir1 #define get_user_u8(x, gaddr) get_user((x), (gaddr), uint8_t)
41084778508Sblueswir1 #define get_user_s8(x, gaddr) get_user((x), (gaddr), int8_t)
41184778508Sblueswir1
412c2bdd9a1SWarner Losh /*
413c2bdd9a1SWarner Losh * copy_from_user() and copy_to_user() are usually used to copy data
41484778508Sblueswir1 * buffers between the target and host. These internally perform
41584778508Sblueswir1 * locking/unlocking of the memory.
41684778508Sblueswir1 */
41784778508Sblueswir1 abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len);
41884778508Sblueswir1 abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len);
41984778508Sblueswir1
420c2bdd9a1SWarner Losh /*
421c2bdd9a1SWarner Losh * Functions for accessing guest memory. The tget and tput functions
422c2bdd9a1SWarner Losh * read/write single values, byteswapping as necessary. The lock_user function
423c2bdd9a1SWarner Losh * gets a pointer to a contiguous area of guest memory, but does not perform
424c2bdd9a1SWarner Losh * any byteswapping. lock_user may return either a pointer to the guest
425c2bdd9a1SWarner Losh * memory, or a temporary buffer.
426c2bdd9a1SWarner Losh */
42784778508Sblueswir1
428c2bdd9a1SWarner Losh /*
429c2bdd9a1SWarner Losh * Lock an area of guest memory into the host. If copy is true then the
430c2bdd9a1SWarner Losh * host area will have the same contents as the guest.
431c2bdd9a1SWarner Losh */
lock_user(int type,abi_ulong guest_addr,long len,int copy)432c2bdd9a1SWarner Losh static inline void *lock_user(int type, abi_ulong guest_addr, long len,
433c2bdd9a1SWarner Losh int copy)
43484778508Sblueswir1 {
435cb0ea019SWarner Losh if (!access_ok(type, guest_addr, len)) {
43684778508Sblueswir1 return NULL;
437cb0ea019SWarner Losh }
4381f2355f5SIlya Leoshkevich #ifdef CONFIG_DEBUG_REMAP
43984778508Sblueswir1 {
44084778508Sblueswir1 void *addr;
441fd9a3048SMd Haris Iqbal addr = g_malloc(len);
442cb0ea019SWarner Losh if (copy) {
4433e8f1628SRichard Henderson memcpy(addr, g2h_untagged(guest_addr), len);
444cb0ea019SWarner Losh } else {
44584778508Sblueswir1 memset(addr, 0, len);
446cb0ea019SWarner Losh }
44784778508Sblueswir1 return addr;
44884778508Sblueswir1 }
44984778508Sblueswir1 #else
4503e8f1628SRichard Henderson return g2h_untagged(guest_addr);
45184778508Sblueswir1 #endif
45284778508Sblueswir1 }
45384778508Sblueswir1
454c2bdd9a1SWarner Losh /*
455c2bdd9a1SWarner Losh * Unlock an area of guest memory. The first LEN bytes must be flushed back to
456c2bdd9a1SWarner Losh * guest memory. host_ptr = NULL is explicitly allowed and does nothing.
457c2bdd9a1SWarner Losh */
unlock_user(void * host_ptr,abi_ulong guest_addr,long len)45884778508Sblueswir1 static inline void unlock_user(void *host_ptr, abi_ulong guest_addr,
45984778508Sblueswir1 long len)
46084778508Sblueswir1 {
46184778508Sblueswir1
4621f2355f5SIlya Leoshkevich #ifdef CONFIG_DEBUG_REMAP
463cb0ea019SWarner Losh if (!host_ptr) {
46484778508Sblueswir1 return;
465cb0ea019SWarner Losh }
466cb0ea019SWarner Losh if (host_ptr == g2h_untagged(guest_addr)) {
46784778508Sblueswir1 return;
468cb0ea019SWarner Losh }
469cb0ea019SWarner Losh if (len > 0) {
4703e8f1628SRichard Henderson memcpy(g2h_untagged(guest_addr), host_ptr, len);
471cb0ea019SWarner Losh }
472fd9a3048SMd Haris Iqbal g_free(host_ptr);
47384778508Sblueswir1 #endif
47484778508Sblueswir1 }
47584778508Sblueswir1
476c2bdd9a1SWarner Losh /*
477c2bdd9a1SWarner Losh * Return the length of a string in target memory or -TARGET_EFAULT if access
478c2bdd9a1SWarner Losh * error.
479c2bdd9a1SWarner Losh */
48084778508Sblueswir1 abi_long target_strlen(abi_ulong gaddr);
48184778508Sblueswir1
48284778508Sblueswir1 /* Like lock_user but for null terminated strings. */
lock_user_string(abi_ulong guest_addr)48384778508Sblueswir1 static inline void *lock_user_string(abi_ulong guest_addr)
48484778508Sblueswir1 {
48584778508Sblueswir1 abi_long len;
48684778508Sblueswir1 len = target_strlen(guest_addr);
487cb0ea019SWarner Losh if (len < 0) {
48884778508Sblueswir1 return NULL;
489cb0ea019SWarner Losh }
49084778508Sblueswir1 return lock_user(VERIFY_READ, guest_addr, (long)(len + 1), 1);
49184778508Sblueswir1 }
49284778508Sblueswir1
49341d1af4dSStefan Weil /* Helper macros for locking/unlocking a target struct. */
49484778508Sblueswir1 #define lock_user_struct(type, host_ptr, guest_addr, copy) \
49584778508Sblueswir1 (host_ptr = lock_user(type, guest_addr, sizeof(*host_ptr), copy))
49684778508Sblueswir1 #define unlock_user_struct(host_ptr, guest_addr, copy) \
49784778508Sblueswir1 unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
49884778508Sblueswir1
target_arg64(uint32_t word0,uint32_t word1)4990ff05082SWarner Losh static inline uint64_t target_arg64(uint32_t word0, uint32_t word1)
5000ff05082SWarner Losh {
5010ff05082SWarner Losh #if TARGET_ABI_BITS == 32
502ee3eb3a7SMarc-André Lureau #if TARGET_BIG_ENDIAN
5030ff05082SWarner Losh return ((uint64_t)word0 << 32) | word1;
5040ff05082SWarner Losh #else
5050ff05082SWarner Losh return ((uint64_t)word1 << 32) | word0;
5060ff05082SWarner Losh #endif
5070ff05082SWarner Losh #else /* TARGET_ABI_BITS != 32 */
5080ff05082SWarner Losh return word0;
5090ff05082SWarner Losh #endif /* TARGET_ABI_BITS != 32 */
5100ff05082SWarner Losh }
5110ff05082SWarner Losh
51284778508Sblueswir1 #include <pthread.h>
51384778508Sblueswir1
514aae57ac3SWarner Losh #include "user/safe-syscall.h"
515aae57ac3SWarner Losh
51684778508Sblueswir1 #endif /* QEMU_H */
517