linux/arch/x86/kernel/tracepoint.c
<<
>>
Prefs
   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