@@ -811,6 +811,9 @@ static void do_sgi(struct cpu_user_regs *regs, int othercpu, enum gic_sgi sgi)
case GIC_SGI_CALL_FUNCTION:
smp_call_function_interrupt();
break;
+ case GIC_SGI_DUMP_HOST_STATE:
+ show_execution_state(regs);
+ break;
default:
panic("Unhandled SGI %d on CPU%d", sgi, smp_processor_id());
break;
@@ -20,6 +20,7 @@
#include <xen/init.h>
#include <asm/debugger.h>
#include <asm/div64.h>
+#include <asm/gic.h>
static struct keyhandler *key_table[256];
static unsigned char keypress_key;
@@ -149,6 +150,24 @@ static struct keyhandler dump_registers_keyhandler = {
.desc = "dump registers"
};
+static void dump_pcpus(unsigned char key, struct cpu_user_regs *regs)
+{
+ printk("'%c' pressed -> dumping PCPU state\n\n", key);
+
+ send_SGI_self(GIC_SGI_DUMP_HOST_STATE);
+
+ dsb(); /* Wait for SGI write to occur, or else it might be delayed
+ * until later, meaning we don't make a point of having an
+ * IPI interrupting an interrupt. */
+}
+
+static struct keyhandler dump_pcpus_keyhandler = {
+ .irq_callback = 1,
+ .diagnostic = 1,
+ .u.irq_fn = dump_pcpus,
+ .desc = "dump pcpus"
+};
+
static DECLARE_TASKLET(dump_dom0_tasklet, NULL, 0);
static void dump_dom0_action(unsigned long arg)
@@ -539,6 +558,7 @@ void __init initialize_keytable(void)
}
register_keyhandler('A', &toggle_alt_keyhandler);
register_keyhandler('d', &dump_registers_keyhandler);
+ register_keyhandler('P', &dump_pcpus_keyhandler);
register_keyhandler('h', &show_handlers_keyhandler);
register_keyhandler('q', &dump_domains_keyhandler);
register_keyhandler('r', &dump_runq_keyhandler);
@@ -183,6 +183,7 @@ enum gic_sgi {
GIC_SGI_EVENT_CHECK = 0,
GIC_SGI_DUMP_STATE = 1,
GIC_SGI_CALL_FUNCTION = 2,
+ GIC_SGI_DUMP_HOST_STATE = 3,
};
extern void send_SGI_mask(const cpumask_t *cpumask, enum gic_sgi sgi);
extern void send_SGI_one(unsigned int cpu, enum gic_sgi sgi);