[PATCH v4 1/1] RISC-V: Create unique identification for SoC PMU

Nikita Shubin nikita.shubin at maquefel.me
Sun Jun 19 04:11:11 PDT 2022


From: Nikita Shubin <n.shubin at yadro.com>

Provide RISC-V SBI PMU id to distinguish different cores or SoCs via
"devices/platform/riscv-pmu/id" sysfs entry.

The identification is generated as string of marchid, mimpid, mvendorid
in hex format separated by coma - "0x70032,0x70032,0x0".

The CSRs are detailed in the RISC-V privileged spec [1].
[1] https://github.com/riscv/riscv-isa-manual

Inspired-by: João Mário Domingos <joao.mario at tecnico.ulisboa.pt>
Signed-off-by: Nikita Shubin <n.shubin at yadro.com>
---
v3->v4:
- use string for pmuid
- rename pmu_sbi_id_show to id_show
- fix error print message in id_show
- fix DEVICE_ATTR to use octal permissions
---
 arch/riscv/kernel/sbi.c        |  3 +++
 drivers/perf/riscv_pmu_sbi.c   | 41 ++++++++++++++++++++++++++++++++++
 include/linux/perf/riscv_pmu.h |  1 +
 3 files changed, 45 insertions(+)

diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
index 775d3322b422..50dd9b6ecc9e 100644
--- a/arch/riscv/kernel/sbi.c
+++ b/arch/riscv/kernel/sbi.c
@@ -627,16 +627,19 @@ long sbi_get_mvendorid(void)
 {
 	return __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID);
 }
+EXPORT_SYMBOL(sbi_get_mvendorid);
 
 long sbi_get_marchid(void)
 {
 	return __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID);
 }
+EXPORT_SYMBOL(sbi_get_marchid);
 
 long sbi_get_mimpid(void)
 {
 	return __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID);
 }
+EXPORT_SYMBOL(sbi_get_mimpid);
 
 static void sbi_send_cpumask_ipi(const struct cpumask *target)
 {
diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index dca3537a8dcc..be812f855617 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -693,6 +693,28 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde
 	return 0;
 }
 
+static ssize_t id_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int len;
+	struct riscv_pmu *pmu = container_of(dev_get_drvdata(dev), struct riscv_pmu, pmu);
+
+	len = sprintf(buf, "%s\n", pmu->pmuid);
+	if (len <= 0)
+		dev_err(dev, "invalid sprintf len: %d\n", len);
+
+	return len;
+}
+
+static DEVICE_ATTR(id, 0644, id_show, NULL);
+
+static struct attribute *pmu_sbi_attrs[] = {
+	&dev_attr_id.attr,
+	NULL
+};
+
+ATTRIBUTE_GROUPS(pmu_sbi);
+
 static int pmu_sbi_device_probe(struct platform_device *pdev)
 {
 	struct riscv_pmu *pmu = NULL;
@@ -714,6 +736,14 @@ static int pmu_sbi_device_probe(struct platform_device *pdev)
 	if (pmu_sbi_get_ctrinfo(num_counters))
 		goto out_free;
 
+	/* fill pmuid */
+	pmu->pmuid = kasprintf(GFP_KERNEL, "0x%lx,0x%lx,0x%lx",
+			       sbi_get_marchid(),
+			       sbi_get_mimpid(),
+			       sbi_get_mvendorid());
+	if (!pmu->pmuid)
+		goto out_free_pmuid;
+
 	ret = pmu_sbi_setup_irqs(pmu, pdev);
 	if (ret < 0) {
 		pr_info("Perf sampling/filtering is not supported as sscof extension is not available\n");
@@ -739,8 +769,19 @@ static int pmu_sbi_device_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	ret = sysfs_create_group(&pdev->dev.kobj, &pmu_sbi_group);
+	if (ret) {
+		dev_err(&pdev->dev, "sysfs creation failed\n");
+		return ret;
+	}
+
+	pdev->dev.groups = pmu_sbi_groups;
+	dev_set_drvdata(&pdev->dev, pmu);
+
 	return 0;
 
+out_free_pmuid:
+	kfree(pmu->pmuid);
 out_free:
 	kfree(pmu);
 	return ret;
diff --git a/include/linux/perf/riscv_pmu.h b/include/linux/perf/riscv_pmu.h
index 46f9b6fe306e..cf3557b77fb8 100644
--- a/include/linux/perf/riscv_pmu.h
+++ b/include/linux/perf/riscv_pmu.h
@@ -42,6 +42,7 @@ struct cpu_hw_events {
 struct riscv_pmu {
 	struct pmu	pmu;
 	char		*name;
+	char		*pmuid;
 
 	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
 
-- 
2.35.1




More information about the linux-arm-kernel mailing list