Received: by 2002:a25:e7d8:0:0:0:0:0 with SMTP id e207csp1054091ybh; Thu, 12 Mar 2020 16:20:28 -0700 (PDT) X-Google-Smtp-Source: ADFU+vvpGqnzeWE1wq0oVrKDNeSYo4f+7JN7AMNSKXghV0T/ADGwjlB+Pctf7wdx/aTigck5BHUz X-Received: by 2002:a05:6808:4cd:: with SMTP id a13mr4822786oie.137.1584055228638; Thu, 12 Mar 2020 16:20:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1584055228; cv=none; d=google.com; s=arc-20160816; b=Rcj0g22Vykj3o+DW9hHMJ66o8inWtatiJxBh8ROBO0tyjLBKmvxf0Bsjt0dnTXGl1w HP2kQtGBL4wNfbFF3X8Fd+SNzAkjbRlsqcm7Wewoqzx8MryCET9xT3nEV0duL+iarOZO gsMGnWnc1jzK1C2Gi6C2UmV3tBlHAze2oDZu3+xdhyQrmA6+sQCfa/nn/W0jdkmieyZh G/VyIeIMAnzHYKUrWfRzP0l13hU1VoJAACUbGd36RPV6eeNNlAuulDmDLuxVAH8drEG2 nYHYeSzQHm63qPtBa5B8JtXtXXtICvHn6f6xaMwDXwbLkusKETmKLAPUbv76dpHlxV06 SuGA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=24uCzlKCP9xmj1QeclKyMR0MMS3/JmPHq0CBDqNFcYE=; b=P9+gLzuWDt1Mk8hAt3WgbzBv0roVR5ntxEhIsnhYORo1akzfEXgwOruJouD+UeKDj8 LK64O+Dg/aQOI91afuxcXj6/Y6yppdK+v675f24+YazG85k9S3d/PPm/8SDGqNhVBvOh NkE+S6vjh5ZowjP3uZIqmN+ELZsMwDJhd5Xr7KgSm9IDBkZ+y8OajbHCBQL/k+UfSrEx LxE+I2zFUWT9criFtU8QVldoEczKcNqxQSIVqe8S0jzEXrD6fLnSL24pDg1jrrsEwXq9 Gr0yTcSasHG30nnyY5AaV9Rq3QxJmp2nL1LXE5fFNzMlCzr6XxeecwTl4CiuEsCCXjSJ qt0w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j8si3494495oib.260.2020.03.12.16.20.15; Thu, 12 Mar 2020 16:20:28 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726834AbgCLXTV (ORCPT + 99 others); Thu, 12 Mar 2020 19:19:21 -0400 Received: from mga04.intel.com ([192.55.52.120]:41667 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726710AbgCLXTV (ORCPT ); Thu, 12 Mar 2020 19:19:21 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Mar 2020 16:19:20 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,546,1574150400"; d="scan'208";a="322629795" Received: from tassilo.jf.intel.com (HELO tassilo.localdomain) ([10.7.201.21]) by orsmga001.jf.intel.com with ESMTP; 12 Mar 2020 16:19:19 -0700 Received: by tassilo.localdomain (Postfix, from userid 1000) id DAC7B301BF9; Thu, 12 Mar 2020 16:19:19 -0700 (PDT) From: Andi Kleen To: x86@kernel.org Cc: linux-kernel@vger.kernel.org, Andi Kleen Subject: [PATCH] x86: Add trace points to (nearly) all vectors Date: Thu, 12 Mar 2020 16:19:16 -0700 Message-Id: <20200312231916.132753-1-andi@firstfloor.org> X-Mailer: git-send-email 2.24.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Andi Kleen In some scenarios it can be useful to count or trace every kernel entry. Most entry paths are covered by trace points already, but some of the more obscure entry points do not have trace points. The most common uncovered one was KVM async page fault. This patch kit adds trace points to all the other vectors, except UV (anyone uses?), Xen (generic code), reboot (pointless) To avoid creating a lot of new trace points this just lumps them all together into a "other_vector" trace point, because they're all fairly obscure and uncommon, and can be figured out from the number when needed, or filtered using the filter expression. This makes the needed perf command line much shorter. The exception is the KVM async page fault which is fairly common inside KVM guests, so is worth breaking out. The Xen vectors could be done done as a followon if desired. Signed-off-by: Andi Kleen -- v2: Fix build errors found by 0day for some configurations. v3: Finally use correct CONFIG symbol to check for KVM guest. Thanks 0day. v4: Fix build for 32bit with !CONFIG_X86_LOCAL_APIC. Thanks 0day. v5: Rebase. No changes. --- arch/x86/hyperv/hv_init.c | 3 ++ arch/x86/include/asm/trace/irq_vectors.h | 17 ++++++++-- arch/x86/kernel/apic/vector.c | 3 ++ arch/x86/kernel/cpu/mce/core.c | 3 ++ arch/x86/kernel/irq.c | 6 ++++ arch/x86/kernel/kvm.c | 5 +++ arch/x86/kernel/traps.c | 40 +++++++++++++++++++----- 7 files changed, 67 insertions(+), 10 deletions(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 2db3972c0e0f..d97e570e37b6 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -21,6 +21,7 @@ #include #include #include +#include void *hv_hypercall_pg; EXPORT_SYMBOL_GPL(hv_hypercall_pg); @@ -144,8 +145,10 @@ __visible void __irq_entry hyperv_reenlightenment_intr(struct pt_regs *regs) inc_irq_stat(irq_hv_reenlightenment_count); + trace_other_vector_entry(HYPERV_REENLIGHTENMENT_VECTOR); schedule_delayed_work(&hv_reenlightenment_work, HZ/10); + trace_other_vector_exit(HYPERV_REENLIGHTENMENT_VECTOR); exiting_irq(); } diff --git a/arch/x86/include/asm/trace/irq_vectors.h b/arch/x86/include/asm/trace/irq_vectors.h index 33b9d0f0aafe..b50b3dc02e71 100644 --- a/arch/x86/include/asm/trace/irq_vectors.h +++ b/arch/x86/include/asm/trace/irq_vectors.h @@ -8,8 +8,6 @@ #include #include -#ifdef CONFIG_X86_LOCAL_APIC - extern int trace_resched_ipi_reg(void); extern void trace_resched_ipi_unreg(void); @@ -49,6 +47,8 @@ DEFINE_EVENT_FN(x86_irq_vector, name##_exit, \ trace_resched_ipi_reg, \ trace_resched_ipi_unreg); +#ifdef CONFIG_X86_LOCAL_APIC + /* * local_timer - called when entering/exiting a local timer interrupt * vector handler @@ -138,6 +138,19 @@ DEFINE_IRQ_VECTOR_EVENT(deferred_error_apic); DEFINE_IRQ_VECTOR_EVENT(thermal_apic); #endif +#endif /* CONFIG_X86_LOCAL_APIC */ + +#ifdef CONFIG_KVM_GUEST +DEFINE_IRQ_VECTOR_EVENT(async_page_fault); +#endif + +/* + * Handle all other vectors. + */ +DEFINE_IRQ_VECTOR_EVENT(other_vector); + +#ifdef CONFIG_X86_LOCAL_APIC + TRACE_EVENT(vector_config, TP_PROTO(unsigned int irq, unsigned int vector, diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 2c5676b0a6e7..2e883f38b895 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -860,6 +860,7 @@ asmlinkage __visible void __irq_entry smp_irq_move_cleanup_interrupt(void) struct hlist_node *tmp; entering_ack_irq(); + trace_other_vector_entry(IRQ_MOVE_CLEANUP_VECTOR); /* Prevent vectors vanishing under us */ raw_spin_lock(&vector_lock); @@ -884,6 +885,8 @@ asmlinkage __visible void __irq_entry smp_irq_move_cleanup_interrupt(void) } raw_spin_unlock(&vector_lock); + trace_other_vector_exit(IRQ_MOVE_CLEANUP_VECTOR); + /* Prevent vectors vanishing under us */ exiting_irq(); } diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c index 743370ee4983..f593bd6b0ed7 100644 --- a/arch/x86/kernel/cpu/mce/core.c +++ b/arch/x86/kernel/cpu/mce/core.c @@ -61,6 +61,9 @@ static DEFINE_MUTEX(mce_sysfs_mutex); #define CREATE_TRACE_POINTS #include +#undef CREATE_TRACE_POINTS +#include + #define SPINUNIT 100 /* 100ns */ DEFINE_PER_CPU(unsigned, mce_exception_count); diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 21efee32e2b1..f57c148dc578 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -308,8 +308,10 @@ __visible void smp_kvm_posted_intr_ipi(struct pt_regs *regs) struct pt_regs *old_regs = set_irq_regs(regs); entering_ack_irq(); + trace_other_vector_entry(POSTED_INTR_VECTOR); inc_irq_stat(kvm_posted_intr_ipis); exiting_irq(); + trace_other_vector_exit(POSTED_INTR_VECTOR); set_irq_regs(old_regs); } @@ -321,8 +323,10 @@ __visible void smp_kvm_posted_intr_wakeup_ipi(struct pt_regs *regs) struct pt_regs *old_regs = set_irq_regs(regs); entering_ack_irq(); + trace_other_vector_entry(POSTED_INTR_WAKEUP_VECTOR); inc_irq_stat(kvm_posted_intr_wakeup_ipis); kvm_posted_intr_wakeup_handler(); + trace_other_vector_exit(POSTED_INTR_WAKEUP_VECTOR); exiting_irq(); set_irq_regs(old_regs); } @@ -335,7 +339,9 @@ __visible void smp_kvm_posted_intr_nested_ipi(struct pt_regs *regs) struct pt_regs *old_regs = set_irq_regs(regs); entering_ack_irq(); + trace_other_vector_entry(POSTED_INTR_NESTED_VECTOR); inc_irq_stat(kvm_posted_intr_nested_ipis); + trace_other_vector_exit(POSTED_INTR_NESTED_VECTOR); exiting_irq(); set_irq_regs(old_regs); } diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index e820568ed4d5..8d915b559617 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -33,6 +33,7 @@ #include #include #include +#include static int kvmapf = 1; @@ -246,6 +247,8 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned lon { enum ctx_state prev_state; + trace_async_page_fault_entry(0); + switch (kvm_read_and_reset_pf_reason()) { default: do_page_fault(regs, error_code, address); @@ -262,6 +265,8 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned lon rcu_irq_exit(); break; } + + trace_async_page_fault_exit(0); } NOKPROBE_SYMBOL(do_async_page_fault); diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 4bb0f8447112..6ccc01d74747 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -62,6 +62,8 @@ #include #include +#include + #ifdef CONFIG_X86_64 #include #include @@ -264,19 +266,22 @@ static void do_error_trap(struct pt_regs *regs, long error_code, char *str, unsigned long trapnr, int signr, int sicode, void __user *addr) { RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); + trace_other_vector_entry(trapnr); /* * WARN*()s end up here; fix them up before we call the * notifier chain. */ if (!user_mode(regs) && fixup_bug(regs, trapnr)) - return; + goto out; if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) != NOTIFY_STOP) { cond_local_irq_enable(regs); do_trap(trapnr, signr, str, regs, error_code, sicode, addr); } +out: + trace_other_vector_exit(trapnr); } #define IP ((void __user *)uprobe_get_trap_addr(regs)) @@ -433,9 +438,10 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) const struct mpx_bndcsr *bndcsr; RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); + trace_other_vector_entry(X86_TRAP_BR); if (notify_die(DIE_TRAP, "bounds", regs, error_code, X86_TRAP_BR, SIGSEGV) == NOTIFY_STOP) - return; + goto exit; cond_local_irq_enable(regs); if (!user_mode(regs)) @@ -501,6 +507,8 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) die("bounds", regs, error_code); } +exit: + trace_other_vector_exit(X86_TRAP_BR); return; exit_trap: @@ -512,6 +520,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) * time.. */ do_trap(X86_TRAP_BR, SIGSEGV, "bounds", regs, error_code, 0, NULL); + goto exit; } dotraplinkage void @@ -522,22 +531,23 @@ do_general_protection(struct pt_regs *regs, long error_code) RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); cond_local_irq_enable(regs); + trace_other_vector_entry(X86_TRAP_GP); if (static_cpu_has(X86_FEATURE_UMIP)) { if (user_mode(regs) && fixup_umip_exception(regs)) - return; + goto out; } if (v8086_mode(regs)) { local_irq_enable(); handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); - return; + goto out; } tsk = current; if (!user_mode(regs)) { if (fixup_exception(regs, X86_TRAP_GP, error_code, 0)) - return; + goto out; tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_GP; @@ -549,12 +559,12 @@ do_general_protection(struct pt_regs *regs, long error_code) */ if (!preemptible() && kprobe_running() && kprobe_fault_handler(regs, X86_TRAP_GP)) - return; + goto out; if (notify_die(DIE_GPF, desc, regs, error_code, X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP) die(desc, regs, error_code); - return; + goto out; } tsk->thread.error_code = error_code; @@ -563,6 +573,9 @@ do_general_protection(struct pt_regs *regs, long error_code) show_signal(tsk, SIGSEGV, "", desc, regs, error_code); force_sig(SIGSEGV); + +out: + trace_other_vector_exit(X86_TRAP_GP); } NOKPROBE_SYMBOL(do_general_protection); @@ -588,6 +601,7 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) * This means that we can't schedule. That's okay. */ ist_enter(regs); + trace_other_vector_entry(X86_TRAP_BP); RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, @@ -609,6 +623,7 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) cond_local_irq_disable(regs); exit: + trace_other_vector_exit(X86_TRAP_BP); ist_exit(regs); } NOKPROBE_SYMBOL(do_int3); @@ -714,6 +729,7 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) int si_code; ist_enter(regs); + trace_other_vector_entry(X86_TRAP_DB); get_debugreg(dr6, 6); /* @@ -806,6 +822,7 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) debug_stack_usage_dec(); exit: + trace_other_vector_exit(X86_TRAP_DB); ist_exit(regs); } NOKPROBE_SYMBOL(do_debug); @@ -858,14 +875,18 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) { RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); + trace_other_vector_entry(X86_TRAP_MF); math_error(regs, error_code, X86_TRAP_MF); + trace_other_vector_exit(X86_TRAP_MF); } dotraplinkage void do_simd_coprocessor_error(struct pt_regs *regs, long error_code) { RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); + trace_other_vector_entry(X86_TRAP_XF); math_error(regs, error_code, X86_TRAP_XF); + trace_other_vector_exit(X86_TRAP_XF); } dotraplinkage void @@ -881,6 +902,7 @@ do_device_not_available(struct pt_regs *regs, long error_code) RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); + trace_other_vector_entry(X86_TRAP_NM); #ifdef CONFIG_MATH_EMULATION if (!boot_cpu_has(X86_FEATURE_FPU) && (cr0 & X86_CR0_EM)) { struct math_emu_info info = { }; @@ -889,7 +911,7 @@ do_device_not_available(struct pt_regs *regs, long error_code) info.regs = regs; math_emulate(&info); - return; + goto out; } #endif @@ -905,6 +927,8 @@ do_device_not_available(struct pt_regs *regs, long error_code) */ die("unexpected #NM exception", regs, error_code); } +out: __maybe_unused; + trace_other_vector_exit(X86_TRAP_NM); } NOKPROBE_SYMBOL(do_device_not_available); -- 2.24.1