summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoão Mário Domingos <joao.mario@tecnico.ulisboa.pt>2021-11-16 18:48:09 +0300
committerHal Feng <hal.feng@starfivetech.com>2024-03-05 10:18:29 +0300
commit6f46d9c4c1893134d6ddb056ac01992c2e89cc13 (patch)
tree451332055ca8e02200afba2263c3493b422b6920
parentc0855d2d612216523b634d74cbe8065f86d98eac (diff)
downloadlinux-6f46d9c4c1893134d6ddb056ac01992c2e89cc13.tar.xz
RISC-V: Create unique identification for SoC PMU
The SBI PMU platform driver did not provide any identification for perf events matching. This patch introduces a new sysfs file inside the platform device (soc:pmu/id) for pmu identification. The identification is a 64-bit value generated as: [63-32]: mvendorid; [31]: marchid[MSB]; [30-16]: marchid[15-0]; [15-0]: mimpid[15MSBs]; The CSRs are detailed in the RISC-V privileged spec [1]. The marchid is split in MSB + 15LSBs, due to the MSB being used for open-source architecture identification. [1] https://github.com/riscv/riscv-isa-manual Signed-off-by: João Mário Domingos <joao.mario@tecnico.ulisboa.pt>
-rw-r--r--drivers/perf/riscv_pmu_sbi.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index cd8a2b9efd78..de4f47f73919 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -1019,6 +1019,46 @@ static struct ctl_table sbi_pmu_sysctl_table[] = {
{ }
};
+static uint64_t pmu_sbi_get_pmu_id(void)
+{
+ union sbi_pmu_id {
+ uint64_t value;
+ struct {
+ uint16_t imp:16;
+ uint16_t arch:16;
+ uint32_t vendor:32;
+ };
+ } pmuid;
+
+ pmuid.value = 0;
+ pmuid.vendor = (uint32_t) sbi_get_mvendorid();
+ pmuid.arch = (sbi_get_marchid() >> (63 - 15) & (1 << 15)) | (sbi_get_marchid() & 0x7FFF);
+ pmuid.imp = (sbi_get_mimpid() >> 16);
+
+ return pmuid.value;
+}
+
+static ssize_t pmu_sbi_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len;
+
+ len = sprintf(buf, "0x%llx\n", pmu_sbi_get_pmu_id());
+ if (len <= 0)
+ dev_err(dev, "mydrv: Invalid sprintf len: %dn", len);
+
+ return len;
+}
+
+static DEVICE_ATTR(id, S_IRUGO | S_IWUSR, pmu_sbi_id_show, 0);
+
+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;
@@ -1067,6 +1107,13 @@ static int pmu_sbi_device_probe(struct platform_device *pdev)
pmu->event_unmapped = pmu_sbi_event_unmapped;
pmu->csr_index = pmu_sbi_csr_index;
+ 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;
+
ret = cpuhp_state_add_instance(CPUHP_AP_PERF_RISCV_STARTING, &pmu->node);
if (ret)
return ret;