forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/perf/arm_spe_pmu.c
....@@ -1,18 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Perf support for the Statistical Profiling Extension, introduced as
34 * part of ARMv8.2.
4
- *
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License version 2 as
7
- * published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
13
- *
14
- * You should have received a copy of the GNU General Public License
15
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
165 *
176 * Copyright (C) 2016 ARM Limited
187 *
....@@ -38,6 +27,7 @@
3827 #include <linux/of_address.h>
3928 #include <linux/of_device.h>
4029 #include <linux/perf_event.h>
30
+#include <linux/perf/arm_pmu.h>
4131 #include <linux/platform_device.h>
4232 #include <linux/printk.h>
4333 #include <linux/slab.h>
....@@ -48,6 +38,24 @@
4838 #include <asm/cpufeature.h>
4939 #include <asm/mmu.h>
5040 #include <asm/sysreg.h>
41
+
42
+/*
43
+ * Cache if the event is allowed to trace Context information.
44
+ * This allows us to perform the check, i.e, perfmon_capable(),
45
+ * in the context of the event owner, once, during the event_init().
46
+ */
47
+#define SPE_PMU_HW_FLAGS_CX BIT(0)
48
+
49
+static void set_spe_event_has_cx(struct perf_event *event)
50
+{
51
+ if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && perfmon_capable())
52
+ event->hw.flags |= SPE_PMU_HW_FLAGS_CX;
53
+}
54
+
55
+static bool get_spe_event_has_cx(struct perf_event *event)
56
+{
57
+ return !!(event->hw.flags & SPE_PMU_HW_FLAGS_CX);
58
+}
5159
5260 #define ARM_SPE_BUF_PAD_BYTE 0
5361
....@@ -284,7 +292,7 @@
284292 if (!attr->exclude_kernel)
285293 reg |= BIT(SYS_PMSCR_EL1_E1SPE_SHIFT);
286294
287
- if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && capable(CAP_SYS_ADMIN))
295
+ if (get_spe_event_has_cx(event))
288296 reg |= BIT(SYS_PMSCR_EL1_CX_SHIFT);
289297
290298 return reg;
....@@ -709,10 +717,10 @@
709717 !(spe_pmu->features & SPE_PMU_FEAT_FILT_LAT))
710718 return -EOPNOTSUPP;
711719
720
+ set_spe_event_has_cx(event);
712721 reg = arm_spe_event_to_pmscr(event);
713
- if (!capable(CAP_SYS_ADMIN) &&
722
+ if (!perfmon_capable() &&
714723 (reg & (BIT(SYS_PMSCR_EL1_PA_SHIFT) |
715
- BIT(SYS_PMSCR_EL1_CX_SHIFT) |
716724 BIT(SYS_PMSCR_EL1_PCT_SHIFT))))
717725 return -EACCES;
718726
....@@ -841,7 +849,7 @@
841849 * parts and give userspace a fighting chance of getting some
842850 * useful data out of it.
843851 */
844
- if (!nr_pages || (snapshot && (nr_pages & 1)))
852
+ if (snapshot && (nr_pages & 1))
845853 return NULL;
846854
847855 if (cpu == -1)
....@@ -855,16 +863,8 @@
855863 if (!pglist)
856864 goto out_free_buf;
857865
858
- for (i = 0; i < nr_pages; ++i) {
859
- struct page *page = virt_to_page(pages[i]);
860
-
861
- if (PagePrivate(page)) {
862
- pr_warn("unexpected high-order page for auxbuf!");
863
- goto out_free_pglist;
864
- }
865
-
866
+ for (i = 0; i < nr_pages; ++i)
866867 pglist[i] = virt_to_page(pages[i]);
867
- }
868868
869869 buf->base = vmap(pglist, nr_pages, VM_MAP, PAGE_KERNEL);
870870 if (!buf->base)
....@@ -1020,7 +1020,7 @@
10201020 default:
10211021 dev_warn(dev, "unknown PMSIDR_EL1.Interval [%d]; assuming 8\n",
10221022 fld);
1023
- /* Fallthrough */
1023
+ fallthrough;
10241024 case 8:
10251025 spe_pmu->min_period = 4096;
10261026 }
....@@ -1039,7 +1039,7 @@
10391039 default:
10401040 dev_warn(dev, "unknown PMSIDR_EL1.CountSize [%d]; assuming 2\n",
10411041 fld);
1042
- /* Fallthrough */
1042
+ fallthrough;
10431043 case 2:
10441044 spe_pmu->counter_sz = 12;
10451045 }
....@@ -1151,10 +1151,8 @@
11511151 struct platform_device *pdev = spe_pmu->pdev;
11521152 int irq = platform_get_irq(pdev, 0);
11531153
1154
- if (irq < 0) {
1155
- dev_err(&pdev->dev, "failed to get IRQ (%d)\n", irq);
1154
+ if (irq < 0)
11561155 return -ENXIO;
1157
- }
11581156
11591157 if (!irq_is_percpu(irq)) {
11601158 dev_err(&pdev->dev, "expected PPI but got SPI (%d)\n", irq);
....@@ -1174,8 +1172,15 @@
11741172 { .compatible = "arm,statistical-profiling-extension-v1", .data = (void *)1 },
11751173 { /* Sentinel */ },
11761174 };
1175
+MODULE_DEVICE_TABLE(of, arm_spe_pmu_of_match);
11771176
1178
-static int arm_spe_pmu_device_dt_probe(struct platform_device *pdev)
1177
+static const struct platform_device_id arm_spe_match[] = {
1178
+ { ARMV8_SPE_PDEV_NAME, 0},
1179
+ { }
1180
+};
1181
+MODULE_DEVICE_TABLE(platform, arm_spe_match);
1182
+
1183
+static int arm_spe_pmu_device_probe(struct platform_device *pdev)
11791184 {
11801185 int ret;
11811186 struct arm_spe_pmu *spe_pmu;
....@@ -1235,11 +1240,13 @@
12351240 }
12361241
12371242 static struct platform_driver arm_spe_pmu_driver = {
1243
+ .id_table = arm_spe_match,
12381244 .driver = {
12391245 .name = DRVNAME,
12401246 .of_match_table = of_match_ptr(arm_spe_pmu_of_match),
1247
+ .suppress_bind_attrs = true,
12411248 },
1242
- .probe = arm_spe_pmu_device_dt_probe,
1249
+ .probe = arm_spe_pmu_device_probe,
12431250 .remove = arm_spe_pmu_device_remove,
12441251 };
12451252