Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/perf/hv-24x7: Modify definition of request and result buffers

The parameters to the 24x7 HCALL have variable number of elements in them.
Set the minimum number of such elements to 1 rather than 0 and eliminate
the temporary structures.

This would enable us to submit multiple counter requests and process
multiple results from a single HCALL (in a follow on patch).

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Sukadev Bhattiprolu and committed by
Michael Ellerman
145264e2 ed59190e

+41 -44
+37 -40
arch/powerpc/perf/hv-24x7.c
··· 142 142 143 143 static struct kmem_cache *hv_page_cache; 144 144 145 + /* 146 + * request_buffer and result_buffer are not required to be 4k aligned, 147 + * but are not allowed to cross any 4k boundary. Aligning them to 4k is 148 + * the simplest way to ensure that. 149 + */ 150 + #define H24x7_DATA_BUFFER_SIZE 4096 151 + DEFINE_PER_CPU(char, hv_24x7_reqb[H24x7_DATA_BUFFER_SIZE]) __aligned(4096); 152 + DEFINE_PER_CPU(char, hv_24x7_resb[H24x7_DATA_BUFFER_SIZE]) __aligned(4096); 153 + 145 154 static char *event_name(struct hv_24x7_event_data *ev, int *len) 146 155 { 147 156 *len = be16_to_cpu(ev->event_name_len) - 2; ··· 985 976 NULL, 986 977 }; 987 978 988 - DEFINE_PER_CPU(char, hv_24x7_reqb[4096]) __aligned(4096); 989 - DEFINE_PER_CPU(char, hv_24x7_resb[4096]) __aligned(4096); 990 - 991 979 static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, 992 - u16 lpar, u64 *res, 980 + u16 lpar, u64 *count, 993 981 bool success_expected) 994 982 { 995 983 unsigned long ret; 996 984 997 - /* 998 - * request_buffer and result_buffer are not required to be 4k aligned, 999 - * but are not allowed to cross any 4k boundary. Aligning them to 4k is 1000 - * the simplest way to ensure that. 1001 - */ 1002 - struct reqb { 1003 - struct hv_24x7_request_buffer buf; 1004 - struct hv_24x7_request req; 1005 - } __packed *request_buffer; 1006 - 1007 - struct { 1008 - struct hv_24x7_data_result_buffer buf; 1009 - struct hv_24x7_result res; 1010 - struct hv_24x7_result_element elem; 1011 - __be64 result; 1012 - } __packed *result_buffer; 985 + struct hv_24x7_request_buffer *request_buffer; 986 + struct hv_24x7_data_result_buffer *result_buffer; 987 + struct hv_24x7_result *resb; 988 + struct hv_24x7_request *req; 1013 989 1014 990 BUILD_BUG_ON(sizeof(*request_buffer) > 4096); 1015 991 BUILD_BUG_ON(sizeof(*result_buffer) > 4096); ··· 1005 1011 memset(request_buffer, 0, 4096); 1006 1012 memset(result_buffer, 0, 4096); 1007 1013 1008 - *request_buffer = (struct reqb) { 1009 - .buf = { 1010 - .interface_version = HV_24X7_IF_VERSION_CURRENT, 1011 - .num_requests = 1, 1012 - }, 1013 - .req = { 1014 - .performance_domain = domain, 1015 - .data_size = cpu_to_be16(8), 1016 - .data_offset = cpu_to_be32(offset), 1017 - .starting_lpar_ix = cpu_to_be16(lpar), 1018 - .max_num_lpars = cpu_to_be16(1), 1019 - .starting_ix = cpu_to_be16(ix), 1020 - .max_ix = cpu_to_be16(1), 1021 - } 1022 - }; 1014 + request_buffer->interface_version = HV_24X7_IF_VERSION_CURRENT; 1015 + request_buffer->num_requests = 1; 1023 1016 1017 + req = &request_buffer->requests[0]; 1018 + 1019 + req->performance_domain = domain; 1020 + req->data_size = cpu_to_be16(8); 1021 + req->data_offset = cpu_to_be32(offset); 1022 + req->starting_lpar_ix = cpu_to_be16(lpar), 1023 + req->max_num_lpars = cpu_to_be16(1); 1024 + req->starting_ix = cpu_to_be16(ix); 1025 + req->max_ix = cpu_to_be16(1); 1026 + 1027 + /* 1028 + * NOTE: Due to variable number of array elements in request and 1029 + * result buffer(s), sizeof() is not reliable. Use the actual 1030 + * allocated buffer size, H24x7_DATA_BUFFER_SIZE. 1031 + */ 1024 1032 ret = plpar_hcall_norets(H_GET_24X7_DATA, 1025 - virt_to_phys(request_buffer), sizeof(*request_buffer), 1026 - virt_to_phys(result_buffer), sizeof(*result_buffer)); 1033 + virt_to_phys(request_buffer), H24x7_DATA_BUFFER_SIZE, 1034 + virt_to_phys(result_buffer), H24x7_DATA_BUFFER_SIZE); 1027 1035 1028 1036 if (ret) { 1029 1037 if (success_expected) 1030 1038 pr_err_ratelimited("hcall failed: %d %#x %#x %d => " 1031 1039 "0x%lx (%ld) detail=0x%x failing ix=%x\n", 1032 1040 domain, offset, ix, lpar, ret, ret, 1033 - result_buffer->buf.detailed_rc, 1034 - result_buffer->buf.failing_request_ix); 1041 + result_buffer->detailed_rc, 1042 + result_buffer->failing_request_ix); 1035 1043 goto out; 1036 1044 } 1037 1045 1038 - *res = be64_to_cpu(result_buffer->result); 1046 + resb = &result_buffer->results[0]; 1039 1047 1048 + *count = be64_to_cpu(resb->elements[0].element_data[0]); 1040 1049 out: 1041 1050 return ret; 1042 1051 }
+4 -4
arch/powerpc/perf/hv-24x7.h
··· 50 50 __u8 interface_version; 51 51 __u8 num_requests; 52 52 __u8 reserved[0xE]; 53 - struct hv_24x7_request requests[]; 53 + struct hv_24x7_request requests[1]; 54 54 } __packed; 55 55 56 56 struct hv_24x7_result_element { ··· 66 66 __be32 lpar_cfg_instance_id; 67 67 68 68 /* size = @result_element_data_size of cointaining result. */ 69 - __u8 element_data[]; 69 + __u64 element_data[1]; 70 70 } __packed; 71 71 72 72 struct hv_24x7_result { ··· 87 87 /* WARNING: only valid for first result element due to variable sizes 88 88 * of result elements */ 89 89 /* struct hv_24x7_result_element[@num_elements_returned] */ 90 - struct hv_24x7_result_element elements[]; 90 + struct hv_24x7_result_element elements[1]; 91 91 } __packed; 92 92 93 93 struct hv_24x7_data_result_buffer { ··· 103 103 __u8 reserved2[0x8]; 104 104 /* WARNING: only valid for the first result due to variable sizes of 105 105 * results */ 106 - struct hv_24x7_result results[]; /* [@num_results] */ 106 + struct hv_24x7_result results[1]; /* [@num_results] */ 107 107 } __packed; 108 108 109 109 #endif