aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-03-17 19:37:18 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-24 17:57:32 -0400
commitee523ca1e456d754d66be6deab910131e4e1dbf8 (patch)
tree346c3bf4f701a07b124af72a3da4577b2e5dcb3b /arch/x86
parente2a81baf6604a2e08e10c7405b0349106f77c8af (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>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/xen/events.c47
-rw-r--r--arch/x86/xen/smp.c19
-rw-r--r--arch/x86/xen/xen-ops.h3
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
458irqreturn_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
38static cpumask_t xen_cpu_initialized_map; 38static cpumask_t xen_cpu_initialized_map;
39static DEFINE_PER_CPU(int, resched_irq); 39static DEFINE_PER_CPU(int, resched_irq) = -1;
40static DEFINE_PER_CPU(int, callfunc_irq); 40static DEFINE_PER_CPU(int, callfunc_irq) = -1;
41static 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)
89static int xen_smp_intr_init(unsigned int cpu) 90static 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 */
7extern const char xen_hypervisor_callback[]; 8extern const char xen_hypervisor_callback[];
@@ -29,6 +30,8 @@ unsigned long xen_get_wallclock(void);
29int xen_set_wallclock(unsigned long time); 30int xen_set_wallclock(unsigned long time);
30unsigned long long xen_sched_clock(void); 31unsigned long long xen_sched_clock(void);
31 32
33irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
34
32bool xen_vcpu_stolen(int vcpu); 35bool xen_vcpu_stolen(int vcpu);
33 36
34void xen_mark_init_mm_pinned(void); 37void xen_mark_init_mm_pinned(void);