From 34865134335df669132f9c2ed12d1e0be361f30f Mon Sep 17 00:00:00 2001 From: bellard Date: Sun, 5 Oct 2003 14:28:56 +0000 Subject: [PATCH] log activation from gdb - gdb single step support for x86 - stop timer when cpu is being debugged git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@402 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-all.h | 4 ++ exec.c | 23 ++++++++++ gdbstub.c | 17 ++++++++ target-i386/translate.c | 8 +++- vl.c | 97 +++++++++++++++++++++++++++++++---------- 5 files changed, 125 insertions(+), 24 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index 43c03c96cf..00b9399e55 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -377,6 +377,10 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc); int cpu_breakpoint_remove(CPUState *env, uint32_t pc); void cpu_single_step(CPUState *env, int enabled); +#define CPU_LOG_ALL 1 +void cpu_set_log(int log_flags); +void cpu_set_log_filename(const char *filename); + /* memory API */ typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value); diff --git a/exec.c b/exec.c index 46cccb5deb..f4f6a9bc41 100644 --- a/exec.c +++ b/exec.c @@ -78,6 +78,11 @@ CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; static int io_mem_nb; +/* log support */ +char *logfilename = "/tmp/qemu.log"; +FILE *logfile; +int loglevel; + static void page_init(void) { /* NOTE: we can always suppose that host_page_size >= @@ -676,6 +681,24 @@ void cpu_single_step(CPUState *env, int enabled) #endif } +/* enable or disable low levels log */ +void cpu_set_log(int log_flags) +{ + loglevel = log_flags; + if (loglevel && !logfile) { + logfile = fopen(logfilename, "w"); + if (!logfile) { + perror(logfilename); + _exit(1); + } + setvbuf(logfile, NULL, _IOLBF, 0); + } +} + +void cpu_set_log_filename(const char *filename) +{ + logfilename = strdup(filename); +} /* mask must never be zero */ void cpu_interrupt(CPUState *env, int mask) diff --git a/gdbstub.c b/gdbstub.c index d73a7efe36..15b3940ed6 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -437,7 +437,24 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port) goto breakpoint_error; } break; + case 'Q': + if (!strncmp(p, "Tinit", 5)) { + /* init traces */ + put_packet("OK"); + } else if (!strncmp(p, "TStart", 6)) { + /* start log (gdb 'tstart' command) */ + cpu_set_log(CPU_LOG_ALL); + put_packet("OK"); + } else if (!strncmp(p, "TStop", 5)) { + /* stop log (gdb 'tstop' command) */ + cpu_set_log(0); + put_packet("OK"); + } else { + goto unknown_command; + } + break; default: + unknown_command: /* put empty packet */ buf[0] = '\0'; put_packet(buf); diff --git a/target-i386/translate.c b/target-i386/translate.c index 4d89ccbba9..43d3bbcbb8 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -60,6 +60,7 @@ typedef struct DisasContext { int cpl; int iopl; int tf; /* TF cpu flag */ + int singlestep_enabled; /* "hardware" single step enabled */ int jmp_opt; /* use direct block chaining for direct jumps */ int mem_index; /* select memory access functions */ struct TranslationBlock *tb; @@ -1712,7 +1713,9 @@ static void gen_eob(DisasContext *s) { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - if (s->tf) { + if (s->singlestep_enabled) { + gen_op_debug(); + } else if (s->tf) { gen_op_raise_exception(EXCP01_SSTP); } else { gen_op_movl_T0_0(); @@ -4368,6 +4371,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, dc->cpl = (flags >> HF_CPL_SHIFT) & 3; dc->iopl = (flags >> IOPL_SHIFT) & 3; dc->tf = (flags >> TF_SHIFT) & 1; + dc->singlestep_enabled = env->singlestep_enabled; dc->cc_op = CC_OP_DYNAMIC; dc->cs_base = cs_base; dc->tb = tb; @@ -4425,7 +4429,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, break; /* if single step mode, we generate only one instruction and generate an exception */ - if (dc->tf) { + if (dc->tf || dc->singlestep_enabled) { gen_op_jmp_im(pc_ptr - dc->cs_base); gen_eob(dc); break; diff --git a/vl.c b/vl.c index 2978694d63..f027bebb9e 100644 --- a/vl.c +++ b/vl.c @@ -50,7 +50,6 @@ #include "vl.h" -#define DEBUG_LOGFILE "/tmp/vl.log" #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" #define BIOS_FILENAME "bios.bin" #define VGABIOS_FILENAME "vgabios.bin" @@ -209,8 +208,6 @@ static const char *bios_dir = CONFIG_QEMU_SHAREDIR; char phys_ram_file[1024]; CPUX86State *global_env; CPUX86State *cpu_single_env; -FILE *logfile = NULL; -int loglevel; IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; BlockDriverState *bs_table[MAX_DISKS]; @@ -832,20 +829,76 @@ int speaker_data_on; int dummy_refresh_clock; int pit_min_timer_count = 0; -int64_t get_clock(void) + +#if defined(__powerpc__) + +static inline uint32_t get_tbl(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000LL + tv.tv_usec; + uint32_t tbl; + asm volatile("mftb %0" : "=r" (tbl)); + return tbl; } -int64_t cpu_get_ticks(void) +static inline uint32_t get_tbu(void) +{ + uint32_t tbl; + asm volatile("mftbu %0" : "=r" (tbl)); + return tbl; +} + +int64_t cpu_get_real_ticks(void) +{ + uint32_t l, h, h1; + /* NOTE: we test if wrapping has occurred */ + do { + h = get_tbu(); + l = get_tbl(); + h1 = get_tbu(); + } while (h != h1); + return ((int64_t)h << 32) | l; +} + +#elif defined(__i386__) + +int64_t cpu_get_real_ticks(void) { int64_t val; asm("rdtsc" : "=A" (val)); return val; } +#else +#error unsupported CPU +#endif + +static int64_t cpu_ticks_offset; +static int64_t cpu_ticks_last; + +int64_t cpu_get_ticks(void) +{ + return cpu_get_real_ticks() + cpu_ticks_offset; +} + +/* enable cpu_get_ticks() */ +void cpu_enable_ticks(void) +{ + cpu_ticks_offset = cpu_ticks_last - cpu_get_real_ticks(); +} + +/* disable cpu_get_ticks() : the clock is stopped. You must not call + cpu_get_ticks() after that. */ +void cpu_disable_ticks(void) +{ + cpu_ticks_last = cpu_get_ticks(); +} + +int64_t get_clock(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000LL + tv.tv_usec; +} + void cpu_calibrate_ticks(void) { int64_t usec, ticks; @@ -3297,12 +3350,17 @@ int main_loop(void *opaque) } serial_ok = 1; + cpu_enable_ticks(); for(;;) { ret = cpu_x86_exec(env); - if (reset_requested) + if (reset_requested) { + ret = EXCP_INTERRUPT; break; - if (ret == EXCP_DEBUG) - return EXCP_DEBUG; + } + if (ret == EXCP_DEBUG) { + ret = EXCP_DEBUG; + break; + } /* if hlt instruction, we wait until the next IRQ */ if (ret == EXCP_HLT) timeout = 10; @@ -3359,8 +3417,10 @@ int main_loop(void *opaque) uint8_t buf[1]; /* stop emulation if requested by gdb */ n = read(gdbstub_fd, buf, 1); - if (n == 1) + if (n == 1) { + ret = EXCP_INTERRUPT; break; + } } } @@ -3377,7 +3437,8 @@ int main_loop(void *opaque) gui_refresh_pending = 0; } } - return EXCP_INTERRUPT; + cpu_disable_ticks(); + return ret; } void help(void) @@ -3535,7 +3596,7 @@ int main(int argc, char **argv) } break; case 'd': - loglevel = 1; + cpu_set_log(CPU_LOG_ALL); break; case 'n': pstrcpy(network_script, sizeof(network_script), optarg); @@ -3563,14 +3624,6 @@ int main(int argc, char **argv) /* init debug */ setvbuf(stdout, NULL, _IOLBF, 0); - if (loglevel) { - logfile = fopen(DEBUG_LOGFILE, "w"); - if (!logfile) { - perror(DEBUG_LOGFILE); - _exit(1); - } - setvbuf(logfile, NULL, _IOLBF, 0); - } /* init network tun interface */ if (net_fd < 0) -- 2.39.2