qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 6/9] hmp: added local apic dump state


From: Paolo Bonzini
Subject: Re: [Qemu-devel] [PATCH 6/9] hmp: added local apic dump state
Date: Tue, 15 Sep 2015 12:20:25 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0


On 15/09/2015 11:23, Denis V. Lunev wrote:
> From: Pavel Butsykin <address@hidden>
> 
> 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".

I would call them "info lapic" and "info ioapic"
> 
> (qemu) info apic-local
> apic.lvt    00-timer   000300fd int=fd .H.EMP delmod=0:Fixed
> apic.lvt    00-thermal 00010000 int=00 .H.EM. delmod=0:Fixed
> apic.lvt    00-perfmon 000000fe int=fe .H.E.. delmod=0:Fixed
> apic.lvt    00-LINT0   0001001f int=1f .H.EM. delmod=0:Fixed
> apic.lvt    00-LINT1   000004ff int=ff .H.E.. delmod=4:NMI
> apic.lvt    00-Error   000000e3 int=e3 .H.E.. delmod=0:Fixed
> apic.error  00 esr 00000000 S:... R:... .
> apic.timer  00 DCR=0000000b(b) initial_count=1000090000
> apic.icr    00 02000000000c00d1: int=d1 delmod=0:Fixed P..E
>                 shorthand=3:all dest=2
> apic.prio   00 apr=00(0:0)  tpr=40(4:0)
> apic.dest   00 dfr=f0(f)    ldr=01(01)
> apic.svr    00 0000011f vec=1f on focus=off
> apic.interrupt  00 065:R.E

This is not very readable :)

What about:

Dumping local APIC state for CPU 0

LVT0      0x0001001f activehi edge masked                   Fixed (vec 31)
LVT1      0x000004ff activehi edge                          NMI
LVTPC     0x000000fe activehi edge                          Fixed (vec 254)
LVTERR    0x000000e3 activehi edge                          Fixed (vec 243)
LVTTHMR   0x00010000 activehi edge masked                   Fixed (vec 0)
LVTT      0x000300fd activehi edge masked          periodic Fixed (vec 253)
Timer     DCR=0xb (divide by 1), initial count = 1000090000
SPIV      0x0000011f APIC enabled, focus=off, spurious vec 31
ICR       0x000c00d1 physical edge deassert all
ICR2      0x02000000
ESR       0x00000000
ISR       31(level) 65
IRR       31(level) 42(level)

APR 0x00  TPR 0x20  DFR 0xf0  LDR 0x01  PPR 0x40

Some notes:

- no need to detail ESR, it's never used

- no need to detail ICR2 if ICR uses a shorthand, otherwise could be one of
  these formats

      "cpu NN" if this APIC is in xapic flat mode
      "cluster NN mask BBBB" if this APIC is in xapic cluster mode
      "cluster NN mask BBBBBBBBBBBBBBBB" if this APIC is in x2apic mode

- the empty space after "masked" is for "pending"

- please add support for TSC deadline mode too

Paolo

> 
> Signed-off-by: Pavel Butsykin <address@hidden>
> Signed-off-by: Denis V. Lunev <address@hidden>
> CC: Andreas Färber <address@hidden>
> CC: Paolo Bonzini <address@hidden>
> ---
>  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
>  
> +#if defined(TARGET_I386)
> +    {
> +        .name       = "apic-local",
> +        .args_type  = "",
> +        .params     = "",
> +        .help       = "show local apic state",
> +        .mhandler.cmd = hmp_info_apic_local,
> +    },
> +#endif
> +
> +STEXI
> address@hidden info apic-local
> address@hidden apic-local
> +Show local APIC state
> +ETEXI
> +
>      {
>          .name       = "cpus",
>          .args_type  = "",
> diff --git a/include/monitor/monitor-common.h 
> b/include/monitor/monitor-common.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);
>  
>  #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
>  
> +void x86_cpu_dump_apic_local_state(CPUState *cs, FILE *f,
> +                                   fprintf_function cpu_fprintf, int flags);
> +
>  #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
>  
>  static void cpu_x86_version(CPUX86State *env, int *family, int *model)
> @@ -177,6 +178,160 @@ done:
>      cpu_fprintf(f, "\n");
>  }
>  
> +#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[] = {
> +        "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 = (lvt & APIC_LVT_DELIV_MOD) >> APIC_LVT_DELIV_MOD_SHIFT;
> +    cpu_fprintf(f,
> +                "apic.lvt\t%02u-%-7s %08x int=%02x %c%c%c%c%c%c 
> delmod=%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[] = {
> +        "no", "self", "all-self", "all"
> +    };
> +    return str[shorthand];
> +}
> +
> +void x86_cpu_dump_apic_local_state(CPUState *cs, FILE *f,
> +                                   fprintf_function cpu_fprintf, int flags)
> +{
> +    X86CPU *cpu = X86_CPU(cs);
> +    APICCommonState *s = APIC_COMMON(cpu->apic_state);
> +    uint32_t *irr_tab = s->irr, *isr_tab = s->isr, *tmr_tab = s->tmr;
> +    uint32_t *lvt = s->lvt;
> +    uint32_t icr0 = s->icr[0], icr1 = s->icr[1];
> +    uint32_t esr = s->esr;
> +    uint32_t cpu_idx = 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=%08x(%x) initial_count=%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=%02x "
> +                "delmod=%x:%s %c%c%c%c shorthand=%x:%s dest=%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_SHIFT,
> +                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=%02x(%x:%x)\ttpr=%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=%02x(%x)\tldr=%02x",
> +                cpu_idx, s->dest_mode << 4, s->dest_mode, s->log_dest);
> +    if (s->dest_mode == 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 == 0xf) {
> +        cpu_fprintf(f, "(%02x)\n", s->log_dest);
> +    } else {
> +        cpu_fprintf(f, "(BAD)\n");
> +    }
> +
> +    cpu_fprintf(f, "apic.svr\t%02u %08x vec=%02x %s focus=%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 = 0; i < 256; i++) {
> +        if (irr_tab[i] || isr_tab[i]) {
> +            bool irr_bit = apic_get_bit(irr_tab, i);
> +            bool isr_bit = 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 flags)
> +{
> +}
> +#endif /* !CONFIG_USER_ONLY */
> +
>  #define DUMP_CODE_BYTES_TOTAL    50
>  #define DUMP_CODE_BYTES_BACKWARD 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_fprintf,
> +                                  CPU_DUMP_FPU);
> +}
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]