summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Butsykin <pbutsykin@virtuozzo.com>2015-09-22 16:18:20 +0300
committerPaolo Bonzini <pbonzini@redhat.com>2015-09-25 12:04:42 +0200
commitd665d696c53f776ec2cb91505658969b9eb9906b (patch)
tree1f68763a1487709070dc540b38ce3749dbd0037a
parentaf599407352a2e05235d96196e8841ad1b39dd0f (diff)
downloadqemu-d665d696c53f776ec2cb91505658969b9eb9906b.tar.gz
qemu-d665d696c53f776ec2cb91505658969b9eb9906b.tar.bz2
qemu-d665d696c53f776ec2cb91505658969b9eb9906b.zip
hmp: added io apic dump state
Added the hmp command to query io apic state, may be usefull after guest crashes to understand IRQ routing in guest. Implementation is only for kvm here. The dump will look like (qemu) info ioapic ioapic id=0x00 sel=0x26 (redir[11]) pin 0 0x0000000000010000 dest=0 vec=0 active-hi edge masked fixed physical pin 1 0x0000000000000031 dest=0 vec=49 active-hi edge fixed physical ... pin 23 0x0000000000010000 dest=0 vec=0 active-hi edge masked fixed physical IRR (none) Remote IRR (none) Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com> Signed-off-by: Denis V. Lunev <den@openvz.org> CC: Paolo Bonzini <pbonzini@redhat.com> CC: Andreas Färber <afaerber@suse.de> Message-Id: <1442927901-1084-9-git-send-email-den@openvz.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--hmp-commands-info.hx16
-rw-r--r--hw/i386/kvm/ioapic.c10
-rw-r--r--hw/intc/ioapic_common.c55
-rw-r--r--include/hw/i386/ioapic_internal.h2
-rw-r--r--include/hw/i386/pc.h4
-rw-r--r--include/monitor/hmp-target.h1
-rw-r--r--target-i386/monitor.c9
7 files changed, 97 insertions, 0 deletions
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index b02876c83c..9b71351d01 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -128,6 +128,22 @@ STEXI
Show local APIC state
ETEXI
+#if defined(TARGET_I386)
+ {
+ .name = "ioapic",
+ .args_type = "",
+ .params = "",
+ .help = "show io apic state",
+ .mhandler.cmd = hmp_info_io_apic,
+ },
+#endif
+
+STEXI
+@item info ioapic
+@findex ioapic
+Show io APIC state
+ETEXI
+
{
.name = "cpus",
.args_type = "",
diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c
index d2a6c4cf60..b7390ca0da 100644
--- a/hw/i386/kvm/ioapic.c
+++ b/hw/i386/kvm/ioapic.c
@@ -10,6 +10,7 @@
* See the COPYING file in the top-level directory.
*/
+#include "monitor/monitor.h"
#include "hw/i386/pc.h"
#include "hw/i386/ioapic_internal.h"
#include "hw/i386/apic_internal.h"
@@ -110,6 +111,15 @@ static void kvm_ioapic_put(IOAPICCommonState *s)
}
}
+void kvm_ioapic_dump_state(Monitor *mon, const QDict *qdict)
+{
+ IOAPICCommonState s;
+
+ kvm_ioapic_get(&s);
+
+ ioapic_print_redtbl(mon, &s);
+}
+
static void kvm_ioapic_reset(DeviceState *dev)
{
IOAPICCommonState *s = IOAPIC_COMMON(dev);
diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c
index 8b7d11806c..65f6877d79 100644
--- a/hw/intc/ioapic_common.c
+++ b/hw/intc/ioapic_common.c
@@ -19,6 +19,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "monitor/monitor.h"
#include "hw/i386/ioapic.h"
#include "hw/i386/ioapic_internal.h"
#include "hw/sysbus.h"
@@ -31,6 +32,60 @@
*/
int ioapic_no;
+static void ioapic_irr_dump(Monitor *mon, const char *name, uint32_t bitmap)
+{
+ int i;
+
+ monitor_printf(mon, "%-10s ", name);
+ if (bitmap == 0) {
+ monitor_printf(mon, "(none)\n");
+ return;
+ }
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ if (bitmap & (1 << i)) {
+ monitor_printf(mon, "%-2u ", i);
+ }
+ }
+ monitor_printf(mon, "\n");
+}
+
+void ioapic_print_redtbl(Monitor *mon, IOAPICCommonState *s)
+{
+ static const char *delm_str[] = {
+ "fixed", "lowest", "SMI", "...", "NMI", "INIT", "...", "extINT"};
+ uint32_t remote_irr = 0;
+ int i;
+
+ monitor_printf(mon, "ioapic id=0x%02x sel=0x%02x", s->id, s->ioregsel);
+ if (s->ioregsel) {
+ monitor_printf(mon, " (redir[%u])\n",
+ (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1);
+ } else {
+ monitor_printf(mon, "\n");
+ }
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ uint64_t entry = s->ioredtbl[i];
+ uint32_t delm = (uint32_t)((entry & IOAPIC_LVT_DELIV_MODE) >>
+ IOAPIC_LVT_DELIV_MODE_SHIFT);
+ monitor_printf(mon, "pin %-2u 0x%016"PRIx64" dest=%"PRIx64
+ " vec=%-3"PRIu64" %s %-5s %-6s %-6s %s\n",
+ i, entry,
+ (entry >> IOAPIC_LVT_DEST_SHIFT) &
+ (entry & IOAPIC_LVT_DEST_MODE ? 0xff : 0xf),
+ entry & IOAPIC_VECTOR_MASK,
+ entry & IOAPIC_LVT_POLARITY ? "active-lo" : "active-hi",
+ entry & IOAPIC_LVT_TRIGGER_MODE ? "level" : "edge",
+ entry & IOAPIC_LVT_MASKED ? "masked" : "",
+ delm_str[delm],
+ entry & IOAPIC_LVT_DEST_MODE ? "logical" : "physical");
+
+ remote_irr |= entry & IOAPIC_LVT_TRIGGER_MODE ?
+ (entry & IOAPIC_LVT_REMOTE_IRR ? (1 << i) : 0) : 0;
+ }
+ ioapic_irr_dump(mon, "IRR", s->irr);
+ ioapic_irr_dump(mon, "Remote IRR", remote_irr);
+}
+
void ioapic_reset_common(DeviceState *dev)
{
IOAPICCommonState *s = IOAPIC_COMMON(dev);
diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h
index 4f7764e183..797ed47305 100644
--- a/include/hw/i386/ioapic_internal.h
+++ b/include/hw/i386/ioapic_internal.h
@@ -105,4 +105,6 @@ struct IOAPICCommonState {
void ioapic_reset_common(DeviceState *dev);
+void ioapic_print_redtbl(Monitor *mon, IOAPICCommonState *s);
+
#endif /* !QEMU_IOAPIC_INTERNAL_H */
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 3e002c9da6..539cf64ed6 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -123,6 +123,10 @@ int pic_get_output(DeviceState *d);
void hmp_info_pic(Monitor *mon, const QDict *qdict);
void hmp_info_irq(Monitor *mon, const QDict *qdict);
+/* ioapic.c */
+
+void kvm_ioapic_dump_state(Monitor *mon, const QDict *qdict);
+
/* Global System Interrupts */
#define GSI_NUM_PINS IOAPIC_NUM_PINS
diff --git a/include/monitor/hmp-target.h b/include/monitor/hmp-target.h
index be50577b37..213566c612 100644
--- a/include/monitor/hmp-target.h
+++ b/include/monitor/hmp-target.h
@@ -43,5 +43,6 @@ 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_local_apic(Monitor *mon, const QDict *qdict);
+void hmp_info_io_apic(Monitor *mon, const QDict *qdict);
#endif /* MONITOR_COMMON */
diff --git a/target-i386/monitor.c b/target-i386/monitor.c
index 9479a770fa..829fff9e03 100644
--- a/target-i386/monitor.c
+++ b/target-i386/monitor.c
@@ -24,6 +24,8 @@
#include "cpu.h"
#include "monitor/monitor.h"
#include "monitor/hmp-target.h"
+#include "hw/i386/pc.h"
+#include "sysemu/kvm.h"
#include "hmp.h"
@@ -498,3 +500,10 @@ void hmp_info_local_apic(Monitor *mon, const QDict *qdict)
x86_cpu_dump_local_apic_state(mon_get_cpu(), (FILE *)mon, monitor_fprintf,
CPU_DUMP_FPU);
}
+
+void hmp_info_io_apic(Monitor *mon, const QDict *qdict)
+{
+ if (kvm_irqchip_in_kernel()) {
+ kvm_ioapic_dump_state(mon, qdict);
+ }
+}