Commit 34865134335df669132f9c2ed12d1e0be361f30f

Authored by bellard
1 parent 0806e3f6

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
@@ -377,6 +377,10 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc); @@ -377,6 +377,10 @@ int cpu_breakpoint_insert(CPUState *env, uint32_t pc);
377 int cpu_breakpoint_remove(CPUState *env, uint32_t pc); 377 int cpu_breakpoint_remove(CPUState *env, uint32_t pc);
378 void cpu_single_step(CPUState *env, int enabled); 378 void cpu_single_step(CPUState *env, int enabled);
379 379
  380 +#define CPU_LOG_ALL 1
  381 +void cpu_set_log(int log_flags);
  382 +void cpu_set_log_filename(const char *filename);
  383 +
380 /* memory API */ 384 /* memory API */
381 385
382 typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value); 386 typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value);
@@ -78,6 +78,11 @@ CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; @@ -78,6 +78,11 @@ CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
78 CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; 78 CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
79 static int io_mem_nb; 79 static int io_mem_nb;
80 80
  81 +/* log support */
  82 +char *logfilename = "/tmp/qemu.log";
  83 +FILE *logfile;
  84 +int loglevel;
  85 +
81 static void page_init(void) 86 static void page_init(void)
82 { 87 {
83 /* NOTE: we can always suppose that host_page_size >= 88 /* NOTE: we can always suppose that host_page_size >=
@@ -676,6 +681,24 @@ void cpu_single_step(CPUState *env, int enabled) @@ -676,6 +681,24 @@ void cpu_single_step(CPUState *env, int enabled)
676 #endif 681 #endif
677 } 682 }
678 683
  684 +/* enable or disable low levels log */
  685 +void cpu_set_log(int log_flags)
  686 +{
  687 + loglevel = log_flags;
  688 + if (loglevel && !logfile) {
  689 + logfile = fopen(logfilename, "w");
  690 + if (!logfile) {
  691 + perror(logfilename);
  692 + _exit(1);
  693 + }
  694 + setvbuf(logfile, NULL, _IOLBF, 0);
  695 + }
  696 +}
  697 +
  698 +void cpu_set_log_filename(const char *filename)
  699 +{
  700 + logfilename = strdup(filename);
  701 +}
679 702
680 /* mask must never be zero */ 703 /* mask must never be zero */
681 void cpu_interrupt(CPUState *env, int mask) 704 void cpu_interrupt(CPUState *env, int mask)
gdbstub.c
@@ -437,7 +437,24 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port) @@ -437,7 +437,24 @@ int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
437 goto breakpoint_error; 437 goto breakpoint_error;
438 } 438 }
439 break; 439 break;
  440 + case 'Q':
  441 + if (!strncmp(p, "Tinit", 5)) {
  442 + /* init traces */
  443 + put_packet("OK");
  444 + } else if (!strncmp(p, "TStart", 6)) {
  445 + /* start log (gdb 'tstart' command) */
  446 + cpu_set_log(CPU_LOG_ALL);
  447 + put_packet("OK");
  448 + } else if (!strncmp(p, "TStop", 5)) {
  449 + /* stop log (gdb 'tstop' command) */
  450 + cpu_set_log(0);
  451 + put_packet("OK");
  452 + } else {
  453 + goto unknown_command;
  454 + }
  455 + break;
440 default: 456 default:
  457 + unknown_command:
441 /* put empty packet */ 458 /* put empty packet */
442 buf[0] = '\0'; 459 buf[0] = '\0';
443 put_packet(buf); 460 put_packet(buf);
target-i386/translate.c
@@ -60,6 +60,7 @@ typedef struct DisasContext { @@ -60,6 +60,7 @@ typedef struct DisasContext {
60 int cpl; 60 int cpl;
61 int iopl; 61 int iopl;
62 int tf; /* TF cpu flag */ 62 int tf; /* TF cpu flag */
  63 + int singlestep_enabled; /* "hardware" single step enabled */
63 int jmp_opt; /* use direct block chaining for direct jumps */ 64 int jmp_opt; /* use direct block chaining for direct jumps */
64 int mem_index; /* select memory access functions */ 65 int mem_index; /* select memory access functions */
65 struct TranslationBlock *tb; 66 struct TranslationBlock *tb;
@@ -1712,7 +1713,9 @@ static void gen_eob(DisasContext *s) @@ -1712,7 +1713,9 @@ static void gen_eob(DisasContext *s)
1712 { 1713 {
1713 if (s->cc_op != CC_OP_DYNAMIC) 1714 if (s->cc_op != CC_OP_DYNAMIC)
1714 gen_op_set_cc_op(s->cc_op); 1715 gen_op_set_cc_op(s->cc_op);
1715 - if (s->tf) { 1716 + if (s->singlestep_enabled) {
  1717 + gen_op_debug();
  1718 + } else if (s->tf) {
1716 gen_op_raise_exception(EXCP01_SSTP); 1719 gen_op_raise_exception(EXCP01_SSTP);
1717 } else { 1720 } else {
1718 gen_op_movl_T0_0(); 1721 gen_op_movl_T0_0();
@@ -4368,6 +4371,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, @@ -4368,6 +4371,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
4368 dc->cpl = (flags >> HF_CPL_SHIFT) & 3; 4371 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
4369 dc->iopl = (flags >> IOPL_SHIFT) & 3; 4372 dc->iopl = (flags >> IOPL_SHIFT) & 3;
4370 dc->tf = (flags >> TF_SHIFT) & 1; 4373 dc->tf = (flags >> TF_SHIFT) & 1;
  4374 + dc->singlestep_enabled = env->singlestep_enabled;
4371 dc->cc_op = CC_OP_DYNAMIC; 4375 dc->cc_op = CC_OP_DYNAMIC;
4372 dc->cs_base = cs_base; 4376 dc->cs_base = cs_base;
4373 dc->tb = tb; 4377 dc->tb = tb;
@@ -4425,7 +4429,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, @@ -4425,7 +4429,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
4425 break; 4429 break;
4426 /* if single step mode, we generate only one instruction and 4430 /* if single step mode, we generate only one instruction and
4427 generate an exception */ 4431 generate an exception */
4428 - if (dc->tf) { 4432 + if (dc->tf || dc->singlestep_enabled) {
4429 gen_op_jmp_im(pc_ptr - dc->cs_base); 4433 gen_op_jmp_im(pc_ptr - dc->cs_base);
4430 gen_eob(dc); 4434 gen_eob(dc);
4431 break; 4435 break;
@@ -50,7 +50,6 @@ @@ -50,7 +50,6 @@
50 50
51 #include "vl.h" 51 #include "vl.h"
52 52
53 -#define DEBUG_LOGFILE "/tmp/vl.log"  
54 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" 53 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
55 #define BIOS_FILENAME "bios.bin" 54 #define BIOS_FILENAME "bios.bin"
56 #define VGABIOS_FILENAME "vgabios.bin" 55 #define VGABIOS_FILENAME "vgabios.bin"
@@ -209,8 +208,6 @@ static const char *bios_dir = CONFIG_QEMU_SHAREDIR; @@ -209,8 +208,6 @@ static const char *bios_dir = CONFIG_QEMU_SHAREDIR;
209 char phys_ram_file[1024]; 208 char phys_ram_file[1024];
210 CPUX86State *global_env; 209 CPUX86State *global_env;
211 CPUX86State *cpu_single_env; 210 CPUX86State *cpu_single_env;
212 -FILE *logfile = NULL;  
213 -int loglevel;  
214 IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; 211 IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
215 IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; 212 IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
216 BlockDriverState *bs_table[MAX_DISKS]; 213 BlockDriverState *bs_table[MAX_DISKS];
@@ -832,20 +829,76 @@ int speaker_data_on; @@ -832,20 +829,76 @@ int speaker_data_on;
832 int dummy_refresh_clock; 829 int dummy_refresh_clock;
833 int pit_min_timer_count = 0; 830 int pit_min_timer_count = 0;
834 831
835 -int64_t get_clock(void) 832 +
  833 +#if defined(__powerpc__)
  834 +
  835 +static inline uint32_t get_tbl(void)
836 { 836 {
837 - struct timeval tv;  
838 - gettimeofday(&tv, NULL);  
839 - return tv.tv_sec * 1000000LL + tv.tv_usec; 837 + uint32_t tbl;
  838 + asm volatile("mftb %0" : "=r" (tbl));
  839 + return tbl;
840 } 840 }
841 841
842 -int64_t cpu_get_ticks(void) 842 +static inline uint32_t get_tbu(void)
  843 +{
  844 + uint32_t tbl;
  845 + asm volatile("mftbu %0" : "=r" (tbl));
  846 + return tbl;
  847 +}
  848 +
  849 +int64_t cpu_get_real_ticks(void)
  850 +{
  851 + uint32_t l, h, h1;
  852 + /* NOTE: we test if wrapping has occurred */
  853 + do {
  854 + h = get_tbu();
  855 + l = get_tbl();
  856 + h1 = get_tbu();
  857 + } while (h != h1);
  858 + return ((int64_t)h << 32) | l;
  859 +}
  860 +
  861 +#elif defined(__i386__)
  862 +
  863 +int64_t cpu_get_real_ticks(void)
843 { 864 {
844 int64_t val; 865 int64_t val;
845 asm("rdtsc" : "=A" (val)); 866 asm("rdtsc" : "=A" (val));
846 return val; 867 return val;
847 } 868 }
848 869
  870 +#else
  871 +#error unsupported CPU
  872 +#endif
  873 +
  874 +static int64_t cpu_ticks_offset;
  875 +static int64_t cpu_ticks_last;
  876 +
  877 +int64_t cpu_get_ticks(void)
  878 +{
  879 + return cpu_get_real_ticks() + cpu_ticks_offset;
  880 +}
  881 +
  882 +/* enable cpu_get_ticks() */
  883 +void cpu_enable_ticks(void)
  884 +{
  885 + cpu_ticks_offset = cpu_ticks_last - cpu_get_real_ticks();
  886 +}
  887 +
  888 +/* disable cpu_get_ticks() : the clock is stopped. You must not call
  889 + cpu_get_ticks() after that. */
  890 +void cpu_disable_ticks(void)
  891 +{
  892 + cpu_ticks_last = cpu_get_ticks();
  893 +}
  894 +
  895 +int64_t get_clock(void)
  896 +{
  897 + struct timeval tv;
  898 + gettimeofday(&tv, NULL);
  899 + return tv.tv_sec * 1000000LL + tv.tv_usec;
  900 +}
  901 +
849 void cpu_calibrate_ticks(void) 902 void cpu_calibrate_ticks(void)
850 { 903 {
851 int64_t usec, ticks; 904 int64_t usec, ticks;
@@ -3297,12 +3350,17 @@ int main_loop(void *opaque) @@ -3297,12 +3350,17 @@ int main_loop(void *opaque)
3297 } 3350 }
3298 3351
3299 serial_ok = 1; 3352 serial_ok = 1;
  3353 + cpu_enable_ticks();
3300 for(;;) { 3354 for(;;) {
3301 ret = cpu_x86_exec(env); 3355 ret = cpu_x86_exec(env);
3302 - if (reset_requested) 3356 + if (reset_requested) {
  3357 + ret = EXCP_INTERRUPT;
3303 break; 3358 break;
3304 - if (ret == EXCP_DEBUG)  
3305 - return EXCP_DEBUG; 3359 + }
  3360 + if (ret == EXCP_DEBUG) {
  3361 + ret = EXCP_DEBUG;
  3362 + break;
  3363 + }
3306 /* if hlt instruction, we wait until the next IRQ */ 3364 /* if hlt instruction, we wait until the next IRQ */
3307 if (ret == EXCP_HLT) 3365 if (ret == EXCP_HLT)
3308 timeout = 10; 3366 timeout = 10;
@@ -3359,8 +3417,10 @@ int main_loop(void *opaque) @@ -3359,8 +3417,10 @@ int main_loop(void *opaque)
3359 uint8_t buf[1]; 3417 uint8_t buf[1];
3360 /* stop emulation if requested by gdb */ 3418 /* stop emulation if requested by gdb */
3361 n = read(gdbstub_fd, buf, 1); 3419 n = read(gdbstub_fd, buf, 1);
3362 - if (n == 1) 3420 + if (n == 1) {
  3421 + ret = EXCP_INTERRUPT;
3363 break; 3422 break;
  3423 + }
3364 } 3424 }
3365 } 3425 }
3366 3426
@@ -3377,7 +3437,8 @@ int main_loop(void *opaque) @@ -3377,7 +3437,8 @@ int main_loop(void *opaque)
3377 gui_refresh_pending = 0; 3437 gui_refresh_pending = 0;
3378 } 3438 }
3379 } 3439 }
3380 - return EXCP_INTERRUPT; 3440 + cpu_disable_ticks();
  3441 + return ret;
3381 } 3442 }
3382 3443
3383 void help(void) 3444 void help(void)
@@ -3535,7 +3596,7 @@ int main(int argc, char **argv) @@ -3535,7 +3596,7 @@ int main(int argc, char **argv)
3535 } 3596 }
3536 break; 3597 break;
3537 case 'd': 3598 case 'd':
3538 - loglevel = 1; 3599 + cpu_set_log(CPU_LOG_ALL);
3539 break; 3600 break;
3540 case 'n': 3601 case 'n':
3541 pstrcpy(network_script, sizeof(network_script), optarg); 3602 pstrcpy(network_script, sizeof(network_script), optarg);
@@ -3563,14 +3624,6 @@ int main(int argc, char **argv) @@ -3563,14 +3624,6 @@ int main(int argc, char **argv)
3563 3624
3564 /* init debug */ 3625 /* init debug */
3565 setvbuf(stdout, NULL, _IOLBF, 0); 3626 setvbuf(stdout, NULL, _IOLBF, 0);
3566 - if (loglevel) {  
3567 - logfile = fopen(DEBUG_LOGFILE, "w");  
3568 - if (!logfile) {  
3569 - perror(DEBUG_LOGFILE);  
3570 - _exit(1);  
3571 - }  
3572 - setvbuf(logfile, NULL, _IOLBF, 0);  
3573 - }  
3574 3627
3575 /* init network tun interface */ 3628 /* init network tun interface */
3576 if (net_fd < 0) 3629 if (net_fd < 0)