#include "qemu/envlist.h"
#include "elf.h"
-#define DEBUG_LOGFILE "/tmp/qemu.log"
-
char *exec_path;
int singlestep;
* This way we will never overlap with our own libraries or binaries or stack
* or anything else that QEMU maps.
*/
+# ifdef TARGET_MIPS
+/* MIPS only supports 31 bits of virtual address space for user space */
+unsigned long reserved_va = 0x77000000;
+# else
unsigned long reserved_va = 0xf7000000;
+# endif
#else
unsigned long reserved_va;
#endif
/* Make sure everything is in a consistent state for calling fork(). */
void fork_start(void)
{
- pthread_mutex_lock(&tb_lock);
+ pthread_mutex_lock(&tcg_ctx.tb_ctx.tb_lock);
pthread_mutex_lock(&exclusive_lock);
mmap_fork_start();
}
pthread_mutex_init(&cpu_list_mutex, NULL);
pthread_cond_init(&exclusive_cond, NULL);
pthread_cond_init(&exclusive_resume, NULL);
- pthread_mutex_init(&tb_lock, NULL);
+ pthread_mutex_init(&tcg_ctx.tb_ctx.tb_lock, NULL);
gdbserver_fork(thread_env);
} else {
pthread_mutex_unlock(&exclusive_lock);
- pthread_mutex_unlock(&tb_lock);
+ pthread_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock);
}
}
static inline void start_exclusive(void)
{
CPUArchState *other;
+ CPUState *other_cpu;
+
pthread_mutex_lock(&exclusive_lock);
exclusive_idle();
pending_cpus = 1;
/* Make all other cpus stop executing. */
for (other = first_cpu; other; other = other->next_cpu) {
- if (other->running) {
+ other_cpu = ENV_GET_CPU(other);
+ if (other_cpu->running) {
pending_cpus++;
cpu_exit(other);
}
}
/* Wait for exclusive ops to finish, and begin cpu execution. */
-static inline void cpu_exec_start(CPUArchState *env)
+static inline void cpu_exec_start(CPUState *cpu)
{
pthread_mutex_lock(&exclusive_lock);
exclusive_idle();
- env->running = 1;
+ cpu->running = true;
pthread_mutex_unlock(&exclusive_lock);
}
/* Mark cpu as not executing, and release pending exclusive ops. */
-static inline void cpu_exec_end(CPUArchState *env)
+static inline void cpu_exec_end(CPUState *cpu)
{
pthread_mutex_lock(&exclusive_lock);
- env->running = 0;
+ cpu->running = false;
if (pending_cpus > 1) {
pending_cpus--;
if (pending_cpus == 1) {
}
#else /* if !CONFIG_USE_NPTL */
/* These are no-ops because we are not threadsafe. */
-static inline void cpu_exec_start(CPUArchState *env)
+static inline void cpu_exec_start(CPUState *cpu)
{
}
-static inline void cpu_exec_end(CPUArchState *env)
+static inline void cpu_exec_end(CPUState *cpu)
{
}
void cpu_loop(CPUARMState *env)
{
+ CPUState *cs = CPU(arm_env_get_cpu(env));
int trapnr;
unsigned int n, insn;
target_siginfo_t info;
uint32_t addr;
for(;;) {
- cpu_exec_start(env);
+ cpu_exec_start(cs);
trapnr = cpu_arm_exec(env);
- cpu_exec_end(env);
+ cpu_exec_end(cs);
switch(trapnr) {
case EXCP_UDEF:
{
void cpu_loop(CPUUniCore32State *env)
{
+ CPUState *cs = CPU(uc32_env_get_cpu(env));
int trapnr;
unsigned int n, insn;
target_siginfo_t info;
for (;;) {
- cpu_exec_start(env);
+ cpu_exec_start(cs);
trapnr = uc32_cpu_exec(env);
- cpu_exec_end(env);
+ cpu_exec_end(cs);
switch (trapnr) {
case UC32_EXCP_PRIV:
{
void cpu_loop(CPUPPCState *env)
{
+ CPUState *cs = CPU(ppc_env_get_cpu(env));
target_siginfo_t info;
int trapnr;
target_ulong ret;
for(;;) {
- cpu_exec_start(env);
+ cpu_exec_start(cs);
trapnr = cpu_ppc_exec(env);
- cpu_exec_end(env);
+ cpu_exec_end(cs);
switch(trapnr) {
case POWERPC_EXCP_NONE:
/* Just go on */
void cpu_loop(CPUMIPSState *env)
{
+ CPUState *cs = CPU(mips_env_get_cpu(env));
target_siginfo_t info;
int trapnr, ret;
unsigned int syscall_num;
for(;;) {
- cpu_exec_start(env);
+ cpu_exec_start(cs);
trapnr = cpu_mips_exec(env);
- cpu_exec_end(env);
+ cpu_exec_end(cs);
switch(trapnr) {
case EXCP_SYSCALL:
syscall_num = env->active_tc.gpr[2] - 4000;
#ifdef TARGET_S390X
void cpu_loop(CPUS390XState *env)
{
- int trapnr;
+ int trapnr, n, sig;
target_siginfo_t info;
+ target_ulong addr;
while (1) {
- trapnr = cpu_s390x_exec (env);
-
+ trapnr = cpu_s390x_exec(env);
switch (trapnr) {
case EXCP_INTERRUPT:
- /* just indicate that signals should be handled asap */
+ /* Just indicate that signals should be handled asap. */
break;
- case EXCP_DEBUG:
- {
- int sig;
- sig = gdb_handlesig (env, TARGET_SIGTRAP);
- if (sig) {
- info.si_signo = sig;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, &info);
- }
+ case EXCP_SVC:
+ n = env->int_svc_code;
+ if (!n) {
+ /* syscalls > 255 */
+ n = env->regs[1];
}
+ env->psw.addr += env->int_svc_ilen;
+ env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
+ env->regs[4], env->regs[5],
+ env->regs[6], env->regs[7], 0, 0);
break;
- case EXCP_SVC:
- {
- int n = env->int_svc_code;
- if (!n) {
- /* syscalls > 255 */
- n = env->regs[1];
- }
- env->psw.addr += env->int_svc_ilc;
- env->regs[2] = do_syscall(env, n,
- env->regs[2],
- env->regs[3],
- env->regs[4],
- env->regs[5],
- env->regs[6],
- env->regs[7],
- 0, 0);
+
+ case EXCP_DEBUG:
+ sig = gdb_handlesig(env, TARGET_SIGTRAP);
+ if (sig) {
+ n = TARGET_TRAP_BRKPT;
+ goto do_signal_pc;
}
break;
- case EXCP_ADDR:
- {
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
+ case EXCP_PGM:
+ n = env->int_pgm_code;
+ switch (n) {
+ case PGM_OPERATION:
+ case PGM_PRIVILEGED:
+ sig = SIGILL;
+ n = TARGET_ILL_ILLOPC;
+ goto do_signal_pc;
+ case PGM_PROTECTION:
+ case PGM_ADDRESSING:
+ sig = SIGSEGV;
/* XXX: check env->error_code */
- info.si_code = TARGET_SEGV_MAPERR;
- info._sifields._sigfault._addr = env->__excp_addr;
- queue_signal(env, info.si_signo, &info);
+ n = TARGET_SEGV_MAPERR;
+ addr = env->__excp_addr;
+ goto do_signal;
+ case PGM_EXECUTE:
+ case PGM_SPECIFICATION:
+ case PGM_SPECIAL_OP:
+ case PGM_OPERAND:
+ do_sigill_opn:
+ sig = SIGILL;
+ n = TARGET_ILL_ILLOPN;
+ goto do_signal_pc;
+
+ case PGM_FIXPT_OVERFLOW:
+ sig = SIGFPE;
+ n = TARGET_FPE_INTOVF;
+ goto do_signal_pc;
+ case PGM_FIXPT_DIVIDE:
+ sig = SIGFPE;
+ n = TARGET_FPE_INTDIV;
+ goto do_signal_pc;
+
+ case PGM_DATA:
+ n = (env->fpc >> 8) & 0xff;
+ if (n == 0xff) {
+ /* compare-and-trap */
+ goto do_sigill_opn;
+ } else {
+ /* An IEEE exception, simulated or otherwise. */
+ if (n & 0x80) {
+ n = TARGET_FPE_FLTINV;
+ } else if (n & 0x40) {
+ n = TARGET_FPE_FLTDIV;
+ } else if (n & 0x20) {
+ n = TARGET_FPE_FLTOVF;
+ } else if (n & 0x10) {
+ n = TARGET_FPE_FLTUND;
+ } else if (n & 0x08) {
+ n = TARGET_FPE_FLTRES;
+ } else {
+ /* ??? Quantum exception; BFP, DFP error. */
+ goto do_sigill_opn;
+ }
+ sig = SIGFPE;
+ goto do_signal_pc;
+ }
+
+ default:
+ fprintf(stderr, "Unhandled program exception: %#x\n", n);
+ cpu_dump_state(env, stderr, fprintf, 0);
+ exit(1);
}
break;
- case EXCP_SPEC:
- {
- fprintf(stderr,"specification exception insn 0x%08x%04x\n", ldl(env->psw.addr), lduw(env->psw.addr + 4));
- info.si_signo = SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_ILLOPC;
- info._sifields._sigfault._addr = env->__excp_addr;
- queue_signal(env, info.si_signo, &info);
- }
+
+ do_signal_pc:
+ addr = env->psw.addr;
+ do_signal:
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = n;
+ info._sifields._sigfault._addr = addr;
+ queue_signal(env, info.si_signo, &info);
break;
+
default:
- printf ("Unhandled trap: 0x%x\n", trapnr);
+ fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
- exit (1);
+ exit(1);
}
process_pending_signals (env);
}
static void handle_arg_log(const char *arg)
{
int mask;
- const CPULogItem *item;
- mask = cpu_str_to_log_mask(arg);
+ mask = qemu_str_to_log_mask(arg);
if (!mask) {
- printf("Log items (comma separated):\n");
- for (item = cpu_log_items; item->mask != 0; item++) {
- printf("%-10s %s\n", item->name, item->help);
- }
+ qemu_print_log_usage(stdout);
exit(1);
}
- cpu_set_log(mask);
+ qemu_set_log(mask);
}
static void handle_arg_log_filename(const char *arg)
{
- cpu_set_log_filename(arg);
+ qemu_set_log_filename(arg);
}
static void handle_arg_set_env(const char *arg)
"size", "reserve 'size' bytes for guest virtual address space"},
#endif
{"d", "QEMU_LOG", true, handle_arg_log,
- "options", "activate log"},
+ "item[,...]", "enable logging of specified items "
+ "(use '-d help' for a list of items)"},
{"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
- "logfile", "override default logfile location"},
+ "logfile", "write logs to 'logfile' (default stderr)"},
{"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
"pagesize", "set the host page size to 'pagesize'"},
{"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep,
printf("\n"
"Defaults:\n"
"QEMU_LD_PREFIX = %s\n"
- "QEMU_STACK_SIZE = %ld byte\n"
- "QEMU_LOG = %s\n",
+ "QEMU_STACK_SIZE = %ld byte\n",
interp_prefix,
- guest_stack_size,
- DEBUG_LOGFILE);
+ guest_stack_size);
printf("\n"
"You can use -E and -U options or the QEMU_SET_ENV and\n"
int main(int argc, char **argv, char **envp)
{
- const char *log_file = DEBUG_LOGFILE;
struct target_pt_regs regs1, *regs = ®s1;
struct image_info info1, *info = &info1;
struct linux_binprm bprm;
cpudef_setup(); /* parse cpu definitions in target config file (TBD) */
#endif
- /* init debug */
- cpu_set_log_filename(log_file);
optind = parse_args(argc, argv);
/* Zero out regs */
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
-#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
+#if defined(TARGET_SPARC) || defined(TARGET_PPC)
cpu_reset(ENV_GET_CPU(env));
#endif