git: b48a2770d48b - main - powerpc64: add Power8 and Power9 PMCs

Leandro Lupori luporl at FreeBSD.org
Mon Jul 26 13:30:41 UTC 2021


The branch main has been updated by luporl:

URL: https://cgit.FreeBSD.org/src/commit/?id=b48a2770d48b9f9aa61788704897e9a2e9e10c09

commit b48a2770d48b9f9aa61788704897e9a2e9e10c09
Author:     Leandro Lupori <luporl at FreeBSD.org>
AuthorDate: 2021-07-23 18:09:09 +0000
Commit:     Leandro Lupori <luporl at FreeBSD.org>
CommitDate: 2021-07-26 13:27:23 +0000

    powerpc64: add Power8 and Power9 PMCs
    
    Add support to allocate Power8 and 9 PMCs.
    
    Submitted by:           Leonardo Bianconi <leonardo.bianconi at eldorado.org.br>
    Reviewed by:            mhorne
    Sponsored by:           Instituto de Pesquisas Eldorado (eldorado.org.br)
    Differential Revision:  https://reviews.freebsd.org/D31109
---
 lib/libpmc/libpmc_pmu_util.c   | 34 ++++++++++++++++++++++++
 sys/dev/hwpmc/hwpmc_power8.c   | 59 +++++++++++++++++++++++++++++++++++++++---
 sys/dev/hwpmc/hwpmc_powerpc.c  |  3 +++
 sys/powerpc/include/pmc_mdep.h |  1 +
 4 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/lib/libpmc/libpmc_pmu_util.c b/lib/libpmc/libpmc_pmu_util.c
index e6f74e6abe81..edd99357678e 100644
--- a/lib/libpmc/libpmc_pmu_util.c
+++ b/lib/libpmc/libpmc_pmu_util.c
@@ -142,6 +142,13 @@ pmu_alias_get(const char *name)
 
 	return (name);
 }
+#elif defined(__powerpc64__)
+
+static const char *
+pmu_alias_get(const char *name)
+{
+	return (name);
+}
 
 #elif defined(__aarch64__)
 
@@ -571,6 +578,33 @@ pmc_pmu_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm)
 		return (pmc_pmu_amd_pmcallocate(event_name, pm, &ped));
 }
 
+#elif defined(__powerpc64__)
+
+int
+pmc_pmu_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm)
+{
+	const struct pmu_event *pe;
+	struct pmu_event_desc ped;
+	int idx = -1;
+
+	bzero(&pm->pm_md, sizeof(pm->pm_md));
+	pm->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
+	event_name = pmu_alias_get(event_name);
+
+	if ((pe = pmu_event_get(NULL, event_name, &idx)) == NULL)
+		return (ENOENT);
+	if (pe->event == NULL)
+		return (ENOENT);
+	if (pmu_parse_event(&ped, pe->event))
+		return (ENOENT);
+
+	assert(ped.ped_event >= 0);
+	pm->pm_ev = idx;
+	pm->pm_md.pm_event = ped.ped_event;
+	pm->pm_class = PMC_CLASS_POWER8;
+	return (0);
+}
+
 #elif defined(__aarch64__)
 
 int
diff --git a/sys/dev/hwpmc/hwpmc_power8.c b/sys/dev/hwpmc/hwpmc_power8.c
index 7cc2ac8295f6..ce063a57a10e 100644
--- a/sys/dev/hwpmc/hwpmc_power8.c
+++ b/sys/dev/hwpmc/hwpmc_power8.c
@@ -43,6 +43,12 @@ __FBSDID("$FreeBSD$");
 
 #define	POWER8_MAX_PMCS		6
 
+#define PM_EVENT_CODE(pe)	(pe & 0xffff)
+#define PM_EVENT_COUNTER(pe)	((pe >> 16) & 0xffff)
+
+#define PM_CYC			0x1e
+#define PM_INST_CMPL		0x02
+
 static struct pmc_ppc_event power8_event_codes[] = {
 	{PMC_EV_POWER8_INSTR_COMPLETED,
 	    .pe_flags = PMC_FLAG_PMC5,
@@ -275,6 +281,54 @@ power8_resume_pmc(bool ie)
 	mtspr(SPR_MMCR0, mmcr0);
 }
 
+static int
+power8_allocate_pmc(int cpu, int ri, struct pmc *pm,
+	const struct pmc_op_pmcallocate *a)
+{
+	uint32_t caps, config, counter, pe;
+
+	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
+	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
+	KASSERT(ri >= 0 && ri < ppc_max_pmcs,
+	    ("[powerpc,%d] illegal row index %d", __LINE__, ri));
+
+	pe = a->pm_md.pm_event;
+	counter = PM_EVENT_COUNTER(pe);
+	config = PM_EVENT_CODE(pe);
+
+	/*
+	 * PMC5 and PMC6 are not programmable and always count instructions
+	 * completed and cycles, respectively.
+	 *
+	 * When counter is 0 any of the 4 programmable PMCs may be used for
+	 * the specified event, otherwise it must match ri + 1.
+	 */
+	if (counter == 0 && config == PM_INST_CMPL)
+		counter = 5;
+	else if (counter == 0 && config == PM_CYC)
+		counter = 6;
+	else if (counter > 4)
+		return (EINVAL);
+
+	if (counter != 0 && counter != ri + 1)
+		return (EINVAL);
+
+	caps = a->pm_caps;
+
+	if (caps & PMC_CAP_SYSTEM)
+		config |= POWERPC_PMC_KERNEL_ENABLE;
+	if (caps & PMC_CAP_USER)
+		config |= POWERPC_PMC_USER_ENABLE;
+	if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
+		config |= POWERPC_PMC_ENABLE;
+
+	pm->pm_md.pm_powerpc.pm_powerpc_evsel = config;
+
+	PMCDBG3(MDP,ALL,1,"powerpc-allocate cpu=%d ri=%d -> config=0x%x",
+	    cpu, ri, config);
+	return (0);
+}
+
 int
 pmc_power8_initialize(struct pmc_mdep *pmc_mdep)
 {
@@ -291,7 +345,7 @@ pmc_power8_initialize(struct pmc_mdep *pmc_mdep)
 
 	pcd->pcd_pcpu_init      = power8_pcpu_init;
 	pcd->pcd_pcpu_fini      = power8_pcpu_fini;
-	pcd->pcd_allocate_pmc   = powerpc_allocate_pmc;
+	pcd->pcd_allocate_pmc   = power8_allocate_pmc;
 	pcd->pcd_release_pmc    = powerpc_release_pmc;
 	pcd->pcd_start_pmc      = powerpc_start_pmc;
 	pcd->pcd_stop_pmc       = powerpc_stop_pmc;
@@ -304,10 +358,7 @@ pmc_power8_initialize(struct pmc_mdep *pmc_mdep)
 	pmc_mdep->pmd_npmc     += POWER8_MAX_PMCS;
 	pmc_mdep->pmd_intr      = powerpc_pmc_intr;
 
-	ppc_event_codes = power8_event_codes;
 	ppc_event_codes_size = power8_event_codes_size;
-	ppc_event_first = PMC_EV_POWER8_FIRST;
-	ppc_event_last = PMC_EV_POWER8_LAST;
 	ppc_max_pmcs = POWER8_MAX_PMCS;
 
 	powerpc_set_pmc = power8_set_pmc;
diff --git a/sys/dev/hwpmc/hwpmc_powerpc.c b/sys/dev/hwpmc/hwpmc_powerpc.c
index e97211f0d9a6..3a2115ece3cb 100644
--- a/sys/dev/hwpmc/hwpmc_powerpc.c
+++ b/sys/dev/hwpmc/hwpmc_powerpc.c
@@ -603,6 +603,9 @@ pmc_md_initialize()
 		pmc_mdep = NULL;
 	}
 
+	/* Set the value for kern.hwpmc.cpuid */
+	snprintf(pmc_cpuid, sizeof(pmc_cpuid), "%08lx", mfpvr());
+
 	return (pmc_mdep);
 }
 
diff --git a/sys/powerpc/include/pmc_mdep.h b/sys/powerpc/include/pmc_mdep.h
index 0a1609196ef9..3d31ff7b99cd 100644
--- a/sys/powerpc/include/pmc_mdep.h
+++ b/sys/powerpc/include/pmc_mdep.h
@@ -10,6 +10,7 @@
 #define PMC_MDEP_CLASS_INDEX_POWERPC	1
 
 union pmc_md_op_pmcallocate {
+	uint32_t		pm_event;
 	uint64_t		__pad[4];
 };
 


More information about the dev-commits-src-all mailing list