aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Jung Bauermann <bauerman@linux.vnet.ibm.com>2017-06-29 17:55:33 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2017-07-02 06:40:30 -0400
commit41f577eb012f33d9af9c9fcee6a68a499562f875 (patch)
tree7e32d574bd59169a6daabd5d3e5a93ebad36f9b7
parent36c8fb2c616d9373758b155d9723774353067a87 (diff)
powerpc/perf/hv-24x7: Properly iterate through results
hv-24x7.h has a comment mentioning that result_buffer->results can't be indexed as a normal array because it may contain results of variable sizes, so fix the loop in h_24x7_event_commit_txn to take the variation into account when iterating through results. Another problem in that loop is that it sets h24x7hw->events[i] to NULL. This assumes that only the i'th result maps to the i'th request, but that is not guaranteed to be true. We need to leave the event in the array so that we don't dereference a NULL pointer in case more than one result maps to one request. We still assume that each result has only one result element, so warn if that assumption is violated. Reviewed-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> Signed-off-by: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/perf/hv-24x7.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index 141de0f708f7..8b1a3e849d23 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -1144,7 +1144,9 @@ static int add_event_to_24x7_request(struct perf_event *event,
1144 1144
1145static unsigned long single_24x7_request(struct perf_event *event, u64 *count) 1145static unsigned long single_24x7_request(struct perf_event *event, u64 *count)
1146{ 1146{
1147 u16 num_elements;
1147 unsigned long ret; 1148 unsigned long ret;
1149 struct hv_24x7_result *result;
1148 struct hv_24x7_request_buffer *request_buffer; 1150 struct hv_24x7_request_buffer *request_buffer;
1149 struct hv_24x7_data_result_buffer *result_buffer; 1151 struct hv_24x7_data_result_buffer *result_buffer;
1150 1152
@@ -1166,8 +1168,14 @@ static unsigned long single_24x7_request(struct perf_event *event, u64 *count)
1166 goto out; 1168 goto out;
1167 } 1169 }
1168 1170
1171 result = result_buffer->results;
1172
1173 /* This code assumes that a result has only one element. */
1174 num_elements = be16_to_cpu(result->num_elements_returned);
1175 WARN_ON_ONCE(num_elements != 1);
1176
1169 /* process result from hcall */ 1177 /* process result from hcall */
1170 *count = be64_to_cpu(result_buffer->results[0].elements[0].element_data[0]); 1178 *count = be64_to_cpu(result->elements[0].element_data[0]);
1171 1179
1172out: 1180out:
1173 put_cpu_var(hv_24x7_reqb); 1181 put_cpu_var(hv_24x7_reqb);
@@ -1400,8 +1408,7 @@ static int h_24x7_event_commit_txn(struct pmu *pmu)
1400{ 1408{
1401 struct hv_24x7_request_buffer *request_buffer; 1409 struct hv_24x7_request_buffer *request_buffer;
1402 struct hv_24x7_data_result_buffer *result_buffer; 1410 struct hv_24x7_data_result_buffer *result_buffer;
1403 struct hv_24x7_result *resb; 1411 struct hv_24x7_result *res, *next_res;
1404 struct perf_event *event;
1405 u64 count; 1412 u64 count;
1406 int i, ret, txn_flags; 1413 int i, ret, txn_flags;
1407 struct hv_24x7_hw *h24x7hw; 1414 struct hv_24x7_hw *h24x7hw;
@@ -1428,13 +1435,20 @@ static int h_24x7_event_commit_txn(struct pmu *pmu)
1428 1435
1429 h24x7hw = &get_cpu_var(hv_24x7_hw); 1436 h24x7hw = &get_cpu_var(hv_24x7_hw);
1430 1437
1431 /* Update event counts from hcall */ 1438 /* Go through results in the result buffer to update event counts. */
1432 for (i = 0; i < request_buffer->num_requests; i++) { 1439 for (i = 0, res = result_buffer->results;
1433 resb = &result_buffer->results[i]; 1440 i < result_buffer->num_results; i++, res = next_res) {
1434 count = be64_to_cpu(resb->elements[0].element_data[0]); 1441 struct perf_event *event = h24x7hw->events[res->result_ix];
1435 event = h24x7hw->events[i]; 1442 u16 num_elements = be16_to_cpu(res->num_elements_returned);
1436 h24x7hw->events[i] = NULL; 1443 u16 data_size = be16_to_cpu(res->result_element_data_size);
1444
1445 /* This code assumes that a result has only one element. */
1446 WARN_ON_ONCE(num_elements != 1);
1447
1448 count = be64_to_cpu(res->elements[0].element_data[0]);
1437 update_event_count(event, count); 1449 update_event_count(event, count);
1450
1451 next_res = (void *) res->elements[0].element_data + data_size;
1438 } 1452 }
1439 1453
1440 put_cpu_var(hv_24x7_hw); 1454 put_cpu_var(hv_24x7_hw);