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>
This commit is contained in:
João Mário Domingos 2021-11-16 15:48:09 +00:00 committed by Hal Feng
parent c0855d2d61
commit 6f46d9c4c1

View file

@ -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;