#ifndef QEMU_H
#define QEMU_H
-
+#include "qemu/osdep.h"
#include "cpu.h"
+#include "qemu/units.h"
#include "exec/cpu_ldst.h"
+#include "exec/exec-all.h"
#undef DEBUG_REMAP
-#ifdef DEBUG_REMAP
-#endif /* DEBUG_REMAP */
#include "exec/user/abitypes.h"
extern char **environ;
-enum BSDType {
- target_freebsd,
- target_netbsd,
- target_openbsd,
-};
-extern enum BSDType bsd_type;
-
+#include "exec/user/thunk.h"
+#include "target_arch.h"
#include "syscall_defs.h"
#include "target_syscall.h"
-#include "target_signal.h"
+#include "target_os_vmparam.h"
+#include "target_os_signal.h"
#include "exec/gdbstub.h"
-#if defined(CONFIG_USE_NPTL)
-#define THREAD __thread
-#else
-#define THREAD
-#endif
-
-/* This struct is used to hold certain information about the image.
- * Basically, it replicates in user space what would be certain
- * task_struct fields in the kernel
+/*
+ * This struct is used to hold certain information about the image. Basically,
+ * it replicates in user space what would be certain task_struct fields in the
+ * kernel
*/
struct image_info {
+ abi_ulong load_bias;
abi_ulong load_addr;
abi_ulong start_code;
abi_ulong end_code;
abi_ulong entry;
abi_ulong code_offset;
abi_ulong data_offset;
- int personality;
-};
-
-#define MAX_SIGQUEUE_SIZE 1024
-
-struct sigqueue {
- struct sigqueue *next;
+ abi_ulong arg_start;
+ abi_ulong arg_end;
+ uint32_t elf_flags;
};
struct emulated_sigtable {
int pending; /* true if signal is pending */
- struct sigqueue *first;
- struct sigqueue info; /* in order to always have memory for the
- first signal, we put it here */
+ target_siginfo_t info;
};
-/* NOTE: we force a big alignment so that the stack stored after is
- aligned too */
+/*
+ * NOTE: we force a big alignment so that the stack stored after is aligned too
+ */
typedef struct TaskState {
pid_t ts_tid; /* tid (or pid) of this task */
struct TaskState *next;
- int used; /* non zero if used */
+ struct bsd_binprm *bprm;
struct image_info *info;
+ struct emulated_sigtable sync_signal;
+ /*
+ * TODO: Since we block all signals while returning to the main CPU
+ * loop, this needn't be an array
+ */
struct emulated_sigtable sigtab[TARGET_NSIG];
- struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
- struct sigqueue *first_free; /* first free siginfo queue entry */
- int signal_pending; /* non zero if a signal may be pending */
-
- uint8_t stack[];
+ /*
+ * Nonzero if process_pending_signals() needs to do something (either
+ * handle a pending signal or unblock signals).
+ * This flag is written from a signal handler so should be accessed via
+ * the qatomic_read() and qatomic_set() functions. (It is not accessed
+ * from multiple threads.)
+ */
+ int signal_pending;
+ /* True if we're leaving a sigsuspend and sigsuspend_mask is valid. */
+ bool in_sigsuspend;
+ /*
+ * This thread's signal mask, as requested by the guest program.
+ * The actual signal mask of this thread may differ:
+ * + we don't let SIGSEGV and SIGBUS be blocked while running guest code
+ * + sometimes we block all signals to avoid races
+ */
+ sigset_t signal_mask;
+ /*
+ * The signal mask imposed by a guest sigsuspend syscall, if we are
+ * currently in the middle of such a syscall
+ */
+ sigset_t sigsuspend_mask;
+
+ /* This thread's sigaltstack, if it has one */
+ struct target_sigaltstack sigaltstack_used;
} __attribute__((aligned(16))) TaskState;
-void init_task_state(TaskState *ts);
+void stop_all_tasks(void);
extern const char *qemu_uname_release;
-extern unsigned long mmap_min_addr;
-/* ??? See if we can avoid exposing so much of the loader internals. */
/*
- * MAX_ARG_PAGES defines the number of pages allocated for arguments
- * and envelope for the new program. 32 should suffice, this gives
- * a maximum env+arg of 128kB w/4KB pages!
+ * TARGET_ARG_MAX defines the number of bytes allocated for arguments
+ * and envelope for the new program. 256k should suffice for a reasonable
+ * maxiumum env+arg in 32-bit environments, bump it up to 512k for !ILP32
+ * platforms.
*/
-#define MAX_ARG_PAGES 32
+#if TARGET_ABI_BITS > 32
+#define TARGET_ARG_MAX (512 * KiB)
+#else
+#define TARGET_ARG_MAX (256 * KiB)
+#endif
+#define MAX_ARG_PAGES (TARGET_ARG_MAX / TARGET_PAGE_SIZE)
/*
* This structure is used to hold the arguments that are
* used when loading binaries.
*/
-struct linux_binprm {
+struct bsd_binprm {
char buf[128];
void *page[MAX_ARG_PAGES];
abi_ulong p;
+ abi_ulong stringp;
int fd;
int e_uid, e_gid;
int argc, envc;
char **argv;
char **envp;
- char * filename; /* Name of binary */
+ char *filename; /* (Given) Name of binary */
+ char *fullpath; /* Full path of binary */
+ int (*core_dump)(int, CPUArchState *);
};
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
- abi_ulong stringp, int push_ptr);
-int loader_exec(const char * filename, char ** argv, char ** envp,
- struct target_pt_regs * regs, struct image_info *infop);
+ abi_ulong stringp);
+int loader_exec(const char *filename, char **argv, char **envp,
+ struct target_pt_regs *regs, struct image_info *infop,
+ struct bsd_binprm *bprm);
-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
- struct image_info * info);
-int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
- struct image_info * info);
+int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
+ struct image_info *info);
+int load_flt_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
+ struct image_info *info);
+int is_target_elf_binary(int fd);
abi_long memcpy_to_target(abi_ulong dest, const void *src,
unsigned long len);
abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6);
void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-extern THREAD CPUState *thread_cpu;
+extern __thread CPUState *thread_cpu;
void cpu_loop(CPUArchState *env);
char *target_strerror(int err);
int get_osversion(void);
abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6);
void print_openbsd_syscall_ret(int num, abi_long ret);
+/**
+ * print_taken_signal:
+ * @target_signum: target signal being taken
+ * @tinfo: target_siginfo_t which will be passed to the guest for the signal
+ *
+ * Print strace output indicating that this signal is being taken by the guest,
+ * in a format similar to:
+ * --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
+ */
+void print_taken_signal(int target_signum, const target_siginfo_t *tinfo);
extern int do_strace;
-/* signal.c */
-void process_pending_signals(CPUArchState *cpu_env);
-void signal_init(void);
-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);
-
/* mmap.c */
int target_mprotect(abi_ulong start, abi_ulong len, int prot);
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
- int flags, int fd, abi_ulong offset);
+ int flags, int fd, off_t offset);
int target_munmap(abi_ulong start, abi_ulong len);
abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_size, unsigned long flags,
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;
+abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
void mmap_fork_start(void);
void mmap_fork_end(int child);
/* main.c */
-extern unsigned long x86_stack_size;
+extern char qemu_proc_pathname[];
+extern unsigned long target_maxtsiz;
+extern unsigned long target_dfldsiz;
+extern unsigned long target_maxdsiz;
+extern unsigned long target_dflssiz;
+extern unsigned long target_maxssiz;
+extern unsigned long target_sgrowsiz;
+
+/* syscall.c */
+abi_long get_errno(abi_long ret);
+bool is_error(abi_long ret);
+
+/* os-sys.c */
+abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2);
/* user access */
return page_check_range((target_ulong)addr, size, type) == 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().
+/*
+ * 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)\
({\
break;\
default:\
abort();\
- }\
+ } \
0;\
})
x = (typeof(*hptr))tswap64(*(uint64_t *)(hptr));\
break;\
default:\
- /* avoid warning */\
x = 0;\
abort();\
- }\
+ } \
0;\
})
-/* 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,
- * that has been passed by address. These internally perform locking
- * and unlocking on the data type.
+/*
+ * 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, that
+ * has been passed by address. These internally perform locking and unlocking
+ * on the data type.
*/
#define put_user(x, gaddr, target_type) \
({ \
abi_ulong __gaddr = (gaddr); \
target_type *__hptr; \
abi_long __ret; \
- if ((__hptr = lock_user(VERIFY_WRITE, __gaddr, sizeof(target_type), 0))) { \
+ __hptr = lock_user(VERIFY_WRITE, __gaddr, sizeof(target_type), 0); \
+ if (__hptr) { \
__ret = __put_user((x), __hptr); \
unlock_user(__hptr, __gaddr, sizeof(target_type)); \
} else \
abi_ulong __gaddr = (gaddr); \
target_type *__hptr; \
abi_long __ret; \
- if ((__hptr = lock_user(VERIFY_READ, __gaddr, sizeof(target_type), 1))) { \
+ __hptr = lock_user(VERIFY_READ, __gaddr, sizeof(target_type), 1); \
+ if (__hptr) { \
__ret = __get_user((x), __hptr); \
unlock_user(__hptr, __gaddr, 0); \
} else { \
- /* avoid warning */ \
(x) = 0; \
__ret = -TARGET_EFAULT; \
} \
#define get_user_u8(x, gaddr) get_user((x), (gaddr), uint8_t)
#define get_user_s8(x, gaddr) get_user((x), (gaddr), int8_t)
-/* copy_from_user() and copy_to_user() are usually used to copy data
+/*
+ * copy_from_user() and copy_to_user() are usually used to copy data
* buffers between the target and host. These internally perform
* locking/unlocking of the memory.
*/
abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len);
abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len);
-/* Functions for accessing guest memory. The tget and tput functions
- read/write single values, byteswapping as necessary. The lock_user function
- gets a pointer to a contiguous area of guest memory, but does not perform
- any byteswapping. lock_user may return either a pointer to the guest
- memory, or a temporary buffer. */
+/*
+ * Functions for accessing guest memory. The tget and tput functions
+ * read/write single values, byteswapping as necessary. The lock_user function
+ * gets a pointer to a contiguous area of guest memory, but does not perform
+ * any byteswapping. lock_user may return either a pointer to the guest
+ * memory, or a temporary buffer.
+ */
-/* Lock an area of guest memory into the host. If copy is true then the
- host area will have the same contents as the guest. */
-static inline void *lock_user(int type, abi_ulong guest_addr, long len, int copy)
+/*
+ * Lock an area of guest memory into the host. If copy is true then the
+ * host area will have the same contents as the guest.
+ */
+static inline void *lock_user(int type, abi_ulong guest_addr, long len,
+ int copy)
{
- if (!access_ok(type, guest_addr, len))
+ if (!access_ok(type, guest_addr, len)) {
return NULL;
+ }
#ifdef DEBUG_REMAP
{
void *addr;
addr = g_malloc(len);
- if (copy)
+ if (copy) {
memcpy(addr, g2h_untagged(guest_addr), len);
- else
+ } else {
memset(addr, 0, len);
+ }
return addr;
}
#else
#endif
}
-/* Unlock an area of guest memory. The first LEN bytes must be
- flushed back to guest memory. host_ptr = NULL is explicitly
- allowed and does nothing. */
+/*
+ * Unlock an area of guest memory. The first LEN bytes must be flushed back to
+ * guest memory. host_ptr = NULL is explicitly allowed and does nothing.
+ */
static inline void unlock_user(void *host_ptr, abi_ulong guest_addr,
long len)
{
#ifdef DEBUG_REMAP
- if (!host_ptr)
+ if (!host_ptr) {
return;
- if (host_ptr == g2h_untagged(guest_addr))
+ }
+ if (host_ptr == g2h_untagged(guest_addr)) {
return;
- if (len > 0)
+ }
+ if (len > 0) {
memcpy(g2h_untagged(guest_addr), host_ptr, len);
+ }
g_free(host_ptr);
#endif
}
-/* Return the length of a string in target memory or -TARGET_EFAULT if
- access error. */
+/*
+ * Return the length of a string in target memory or -TARGET_EFAULT if access
+ * error.
+ */
abi_long target_strlen(abi_ulong gaddr);
/* Like lock_user but for null terminated strings. */
{
abi_long len;
len = target_strlen(guest_addr);
- if (len < 0)
+ if (len < 0) {
return NULL;
+ }
return lock_user(VERIFY_READ, guest_addr, (long)(len + 1), 1);
}
#define unlock_user_struct(host_ptr, guest_addr, copy) \
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
-#if defined(CONFIG_USE_NPTL)
#include <pthread.h>
-#endif
+
+#include "user/safe-syscall.h"
#endif /* QEMU_H */