]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'x86-tracing-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 2 Jul 2013 23:31:49 +0000 (16:31 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 2 Jul 2013 23:31:49 +0000 (16:31 -0700)
Pull x86 tracing updates from Ingo Molnar:
 "This tree adds IRQ vector tracepoints that are named after the handler
  and which output the vector #, based on a zero-overhead approach that
  relies on changing the IDT entries, by Seiji Aguchi.

  The new tracepoints look like this:

   # perf list | grep -i irq_vector
    irq_vectors:local_timer_entry                      [Tracepoint event]
    irq_vectors:local_timer_exit                       [Tracepoint event]
    irq_vectors:reschedule_entry                       [Tracepoint event]
    irq_vectors:reschedule_exit                        [Tracepoint event]
    irq_vectors:spurious_apic_entry                    [Tracepoint event]
    irq_vectors:spurious_apic_exit                     [Tracepoint event]
    irq_vectors:error_apic_entry                       [Tracepoint event]
    irq_vectors:error_apic_exit                        [Tracepoint event]
   [...]"

* 'x86-tracing-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/tracing: Add config option checking to the definitions of mce handlers
  trace,x86: Do not call local_irq_save() in load_current_idt()
  trace,x86: Move creation of irq tracepoints from apic.c to irq.c
  x86, trace: Add irq vector tracepoints
  x86: Rename variables for debugging
  x86, trace: Introduce entering/exiting_irq()
  tracing: Add DEFINE_EVENT_FN() macro

1  2 
arch/x86/kernel/Makefile
arch/x86/kernel/apic/apic.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/traps.c

diff --combined arch/x86/kernel/Makefile
index 612ed3435c0d90364d17fc2ba8a0ebdcc912ddf2,44e763f94ad46345edfd832e50963127baf64f71..88d99ea77723f768385c602e98fa9a5a1ed58e1c
@@@ -16,6 -16,8 +16,8 @@@ CFLAGS_REMOVE_ftrace.o = -p
  CFLAGS_REMOVE_early_printk.o = -pg
  endif
  
+ CFLAGS_irq.o := -I$(src)/../include/asm/trace
  obj-y                 := process_$(BITS).o signal.o entry_$(BITS).o
  obj-y                 += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
  obj-y                 += time.o ioport.o ldt.o dumpstack.o nmi.o
@@@ -67,7 -69,7 +69,7 @@@ obj-$(CONFIG_KEXEC)           += relocate_kernel
  obj-$(CONFIG_CRASH_DUMP)      += crash_dump_$(BITS).o
  obj-y                         += kprobes/
  obj-$(CONFIG_MODULES)         += module.o
 -obj-$(CONFIG_DOUBLEFAULT)     += doublefault_32.o
 +obj-$(CONFIG_DOUBLEFAULT)     += doublefault.o
  obj-$(CONFIG_KGDB)            += kgdb.o
  obj-$(CONFIG_VM86)            += vm86_32.o
  obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o
@@@ -93,7 -95,6 +95,7 @@@ obj-$(CONFIG_MICROCODE_INTEL_LIB)     += mi
  microcode-y                           := microcode_core.o
  microcode-$(CONFIG_MICROCODE_INTEL)   += microcode_intel.o
  microcode-$(CONFIG_MICROCODE_AMD)     += microcode_amd.o
 +obj-$(CONFIG_MICROCODE_AMD_EARLY)     += microcode_amd_early.o
  obj-$(CONFIG_MICROCODE)                       += microcode.o
  
  obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
@@@ -103,6 -104,7 +105,7 @@@ obj-$(CONFIG_OF)                   += devicetree.
  obj-$(CONFIG_UPROBES)                 += uprobes.o
  
  obj-$(CONFIG_PERF_EVENTS)             += perf_regs.o
+ obj-$(CONFIG_TRACING)                 += tracepoint.o
  
  ###
  # 64 bit specific files
index 1600b1ca4f04615958e2ebb94dbd5f9df873bcbc,961676c9b8d86b79e75db9c7e6c102c3a019b3cf..99663b59123a0066fe42a427bb2a2cb51b8b8a55
@@@ -35,6 -35,7 +35,7 @@@
  #include <linux/smp.h>
  #include <linux/mm.h>
  
+ #include <asm/trace/irq_vectors.h>
  #include <asm/irq_remapping.h>
  #include <asm/perf_event.h>
  #include <asm/x86_init.h>
@@@ -919,17 -920,35 +920,35 @@@ void __irq_entry smp_apic_timer_interru
        /*
         * NOTE! We'd better ACK the irq immediately,
         * because timer handling can be slow.
+        *
+        * update_process_times() expects us to have done irq_enter().
+        * Besides, if we don't timer interrupts ignore the global
+        * interrupt lock, which is the WrongThing (tm) to do.
         */
-       ack_APIC_irq();
+       entering_ack_irq();
+       local_apic_timer_interrupt();
+       exiting_irq();
+       set_irq_regs(old_regs);
+ }
+ void __irq_entry smp_trace_apic_timer_interrupt(struct pt_regs *regs)
+ {
+       struct pt_regs *old_regs = set_irq_regs(regs);
        /*
+        * NOTE! We'd better ACK the irq immediately,
+        * because timer handling can be slow.
+        *
         * update_process_times() expects us to have done irq_enter().
         * Besides, if we don't timer interrupts ignore the global
         * interrupt lock, which is the WrongThing (tm) to do.
         */
-       irq_enter();
-       exit_idle();
+       entering_ack_irq();
+       trace_local_timer_entry(LOCAL_TIMER_VECTOR);
        local_apic_timer_interrupt();
-       irq_exit();
+       trace_local_timer_exit(LOCAL_TIMER_VECTOR);
+       exiting_irq();
  
        set_irq_regs(old_regs);
  }
@@@ -1907,12 -1926,10 +1926,10 @@@ int __init APIC_init_uniprocessor(void
  /*
   * This interrupt should _never_ happen with our APIC/SMP architecture
   */
void smp_spurious_interrupt(struct pt_regs *regs)
static inline void __smp_spurious_interrupt(void)
  {
        u32 v;
  
-       irq_enter();
-       exit_idle();
        /*
         * Check if this really is a spurious interrupt and ACK it
         * if it is a vectored one.  Just in case...
        /* see sw-dev-man vol 3, chapter 7.4.13.5 */
        pr_info("spurious APIC interrupt on CPU#%d, "
                "should never happen.\n", smp_processor_id());
-       irq_exit();
+ }
+ void smp_spurious_interrupt(struct pt_regs *regs)
+ {
+       entering_irq();
+       __smp_spurious_interrupt();
+       exiting_irq();
+ }
+ void smp_trace_spurious_interrupt(struct pt_regs *regs)
+ {
+       entering_irq();
+       trace_spurious_apic_entry(SPURIOUS_APIC_VECTOR);
+       __smp_spurious_interrupt();
+       trace_spurious_apic_exit(SPURIOUS_APIC_VECTOR);
+       exiting_irq();
  }
  
  /*
   * This interrupt should never happen with our APIC/SMP architecture
   */
void smp_error_interrupt(struct pt_regs *regs)
static inline void __smp_error_interrupt(struct pt_regs *regs)
  {
        u32 v0, v1;
        u32 i = 0;
                "Illegal register address",     /* APIC Error Bit 7 */
        };
  
-       irq_enter();
-       exit_idle();
        /* First tickle the hardware, only then report what went on. -- REW */
        v0 = apic_read(APIC_ESR);
        apic_write(APIC_ESR, 0);
  
        apic_printk(APIC_DEBUG, KERN_CONT "\n");
  
-       irq_exit();
+ }
+ void smp_error_interrupt(struct pt_regs *regs)
+ {
+       entering_irq();
+       __smp_error_interrupt(regs);
+       exiting_irq();
+ }
+ void smp_trace_error_interrupt(struct pt_regs *regs)
+ {
+       entering_irq();
+       trace_error_apic_entry(ERROR_APIC_VECTOR);
+       __smp_error_interrupt(regs);
+       trace_error_apic_exit(ERROR_APIC_VECTOR);
+       exiting_irq();
  }
  
  /**
@@@ -2302,7 -2347,7 +2347,7 @@@ static void lapic_resume(void
        apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
        apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
        apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
 -#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL)
 +#if defined(CONFIG_X86_MCE_INTEL)
        if (maxlvt >= 5)
                apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
  #endif
index a4a07c0acb1f2e0428055b00c709ced475c41d9d,d9c8c0947ec2ee37e158393a689eba95b0f7e43e..548bd039784e631570a7628137d16cb8213ec411
@@@ -711,9 -711,10 +711,9 @@@ static void __init early_identify_cpu(s
                return;
  
        cpu_detect(c);
 -
        get_cpu_vendor(c);
 -
        get_cpu_cap(c);
 +      fpu_detect(c);
  
        if (this_cpu->c_early_init)
                this_cpu->c_early_init(c);
  
        if (this_cpu->c_bsp_init)
                this_cpu->c_bsp_init(c);
 +
 +      setup_force_cpu_cap(X86_FEATURE_ALWAYS);
  }
  
  void __init early_cpu_init(void)
@@@ -1072,8 -1071,8 +1072,8 @@@ __setup("clearcpuid=", setup_disablecpu
  
  #ifdef CONFIG_X86_64
  struct desc_ptr idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) idt_table };
- struct desc_ptr nmi_idt_descr = { NR_VECTORS * 16 - 1,
-                                   (unsigned long) nmi_idt_table };
+ struct desc_ptr debug_idt_descr = { NR_VECTORS * 16 - 1,
+                                   (unsigned long) debug_idt_table };
  
  DEFINE_PER_CPU_FIRST(union irq_stack_union,
                     irq_stack_union) __aligned(PAGE_SIZE);
@@@ -1149,20 -1148,20 +1149,20 @@@ int is_debug_stack(unsigned long addr
                 addr > (__get_cpu_var(debug_stack_addr) - DEBUG_STKSZ));
  }
  
static DEFINE_PER_CPU(u32, debug_stack_use_ctr);
DEFINE_PER_CPU(u32, debug_idt_ctr);
  
  void debug_stack_set_zero(void)
  {
-       this_cpu_inc(debug_stack_use_ctr);
-       load_idt((const struct desc_ptr *)&nmi_idt_descr);
+       this_cpu_inc(debug_idt_ctr);
+       load_current_idt();
  }
  
  void debug_stack_reset(void)
  {
-       if (WARN_ON(!this_cpu_read(debug_stack_use_ctr)))
+       if (WARN_ON(!this_cpu_read(debug_idt_ctr)))
                return;
-       if (this_cpu_dec_return(debug_stack_use_ctr) == 0)
-               load_idt((const struct desc_ptr *)&idt_descr);
+       if (this_cpu_dec_return(debug_idt_ctr) == 0)
+               load_current_idt();
  }
  
  #else /* CONFIG_X86_64 */
@@@ -1258,7 -1257,7 +1258,7 @@@ void __cpuinit cpu_init(void
        switch_to_new_gdt(cpu);
        loadsegment(fs, 0);
  
-       load_idt((const struct desc_ptr *)&idt_descr);
+       load_current_idt();
  
        memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8);
        syscall_init();
@@@ -1335,7 -1334,7 +1335,7 @@@ void __cpuinit cpu_init(void
        if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
                clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
  
-       load_idt(&idt_descr);
+       load_current_idt();
        switch_to_new_gdt(cpu);
  
        /*
        fpu_init();
  }
  #endif
 +
 +#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS
 +void warn_pre_alternatives(void)
 +{
 +      WARN(1, "You're using static_cpu_has before alternatives have run!\n");
 +}
 +EXPORT_SYMBOL_GPL(warn_pre_alternatives);
 +#endif
 +
 +inline bool __static_cpu_has_safe(u16 bit)
 +{
 +      return boot_cpu_has(bit);
 +}
 +EXPORT_SYMBOL_GPL(__static_cpu_has_safe);
index 5fe1fb2d1490a286bb11c08f286cf35096130263,53d639831a6c4b1819cb61995a0377e248bbbcd3..1b69951a81e2b61bff752621872d5750736f96d4
@@@ -365,7 -365,7 +365,7 @@@ ENDPROC(native_usergs_sysret64
        /*CFI_REL_OFFSET        ss,0*/
        pushq_cfi %rax /* rsp */
        CFI_REL_OFFSET  rsp,0
 -      pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_BIT1) /* eflags - interrupts on */
 +      pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_FIXED) /* eflags - interrupts on */
        /*CFI_REL_OFFSET        rflags,0*/
        pushq_cfi $__KERNEL_CS /* cs */
        /*CFI_REL_OFFSET        cs,0*/
@@@ -1138,7 -1138,7 +1138,7 @@@ END(common_interrupt
  /*
   * APIC interrupts.
   */
- .macro apicinterrupt num sym do_sym
+ .macro apicinterrupt3 num sym do_sym
  ENTRY(\sym)
        INTR_FRAME
        ASM_CLAC
  END(\sym)
  .endm
  
+ #ifdef CONFIG_TRACING
+ #define trace(sym) trace_##sym
+ #define smp_trace(sym) smp_trace_##sym
+ .macro trace_apicinterrupt num sym
+ apicinterrupt3 \num trace(\sym) smp_trace(\sym)
+ .endm
+ #else
+ .macro trace_apicinterrupt num sym do_sym
+ .endm
+ #endif
+ .macro apicinterrupt num sym do_sym
+ apicinterrupt3 \num \sym \do_sym
+ trace_apicinterrupt \num \sym
+ .endm
  #ifdef CONFIG_SMP
- apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \
+ apicinterrupt3 IRQ_MOVE_CLEANUP_VECTOR \
        irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt
- apicinterrupt REBOOT_VECTOR \
+ apicinterrupt3 REBOOT_VECTOR \
        reboot_interrupt smp_reboot_interrupt
  #endif
  
  #ifdef CONFIG_X86_UV
- apicinterrupt UV_BAU_MESSAGE \
+ apicinterrupt3 UV_BAU_MESSAGE \
        uv_bau_message_intr1 uv_bau_message_interrupt
  #endif
  apicinterrupt LOCAL_TIMER_VECTOR \
@@@ -1167,14 -1184,19 +1184,19 @@@ apicinterrupt X86_PLATFORM_IPI_VECTOR 
        x86_platform_ipi smp_x86_platform_ipi
  
  #ifdef CONFIG_HAVE_KVM
- apicinterrupt POSTED_INTR_VECTOR \
+ apicinterrupt3 POSTED_INTR_VECTOR \
        kvm_posted_intr_ipi smp_kvm_posted_intr_ipi
  #endif
  
+ #ifdef CONFIG_X86_MCE_THRESHOLD
  apicinterrupt THRESHOLD_APIC_VECTOR \
        threshold_interrupt smp_threshold_interrupt
+ #endif
+ #ifdef CONFIG_X86_THERMAL_VECTOR
  apicinterrupt THERMAL_APIC_VECTOR \
        thermal_interrupt smp_thermal_interrupt
+ #endif
  
  #ifdef CONFIG_SMP
  apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \
@@@ -1451,13 -1473,13 +1473,13 @@@ ENTRY(xen_failsafe_callback
        CFI_ENDPROC
  END(xen_failsafe_callback)
  
- apicinterrupt HYPERVISOR_CALLBACK_VECTOR \
+ apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \
        xen_hvm_callback_vector xen_evtchn_do_upcall
  
  #endif /* CONFIG_XEN */
  
  #if IS_ENABLED(CONFIG_HYPERV)
- apicinterrupt HYPERVISOR_CALLBACK_VECTOR \
+ apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \
        hyperv_callback_vector hyperv_vector_handler
  #endif /* CONFIG_HYPERV */
  
diff --combined arch/x86/kernel/traps.c
index ee3d8e510504b1be01a69018e8be50ce82038cf5,d27182d6ed2ab3f5ad7af8d1a58def38e6b31053..b0865e88d3ccf4e272e5dbf654ff5de25492e672
@@@ -254,9 -254,6 +254,9 @@@ dotraplinkage void do_double_fault(stru
        tsk->thread.error_code = error_code;
        tsk->thread.trap_nr = X86_TRAP_DF;
  
 +#ifdef CONFIG_DOUBLEFAULT
 +      df_debug(regs, error_code);
 +#endif
        /*
         * This is always a kernel trap and never fixable (and thus must
         * never return).
@@@ -440,7 -437,7 +440,7 @@@ dotraplinkage void __kprobes do_debug(s
        /* Store the virtualized DR6 value */
        tsk->thread.debugreg6 = dr6;
  
 -      if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code,
 +      if (notify_die(DIE_DEBUG, "debug", regs, (long)&dr6, error_code,
                                                        SIGTRAP) == NOTIFY_STOP)
                goto exit;
  
@@@ -788,7 -785,7 +788,7 @@@ void __init trap_init(void
        x86_init.irqs.trap_init();
  
  #ifdef CONFIG_X86_64
-       memcpy(&nmi_idt_table, &idt_table, IDT_ENTRIES * 16);
+       memcpy(&debug_idt_table, &idt_table, IDT_ENTRIES * 16);
        set_nmi_gate(X86_TRAP_DB, &debug);
        set_nmi_gate(X86_TRAP_BP, &int3);
  #endif