From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46001) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZbmST-0000hA-NZ for qemu-devel@nongnu.org; Tue, 15 Sep 2015 05:23:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZbmSR-0006Cs-DO for qemu-devel@nongnu.org; Tue, 15 Sep 2015 05:23:25 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:6736 helo=relay.sw.ru) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZbmSQ-0006Bu-RJ for qemu-devel@nongnu.org; Tue, 15 Sep 2015 05:23:23 -0400 From: "Denis V. Lunev" Date: Tue, 15 Sep 2015 12:23:05 +0300 Message-Id: <1442308988-653-7-git-send-email-den@openvz.org> In-Reply-To: <1442308988-653-1-git-send-email-den@openvz.org> References: <1442308988-653-1-git-send-email-den@openvz.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH 6/9] hmp: added local apic dump state List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Denis V. Lunev" , =?UTF-8?q?Andreas=20F=C3=A4rber?= , Paolo Bonzini , qemu-devel@nongnu.org, Pavel Butsykin From: Pavel Butsykin Added the hmp command to query local apic registers state, may be usefull after guest crashes to understand IRQ routing in guest. For command name uses "apic-local" because it has to be grouped with command "apic-io". (qemu) info apic-local apic.lvt 00-timer 000300fd int=3Dfd .H.EMP delmod=3D0:Fixed apic.lvt 00-thermal 00010000 int=3D00 .H.EM. delmod=3D0:Fixed apic.lvt 00-perfmon 000000fe int=3Dfe .H.E.. delmod=3D0:Fixed apic.lvt 00-LINT0 0001001f int=3D1f .H.EM. delmod=3D0:Fixed apic.lvt 00-LINT1 000004ff int=3Dff .H.E.. delmod=3D4:NMI apic.lvt 00-Error 000000e3 int=3De3 .H.E.. delmod=3D0:Fixed apic.error 00 esr 00000000 S:... R:... . apic.timer 00 DCR=3D0000000b(b) initial_count=3D1000090000 apic.icr 00 02000000000c00d1: int=3Dd1 delmod=3D0:Fixed P..E shorthand=3D3:all dest=3D2 apic.prio 00 apr=3D00(0:0) tpr=3D40(4:0) apic.dest 00 dfr=3Df0(f) ldr=3D01(01) apic.svr 00 0000011f vec=3D1f on focus=3Doff apic.interrupt 00 065:R.E Signed-off-by: Pavel Butsykin Signed-off-by: Denis V. Lunev CC: Andreas F=C3=A4rber CC: Paolo Bonzini --- hmp-commands-info.hx | 16 ++++ include/monitor/monitor-common.h | 1 + target-i386/cpu.h | 3 + target-i386/helper.c | 155 +++++++++++++++++++++++++++++++++= ++++++ target-i386/monitor.c | 6 ++ 5 files changed, 181 insertions(+) diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 9f5a158..5ffc181 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -112,6 +112,22 @@ STEXI Show the cpu registers. ETEXI =20 +#if defined(TARGET_I386) + { + .name =3D "apic-local", + .args_type =3D "", + .params =3D "", + .help =3D "show local apic state", + .mhandler.cmd =3D hmp_info_apic_local, + }, +#endif + +STEXI +@item info apic-local +@findex apic-local +Show local APIC state +ETEXI + { .name =3D "cpus", .args_type =3D "", diff --git a/include/monitor/monitor-common.h b/include/monitor/monitor-c= ommon.h index abd7a6c..462c35e 100644 --- a/include/monitor/monitor-common.h +++ b/include/monitor/monitor-common.h @@ -42,5 +42,6 @@ CPUState *mon_get_cpu(void); void hmp_info_mem(Monitor *mon, const QDict *qdict); void hmp_info_tlb(Monitor *mon, const QDict *qdict); void hmp_mce(Monitor *mon, const QDict *qdict); +void hmp_info_apic_local(Monitor *mon, const QDict *qdict); =20 #endif /* MONITOR_COMMON */ diff --git a/target-i386/cpu.h b/target-i386/cpu.h index af97772..f37a9c6 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1347,4 +1347,7 @@ void enable_compat_apic_id_mode(void); #define APIC_DEFAULT_ADDRESS 0xfee00000 #define APIC_SPACE_SIZE 0x100000 =20 +void x86_cpu_dump_apic_local_state(CPUState *cs, FILE *f, + fprintf_function cpu_fprintf, int fla= gs); + #endif /* CPU_I386_H */ diff --git a/target-i386/helper.c b/target-i386/helper.c index 5480a96..8d883f5 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -23,6 +23,7 @@ #ifndef CONFIG_USER_ONLY #include "sysemu/sysemu.h" #include "monitor/monitor.h" +#include "hw/i386/apic_internal.h" #endif =20 static void cpu_x86_version(CPUX86State *env, int *family, int *model) @@ -177,6 +178,160 @@ done: cpu_fprintf(f, "\n"); } =20 +#ifndef CONFIG_USER_ONLY + +/* ARRAY_SIZE check is not required because + * DeliveryMode(dm) has a size of 3 bit. + */ +static inline const char *dm2str(uint32_t dm) +{ + static const char *str[] =3D { + "Fixed", + "...", + "SMI", + "...", + "NMI", + "INIT", + "...", + "ExtINT" + }; + return str[dm]; +} + +static void dump_apic_lvt(FILE *f, fprintf_function cpu_fprintf, + uint32_t cpu_idx, const char *name, + uint32_t lvt, bool is_timer) +{ + uint32_t dm =3D (lvt & APIC_LVT_DELIV_MOD) >> APIC_LVT_DELIV_MOD_SHI= FT; + cpu_fprintf(f, + "apic.lvt\t%02u-%-7s %08x int=3D%02x %c%c%c%c%c%c delmod= =3D%x:%s\n", + cpu_idx, name, lvt, + lvt & APIC_VECTOR_MASK, + lvt & APIC_LVT_DELIV_STS ? 'P' : '.', + lvt & APIC_LVT_INT_POLARITY ? 'L' : 'H', + lvt & APIC_LVT_REMOTE_IRR ? 'R' : '.', + lvt & APIC_LVT_LEVEL_TRIGGER ? 'L' : 'E', + lvt & APIC_LVT_MASKED ? 'M' : '.', + !is_timer ? '.' : (lvt & APIC_LVT_TIMER_PERIODIC ? 'P' := 'S'), + dm, + dm2str(dm)); + +} + +/* ARRAY_SIZE check is not required because + * destination shorthand has a size of 2 bit. + */ +static inline const char *shorthand2str(uint32_t shorthand) +{ + const char *str[] =3D { + "no", "self", "all-self", "all" + }; + return str[shorthand]; +} + +void x86_cpu_dump_apic_local_state(CPUState *cs, FILE *f, + fprintf_function cpu_fprintf, int fla= gs) +{ + X86CPU *cpu =3D X86_CPU(cs); + APICCommonState *s =3D APIC_COMMON(cpu->apic_state); + uint32_t *irr_tab =3D s->irr, *isr_tab =3D s->isr, *tmr_tab =3D s->t= mr; + uint32_t *lvt =3D s->lvt; + uint32_t icr0 =3D s->icr[0], icr1 =3D s->icr[1]; + uint32_t esr =3D s->esr; + uint32_t cpu_idx =3D CPU(cpu)->cpu_index; + int i; + + dump_apic_lvt(f, cpu_fprintf, cpu_idx, "timer", + lvt[APIC_LVT_TIMER], true); + dump_apic_lvt(f, cpu_fprintf, cpu_idx, "thermal", + lvt[APIC_LVT_THERMAL], false); + dump_apic_lvt(f, cpu_fprintf, cpu_idx, "perfmon", + lvt[APIC_LVT_PERFORM], false); + dump_apic_lvt(f, cpu_fprintf, cpu_idx, "LINT0", + lvt[APIC_LVT_LINT0], false); + dump_apic_lvt(f, cpu_fprintf, cpu_idx, "LINT1", + lvt[APIC_LVT_LINT1], false); + dump_apic_lvt(f, cpu_fprintf, cpu_idx, "Error", + lvt[APIC_LVT_ERROR], false); + + cpu_fprintf(f, "apic.error\t%02u esr %08x S:%c%c%c R:%c%c%c %c\n", + cpu_idx, esr, + esr & APIC_ESR_SEND_CHECK_SUM ? 'C' : '.', + esr & APIC_ESR_SEND_ACCEPT ? 'A' : '.', + esr & APIC_ESR_SEND_ILLEGAL_VECT ? 'I' : '.', + esr & APIC_ESR_RECV_CHECK_SUM ? 'C' : '.', + esr & APIC_ESR_RECV_ACCEPT ? 'A' : '.', + esr & APIC_ESR_RECV_ILLEGAL_VECT ? 'I' : '.', + esr & APIC_ESR_ILLEGAL_ADDRESS ? 'R' : '.'); + + cpu_fprintf(f, "apic.timer\t%02u DCR=3D%08x(%x) initial_count=3D%d\n= ", + cpu_idx, s->divide_conf, s->divide_conf & APIC_DCR_MASK, + s->initial_count); + + cpu_fprintf(f, "apic.icr\t%02u %016jx: int=3D%02x " + "delmod=3D%x:%s %c%c%c%c shorthand=3D%x:%s dest=3D%x\n", + cpu_idx, ((uint64_t *)s->icr)[0], + icr0 & APIC_VECTOR_MASK, + (icr0 & APIC_ICR_DELIV_MOD) >> APIC_ICR_DELIV_MOD_SHIFT, + dm2str((icr0 & APIC_ICR_DELIV_MOD) >> APIC_ICR_DELIV_MOD= _SHIFT), + icr0 & APIC_ICR_DEST_MOD ? 'L' : 'P', + icr0 & APIC_ICR_DELIV_STS ? 'P' : '.', + icr0 & APIC_ICR_LEVEL ? 'A' : '.', + icr0 & APIC_ICR_TRIGGER_MOD ? 'L' : 'E', + (icr0 & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIF= T, + shorthand2str( + (icr0 & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_= SHIFT), + (icr1 >> APIC_ICR_DEST_SHIFT) & + (icr0 & APIC_ICR_DEST_MOD ? 0xff : 0xf)); + + cpu_fprintf(f, "apic.prio\t%02u apr=3D%02x(%x:%x)\ttpr=3D%02x(%x:%x)= \n", + cpu_idx, + s->arb_id, + s->arb_id >> APIC_PR_CLASS_SHIFT, + s->arb_id & APIC_PR_SUB_CLASS, + s->tpr, + s->tpr >> APIC_PR_CLASS_SHIFT, + s->tpr & APIC_PR_SUB_CLASS); + + cpu_fprintf(f, "apic.dest\t%02u dfr=3D%02x(%x)\tldr=3D%02x", + cpu_idx, s->dest_mode << 4, s->dest_mode, s->log_dest); + if (s->dest_mode =3D=3D 0) { + cpu_fprintf(f, "(%x:%x)\n", + s->log_dest & APIC_LOGDEST_APIC_ID, + s->log_dest >> APIC_LOGDEST_ID_SHIFT); + } else if (s->dest_mode =3D=3D 0xf) { + cpu_fprintf(f, "(%02x)\n", s->log_dest); + } else { + cpu_fprintf(f, "(BAD)\n"); + } + + cpu_fprintf(f, "apic.svr\t%02u %08x vec=3D%02x %s focus=3D%s\n", + cpu_idx, s->spurious_vec, + s->spurious_vec & APIC_VECTOR_MASK, + s->spurious_vec & APIC_SPURIO_ENABLED ? "on" : "off", + s->spurious_vec & APIC_SPURIO_FOCUS ? "on" : "off"); + + for (i =3D 0; i < 256; i++) { + if (irr_tab[i] || isr_tab[i]) { + bool irr_bit =3D apic_get_bit(irr_tab, i); + bool isr_bit =3D apic_get_bit(isr_tab, i); + + if (irr_bit || isr_bit) { + cpu_fprintf(f, "apic.interrupt\t%02u %03u:%c%c%c\n", cpu= _idx, i, + irr_bit ? 'R' : '.', + isr_bit ? 'S' : '.', + apic_get_bit(tmr_tab, i) ? 'L' : 'E'); + } + } + } +} +#else +void x86_cpu_dump_apic_local_state(CPUState *cs, FILE *f, + fprintf_function cpu_fprintf, int fla= gs) +{ +} +#endif /* !CONFIG_USER_ONLY */ + #define DUMP_CODE_BYTES_TOTAL 50 #define DUMP_CODE_BYTES_BACKWARD 20 =20 diff --git a/target-i386/monitor.c b/target-i386/monitor.c index e775561..fbc9fcd 100644 --- a/target-i386/monitor.c +++ b/target-i386/monitor.c @@ -492,3 +492,9 @@ const MonitorDef *target_monitor_defs(void) { return monitor_defs; } + +void hmp_info_apic_local(Monitor *mon, const QDict *qdict) +{ + x86_cpu_dump_apic_local_state(mon_get_cpu(), (FILE *)mon, monitor_fp= rintf, + CPU_DUMP_FPU); +} --=20 2.1.4