diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2008-03-17 19:37:18 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-24 17:57:32 -0400 |
commit | ee523ca1e456d754d66be6deab910131e4e1dbf8 (patch) | |
tree | 346c3bf4f701a07b124af72a3da4577b2e5dcb3b | |
parent | e2a81baf6604a2e08e10c7405b0349106f77c8af (diff) |
xen: implement a debug-interrupt handler
Xen supports the notion of a debug interrupt which can be triggered
from the console. For now this is implemented to show pending events,
masks and each CPU's pending event set.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | arch/x86/xen/events.c | 47 | ||||
-rw-r--r-- | arch/x86/xen/smp.c | 19 | ||||
-rw-r--r-- | arch/x86/xen/xen-ops.h | 3 |
3 files changed, 64 insertions, 5 deletions
diff --git a/arch/x86/xen/events.c b/arch/x86/xen/events.c index dcf613e17581..0140981e93c4 100644 --- a/arch/x86/xen/events.c +++ b/arch/x86/xen/events.c | |||
@@ -455,6 +455,53 @@ void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector) | |||
455 | notify_remote_via_irq(irq); | 455 | notify_remote_via_irq(irq); |
456 | } | 456 | } |
457 | 457 | ||
458 | irqreturn_t xen_debug_interrupt(int irq, void *dev_id) | ||
459 | { | ||
460 | struct shared_info *sh = HYPERVISOR_shared_info; | ||
461 | int cpu = smp_processor_id(); | ||
462 | int i; | ||
463 | unsigned long flags; | ||
464 | static DEFINE_SPINLOCK(debug_lock); | ||
465 | |||
466 | spin_lock_irqsave(&debug_lock, flags); | ||
467 | |||
468 | printk("vcpu %d\n ", cpu); | ||
469 | |||
470 | for_each_online_cpu(i) { | ||
471 | struct vcpu_info *v = per_cpu(xen_vcpu, i); | ||
472 | printk("%d: masked=%d pending=%d event_sel %08lx\n ", i, | ||
473 | (get_irq_regs() && i == cpu) ? !(get_irq_regs()->flags & X86_EFLAGS_IF) : v->evtchn_upcall_mask, | ||
474 | v->evtchn_upcall_pending, | ||
475 | v->evtchn_pending_sel); | ||
476 | } | ||
477 | printk("pending:\n "); | ||
478 | for(i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--) | ||
479 | printk("%08lx%s", sh->evtchn_pending[i], | ||
480 | i % 8 == 0 ? "\n " : " "); | ||
481 | printk("\nmasks:\n "); | ||
482 | for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) | ||
483 | printk("%08lx%s", sh->evtchn_mask[i], | ||
484 | i % 8 == 0 ? "\n " : " "); | ||
485 | |||
486 | printk("\nunmasked:\n "); | ||
487 | for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) | ||
488 | printk("%08lx%s", sh->evtchn_pending[i] & ~sh->evtchn_mask[i], | ||
489 | i % 8 == 0 ? "\n " : " "); | ||
490 | |||
491 | printk("\npending list:\n"); | ||
492 | for(i = 0; i < NR_EVENT_CHANNELS; i++) { | ||
493 | if (sync_test_bit(i, sh->evtchn_pending)) { | ||
494 | printk(" %d: event %d -> irq %d\n", | ||
495 | cpu_evtchn[i], i, | ||
496 | evtchn_to_irq[i]); | ||
497 | } | ||
498 | } | ||
499 | |||
500 | spin_unlock_irqrestore(&debug_lock, flags); | ||
501 | |||
502 | return IRQ_HANDLED; | ||
503 | } | ||
504 | |||
458 | 505 | ||
459 | /* | 506 | /* |
460 | * Search the CPUs pending events bitmasks. For each one found, map | 507 | * Search the CPUs pending events bitmasks. For each one found, map |
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index d61e4f8b07c7..92dd3dbf3ffb 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -36,8 +36,9 @@ | |||
36 | #include "mmu.h" | 36 | #include "mmu.h" |
37 | 37 | ||
38 | static cpumask_t xen_cpu_initialized_map; | 38 | static cpumask_t xen_cpu_initialized_map; |
39 | static DEFINE_PER_CPU(int, resched_irq); | 39 | static DEFINE_PER_CPU(int, resched_irq) = -1; |
40 | static DEFINE_PER_CPU(int, callfunc_irq); | 40 | static DEFINE_PER_CPU(int, callfunc_irq) = -1; |
41 | static DEFINE_PER_CPU(int, debug_irq) = -1; | ||
41 | 42 | ||
42 | /* | 43 | /* |
43 | * Structure and data for smp_call_function(). This is designed to minimise | 44 | * Structure and data for smp_call_function(). This is designed to minimise |
@@ -89,9 +90,7 @@ static __cpuinit void cpu_bringup_and_idle(void) | |||
89 | static int xen_smp_intr_init(unsigned int cpu) | 90 | static int xen_smp_intr_init(unsigned int cpu) |
90 | { | 91 | { |
91 | int rc; | 92 | int rc; |
92 | const char *resched_name, *callfunc_name; | 93 | const char *resched_name, *callfunc_name, *debug_name; |
93 | |||
94 | per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1; | ||
95 | 94 | ||
96 | resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu); | 95 | resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu); |
97 | rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, | 96 | rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, |
@@ -115,6 +114,14 @@ static int xen_smp_intr_init(unsigned int cpu) | |||
115 | goto fail; | 114 | goto fail; |
116 | per_cpu(callfunc_irq, cpu) = rc; | 115 | per_cpu(callfunc_irq, cpu) = rc; |
117 | 116 | ||
117 | debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu); | ||
118 | rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt, | ||
119 | IRQF_DISABLED | IRQF_PERCPU | IRQF_NOBALANCING, | ||
120 | debug_name, NULL); | ||
121 | if (rc < 0) | ||
122 | goto fail; | ||
123 | per_cpu(debug_irq, cpu) = rc; | ||
124 | |||
118 | return 0; | 125 | return 0; |
119 | 126 | ||
120 | fail: | 127 | fail: |
@@ -122,6 +129,8 @@ static int xen_smp_intr_init(unsigned int cpu) | |||
122 | unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); | 129 | unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); |
123 | if (per_cpu(callfunc_irq, cpu) >= 0) | 130 | if (per_cpu(callfunc_irq, cpu) >= 0) |
124 | unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); | 131 | unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); |
132 | if (per_cpu(debug_irq, cpu) >= 0) | ||
133 | unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL); | ||
125 | return rc; | 134 | return rc; |
126 | } | 135 | } |
127 | 136 | ||
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 01d4ff2ce404..22395d20dd6e 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define XEN_OPS_H | 2 | #define XEN_OPS_H |
3 | 3 | ||
4 | #include <linux/init.h> | 4 | #include <linux/init.h> |
5 | #include <linux/irqreturn.h> | ||
5 | 6 | ||
6 | /* These are code, but not functions. Defined in entry.S */ | 7 | /* These are code, but not functions. Defined in entry.S */ |
7 | extern const char xen_hypervisor_callback[]; | 8 | extern const char xen_hypervisor_callback[]; |
@@ -29,6 +30,8 @@ unsigned long xen_get_wallclock(void); | |||
29 | int xen_set_wallclock(unsigned long time); | 30 | int xen_set_wallclock(unsigned long time); |
30 | unsigned long long xen_sched_clock(void); | 31 | unsigned long long xen_sched_clock(void); |
31 | 32 | ||
33 | irqreturn_t xen_debug_interrupt(int irq, void *dev_id); | ||
34 | |||
32 | bool xen_vcpu_stolen(int vcpu); | 35 | bool xen_vcpu_stolen(int vcpu); |
33 | 36 | ||
34 | void xen_mark_init_mm_pinned(void); | 37 | void xen_mark_init_mm_pinned(void); |