X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/11ddeea91a3b22bd4d4647c732bed32cb6d5112c..658f2dc970996d547a641b5685e384ebe6f2648e:/linux-user/qemu.h diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 55ad9d8586..31a220af81 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -11,14 +11,14 @@ #include #endif /* DEBUG_REMAP */ -#include "qemu-types.h" +#include "exec/user/abitypes.h" -#include "thunk.h" +#include "exec/user/thunk.h" #include "syscall_defs.h" #include "syscall.h" #include "target_signal.h" -#include "gdbstub.h" -#include "qemu-queue.h" +#include "exec/gdbstub.h" +#include "qemu/queue.h" #if defined(CONFIG_USE_NPTL) #define THREAD __thread @@ -48,8 +48,10 @@ struct image_info { abi_ulong code_offset; abi_ulong data_offset; abi_ulong saved_auxv; + abi_ulong auxv_len; abi_ulong arg_start; abi_ulong arg_end; + uint32_t elf_flags; int personality; #ifdef CONFIG_USE_FDPIC abi_ulong loadmap_addr; @@ -123,10 +125,10 @@ typedef struct TaskState { #endif #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) /* Extra fields for semihosted binaries. */ - uint32_t stack_base; uint32_t heap_base; uint32_t heap_limit; #endif + uint32_t stack_base; int used; /* non zero if used */ struct image_info *info; struct linux_binprm *bprm; @@ -170,7 +172,7 @@ struct linux_binprm { char **argv; char **envp; char * filename; /* Name of binary */ - int (*core_dump)(int, const CPUState *); /* coredump routine */ + int (*core_dump)(int, const CPUArchState *); /* coredump routine */ }; void do_init_thread(struct target_pt_regs *regs, struct image_info *infop); @@ -195,20 +197,30 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg5, abi_long arg6, abi_long arg7, abi_long arg8); void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2); -extern THREAD CPUState *thread_env; -void cpu_loop(CPUState *env); +extern THREAD CPUArchState *thread_env; +void cpu_loop(CPUArchState *env); char *target_strerror(int err); int get_osversion(void); void fork_start(void); void fork_end(int child); -/* Return true if the proposed guest_base is suitable for the guest. - * The guest code may leave a page mapped and populate it if the - * address is suitable. +/* Creates the initial guest address space in the host memory space using + * the given host start address hint and size. The guest_start parameter + * specifies the start address of the guest space. guest_base will be the + * difference between the host start address computed by this function and + * guest_start. If fixed is specified, then the mapped address space must + * start at host_start. The real start address of the mapped memory space is + * returned or -1 if there was an error. */ -bool guest_validate_base(unsigned long guest_base); +unsigned long init_guest_space(unsigned long host_start, + unsigned long host_size, + unsigned long guest_start, + bool fixed); + +#include "qemu/log.h" -#include "qemu-log.h" +/* syscall.c */ +int host_to_target_waitstatus(int status); /* strace.c */ void print_syscall(int num, @@ -218,15 +230,15 @@ void print_syscall_ret(int num, abi_long arg1); extern int do_strace; /* signal.c */ -void process_pending_signals(CPUState *cpu_env); +void process_pending_signals(CPUArchState *cpu_env); void signal_init(void); -int queue_signal(CPUState *env, int sig, target_siginfo_t *info); +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info); void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); int target_to_host_signal(int sig); int host_to_target_signal(int sig); -long do_sigreturn(CPUState *env); -long do_rt_sigreturn(CPUState *env); +long do_sigreturn(CPUArchState *env); +long do_rt_sigreturn(CPUArchState *env); abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); #ifdef TARGET_I386 @@ -250,6 +262,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, abi_ulong new_addr); int target_msync(abi_ulong start, abi_ulong len, int flags); extern unsigned long last_brk; +extern abi_ulong mmap_next_start; void mmap_lock(void); void mmap_unlock(void); abi_ulong mmap_find_vma(abi_ulong, abi_ulong); @@ -274,53 +287,39 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size) (type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0; } -/* NOTE __get_user and __put_user use host pointers and don't check access. */ -/* These are usually used to access struct data members once the - * struct has been locked - usually with lock_user_struct(). - */ -#define __put_user(x, hptr)\ -({\ - switch(sizeof(*hptr)) {\ - case 1:\ - *(uint8_t *)(hptr) = (uint8_t)(typeof(*hptr))(x);\ - break;\ - case 2:\ - *(uint16_t *)(hptr) = tswap16((uint16_t)(typeof(*hptr))(x));\ - break;\ - case 4:\ - *(uint32_t *)(hptr) = tswap32((uint32_t)(typeof(*hptr))(x));\ - break;\ - case 8:\ - *(uint64_t *)(hptr) = tswap64((typeof(*hptr))(x));\ - break;\ - default:\ - abort();\ - }\ - 0;\ -}) - -#define __get_user(x, hptr) \ -({\ - switch(sizeof(*hptr)) {\ - case 1:\ - x = (typeof(*hptr))*(uint8_t *)(hptr);\ - break;\ - case 2:\ - x = (typeof(*hptr))tswap16(*(uint16_t *)(hptr));\ - break;\ - case 4:\ - x = (typeof(*hptr))tswap32(*(uint32_t *)(hptr));\ - break;\ - case 8:\ - x = (typeof(*hptr))tswap64(*(uint64_t *)(hptr));\ - break;\ - default:\ - /* avoid warning */\ - x = 0;\ - abort();\ - }\ - 0;\ -}) +/* NOTE __get_user and __put_user use host pointers and don't check access. + These are usually used to access struct data members once the struct has + been locked - usually with lock_user_struct. */ + +/* Tricky points: + - Use __builtin_choose_expr to avoid type promotion from ?:, + - Invalid sizes result in a compile time error stemming from + the fact that abort has no parameters. + - It's easier to use the endian-specific unaligned load/store + functions than host-endian unaligned load/store plus tswapN. */ + +#define __put_user_e(x, hptr, e) \ + (__builtin_choose_expr(sizeof(*(hptr)) == 1, stb_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 2, stw_##e##_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 4, stl_##e##_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 8, stq_##e##_p, abort)))) \ + ((hptr), (x)), 0) + +#define __get_user_e(x, hptr, e) \ + ((x) = \ + __builtin_choose_expr(sizeof(*(hptr)) == 1, ldub_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 2, lduw_##e##_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 4, ldl_##e##_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 8, ldq_##e##_p, abort)))) \ + (hptr), 0) + +#ifdef TARGET_WORDS_BIGENDIAN +# define __put_user(x, hptr) __put_user_e(x, hptr, be) +# define __get_user(x, hptr) __get_user_e(x, hptr, be) +#else +# define __put_user(x, hptr) __put_user_e(x, hptr, le) +# define __get_user(x, hptr) __get_user_e(x, hptr, le) +#endif /* put_user()/get_user() take a guest address and check access */ /* These are usually used to access an atomic data type, such as an int,