| From 118a6499d8c5d940210c6543309addc97b48122c Mon Sep 17 00:00:00 2001 |
| From: Robin Murphy <robin.murphy@arm.com> |
| Date: Fri, 3 Dec 2021 11:44:58 +0000 |
| Subject: [PATCH 23/40] perf/arm-cmn: Move group validation data off-stack |
| |
| With the value of CMN_MAX_DTMS increasing significantly, our validation |
| data structure is set to get quite big. Technically we could pack it at |
| least twice as densely, since we only need around 19 bits of information |
| per DTM, but that makes the code even more mind-bogglingly impenetrable, |
| and even half of "quite big" may still be uncomfortably large for a |
| stack frame (~1KB). Just move it to an off-stack allocation instead. |
| |
| Signed-off-by: Robin Murphy <robin.murphy@arm.com> |
| Link: https://lore.kernel.org/r/0cabff2e5839ddc0979e757c55515966f65359e4.1638530442.git.robin.murphy@arm.com |
| Signed-off-by: Will Deacon <will@kernel.org> |
| |
| Upstream-Status: Backport [https://lore.kernel.org/r/0cabff2e5839ddc0979e757c55515966f65359e4.1638530442.git.robin.murphy@arm.com] |
| Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com> |
| --- |
| drivers/perf/arm-cmn.c | 43 ++++++++++++++++++++++++------------------ |
| 1 file changed, 25 insertions(+), 18 deletions(-) |
| |
| diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c |
| index acff8683af2c..d2dd02f040b8 100644 |
| --- a/drivers/perf/arm-cmn.c |
| +++ b/drivers/perf/arm-cmn.c |
| @@ -876,8 +876,8 @@ static int arm_cmn_validate_group(struct perf_event *event) |
| struct arm_cmn_node *dn; |
| struct perf_event *sibling, *leader = event->group_leader; |
| enum cmn_node_type type; |
| - struct arm_cmn_val val; |
| - int i; |
| + struct arm_cmn_val *val; |
| + int i, ret = -EINVAL; |
| u8 occupid; |
| |
| if (leader == event) |
| @@ -886,18 +886,22 @@ static int arm_cmn_validate_group(struct perf_event *event) |
| if (event->pmu != leader->pmu && !is_software_event(leader)) |
| return -EINVAL; |
| |
| - memset(&val, 0, sizeof(val)); |
| + val = kzalloc(sizeof(*val), GFP_KERNEL); |
| + if (!val) |
| + return -ENOMEM; |
| |
| - arm_cmn_val_add_event(&val, leader); |
| + arm_cmn_val_add_event(val, leader); |
| for_each_sibling_event(sibling, leader) |
| - arm_cmn_val_add_event(&val, sibling); |
| + arm_cmn_val_add_event(val, sibling); |
| |
| type = CMN_EVENT_TYPE(event); |
| - if (type == CMN_TYPE_DTC) |
| - return val.cycles ? -EINVAL : 0; |
| + if (type == CMN_TYPE_DTC) { |
| + ret = val->cycles ? -EINVAL : 0; |
| + goto done; |
| + } |
| |
| - if (val.dtc_count == CMN_DT_NUM_COUNTERS) |
| - return -EINVAL; |
| + if (val->dtc_count == CMN_DT_NUM_COUNTERS) |
| + goto done; |
| |
| if (arm_cmn_is_occup_event(type, CMN_EVENT_EVENTID(event))) |
| occupid = CMN_EVENT_OCCUPID(event) + 1; |
| @@ -907,25 +911,28 @@ static int arm_cmn_validate_group(struct perf_event *event) |
| for_each_hw_dn(hw, dn, i) { |
| int wp_idx, wp_cmb, dtm = dn->dtm; |
| |
| - if (val.dtm_count[dtm] == CMN_DTM_NUM_COUNTERS) |
| - return -EINVAL; |
| + if (val->dtm_count[dtm] == CMN_DTM_NUM_COUNTERS) |
| + goto done; |
| |
| - if (occupid && val.occupid[dtm] && occupid != val.occupid[dtm]) |
| - return -EINVAL; |
| + if (occupid && val->occupid[dtm] && occupid != val->occupid[dtm]) |
| + goto done; |
| |
| if (type != CMN_TYPE_WP) |
| continue; |
| |
| wp_idx = arm_cmn_wp_idx(event); |
| - if (val.wp[dtm][wp_idx]) |
| - return -EINVAL; |
| + if (val->wp[dtm][wp_idx]) |
| + goto done; |
| |
| - wp_cmb = val.wp[dtm][wp_idx ^ 1]; |
| + wp_cmb = val->wp[dtm][wp_idx ^ 1]; |
| if (wp_cmb && wp_cmb != CMN_EVENT_WP_COMBINE(event) + 1) |
| - return -EINVAL; |
| + goto done; |
| } |
| |
| - return 0; |
| + ret = 0; |
| +done: |
| + kfree(val); |
| + return ret; |
| } |
| |
| static int arm_cmn_event_init(struct perf_event *event) |
| -- |
| 2.34.1 |
| |