Commit | Line | Data |
---|---|---|
cf910e83 SA |
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 | struct desc_ptr trace_idt_descr = { NR_VECTORS * 16 - 1, | |
13 | (unsigned long) trace_idt_table }; | |
14 | ||
4df05f36 KC |
15 | /* No need to be aligned, but done to keep all IDTs defined the same way. */ |
16 | gate_desc trace_idt_table[NR_VECTORS] __page_aligned_bss; | |
cf910e83 SA |
17 | |
18 | static int trace_irq_vector_refcount; | |
19 | static DEFINE_MUTEX(irq_vector_mutex); | |
20 | ||
21 | static 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 | ||
28 | static void switch_idt(void *arg) | |
29 | { | |
2b4bc789 SRRH |
30 | unsigned long flags; |
31 | ||
32 | local_irq_save(flags); | |
cf910e83 | 33 | load_current_idt(); |
2b4bc789 | 34 | local_irq_restore(flags); |
cf910e83 SA |
35 | } |
36 | ||
37 | void 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 | ||
49 | void 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 | } |