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 11atomic_t trace_idt_ctr = ATOMIC_INIT(0); 12struct desc_ptr trace_idt_descr = { NR_VECTORS * 16 - 1, 13 (unsigned long) trace_idt_table }; 14 15/* No need to be aligned, but done to keep all IDTs defined the same way. */ 16gate_desc trace_idt_table[NR_VECTORS] __page_aligned_bss; 17 18static int trace_irq_vector_refcount; 19static DEFINE_MUTEX(irq_vector_mutex); 20 21static void set_trace_idt_ctr(int val) 22{ 23 atomic_set(&trace_idt_ctr, val); 24 /* Ensure the trace_idt_ctr is set before sending IPI */ 25 wmb(); 26} 27 28static void switch_idt(void *arg) 29{ 30 unsigned long flags; 31 32 local_irq_save(flags); 33 load_current_idt(); 34 local_irq_restore(flags); 35} 36 37void trace_irq_vector_regfunc(void) 38{ 39 mutex_lock(&irq_vector_mutex); 40 if (!trace_irq_vector_refcount) { 41 set_trace_idt_ctr(1); 42 smp_call_function(switch_idt, NULL, 0); 43 switch_idt(NULL); 44 } 45 trace_irq_vector_refcount++; 46 mutex_unlock(&irq_vector_mutex); 47} 48 49void trace_irq_vector_unregfunc(void) 50{ 51 mutex_lock(&irq_vector_mutex); 52 trace_irq_vector_refcount--; 53 if (!trace_irq_vector_refcount) { 54 set_trace_idt_ctr(0); 55 smp_call_function(switch_idt, NULL, 0); 56 switch_idt(NULL); 57 } 58 mutex_unlock(&irq_vector_mutex); 59} 60