1 /* 2 * Code for supporting irq vector tracepoints. 3 * 4 * Copyright (C) 2013 Seiji Aguchi <seiji.aguchi@hds.com> 5 * 6 */ 7 #include <asm/hw_irq.h> 8 #include <asm/desc.h> 9 #include <linux/atomic.h> 10 11 atomic_t trace_idt_ctr = ATOMIC_INIT(0); 12 __aligned(PAGE_SIZE) 13 struct desc_ptr trace_idt_descr = { NR_VECTORS * 16 - 1, 14 (unsigned long) trace_idt_table }; 15 16 /* No need to be aligned, but done to keep all IDTs defined the same way. */ 17 __aligned(PAGE_SIZE) 18 gate_desc trace_idt_table[NR_VECTORS] __page_aligned_bss; 19 20 static int trace_irq_vector_refcount; 21 static DEFINE_MUTEX(irq_vector_mutex); 22 set_trace_idt_ctr(int val)23static void set_trace_idt_ctr(int val) 24 { 25 atomic_set(&trace_idt_ctr, val); 26 /* Ensure the trace_idt_ctr is set before sending IPI */ 27 wmb(); 28 } 29 switch_idt(void * arg)30static void switch_idt(void *arg) 31 { 32 unsigned long flags; 33 34 local_irq_save(flags); 35 load_current_idt(); 36 local_irq_restore(flags); 37 } 38 trace_irq_vector_regfunc(void)39void trace_irq_vector_regfunc(void) 40 { 41 mutex_lock(&irq_vector_mutex); 42 if (!trace_irq_vector_refcount) { 43 set_trace_idt_ctr(1); 44 smp_call_function(switch_idt, NULL, 0); 45 switch_idt(NULL); 46 } 47 trace_irq_vector_refcount++; 48 mutex_unlock(&irq_vector_mutex); 49 } 50 trace_irq_vector_unregfunc(void)51void trace_irq_vector_unregfunc(void) 52 { 53 mutex_lock(&irq_vector_mutex); 54 trace_irq_vector_refcount--; 55 if (!trace_irq_vector_refcount) { 56 set_trace_idt_ctr(0); 57 smp_call_function(switch_idt, NULL, 0); 58 switch_idt(NULL); 59 } 60 mutex_unlock(&irq_vector_mutex); 61 } 62