diff options
-rw-r--r-- | bswap.h | 8 | ||||
-rw-r--r-- | cpu-all.h | 96 | ||||
-rw-r--r-- | cpu-defs.h | 8 | ||||
-rw-r--r-- | cpu-exec.c | 6 | ||||
-rw-r--r-- | dyngen-exec.h | 10 | ||||
-rw-r--r-- | exec.c | 55 | ||||
-rw-r--r-- | gdbstub.c | 22 | ||||
-rw-r--r-- | monitor.c | 37 | ||||
-rw-r--r-- | thunk.h | 77 | ||||
-rw-r--r-- | translate-all.c | 4 | ||||
-rw-r--r-- | vl.c | 20 |
11 files changed, 211 insertions, 132 deletions
@@ -43,14 +43,6 @@ #endif /* !HAVE_BYTESWAP_H */ -#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) -#define HOST_LONG_BITS 64 -#else -#define HOST_LONG_BITS 32 -#endif - -#define HOST_LONG_SIZE (HOST_LONG_BITS / 8) - static inline uint16_t bswap16(uint16_t x) { return bswap_16(x); @@ -37,6 +37,83 @@ * TARGET_WORDS_BIGENDIAN : same for target cpu */ +#include "bswap.h" + +#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) +#define BSWAP_NEEDED +#endif + +#ifdef BSWAP_NEEDED + +static inline uint16_t tswap16(uint16_t s) +{ + return bswap16(s); +} + +static inline uint32_t tswap32(uint32_t s) +{ + return bswap32(s); +} + +static inline uint64_t tswap64(uint64_t s) +{ + return bswap64(s); +} + +static inline void tswap16s(uint16_t *s) +{ + *s = bswap16(*s); +} + +static inline void tswap32s(uint32_t *s) +{ + *s = bswap32(*s); +} + +static inline void tswap64s(uint64_t *s) +{ + *s = bswap64(*s); +} + +#else + +static inline uint16_t tswap16(uint16_t s) +{ + return s; +} + +static inline uint32_t tswap32(uint32_t s) +{ + return s; +} + +static inline uint64_t tswap64(uint64_t s) +{ + return s; +} + +static inline void tswap16s(uint16_t *s) +{ +} + +static inline void tswap32s(uint32_t *s) +{ +} + +static inline void tswap64s(uint64_t *s) +{ +} + +#endif + +#if TARGET_LONG_SIZE == 4 +#define tswapl(s) tswap32(s) +#define tswapls(s) tswap32s((uint32_t *)(s)) +#else +#define tswapl(s) tswap64(s) +#define tswapls(s) tswap64s((uint64_t *)(s)) +#endif + /* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */ typedef union { double d; @@ -554,9 +631,26 @@ void cpu_single_step(CPUState *env, int enabled); if no page found. */ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr); -#define CPU_LOG_ALL 1 +#define CPU_LOG_TB_OUT_ASM (1 << 0) +#define CPU_LOG_TB_IN_ASM (1 << 1) +#define CPU_LOG_TB_OP (1 << 2) +#define CPU_LOG_TB_OP_OPT (1 << 3) +#define CPU_LOG_INT (1 << 4) +#define CPU_LOG_EXEC (1 << 5) +#define CPU_LOG_PCALL (1 << 6) + +/* define log items */ +typedef struct CPULogItem { + int mask; + const char *name; + const char *help; +} CPULogItem; + +extern CPULogItem cpu_log_items[]; + void cpu_set_log(int log_flags); void cpu_set_log_filename(const char *filename); +int cpu_str_to_log_mask(const char *str); /* IO ports API */ @@ -41,6 +41,14 @@ typedef uint64_t target_ulong; #error TARGET_LONG_SIZE undefined #endif +#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) +#define HOST_LONG_BITS 64 +#else +#define HOST_LONG_BITS 32 +#endif + +#define HOST_LONG_SIZE (HOST_LONG_BITS / 8) + #define EXCP_INTERRUPT 256 /* async interruption */ #define EXCP_HLT 257 /* hlt instruction reached */ #define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */ @@ -191,7 +191,7 @@ int cpu_exec(CPUState *env1) !(env->hflags & HF_INHIBIT_IRQ_MASK)) { int intno; intno = cpu_x86_get_pic_interrupt(env); - if (loglevel) { + if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); } do_interrupt(intno, 0, 0, 0, 1); @@ -229,7 +229,7 @@ int cpu_exec(CPUState *env1) } } #ifdef DEBUG_EXEC - if (loglevel) { + if (loglevel & CPU_LOG_EXEC) { #if defined(TARGET_I386) /* restore flags in standard format */ env->regs[R_EAX] = EAX; @@ -362,7 +362,7 @@ int cpu_exec(CPUState *env1) spin_unlock(&tb_lock); } #ifdef DEBUG_EXEC - if (loglevel) { + if (loglevel & CPU_LOG_EXEC) { fprintf(logfile, "Trace 0x%08lx [0x%08lx] %s\n", (long)tb->tc_ptr, (long)tb->pc, lookup_symbol((void *)tb->pc)); diff --git a/dyngen-exec.h b/dyngen-exec.h index 5e9bab6..004ca71 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -45,16 +45,6 @@ typedef signed long long int64_t; #define UINT32_MAX (4294967295U) #define UINT64_MAX ((uint64_t)(18446744073709551615)) -#define bswap32(x) \ -({ \ - uint32_t __x = (x); \ - ((uint32_t)( \ - (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ - (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ - (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ - (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ -}) - typedef struct FILE FILE; extern int fprintf(FILE *, const char *, ...); extern int printf(const char *, ...); @@ -1005,6 +1005,61 @@ void cpu_interrupt(CPUState *env, int mask) } } +CPULogItem cpu_log_items[] = { + { CPU_LOG_TB_OUT_ASM, "out_asm", + "show generated host assembly code for each compiled TB" }, + { CPU_LOG_TB_IN_ASM, "in_asm", + "show target assembly code for each compiled TB" }, + { CPU_LOG_TB_OP, "op", + "show micro ops for each compiled TB (only usable if 'in_asm' used)" }, +#ifdef TARGET_I386 + { CPU_LOG_TB_OP_OPT, "op_opt", + "show micro ops after optimization for each compiled TB" }, +#endif + { CPU_LOG_INT, "int", + "show interrupts/exceptions in short format" }, + { CPU_LOG_EXEC, "exec", + "show trace before each executed TB (lots of logs)" }, +#ifdef TARGET_I386 + { CPU_LOG_PCALL, "pcall", + "show protected mode far calls/returns/exceptions" }, +#endif + { 0, NULL, NULL }, +}; + +static int cmp1(const char *s1, int n, const char *s2) +{ + if (strlen(s2) != n) + return 0; + return memcmp(s1, s2, n) == 0; +} + +/* takes a comma separated list of log masks. Return 0 if error. */ +int cpu_str_to_log_mask(const char *str) +{ + CPULogItem *item; + int mask; + const char *p, *p1; + + p = str; + mask = 0; + for(;;) { + p1 = strchr(p, ','); + if (!p1) + p1 = p + strlen(p); + for(item = cpu_log_items; item->mask != 0; item++) { + if (cmp1(p, p1 - p, item->name)) + goto found; + } + return 0; + found: + mask |= item->mask; + if (*p1 != ',') + break; + p = p1 + 1; + } + return mask; +} void cpu_abort(CPUState *env, const char *fmt, ...) { @@ -27,9 +27,7 @@ #include <netinet/tcp.h> #include <signal.h> -#include "config.h" #include "cpu.h" -#include "thunk.h" #include "exec-all.h" //#define DEBUG_GDB @@ -525,26 +523,8 @@ 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) */ - env = cpu_gdbstub_get_env(opaque); - tb_flush(env); - 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: + // unknown_command: /* put empty packet */ buf[0] = '\0'; put_packet(buf); @@ -118,6 +118,14 @@ static void help_cmd(const char *name) help_cmd1(info_cmds, "info ", NULL); } else { help_cmd1(term_cmds, "", name); + if (name && !strcmp(name, "log")) { + CPULogItem *item; + term_printf("Log items (comma separated):\n"); + term_printf("%-10s %s\n", "none", "remove all logs"); + for(item = cpu_log_items; item->mask != 0; item++) { + term_printf("%-10s %s\n", item->name, item->help); + } + } } } @@ -254,6 +262,25 @@ static void do_screen_dump(int argc, const char **argv) vga_screen_dump(argv[1]); } +static void do_log(int argc, const char **argv) +{ + int mask; + + if (argc != 2) + goto help; + if (!strcmp(argv[1], "none")) { + mask = 0; + } else { + mask = cpu_str_to_log_mask(argv[1]); + if (!mask) { + help: + help_cmd(argv[0]); + return; + } + } + cpu_set_log(mask); +} + static term_cmd_t term_cmds[] = { { "help|?", do_help, "[cmd]", "show the help" }, @@ -269,7 +296,9 @@ static term_cmd_t term_cmds[] = { "device filename", "change a removable media" }, { "screendump", do_screen_dump, "filename", "save screen into PPM image 'filename'" }, - { NULL, NULL, }, + { "log", do_log, + "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" }, + { NULL, NULL, }, }; static term_cmd_t info_cmds[] = { @@ -488,7 +517,6 @@ void term_print_help(void) term_printf("\n" "C-a h print this help\n" "C-a x exit emulatior\n" - "C-a d switch on/off debug log\n" "C-a s save disk data back to file (if -snapshot)\n" "C-a b send break (magic sysrq)\n" "C-a c switch between console and monitor\n" @@ -533,9 +561,6 @@ static void term_received_byte(int ch) term_command = 0; } break; - case 'd': - cpu_set_log(CPU_LOG_ALL); - break; case TERM_ESCAPE: goto send_char; } @@ -558,7 +583,7 @@ static int term_can_read(void *opaque) if (serial_console) { return serial_can_receive(serial_console); } else { - return 1; + return 128; } } @@ -23,83 +23,6 @@ #include <inttypes.h> #include "cpu.h" -#include "bswap.h" - -#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) -#define BSWAP_NEEDED -#endif - -#ifdef BSWAP_NEEDED - -static inline uint16_t tswap16(uint16_t s) -{ - return bswap16(s); -} - -static inline uint32_t tswap32(uint32_t s) -{ - return bswap32(s); -} - -static inline uint64_t tswap64(uint64_t s) -{ - return bswap64(s); -} - -static inline void tswap16s(uint16_t *s) -{ - *s = bswap16(*s); -} - -static inline void tswap32s(uint32_t *s) -{ - *s = bswap32(*s); -} - -static inline void tswap64s(uint64_t *s) -{ - *s = bswap64(*s); -} - -#else - -static inline uint16_t tswap16(uint16_t s) -{ - return s; -} - -static inline uint32_t tswap32(uint32_t s) -{ - return s; -} - -static inline uint64_t tswap64(uint64_t s) -{ - return s; -} - -static inline void tswap16s(uint16_t *s) -{ -} - -static inline void tswap32s(uint32_t *s) -{ -} - -static inline void tswap64s(uint64_t *s) -{ -} - -#endif - -#if TARGET_LONG_SIZE == 4 -#define tswapl(s) tswap32(s) -#define tswapls(s) tswap32s((uint32_t *)(s)) -#else -#define tswapl(s) tswap64(s) -#define tswapls(s) tswap64s((uint64_t *)(s)) -#endif - /* types enums definitions */ typedef enum argtype { diff --git a/translate-all.c b/translate-all.c index dd31402..f10fb62 100644 --- a/translate-all.c +++ b/translate-all.c @@ -129,7 +129,7 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, } *gen_code_size_ptr = gen_code_size; #ifdef DEBUG_DISAS - if (loglevel) { + if (loglevel & CPU_LOG_TB_OUT_ASM) { fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); disas(logfile, tb->tc_ptr, *gen_code_size_ptr, 1, 0); fprintf(logfile, "\n"); @@ -186,7 +186,7 @@ int cpu_restore_state(TranslationBlock *tb, { int cc_op; #ifdef DEBUG_DISAS - if (loglevel) { + if (loglevel & CPU_LOG_TB_OP) { int i; fprintf(logfile, "RESTORE:\n"); for(i=0;i<=j; i++) { @@ -47,7 +47,6 @@ #include <linux/if_tun.h> #include "disas.h" -#include "thunk.h" #include "vl.h" @@ -801,7 +800,7 @@ void help(void) "Debug/Expert options:\n" "-s wait gdb connection to port %d\n" "-p port change gdb connection port\n" - "-d output log to %s\n" + "-d item1,... output log to %s (use -d ? for a list of log items)\n" "-hdachs c,h,s force hard disk 0 geometry (usually qemu can guess it)\n" "-L path set the directory for the BIOS and VGA BIOS\n" #ifdef USE_CODE_COPY @@ -916,7 +915,7 @@ int main(int argc, char **argv) } for(;;) { - c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); + c = getopt_long_only(argc, argv, "hm:d:n:sp:L:", long_options, &long_index); if (c == -1) break; switch(c) { @@ -1037,7 +1036,20 @@ int main(int argc, char **argv) } break; case 'd': - cpu_set_log(CPU_LOG_ALL); + { + int mask; + CPULogItem *item; + + mask = cpu_str_to_log_mask(optarg); + 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); + } + exit(1); + } + cpu_set_log(mask); + } break; case 'n': pstrcpy(network_script, sizeof(network_script), optarg); |