On some occaisons a VM can consume up to 100% host cpu due to intensive portio activity. The current DEBUG_IPPORT prints just write every access into the log file. This patch enable ioport debug statistics so a summary of ioport access is printed every second to the log file. This helps debugging production problems.
Signed-off-by: Dor Laor <[EMAIL PROTECTED]> --- qemu/exec.c | 3 --- qemu/vl.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/qemu/exec.c b/qemu/exec.c index 3e588d5..974ac98 100644 --- a/qemu/exec.c +++ b/qemu/exec.c @@ -50,7 +50,6 @@ //#define DEBUG_TB_CHECK //#define DEBUG_TLB_CHECK -//#define DEBUG_IOPORT //#define DEBUG_SUBPAGE #if !defined(CONFIG_USER_ONLY) @@ -1268,10 +1267,8 @@ CPULogItem cpu_log_items[] = { { CPU_LOG_PCALL, "pcall", "show protected mode far calls/returns/exceptions" }, #endif -#ifdef DEBUG_IOPORT { CPU_LOG_IOPORT, "ioport", "show all i/o ports accesses" }, -#endif { 0, NULL, NULL }, }; diff --git a/qemu/vl.c b/qemu/vl.c index 8dd839e..0e3aa70 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -129,6 +129,7 @@ int inet_aton(const char *cp, struct in_addr *ia); //#define DEBUG_UNUSED_IOPORT //#define DEBUG_IOPORT +#define DEBUG_IOPORT_STAT #if HOST_LONG_BITS < 64 #define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024) @@ -155,6 +156,9 @@ char phys_ram_file[1024]; void *ioport_opaque[MAX_IOPORTS]; IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; +#ifdef DEBUG_IOPORT_STAT +uint32_t ioport_stat[MAX_IOPORTS] = {0}; +#endif /* Note: bs_table[MAX_DISKS] is a dummy block driver if none available to store the VM snapshots */ BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD]; @@ -379,6 +383,10 @@ void cpu_outb(CPUState *env, int addr, int val) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outb: %04x %02x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif + ioport_write_table[0][addr](ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) @@ -392,6 +400,9 @@ void cpu_outw(CPUState *env, int addr, int val) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outw: %04x %04x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif ioport_write_table[1][addr](ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) @@ -405,6 +416,9 @@ void cpu_outl(CPUState *env, int addr, int val) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outl: %04x %08x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif ioport_write_table[2][addr](ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) @@ -420,6 +434,9 @@ int cpu_inb(CPUState *env, int addr) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "inb : %04x %02x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif #ifdef USE_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -435,6 +452,9 @@ int cpu_inw(CPUState *env, int addr) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "inw : %04x %04x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif #ifdef USE_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -450,6 +470,9 @@ int cpu_inl(CPUState *env, int addr) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "inl : %04x %08x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif #ifdef USE_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -1141,6 +1164,36 @@ static int timer_load(QEMUFile *f, void *opaque, int version_id) return 0; } +#ifdef DEBUG_IOPORT_STAT +QEMUTimer *ioport_stat_qtimer; + +static void ioport_stat_timer(void *opaque) +{ + uint64_t curr_time; + int i; + + curr_time = qemu_get_clock(vm_clock); + qemu_mod_timer(ioport_stat_qtimer, curr_time + ticks_per_sec); + + if (loglevel & CPU_LOG_IOPORT) { + fprintf(logfile, "%s: port_addr(h) access_times(d)\n", __FUNCTION__); + for (i = 0; i < MAX_IOPORTS; i++) + if (ioport_stat[i]) { + fprintf(logfile, "%04x %d\n", i, ioport_stat[i]); + ioport_stat[i] = 0; + } + fprintf(logfile, "%s: end stat\n", __FUNCTION__); + } +} + +static void ioport_stat_init(void) +{ + ioport_stat_qtimer = qemu_new_timer(vm_clock, ioport_stat_timer, NULL); + qemu_mod_timer(ioport_stat_qtimer, qemu_get_clock(vm_clock)); +} + +#endif + #ifdef _WIN32 void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) @@ -8738,6 +8791,11 @@ int main(int argc, char **argv) init_timers(); init_timer_alarm(); + +#ifdef DEBUG_IOPORT_STAT + ioport_stat_init(); +#endif + qemu_aio_init(); #ifdef _WIN32 -- 1.5.3
>From 5678da1976a01bc3f1d57a304cd0542a40d75a21 Mon Sep 17 00:00:00 2001 From: Dor Laor <[EMAIL PROTECTED]> Date: Tue, 23 Oct 2007 13:28:06 +0200 Subject: [PATCH] Add ioport statistics On some occaisons a VM can consume up to 100% host cpu due to intensive portio activity. The current DEBUG_IPPORT prints just write every access into the log file. This patch enable ioport debug statistics so a summary of ioport access is printed every second to the log file. This helps debugging production problems. Signed-off-by: Dor Laor <[EMAIL PROTECTED]> --- qemu/exec.c | 3 --- qemu/vl.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/qemu/exec.c b/qemu/exec.c index 3e588d5..974ac98 100644 --- a/qemu/exec.c +++ b/qemu/exec.c @@ -50,7 +50,6 @@ //#define DEBUG_TB_CHECK //#define DEBUG_TLB_CHECK -//#define DEBUG_IOPORT //#define DEBUG_SUBPAGE #if !defined(CONFIG_USER_ONLY) @@ -1268,10 +1267,8 @@ CPULogItem cpu_log_items[] = { { CPU_LOG_PCALL, "pcall", "show protected mode far calls/returns/exceptions" }, #endif -#ifdef DEBUG_IOPORT { CPU_LOG_IOPORT, "ioport", "show all i/o ports accesses" }, -#endif { 0, NULL, NULL }, }; diff --git a/qemu/vl.c b/qemu/vl.c index 8dd839e..0e3aa70 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -129,6 +129,7 @@ int inet_aton(const char *cp, struct in_addr *ia); //#define DEBUG_UNUSED_IOPORT //#define DEBUG_IOPORT +#define DEBUG_IOPORT_STAT #if HOST_LONG_BITS < 64 #define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024) @@ -155,6 +156,9 @@ char phys_ram_file[1024]; void *ioport_opaque[MAX_IOPORTS]; IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; +#ifdef DEBUG_IOPORT_STAT +uint32_t ioport_stat[MAX_IOPORTS] = {0}; +#endif /* Note: bs_table[MAX_DISKS] is a dummy block driver if none available to store the VM snapshots */ BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD]; @@ -379,6 +383,10 @@ void cpu_outb(CPUState *env, int addr, int val) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outb: %04x %02x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif + ioport_write_table[0][addr](ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) @@ -392,6 +400,9 @@ void cpu_outw(CPUState *env, int addr, int val) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outw: %04x %04x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif ioport_write_table[1][addr](ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) @@ -405,6 +416,9 @@ void cpu_outl(CPUState *env, int addr, int val) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outl: %04x %08x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif ioport_write_table[2][addr](ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) @@ -420,6 +434,9 @@ int cpu_inb(CPUState *env, int addr) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "inb : %04x %02x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif #ifdef USE_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -435,6 +452,9 @@ int cpu_inw(CPUState *env, int addr) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "inw : %04x %04x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif #ifdef USE_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -450,6 +470,9 @@ int cpu_inl(CPUState *env, int addr) if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "inl : %04x %08x\n", addr, val); #endif +#ifdef DEBUG_IOPORT_STAT + ioport_stat[addr]++; +#endif #ifdef USE_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -1141,6 +1164,36 @@ static int timer_load(QEMUFile *f, void *opaque, int version_id) return 0; } +#ifdef DEBUG_IOPORT_STAT +QEMUTimer *ioport_stat_qtimer; + +static void ioport_stat_timer(void *opaque) +{ + uint64_t curr_time; + int i; + + curr_time = qemu_get_clock(vm_clock); + qemu_mod_timer(ioport_stat_qtimer, curr_time + ticks_per_sec); + + if (loglevel & CPU_LOG_IOPORT) { + fprintf(logfile, "%s: port_addr(h) access_times(d)\n", __FUNCTION__); + for (i = 0; i < MAX_IOPORTS; i++) + if (ioport_stat[i]) { + fprintf(logfile, "%04x %d\n", i, ioport_stat[i]); + ioport_stat[i] = 0; + } + fprintf(logfile, "%s: end stat\n", __FUNCTION__); + } +} + +static void ioport_stat_init(void) +{ + ioport_stat_qtimer = qemu_new_timer(vm_clock, ioport_stat_timer, NULL); + qemu_mod_timer(ioport_stat_qtimer, qemu_get_clock(vm_clock)); +} + +#endif + #ifdef _WIN32 void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) @@ -8738,6 +8791,11 @@ int main(int argc, char **argv) init_timers(); init_timer_alarm(); + +#ifdef DEBUG_IOPORT_STAT + ioport_stat_init(); +#endif + qemu_aio_init(); #ifdef _WIN32 -- 1.5.3