svn commit: r334827 - in head/sys: amd64/amd64 arm/arm dev/hwpmc i386/i386 kern mips/atheros mips/cavium powerpc/powerpc sys

Matt Macy mmacy at FreeBSD.org
Fri Jun 8 04:58:08 UTC 2018


Author: mmacy
Date: Fri Jun  8 04:58:03 2018
New Revision: 334827
URL: https://svnweb.freebsd.org/changeset/base/334827

Log:
  hwpmc: simplify calling convention for hwpmc interrupt handling
  
  pmc_process_interrupt takes 5 arguments when only 3 are needed.
  cpu is always available in curcpu and inuserspace can always be
  derived from the passed trapframe.
  
  While facially a reasonable cleanup this change was motivated
  by the need to workaround a compiler bug.
  
  core2_intr(cpu, tf) ->
    pmc_process_interrupt(cpu, ring, pmc, tf, inuserspace) ->
      pmc_add_sample(cpu, ring, pm, tf, inuserspace)
  
  In the process of optimizing the tail call the tf pointer was getting
  clobbered:
  
  (kgdb) up
      at /storage/mmacy/devel/freebsd/sys/dev/hwpmc/hwpmc_mod.c:4709
  4709                                pmc_save_kernel_callchain(ps->ps_pc,
  (kgdb) up
  1205                    error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
  
  resulting in a crash in pmc_save_kernel_callchain.

Modified:
  head/sys/amd64/amd64/trap.c
  head/sys/arm/arm/pmu.c
  head/sys/dev/hwpmc/hwpmc_amd.c
  head/sys/dev/hwpmc/hwpmc_arm64.c
  head/sys/dev/hwpmc/hwpmc_armv7.c
  head/sys/dev/hwpmc/hwpmc_core.c
  head/sys/dev/hwpmc/hwpmc_mips.c
  head/sys/dev/hwpmc/hwpmc_mod.c
  head/sys/dev/hwpmc/hwpmc_mpc7xxx.c
  head/sys/dev/hwpmc/hwpmc_ppc970.c
  head/sys/dev/hwpmc/hwpmc_soft.c
  head/sys/i386/i386/trap.c
  head/sys/kern/kern_pmc.c
  head/sys/mips/atheros/apb.c
  head/sys/mips/cavium/octeon_pmc.c
  head/sys/powerpc/powerpc/interrupt.c
  head/sys/sys/pmc.h
  head/sys/sys/pmckern.h

Modified: head/sys/amd64/amd64/trap.c
==============================================================================
--- head/sys/amd64/amd64/trap.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/amd64/amd64/trap.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -214,7 +214,7 @@ trap(struct trapframe *frame)
 		 * the NMI was consumed by it and we can return immediately.
 		 */
 		if (pmc_intr != NULL &&
-		    (*pmc_intr)(PCPU_GET(cpuid), frame) != 0)
+		    (*pmc_intr)(frame) != 0)
 			return;
 #endif
 

Modified: head/sys/arm/arm/pmu.c
==============================================================================
--- head/sys/arm/arm/pmu.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/arm/arm/pmu.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -123,7 +123,7 @@ pmu_intr(void *arg)
 	/* Only call into the HWPMC framework if we know there is work. */
 	if (r != 0 && pmc_intr) {
 		tf = arg;
-		(*pmc_intr)(PCPU_GET(cpuid), tf);
+		(*pmc_intr)(tf);
 	}
 #endif
 

Modified: head/sys/dev/hwpmc/hwpmc_amd.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_amd.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/dev/hwpmc/hwpmc_amd.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -627,14 +627,15 @@ amd_stop_pmc(int cpu, int ri)
  */
 
 static int
-amd_intr(int cpu, struct trapframe *tf)
+amd_intr(struct trapframe *tf)
 {
-	int i, error, retval;
+	int i, error, retval, cpu;
 	uint32_t config, evsel, perfctr;
 	struct pmc *pm;
 	struct amd_cpu *pac;
 	pmc_value_t v;
 
+	cpu = curcpu;
 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 	    ("[amd,%d] out of range CPU %d", __LINE__, cpu));
 
@@ -688,8 +689,7 @@ amd_intr(int cpu, struct trapframe *tf)
 		wrmsr(perfctr, AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(v));
 
 		/* Restart the counter if logging succeeded. */
-		error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
-		    TRAPF_USERMODE(tf));
+		error = pmc_process_interrupt(PMC_HR, pm, tf);
 		if (error == 0)
 			wrmsr(evsel, config);
 	}

Modified: head/sys/dev/hwpmc/hwpmc_arm64.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_arm64.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/dev/hwpmc/hwpmc_arm64.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -323,18 +323,19 @@ arm64_release_pmc(int cpu, int ri, struct pmc *pmc)
 }
 
 static int
-arm64_intr(int cpu, struct trapframe *tf)
+arm64_intr(struct trapframe *tf)
 {
 	struct arm64_cpu *pc;
 	int retval, ri;
 	struct pmc *pm;
 	int error;
-	int reg;
+	int reg, cpu;
 
 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 	    ("[arm64,%d] CPU %d out of range", __LINE__, cpu));
 
 	retval = 0;
+	cpu = curcpu;
 	pc = arm64_pcpu[cpu];
 
 	for (ri = 0; ri < arm64_npmcs; ri++) {
@@ -357,8 +358,7 @@ arm64_intr(int cpu, struct trapframe *tf)
 		if (pm->pm_state != PMC_STATE_RUNNING)
 			continue;
 
-		error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
-		    TRAPF_USERMODE(tf));
+		error = pmc_process_interrupt(PMC_HR, pm, tf);
 		if (error)
 			arm64_stop_pmc(cpu, ri);
 

Modified: head/sys/dev/hwpmc/hwpmc_armv7.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_armv7.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/dev/hwpmc/hwpmc_armv7.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -307,18 +307,19 @@ armv7_release_pmc(int cpu, int ri, struct pmc *pmc)
 }
 
 static int
-armv7_intr(int cpu, struct trapframe *tf)
+armv7_intr(struct trapframe *tf)
 {
 	struct armv7_cpu *pc;
 	int retval, ri;
 	struct pmc *pm;
 	int error;
-	int reg;
+	int reg, cpu;
 
 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
 	    ("[armv7,%d] CPU %d out of range", __LINE__, cpu));
 
 	retval = 0;
+	cpu = curcpu;
 	pc = armv7_pcpu[cpu];
 
 	for (ri = 0; ri < armv7_npmcs; ri++) {
@@ -348,8 +349,7 @@ armv7_intr(int cpu, struct trapframe *tf)
 		if (pm->pm_state != PMC_STATE_RUNNING)
 			continue;
 
-		error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
-		    TRAPF_USERMODE(tf));
+		error = pmc_process_interrupt(PMC_HR, pm, tf);
 		if (error)
 			armv7_stop_pmc(cpu, ri);
 

Modified: head/sys/dev/hwpmc/hwpmc_core.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_core.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/dev/hwpmc/hwpmc_core.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -1056,7 +1056,7 @@ iap_initialize(struct pmc_mdep *md, int maxcpu, int np
 }
 
 static int
-core_intr(int cpu, struct trapframe *tf)
+core_intr(struct trapframe *tf)
 {
 	pmc_value_t v;
 	struct pmc *pm;
@@ -1064,11 +1064,11 @@ core_intr(int cpu, struct trapframe *tf)
 	int error, found_interrupt, ri;
 	uint64_t msr;
 
-	PMCDBG3(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
+	PMCDBG3(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", curcpu, (void *) tf,
 	    TRAPF_USERMODE(tf));
 
 	found_interrupt = 0;
-	cc = core_pcpu[cpu];
+	cc = core_pcpu[curcpu];
 
 	for (ri = 0; ri < core_iap_npmc; ri++) {
 
@@ -1084,8 +1084,7 @@ core_intr(int cpu, struct trapframe *tf)
 		if (pm->pm_state != PMC_STATE_RUNNING)
 			continue;
 
-		error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
-		    TRAPF_USERMODE(tf));
+		error = pmc_process_interrupt(PMC_HR, pm, tf);
 
 		v = pm->pm_sc.pm_reloadcount;
 		v = iap_reload_count_to_perfctr_value(v);
@@ -1117,7 +1116,7 @@ core_intr(int cpu, struct trapframe *tf)
 }
 
 static int
-core2_intr(int cpu, struct trapframe *tf)
+core2_intr(struct trapframe *tf)
 {
 	int error, found_interrupt, n;
 	uint64_t flag, intrstatus, intrenable, msr;
@@ -1141,7 +1140,7 @@ core2_intr(int cpu, struct trapframe *tf)
 	    (uintmax_t) intrstatus);
 
 	found_interrupt = 0;
-	cc = core_pcpu[cpu];
+	cc = core_pcpu[curcpu];
 
 	KASSERT(cc != NULL, ("[core,%d] null pcpu", __LINE__));
 
@@ -1173,8 +1172,7 @@ core2_intr(int cpu, struct trapframe *tf)
 		    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 			continue;
 
-		error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
-		    TRAPF_USERMODE(tf));
+		error = pmc_process_interrupt(PMC_HR, pm, tf);
 
 		if (error)
 			intrenable &= ~flag;
@@ -1184,7 +1182,7 @@ core2_intr(int cpu, struct trapframe *tf)
 		/* Reload sampling count. */
 		wrmsr(IAF_CTR0 + n, v);
 
-		PMCDBG4(MDP,INT, 1, "iaf-intr cpu=%d error=%d v=%jx(%jx)", cpu,
+		PMCDBG4(MDP,INT, 1, "iaf-intr cpu=%d error=%d v=%jx(%jx)", curcpu,
 		    error, (uintmax_t) v, (uintmax_t) rdpmc(IAF_RI_TO_MSR(n)));
 	}
 
@@ -1202,8 +1200,7 @@ core2_intr(int cpu, struct trapframe *tf)
 		    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
 			continue;
 
-		error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
-		    TRAPF_USERMODE(tf));
+		error = pmc_process_interrupt(PMC_HR, pm, tf);
 		if (error)
 			intrenable &= ~flag;
 

Modified: head/sys/dev/hwpmc/hwpmc_mips.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_mips.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/dev/hwpmc/hwpmc_mips.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -289,8 +289,7 @@ mips_pmc_intr(int cpu, struct trapframe *tf)
 		retval = 1;
 		if (pm->pm_state != PMC_STATE_RUNNING)
 			continue;
-		error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
-		    TRAPF_USERMODE(tf));
+		error = pmc_process_interrupt(PMC_HR, pm, tf);
 		if (error) {
 			/* Clear/disable the relevant counter */
 			if (ri == 0)

Modified: head/sys/dev/hwpmc/hwpmc_mod.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_mod.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/dev/hwpmc/hwpmc_mod.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -207,8 +207,7 @@ static int	pmc_debugflags_parse(char *newstr, char *fe
 #endif
 
 static int	load(struct module *module, int cmd, void *arg);
-static int	pmc_add_sample(int cpu, int ring, struct pmc *pm,
-    struct trapframe *tf, int inuserspace);
+static int	pmc_add_sample(int ring, struct pmc *pm, struct trapframe *tf);
 static void	pmc_add_thread_descriptors_from_proc(struct proc *p,
     struct pmc_process *pp);
 static int	pmc_attach_process(struct proc *p, struct pmc *pm);
@@ -4640,10 +4639,9 @@ pmc_post_callchain_callback(void)
  */
 
 static int
-pmc_add_sample(int cpu, int ring, struct pmc *pm, struct trapframe *tf,
-    int inuserspace)
+pmc_add_sample(int ring, struct pmc *pm, struct trapframe *tf)
 {
-	int error, callchaindepth;
+	int error, cpu, callchaindepth, inuserspace;
 	struct thread *td;
 	struct pmc_sample *ps;
 	struct pmc_samplebuffer *psb;
@@ -4653,8 +4651,9 @@ pmc_add_sample(int cpu, int ring, struct pmc *pm, stru
 	/*
 	 * Allocate space for a sample buffer.
 	 */
+	cpu = curcpu;
 	psb = pmc_pcpu[cpu]->pc_sb[ring];
-
+	inuserspace = TRAPF_USERMODE(tf);
 	ps = psb->ps_write;
 	if (ps->ps_nsamples == PMC_SAMPLE_INUSE) {
 		counter_u64_add(ps->ps_pmc->pm_runcount, -1);
@@ -4743,19 +4742,18 @@ pmc_add_sample(int cpu, int ring, struct pmc *pm, stru
  */
 
 int
-pmc_process_interrupt(int cpu, int ring, struct pmc *pm, struct trapframe *tf,
-    int inuserspace)
+pmc_process_interrupt(int ring, struct pmc *pm, struct trapframe *tf)
 {
 	struct thread *td;
 
 	td = curthread;
 	if ((pm->pm_flags & PMC_F_USERCALLCHAIN) &&
-           (td->td_proc->p_flag & P_KPROC) == 0 &&
-           !inuserspace) {
+        (td->td_proc->p_flag & P_KPROC) == 0 &&
+		!TRAPF_USERMODE(tf)) {
 		atomic_add_int(&curthread->td_pmcpend, 1);
-		return (pmc_add_sample(cpu, PMC_UR, pm, tf, 0));
+		return (pmc_add_sample(PMC_UR, pm, tf));
 	}
-	return (pmc_add_sample(cpu, ring, pm, tf, inuserspace));
+	return (pmc_add_sample(ring, pm, tf));
 }
 
 /*

Modified: head/sys/dev/hwpmc/hwpmc_mpc7xxx.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_mpc7xxx.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/dev/hwpmc/hwpmc_mpc7xxx.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -702,8 +702,7 @@ mpc7xxx_intr(int cpu, struct trapframe *tf)
 			continue;
 
 		/* Stop the counter if logging fails. */
-		error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
-		    TRAPF_USERMODE(tf));
+		error = pmc_process_interrupt(PMC_HR, pm, tf);
 		if (error != 0)
 			mpc7xxx_stop_pmc(cpu, i);
 

Modified: head/sys/dev/hwpmc/hwpmc_ppc970.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_ppc970.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/dev/hwpmc/hwpmc_ppc970.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -519,8 +519,7 @@ ppc970_intr(int cpu, struct trapframe *tf)
 		if (pm->pm_state != PMC_STATE_RUNNING)
 			continue;
 
-		error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
-		    TRAPF_USERMODE(tf));
+		error = pmc_process_interrupt(PMC_HR, pm, tf);
 		if (error != 0)
 			ppc970_stop_pmc(cpu, i);
 

Modified: head/sys/dev/hwpmc/hwpmc_soft.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_soft.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/dev/hwpmc/hwpmc_soft.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -425,8 +425,7 @@ pmc_soft_intr(struct pmckern_soft *ks)
 			else
 				continue;
 			user_mode = TRAPF_USERMODE(ks->pm_tf);
-			error = pmc_process_interrupt(ks->pm_cpu, PMC_SR, pm,
-			    ks->pm_tf, user_mode);
+			error = pmc_process_interrupt(PMC_SR, pm, ks->pm_tf);
 			if (error) {
 				soft_stop_pmc(ks->pm_cpu, ri);
 				continue;

Modified: head/sys/i386/i386/trap.c
==============================================================================
--- head/sys/i386/i386/trap.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/i386/i386/trap.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -248,7 +248,7 @@ trap(struct trapframe *frame)
 		 * return immediately.
 		 */
 		if (pmc_intr != NULL &&
-		    (*pmc_intr)(PCPU_GET(cpuid), frame) != 0)
+		    (*pmc_intr)(frame) != 0)
 			return;
 #endif
 

Modified: head/sys/kern/kern_pmc.c
==============================================================================
--- head/sys/kern/kern_pmc.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/kern/kern_pmc.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -71,7 +71,7 @@ const int pmc_kernel_version = PMC_KERNEL_VERSION;
 int __read_mostly (*pmc_hook)(struct thread *td, int function, void *arg) = NULL;
 
 /* Interrupt handler */
-int __read_mostly (*pmc_intr)(int cpu, struct trapframe *tf) = NULL;
+int __read_mostly (*pmc_intr)(struct trapframe *tf) = NULL;
 
 DPCPU_DEFINE(uint8_t, pmc_sampled);
 

Modified: head/sys/mips/atheros/apb.c
==============================================================================
--- head/sys/mips/atheros/apb.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/mips/atheros/apb.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -388,7 +388,7 @@ apb_filter(void *arg)
 					tf = td->td_intr_frame;
 
 					if (pmc_intr)
-						(*pmc_intr)(PCPU_GET(cpuid), tf);
+						(*pmc_intr)(PCPU_GET(tf);
 					continue;
 				}
 				/* Ignore timer interrupts */

Modified: head/sys/mips/cavium/octeon_pmc.c
==============================================================================
--- head/sys/mips/cavium/octeon_pmc.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/mips/cavium/octeon_pmc.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -111,7 +111,7 @@ octeon_pmc_intr(void *arg)
 	struct trapframe *tf = PCPU_GET(curthread)->td_intr_frame;
 
 	if (pmc_intr)
-		(*pmc_intr)(PCPU_GET(cpuid), tf);
+		(*pmc_intr)(PCPU_GET(tf);
 
 	return (FILTER_HANDLED);
 }

Modified: head/sys/powerpc/powerpc/interrupt.c
==============================================================================
--- head/sys/powerpc/powerpc/interrupt.c	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/powerpc/powerpc/interrupt.c	Fri Jun  8 04:58:03 2018	(r334827)
@@ -112,7 +112,7 @@ powerpc_interrupt(struct trapframe *framep)
 	case EXC_PERF:
 		critical_enter();
 		KASSERT(pmc_intr != NULL, ("Performance exception, but no handler!"));
-		(*pmc_intr)(PCPU_GET(cpuid), framep);
+		(*pmc_intr)(framep);
 		if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
 			pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, framep);
 		critical_exit();

Modified: head/sys/sys/pmc.h
==============================================================================
--- head/sys/sys/pmc.h	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/sys/pmc.h	Fri Jun  8 04:58:03 2018	(r334827)
@@ -61,7 +61,7 @@
  *
  * The patch version is incremented for every bug fix.
  */
-#define	PMC_VERSION_MAJOR	0x08
+#define	PMC_VERSION_MAJOR	0x09
 #define	PMC_VERSION_MINOR	0x03
 #define	PMC_VERSION_PATCH	0x0000
 
@@ -1053,7 +1053,7 @@ struct pmc_mdep  {
 	int (*pmd_switch_out)(struct pmc_cpu *_p, struct pmc_process *_pp);
 
 	/* handle a PMC interrupt */
-	int (*pmd_intr)(int _cpu, struct trapframe *_tf);
+	int (*pmd_intr)(struct trapframe *_tf);
 
 	/*
 	 * PMC class dependent information.
@@ -1209,8 +1209,7 @@ MALLOC_DECLARE(M_PMC);
 struct pmc_mdep *pmc_md_initialize(void);	/* MD init function */
 void	pmc_md_finalize(struct pmc_mdep *_md);	/* MD fini function */
 int	pmc_getrowdisp(int _ri);
-int	pmc_process_interrupt(int _cpu, int _ring, struct pmc *_pm,
-    struct trapframe *_tf, int _inuserspace);
+int	pmc_process_interrupt(int _ring, struct pmc *_pm, struct trapframe *_tf);
 int	pmc_save_kernel_callchain(uintptr_t *_cc, int _maxsamples,
     struct trapframe *_tf);
 int	pmc_save_user_callchain(uintptr_t *_cc, int _maxsamples,

Modified: head/sys/sys/pmckern.h
==============================================================================
--- head/sys/sys/pmckern.h	Fri Jun  8 04:18:42 2018	(r334826)
+++ head/sys/sys/pmckern.h	Fri Jun  8 04:58:03 2018	(r334827)
@@ -176,7 +176,7 @@ struct pmc_domain_buffer_header {
 
 /* hook */
 extern int (*pmc_hook)(struct thread *_td, int _function, void *_arg);
-extern int (*pmc_intr)(int _cpu, struct trapframe *_frame);
+extern int (*pmc_intr)(struct trapframe *_frame);
 
 /* SX lock protecting the hook */
 extern struct sx pmc_sx;


More information about the svn-src-head mailing list