summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bswap.h8
-rw-r--r--cpu-all.h96
-rw-r--r--cpu-defs.h8
-rw-r--r--cpu-exec.c6
-rw-r--r--dyngen-exec.h10
-rw-r--r--exec.c55
-rw-r--r--gdbstub.c22
-rw-r--r--monitor.c37
-rw-r--r--thunk.h77
-rw-r--r--translate-all.c4
-rw-r--r--vl.c20
11 files changed, 211 insertions, 132 deletions
diff --git a/bswap.h b/bswap.h
index c52933e493..0df6efcb4d 100644
--- a/bswap.h
+++ b/bswap.h
@@ -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);
diff --git a/cpu-all.h b/cpu-all.h
index 247674c637..b8beddbc34 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -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 */
diff --git a/cpu-defs.h b/cpu-defs.h
index 59a0c0f32e..bbdb390099 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -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 */
diff --git a/cpu-exec.c b/cpu-exec.c
index b6f3de1bb8..cdbebd39be 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -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 5e9bab6f9a..004ca71cdf 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 *, ...);
diff --git a/exec.c b/exec.c
index b945c82718..5d90476aa7 100644
--- a/exec.c
+++ b/exec.c
@@ -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, ...)
{
diff --git a/gdbstub.c b/gdbstub.c
index 29f73c9cbc..8774a9d273 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -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);
diff --git a/monitor.c b/monitor.c
index 195a0b0071..3d5db97016 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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;
}
}
diff --git a/thunk.h b/thunk.h
index b281319a5a..42fd96f3a3 100644
--- a/thunk.h
+++ b/thunk.h
@@ -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 dd314023bc..f10fb62572 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++) {
diff --git a/vl.c b/vl.c
index f358dbed8c..c3204eb71b 100644
--- a/vl.c
+++ b/vl.c
@@ -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);