# HG changeset patch # Parent adebc6b144a3a0cb9c22cc939431ace635414d0e diff -r adebc6b144a3 cpu-defs.h --- a/cpu-defs.h Mon Aug 30 13:09:19 2010 -0400 +++ b/cpu-defs.h Tue Aug 31 12:15:14 2010 -0400 @@ -60,6 +60,7 @@ #define EXCP_HLT 0x10001 /* hlt instruction reached */ #define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */ #define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */ +#define EXCP_TRIPLE 0x10004 /* cpu encountered triple fault */ #define TB_JMP_CACHE_BITS 12 #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) diff -r adebc6b144a3 gdbstub.c --- a/gdbstub.c Mon Aug 30 13:09:19 2010 -0400 +++ b/gdbstub.c Tue Aug 31 12:15:14 2010 -0400 @@ -2610,3 +2610,8 @@ return 0; } #endif + +int gdbserver_running(void) +{ + return gdbserver_state != NULL; +} diff -r adebc6b144a3 gdbstub.h --- a/gdbstub.h Mon Aug 30 13:09:19 2010 -0400 +++ b/gdbstub.h Tue Aug 31 12:15:14 2010 -0400 @@ -26,6 +26,7 @@ #else int gdbserver_start(const char *port); #endif +int gdbserver_running(void); /* Get or set a register. Returns the size of the register. */ typedef int (*gdb_reg_cb)(CPUState *env, uint8_t *buf, int reg); void gdb_register_coprocessor(CPUState *env, diff -r adebc6b144a3 target-i386/op_helper.c --- a/target-i386/op_helper.c Mon Aug 30 13:09:19 2010 -0400 +++ b/target-i386/op_helper.c Tue Aug 31 12:15:14 2010 -0400 @@ -1297,8 +1297,18 @@ qemu_log_mask(CPU_LOG_RESET, "Triple fault\n"); +#if 0 qemu_system_reset_request(); return EXCP_HLT; +#else + // QEMU traditionally resets the machine on triple fault + // because programs written for 286 protected mode would exit + // protected mode by intentionally triple faulting the machine + // (after setting the boot vector to point to their code). + // This sucks for debugging programs that were written after + // 1985, so we instead halt the machine for inspection. + return EXCP_TRIPLE; +#endif } #endif diff -r adebc6b144a3 vl.c --- a/vl.c Mon Aug 30 13:09:19 2010 -0400 +++ b/vl.c Tue Aug 31 12:15:14 2010 -0400 @@ -4057,6 +4057,15 @@ else if (env->stop) break; + if (ret == EXCP_TRIPLE) { + cpu_dump_state(env, stderr, fprintf, 0); + fprintf(stderr, "Triple fault. Halting for inspection via QEMU monitor.\n"); + if (gdbserver_running()) + ret = EXCP_DEBUG; + else + vm_stop(0); + } + if (ret == EXCP_DEBUG) { gdb_set_stop_cpu(env); debug_requested = 1;