diff options
42 files changed, 3122 insertions, 289 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events index 3c1cc24361bd..7b40a3cbc26a 100644 --- a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events +++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events | |||
@@ -57,6 +57,523 @@ What: /sys/devices/cpu/events/PM_1PLUS_PPC_CMPL | |||
57 | /sys/devices/cpu/events/PM_LD_REF_L1 | 57 | /sys/devices/cpu/events/PM_LD_REF_L1 |
58 | /sys/devices/cpu/events/PM_RUN_CYC | 58 | /sys/devices/cpu/events/PM_RUN_CYC |
59 | /sys/devices/cpu/events/PM_RUN_INST_CMPL | 59 | /sys/devices/cpu/events/PM_RUN_INST_CMPL |
60 | /sys/devices/cpu/events/PM_IC_DEMAND_L2_BR_ALL | ||
61 | /sys/devices/cpu/events/PM_GCT_UTIL_7_TO_10_SLOTS | ||
62 | /sys/devices/cpu/events/PM_PMC2_SAVED | ||
63 | /sys/devices/cpu/events/PM_VSU0_16FLOP | ||
64 | /sys/devices/cpu/events/PM_MRK_LSU_DERAT_MISS | ||
65 | /sys/devices/cpu/events/PM_MRK_ST_CMPL | ||
66 | /sys/devices/cpu/events/PM_NEST_PAIR3_ADD | ||
67 | /sys/devices/cpu/events/PM_L2_ST_DISP | ||
68 | /sys/devices/cpu/events/PM_L2_CASTOUT_MOD | ||
69 | /sys/devices/cpu/events/PM_ISEG | ||
70 | /sys/devices/cpu/events/PM_MRK_INST_TIMEO | ||
71 | /sys/devices/cpu/events/PM_L2_RCST_DISP_FAIL_ADDR | ||
72 | /sys/devices/cpu/events/PM_LSU1_DC_PREF_STREAM_CONFIRM | ||
73 | /sys/devices/cpu/events/PM_IERAT_WR_64K | ||
74 | /sys/devices/cpu/events/PM_MRK_DTLB_MISS_16M | ||
75 | /sys/devices/cpu/events/PM_IERAT_MISS | ||
76 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_LMEM | ||
77 | /sys/devices/cpu/events/PM_FLOP | ||
78 | /sys/devices/cpu/events/PM_THRD_PRIO_4_5_CYC | ||
79 | /sys/devices/cpu/events/PM_BR_PRED_TA | ||
80 | /sys/devices/cpu/events/PM_EXT_INT | ||
81 | /sys/devices/cpu/events/PM_VSU_FSQRT_FDIV | ||
82 | /sys/devices/cpu/events/PM_MRK_LD_MISS_EXPOSED_CYC | ||
83 | /sys/devices/cpu/events/PM_LSU1_LDF | ||
84 | /sys/devices/cpu/events/PM_IC_WRITE_ALL | ||
85 | /sys/devices/cpu/events/PM_LSU0_SRQ_STFWD | ||
86 | /sys/devices/cpu/events/PM_PTEG_FROM_RL2L3_MOD | ||
87 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L31_SHR | ||
88 | /sys/devices/cpu/events/PM_DATA_FROM_L21_MOD | ||
89 | /sys/devices/cpu/events/PM_VSU1_SCAL_DOUBLE_ISSUED | ||
90 | /sys/devices/cpu/events/PM_VSU0_8FLOP | ||
91 | /sys/devices/cpu/events/PM_POWER_EVENT1 | ||
92 | /sys/devices/cpu/events/PM_DISP_CLB_HELD_BAL | ||
93 | /sys/devices/cpu/events/PM_VSU1_2FLOP | ||
94 | /sys/devices/cpu/events/PM_LWSYNC_HELD | ||
95 | /sys/devices/cpu/events/PM_PTEG_FROM_DL2L3_SHR | ||
96 | /sys/devices/cpu/events/PM_INST_FROM_L21_MOD | ||
97 | /sys/devices/cpu/events/PM_IERAT_XLATE_WR_16MPLUS | ||
98 | /sys/devices/cpu/events/PM_IC_REQ_ALL | ||
99 | /sys/devices/cpu/events/PM_DSLB_MISS | ||
100 | /sys/devices/cpu/events/PM_L3_MISS | ||
101 | /sys/devices/cpu/events/PM_LSU0_L1_PREF | ||
102 | /sys/devices/cpu/events/PM_VSU_SCALAR_SINGLE_ISSUED | ||
103 | /sys/devices/cpu/events/PM_LSU1_DC_PREF_STREAM_CONFIRM_STRIDE | ||
104 | /sys/devices/cpu/events/PM_L2_INST | ||
105 | /sys/devices/cpu/events/PM_VSU0_FRSP | ||
106 | /sys/devices/cpu/events/PM_FLUSH_DISP | ||
107 | /sys/devices/cpu/events/PM_PTEG_FROM_L2MISS | ||
108 | /sys/devices/cpu/events/PM_VSU1_DQ_ISSUED | ||
109 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_DMEM | ||
110 | /sys/devices/cpu/events/PM_LSU_FLUSH_ULD | ||
111 | /sys/devices/cpu/events/PM_PTEG_FROM_LMEM | ||
112 | /sys/devices/cpu/events/PM_MRK_DERAT_MISS_16M | ||
113 | /sys/devices/cpu/events/PM_THRD_ALL_RUN_CYC | ||
114 | /sys/devices/cpu/events/PM_MEM0_PREFETCH_DISP | ||
115 | /sys/devices/cpu/events/PM_MRK_STALL_CMPLU_CYC_COUNT | ||
116 | /sys/devices/cpu/events/PM_DATA_FROM_DL2L3_MOD | ||
117 | /sys/devices/cpu/events/PM_VSU_FRSP | ||
118 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L21_MOD | ||
119 | /sys/devices/cpu/events/PM_PMC1_OVERFLOW | ||
120 | /sys/devices/cpu/events/PM_VSU0_SINGLE | ||
121 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_L3MISS | ||
122 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_L31_SHR | ||
123 | /sys/devices/cpu/events/PM_VSU0_VECTOR_SP_ISSUED | ||
124 | /sys/devices/cpu/events/PM_VSU1_FEST | ||
125 | /sys/devices/cpu/events/PM_MRK_INST_DISP | ||
126 | /sys/devices/cpu/events/PM_VSU0_COMPLEX_ISSUED | ||
127 | /sys/devices/cpu/events/PM_LSU1_FLUSH_UST | ||
128 | /sys/devices/cpu/events/PM_FXU_IDLE | ||
129 | /sys/devices/cpu/events/PM_LSU0_FLUSH_ULD | ||
130 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_DL2L3_MOD | ||
131 | /sys/devices/cpu/events/PM_LSU_LMQ_SRQ_EMPTY_ALL_CYC | ||
132 | /sys/devices/cpu/events/PM_LSU1_REJECT_LMQ_FULL | ||
133 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_L21_MOD | ||
134 | /sys/devices/cpu/events/PM_INST_FROM_RL2L3_MOD | ||
135 | /sys/devices/cpu/events/PM_SHL_CREATED | ||
136 | /sys/devices/cpu/events/PM_L2_ST_HIT | ||
137 | /sys/devices/cpu/events/PM_DATA_FROM_DMEM | ||
138 | /sys/devices/cpu/events/PM_L3_LD_MISS | ||
139 | /sys/devices/cpu/events/PM_FXU1_BUSY_FXU0_IDLE | ||
140 | /sys/devices/cpu/events/PM_DISP_CLB_HELD_RES | ||
141 | /sys/devices/cpu/events/PM_L2_SN_SX_I_DONE | ||
142 | /sys/devices/cpu/events/PM_STCX_CMPL | ||
143 | /sys/devices/cpu/events/PM_VSU0_2FLOP | ||
144 | /sys/devices/cpu/events/PM_L3_PREF_MISS | ||
145 | /sys/devices/cpu/events/PM_LSU_SRQ_SYNC_CYC | ||
146 | /sys/devices/cpu/events/PM_LSU_REJECT_ERAT_MISS | ||
147 | /sys/devices/cpu/events/PM_L1_ICACHE_MISS | ||
148 | /sys/devices/cpu/events/PM_LSU1_FLUSH_SRQ | ||
149 | /sys/devices/cpu/events/PM_LD_REF_L1_LSU0 | ||
150 | /sys/devices/cpu/events/PM_VSU0_FEST | ||
151 | /sys/devices/cpu/events/PM_VSU_VECTOR_SINGLE_ISSUED | ||
152 | /sys/devices/cpu/events/PM_FREQ_UP | ||
153 | /sys/devices/cpu/events/PM_DATA_FROM_LMEM | ||
154 | /sys/devices/cpu/events/PM_LSU1_LDX | ||
155 | /sys/devices/cpu/events/PM_PMC3_OVERFLOW | ||
156 | /sys/devices/cpu/events/PM_MRK_BR_MPRED | ||
157 | /sys/devices/cpu/events/PM_SHL_MATCH | ||
158 | /sys/devices/cpu/events/PM_MRK_BR_TAKEN | ||
159 | /sys/devices/cpu/events/PM_ISLB_MISS | ||
160 | /sys/devices/cpu/events/PM_DISP_HELD_THERMAL | ||
161 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_RL2L3_SHR | ||
162 | /sys/devices/cpu/events/PM_LSU1_SRQ_STFWD | ||
163 | /sys/devices/cpu/events/PM_PTEG_FROM_DMEM | ||
164 | /sys/devices/cpu/events/PM_VSU_2FLOP | ||
165 | /sys/devices/cpu/events/PM_GCT_FULL_CYC | ||
166 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L3_CYC | ||
167 | /sys/devices/cpu/events/PM_LSU_SRQ_S0_ALLOC | ||
168 | /sys/devices/cpu/events/PM_MRK_DERAT_MISS_4K | ||
169 | /sys/devices/cpu/events/PM_BR_MPRED_TA | ||
170 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_L2MISS | ||
171 | /sys/devices/cpu/events/PM_DPU_HELD_POWER | ||
172 | /sys/devices/cpu/events/PM_MRK_VSU_FIN | ||
173 | /sys/devices/cpu/events/PM_LSU_SRQ_S0_VALID | ||
174 | /sys/devices/cpu/events/PM_GCT_EMPTY_CYC | ||
175 | /sys/devices/cpu/events/PM_IOPS_DISP | ||
176 | /sys/devices/cpu/events/PM_RUN_SPURR | ||
177 | /sys/devices/cpu/events/PM_PTEG_FROM_L21_MOD | ||
178 | /sys/devices/cpu/events/PM_VSU0_1FLOP | ||
179 | /sys/devices/cpu/events/PM_SNOOP_TLBIE | ||
180 | /sys/devices/cpu/events/PM_DATA_FROM_L3MISS | ||
181 | /sys/devices/cpu/events/PM_VSU_SINGLE | ||
182 | /sys/devices/cpu/events/PM_DTLB_MISS_16G | ||
183 | /sys/devices/cpu/events/PM_FLUSH | ||
184 | /sys/devices/cpu/events/PM_L2_LD_HIT | ||
185 | /sys/devices/cpu/events/PM_NEST_PAIR2_AND | ||
186 | /sys/devices/cpu/events/PM_VSU1_1FLOP | ||
187 | /sys/devices/cpu/events/PM_IC_PREF_REQ | ||
188 | /sys/devices/cpu/events/PM_L3_LD_HIT | ||
189 | /sys/devices/cpu/events/PM_DISP_HELD | ||
190 | /sys/devices/cpu/events/PM_L2_LD | ||
191 | /sys/devices/cpu/events/PM_LSU_FLUSH_SRQ | ||
192 | /sys/devices/cpu/events/PM_BC_PLUS_8_CONV | ||
193 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L31_MOD_CYC | ||
194 | /sys/devices/cpu/events/PM_L2_RCST_BUSY_RC_FULL | ||
195 | /sys/devices/cpu/events/PM_TB_BIT_TRANS | ||
196 | /sys/devices/cpu/events/PM_THERMAL_MAX | ||
197 | /sys/devices/cpu/events/PM_LSU1_FLUSH_ULD | ||
198 | /sys/devices/cpu/events/PM_LSU1_REJECT_LHS | ||
199 | /sys/devices/cpu/events/PM_LSU_LRQ_S0_ALLOC | ||
200 | /sys/devices/cpu/events/PM_L3_CO_L31 | ||
201 | /sys/devices/cpu/events/PM_POWER_EVENT4 | ||
202 | /sys/devices/cpu/events/PM_DATA_FROM_L31_SHR | ||
203 | /sys/devices/cpu/events/PM_BR_UNCOND | ||
204 | /sys/devices/cpu/events/PM_LSU1_DC_PREF_STREAM_ALLOC | ||
205 | /sys/devices/cpu/events/PM_PMC4_REWIND | ||
206 | /sys/devices/cpu/events/PM_L2_RCLD_DISP | ||
207 | /sys/devices/cpu/events/PM_THRD_PRIO_2_3_CYC | ||
208 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_L2MISS | ||
209 | /sys/devices/cpu/events/PM_IC_DEMAND_L2_BHT_REDIRECT | ||
210 | /sys/devices/cpu/events/PM_DATA_FROM_L31_SHR | ||
211 | /sys/devices/cpu/events/PM_IC_PREF_CANCEL_L2 | ||
212 | /sys/devices/cpu/events/PM_MRK_FIN_STALL_CYC_COUNT | ||
213 | /sys/devices/cpu/events/PM_BR_PRED_CCACHE | ||
214 | /sys/devices/cpu/events/PM_GCT_UTIL_1_TO_2_SLOTS | ||
215 | /sys/devices/cpu/events/PM_MRK_ST_CMPL_INT | ||
216 | /sys/devices/cpu/events/PM_LSU_TWO_TABLEWALK_CYC | ||
217 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L3MISS | ||
218 | /sys/devices/cpu/events/PM_LSU_SET_MPRED | ||
219 | /sys/devices/cpu/events/PM_FLUSH_DISP_TLBIE | ||
220 | /sys/devices/cpu/events/PM_VSU1_FCONV | ||
221 | /sys/devices/cpu/events/PM_DERAT_MISS_16G | ||
222 | /sys/devices/cpu/events/PM_INST_FROM_LMEM | ||
223 | /sys/devices/cpu/events/PM_IC_DEMAND_L2_BR_REDIRECT | ||
224 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_L2 | ||
225 | /sys/devices/cpu/events/PM_PTEG_FROM_L2 | ||
226 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L21_SHR_CYC | ||
227 | /sys/devices/cpu/events/PM_MRK_DTLB_MISS_4K | ||
228 | /sys/devices/cpu/events/PM_VSU0_FPSCR | ||
229 | /sys/devices/cpu/events/PM_VSU1_VECT_DOUBLE_ISSUED | ||
230 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_RL2L3_MOD | ||
231 | /sys/devices/cpu/events/PM_MEM0_RQ_DISP | ||
232 | /sys/devices/cpu/events/PM_L2_LD_MISS | ||
233 | /sys/devices/cpu/events/PM_VMX_RESULT_SAT_1 | ||
234 | /sys/devices/cpu/events/PM_L1_PREF | ||
235 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_LMEM_CYC | ||
236 | /sys/devices/cpu/events/PM_GRP_IC_MISS_NONSPEC | ||
237 | /sys/devices/cpu/events/PM_PB_NODE_PUMP | ||
238 | /sys/devices/cpu/events/PM_SHL_MERGED | ||
239 | /sys/devices/cpu/events/PM_NEST_PAIR1_ADD | ||
240 | /sys/devices/cpu/events/PM_DATA_FROM_L3 | ||
241 | /sys/devices/cpu/events/PM_LSU_FLUSH | ||
242 | /sys/devices/cpu/events/PM_LSU_SRQ_SYNC_COUNT | ||
243 | /sys/devices/cpu/events/PM_PMC2_OVERFLOW | ||
244 | /sys/devices/cpu/events/PM_LSU_LDF | ||
245 | /sys/devices/cpu/events/PM_POWER_EVENT3 | ||
246 | /sys/devices/cpu/events/PM_DISP_WT | ||
247 | /sys/devices/cpu/events/PM_IC_BANK_CONFLICT | ||
248 | /sys/devices/cpu/events/PM_BR_MPRED_CR_TA | ||
249 | /sys/devices/cpu/events/PM_L2_INST_MISS | ||
250 | /sys/devices/cpu/events/PM_NEST_PAIR2_ADD | ||
251 | /sys/devices/cpu/events/PM_MRK_LSU_FLUSH | ||
252 | /sys/devices/cpu/events/PM_L2_LDST | ||
253 | /sys/devices/cpu/events/PM_INST_FROM_L31_SHR | ||
254 | /sys/devices/cpu/events/PM_VSU0_FIN | ||
255 | /sys/devices/cpu/events/PM_VSU1_FCONV | ||
256 | /sys/devices/cpu/events/PM_INST_FROM_RMEM | ||
257 | /sys/devices/cpu/events/PM_DISP_CLB_HELD_TLBIE | ||
258 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_DMEM_CYC | ||
259 | /sys/devices/cpu/events/PM_BR_PRED_CR | ||
260 | /sys/devices/cpu/events/PM_LSU_REJECT | ||
261 | /sys/devices/cpu/events/PM_GCT_UTIL_3_TO_6_SLOTS | ||
262 | /sys/devices/cpu/events/PM_CMPLU_STALL_END_GCT_NOSLOT | ||
263 | /sys/devices/cpu/events/PM_LSU0_REJECT_LMQ_FULL | ||
264 | /sys/devices/cpu/events/PM_VSU_FEST | ||
265 | /sys/devices/cpu/events/PM_NEST_PAIR0_AND | ||
266 | /sys/devices/cpu/events/PM_PTEG_FROM_L3 | ||
267 | /sys/devices/cpu/events/PM_POWER_EVENT2 | ||
268 | /sys/devices/cpu/events/PM_IC_PREF_CANCEL_PAGE | ||
269 | /sys/devices/cpu/events/PM_VSU0_FSQRT_FDIV | ||
270 | /sys/devices/cpu/events/PM_MRK_GRP_CMPL | ||
271 | /sys/devices/cpu/events/PM_VSU0_SCAL_DOUBLE_ISSUED | ||
272 | /sys/devices/cpu/events/PM_GRP_DISP | ||
273 | /sys/devices/cpu/events/PM_LSU0_LDX | ||
274 | /sys/devices/cpu/events/PM_DATA_FROM_L2 | ||
275 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_RL2L3_MOD | ||
276 | /sys/devices/cpu/events/PM_VSU0_VECT_DOUBLE_ISSUED | ||
277 | /sys/devices/cpu/events/PM_VSU1_2FLOP_DOUBLE | ||
278 | /sys/devices/cpu/events/PM_THRD_PRIO_6_7_CYC | ||
279 | /sys/devices/cpu/events/PM_BC_PLUS_8_RSLV_TAKEN | ||
280 | /sys/devices/cpu/events/PM_BR_MPRED_CR | ||
281 | /sys/devices/cpu/events/PM_L3_CO_MEM | ||
282 | /sys/devices/cpu/events/PM_DATA_FROM_RL2L3_MOD | ||
283 | /sys/devices/cpu/events/PM_LSU_SRQ_FULL_CYC | ||
284 | /sys/devices/cpu/events/PM_TABLEWALK_CYC | ||
285 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_RMEM | ||
286 | /sys/devices/cpu/events/PM_LSU_SRQ_STFWD | ||
287 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_RMEM | ||
288 | /sys/devices/cpu/events/PM_FXU0_FIN | ||
289 | /sys/devices/cpu/events/PM_LSU1_L1_SW_PREF | ||
290 | /sys/devices/cpu/events/PM_PTEG_FROM_L31_MOD | ||
291 | /sys/devices/cpu/events/PM_PMC5_OVERFLOW | ||
292 | /sys/devices/cpu/events/PM_LD_REF_L1_LSU1 | ||
293 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_L21_SHR | ||
294 | /sys/devices/cpu/events/PM_DATA_FROM_RMEM | ||
295 | /sys/devices/cpu/events/PM_VSU0_SCAL_SINGLE_ISSUED | ||
296 | /sys/devices/cpu/events/PM_BR_MPRED_LSTACK | ||
297 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_RL2L3_MOD_CYC | ||
298 | /sys/devices/cpu/events/PM_LSU0_FLUSH_UST | ||
299 | /sys/devices/cpu/events/PM_LSU_NCST | ||
300 | /sys/devices/cpu/events/PM_BR_TAKEN | ||
301 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_LMEM | ||
302 | /sys/devices/cpu/events/PM_DTLB_MISS_4K | ||
303 | /sys/devices/cpu/events/PM_PMC4_SAVED | ||
304 | /sys/devices/cpu/events/PM_VSU1_PERMUTE_ISSUED | ||
305 | /sys/devices/cpu/events/PM_SLB_MISS | ||
306 | /sys/devices/cpu/events/PM_LSU1_FLUSH_LRQ | ||
307 | /sys/devices/cpu/events/PM_DTLB_MISS | ||
308 | /sys/devices/cpu/events/PM_VSU1_FRSP | ||
309 | /sys/devices/cpu/events/PM_VSU_VECTOR_DOUBLE_ISSUED | ||
310 | /sys/devices/cpu/events/PM_L2_CASTOUT_SHR | ||
311 | /sys/devices/cpu/events/PM_DATA_FROM_DL2L3_SHR | ||
312 | /sys/devices/cpu/events/PM_VSU1_STF | ||
313 | /sys/devices/cpu/events/PM_ST_FIN | ||
314 | /sys/devices/cpu/events/PM_PTEG_FROM_L21_SHR | ||
315 | /sys/devices/cpu/events/PM_L2_LOC_GUESS_WRONG | ||
316 | /sys/devices/cpu/events/PM_MRK_STCX_FAIL | ||
317 | /sys/devices/cpu/events/PM_LSU0_REJECT_LHS | ||
318 | /sys/devices/cpu/events/PM_IC_PREF_CANCEL_HIT | ||
319 | /sys/devices/cpu/events/PM_L3_PREF_BUSY | ||
320 | /sys/devices/cpu/events/PM_MRK_BRU_FIN | ||
321 | /sys/devices/cpu/events/PM_LSU1_NCLD | ||
322 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_L31_MOD | ||
323 | /sys/devices/cpu/events/PM_LSU_NCLD | ||
324 | /sys/devices/cpu/events/PM_LSU_LDX | ||
325 | /sys/devices/cpu/events/PM_L2_LOC_GUESS_CORRECT | ||
326 | /sys/devices/cpu/events/PM_THRESH_TIMEO | ||
327 | /sys/devices/cpu/events/PM_L3_PREF_ST | ||
328 | /sys/devices/cpu/events/PM_DISP_CLB_HELD_SYNC | ||
329 | /sys/devices/cpu/events/PM_VSU_SIMPLE_ISSUED | ||
330 | /sys/devices/cpu/events/PM_VSU1_SINGLE | ||
331 | /sys/devices/cpu/events/PM_DATA_TABLEWALK_CYC | ||
332 | /sys/devices/cpu/events/PM_L2_RC_ST_DONE | ||
333 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_L21_MOD | ||
334 | /sys/devices/cpu/events/PM_LARX_LSU1 | ||
335 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_RMEM | ||
336 | /sys/devices/cpu/events/PM_DISP_CLB_HELD | ||
337 | /sys/devices/cpu/events/PM_DERAT_MISS_4K | ||
338 | /sys/devices/cpu/events/PM_L2_RCLD_DISP_FAIL_ADDR | ||
339 | /sys/devices/cpu/events/PM_SEG_EXCEPTION | ||
340 | /sys/devices/cpu/events/PM_FLUSH_DISP_SB | ||
341 | /sys/devices/cpu/events/PM_L2_DC_INV | ||
342 | /sys/devices/cpu/events/PM_PTEG_FROM_DL2L3_MOD | ||
343 | /sys/devices/cpu/events/PM_DSEG | ||
344 | /sys/devices/cpu/events/PM_BR_PRED_LSTACK | ||
345 | /sys/devices/cpu/events/PM_VSU0_STF | ||
346 | /sys/devices/cpu/events/PM_LSU_FX_FIN | ||
347 | /sys/devices/cpu/events/PM_DERAT_MISS_16M | ||
348 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_DL2L3_MOD | ||
349 | /sys/devices/cpu/events/PM_GCT_UTIL_11_PLUS_SLOTS | ||
350 | /sys/devices/cpu/events/PM_INST_FROM_L3 | ||
351 | /sys/devices/cpu/events/PM_MRK_IFU_FIN | ||
352 | /sys/devices/cpu/events/PM_ITLB_MISS | ||
353 | /sys/devices/cpu/events/PM_VSU_STF | ||
354 | /sys/devices/cpu/events/PM_LSU_FLUSH_UST | ||
355 | /sys/devices/cpu/events/PM_L2_LDST_MISS | ||
356 | /sys/devices/cpu/events/PM_FXU1_FIN | ||
357 | /sys/devices/cpu/events/PM_SHL_DEALLOCATED | ||
358 | /sys/devices/cpu/events/PM_L2_SN_M_WR_DONE | ||
359 | /sys/devices/cpu/events/PM_LSU_REJECT_SET_MPRED | ||
360 | /sys/devices/cpu/events/PM_L3_PREF_LD | ||
361 | /sys/devices/cpu/events/PM_L2_SN_M_RD_DONE | ||
362 | /sys/devices/cpu/events/PM_MRK_DERAT_MISS_16G | ||
363 | /sys/devices/cpu/events/PM_VSU_FCONV | ||
364 | /sys/devices/cpu/events/PM_ANY_THRD_RUN_CYC | ||
365 | /sys/devices/cpu/events/PM_LSU_LMQ_FULL_CYC | ||
366 | /sys/devices/cpu/events/PM_MRK_LSU_REJECT_LHS | ||
367 | /sys/devices/cpu/events/PM_MRK_LD_MISS_L1_CYC | ||
368 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L2_CYC | ||
369 | /sys/devices/cpu/events/PM_INST_IMC_MATCH_DISP | ||
370 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_RMEM_CYC | ||
371 | /sys/devices/cpu/events/PM_VSU0_SIMPLE_ISSUED | ||
372 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_RL2L3_SHR | ||
373 | /sys/devices/cpu/events/PM_VSU_FMA_DOUBLE | ||
374 | /sys/devices/cpu/events/PM_VSU_4FLOP | ||
375 | /sys/devices/cpu/events/PM_VSU1_FIN | ||
376 | /sys/devices/cpu/events/PM_NEST_PAIR1_AND | ||
377 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_RL2L3_MOD | ||
378 | /sys/devices/cpu/events/PM_PTEG_FROM_RMEM | ||
379 | /sys/devices/cpu/events/PM_LSU_LRQ_S0_VALID | ||
380 | /sys/devices/cpu/events/PM_LSU0_LDF | ||
381 | /sys/devices/cpu/events/PM_FLUSH_COMPLETION | ||
382 | /sys/devices/cpu/events/PM_ST_MISS_L1 | ||
383 | /sys/devices/cpu/events/PM_L2_NODE_PUMP | ||
384 | /sys/devices/cpu/events/PM_INST_FROM_DL2L3_SHR | ||
385 | /sys/devices/cpu/events/PM_MRK_STALL_CMPLU_CYC | ||
386 | /sys/devices/cpu/events/PM_VSU1_DENORM | ||
387 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L31_SHR_CYC | ||
388 | /sys/devices/cpu/events/PM_NEST_PAIR0_ADD | ||
389 | /sys/devices/cpu/events/PM_INST_FROM_L3MISS | ||
390 | /sys/devices/cpu/events/PM_EE_OFF_EXT_INT | ||
391 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_DMEM | ||
392 | /sys/devices/cpu/events/PM_INST_FROM_DL2L3_MOD | ||
393 | /sys/devices/cpu/events/PM_PMC6_OVERFLOW | ||
394 | /sys/devices/cpu/events/PM_VSU_2FLOP_DOUBLE | ||
395 | /sys/devices/cpu/events/PM_TLB_MISS | ||
396 | /sys/devices/cpu/events/PM_FXU_BUSY | ||
397 | /sys/devices/cpu/events/PM_L2_RCLD_DISP_FAIL_OTHER | ||
398 | /sys/devices/cpu/events/PM_LSU_REJECT_LMQ_FULL | ||
399 | /sys/devices/cpu/events/PM_IC_RELOAD_SHR | ||
400 | /sys/devices/cpu/events/PM_GRP_MRK | ||
401 | /sys/devices/cpu/events/PM_MRK_ST_NEST | ||
402 | /sys/devices/cpu/events/PM_VSU1_FSQRT_FDIV | ||
403 | /sys/devices/cpu/events/PM_LSU0_FLUSH_LRQ | ||
404 | /sys/devices/cpu/events/PM_LARX_LSU0 | ||
405 | /sys/devices/cpu/events/PM_IBUF_FULL_CYC | ||
406 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_DL2L3_SHR_CYC | ||
407 | /sys/devices/cpu/events/PM_LSU_DC_PREF_STREAM_ALLOC | ||
408 | /sys/devices/cpu/events/PM_GRP_MRK_CYC | ||
409 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_RL2L3_SHR_CYC | ||
410 | /sys/devices/cpu/events/PM_L2_GLOB_GUESS_CORRECT | ||
411 | /sys/devices/cpu/events/PM_LSU_REJECT_LHS | ||
412 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_LMEM | ||
413 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_L3 | ||
414 | /sys/devices/cpu/events/PM_FREQ_DOWN | ||
415 | /sys/devices/cpu/events/PM_PB_RETRY_NODE_PUMP | ||
416 | /sys/devices/cpu/events/PM_INST_FROM_RL2L3_SHR | ||
417 | /sys/devices/cpu/events/PM_MRK_INST_ISSUED | ||
418 | /sys/devices/cpu/events/PM_PTEG_FROM_L3MISS | ||
419 | /sys/devices/cpu/events/PM_RUN_PURR | ||
420 | /sys/devices/cpu/events/PM_MRK_GRP_IC_MISS | ||
421 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L3 | ||
422 | /sys/devices/cpu/events/PM_PTEG_FROM_RL2L3_SHR | ||
423 | /sys/devices/cpu/events/PM_LSU_FLUSH_LRQ | ||
424 | /sys/devices/cpu/events/PM_MRK_DERAT_MISS_64K | ||
425 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_DL2L3_MOD | ||
426 | /sys/devices/cpu/events/PM_L2_ST_MISS | ||
427 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_L21_SHR | ||
428 | /sys/devices/cpu/events/PM_LWSYNC | ||
429 | /sys/devices/cpu/events/PM_LSU0_DC_PREF_STREAM_CONFIRM_STRIDE | ||
430 | /sys/devices/cpu/events/PM_MRK_LSU_FLUSH_LRQ | ||
431 | /sys/devices/cpu/events/PM_INST_IMC_MATCH_CMPL | ||
432 | /sys/devices/cpu/events/PM_NEST_PAIR3_AND | ||
433 | /sys/devices/cpu/events/PM_PB_RETRY_SYS_PUMP | ||
434 | /sys/devices/cpu/events/PM_MRK_INST_FIN | ||
435 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_DL2L3_SHR | ||
436 | /sys/devices/cpu/events/PM_INST_FROM_L31_MOD | ||
437 | /sys/devices/cpu/events/PM_MRK_DTLB_MISS_64K | ||
438 | /sys/devices/cpu/events/PM_LSU_FIN | ||
439 | /sys/devices/cpu/events/PM_MRK_LSU_REJECT | ||
440 | /sys/devices/cpu/events/PM_L2_CO_FAIL_BUSY | ||
441 | /sys/devices/cpu/events/PM_MEM0_WQ_DISP | ||
442 | /sys/devices/cpu/events/PM_DATA_FROM_L31_MOD | ||
443 | /sys/devices/cpu/events/PM_THERMAL_WARN | ||
444 | /sys/devices/cpu/events/PM_VSU0_4FLOP | ||
445 | /sys/devices/cpu/events/PM_BR_MPRED_CCACHE | ||
446 | /sys/devices/cpu/events/PM_L1_DEMAND_WRITE | ||
447 | /sys/devices/cpu/events/PM_FLUSH_BR_MPRED | ||
448 | /sys/devices/cpu/events/PM_MRK_DTLB_MISS_16G | ||
449 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_DMEM | ||
450 | /sys/devices/cpu/events/PM_L2_RCST_DISP | ||
451 | /sys/devices/cpu/events/PM_LSU_PARTIAL_CDF | ||
452 | /sys/devices/cpu/events/PM_DISP_CLB_HELD_SB | ||
453 | /sys/devices/cpu/events/PM_VSU0_FMA_DOUBLE | ||
454 | /sys/devices/cpu/events/PM_FXU0_BUSY_FXU1_IDLE | ||
455 | /sys/devices/cpu/events/PM_IC_DEMAND_CYC | ||
456 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L21_SHR | ||
457 | /sys/devices/cpu/events/PM_MRK_LSU_FLUSH_UST | ||
458 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_L3MISS | ||
459 | /sys/devices/cpu/events/PM_VSU_DENORM | ||
460 | /sys/devices/cpu/events/PM_MRK_LSU_PARTIAL_CDF | ||
461 | /sys/devices/cpu/events/PM_INST_FROM_L21_SHR | ||
462 | /sys/devices/cpu/events/PM_IC_PREF_WRITE | ||
463 | /sys/devices/cpu/events/PM_BR_PRED | ||
464 | /sys/devices/cpu/events/PM_INST_FROM_DMEM | ||
465 | /sys/devices/cpu/events/PM_IC_PREF_CANCEL_ALL | ||
466 | /sys/devices/cpu/events/PM_LSU_DC_PREF_STREAM_CONFIRM | ||
467 | /sys/devices/cpu/events/PM_MRK_LSU_FLUSH_SRQ | ||
468 | /sys/devices/cpu/events/PM_MRK_FIN_STALL_CYC | ||
469 | /sys/devices/cpu/events/PM_L2_RCST_DISP_FAIL_OTHER | ||
470 | /sys/devices/cpu/events/PM_VSU1_DD_ISSUED | ||
471 | /sys/devices/cpu/events/PM_PTEG_FROM_L31_SHR | ||
472 | /sys/devices/cpu/events/PM_DATA_FROM_L21_SHR | ||
473 | /sys/devices/cpu/events/PM_LSU0_NCLD | ||
474 | /sys/devices/cpu/events/PM_VSU1_4FLOP | ||
475 | /sys/devices/cpu/events/PM_VSU1_8FLOP | ||
476 | /sys/devices/cpu/events/PM_VSU_8FLOP | ||
477 | /sys/devices/cpu/events/PM_LSU_LMQ_SRQ_EMPTY_CYC | ||
478 | /sys/devices/cpu/events/PM_DTLB_MISS_64K | ||
479 | /sys/devices/cpu/events/PM_THRD_CONC_RUN_INST | ||
480 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_L2 | ||
481 | /sys/devices/cpu/events/PM_PB_SYS_PUMP | ||
482 | /sys/devices/cpu/events/PM_VSU_FIN | ||
483 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L31_MOD | ||
484 | /sys/devices/cpu/events/PM_THRD_PRIO_0_1_CYC | ||
485 | /sys/devices/cpu/events/PM_DERAT_MISS_64K | ||
486 | /sys/devices/cpu/events/PM_PMC2_REWIND | ||
487 | /sys/devices/cpu/events/PM_INST_FROM_L2 | ||
488 | /sys/devices/cpu/events/PM_GRP_BR_MPRED_NONSPEC | ||
489 | /sys/devices/cpu/events/PM_INST_DISP | ||
490 | /sys/devices/cpu/events/PM_MEM0_RD_CANCEL_TOTAL | ||
491 | /sys/devices/cpu/events/PM_LSU0_DC_PREF_STREAM_CONFIRM | ||
492 | /sys/devices/cpu/events/PM_L1_DCACHE_RELOAD_VALID | ||
493 | /sys/devices/cpu/events/PM_VSU_SCALAR_DOUBLE_ISSUED | ||
494 | /sys/devices/cpu/events/PM_L3_PREF_HIT | ||
495 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_L31_MOD | ||
496 | /sys/devices/cpu/events/PM_MRK_FXU_FIN | ||
497 | /sys/devices/cpu/events/PM_PMC4_OVERFLOW | ||
498 | /sys/devices/cpu/events/PM_MRK_PTEG_FROM_L3 | ||
499 | /sys/devices/cpu/events/PM_LSU0_LMQ_LHR_MERGE | ||
500 | /sys/devices/cpu/events/PM_BTAC_HIT | ||
501 | /sys/devices/cpu/events/PM_L3_RD_BUSY | ||
502 | /sys/devices/cpu/events/PM_LSU0_L1_SW_PREF | ||
503 | /sys/devices/cpu/events/PM_INST_FROM_L2MISS | ||
504 | /sys/devices/cpu/events/PM_LSU0_DC_PREF_STREAM_ALLOC | ||
505 | /sys/devices/cpu/events/PM_L2_ST | ||
506 | /sys/devices/cpu/events/PM_VSU0_DENORM | ||
507 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_DL2L3_SHR | ||
508 | /sys/devices/cpu/events/PM_BR_PRED_CR_TA | ||
509 | /sys/devices/cpu/events/PM_VSU0_FCONV | ||
510 | /sys/devices/cpu/events/PM_MRK_LSU_FLUSH_ULD | ||
511 | /sys/devices/cpu/events/PM_BTAC_MISS | ||
512 | /sys/devices/cpu/events/PM_MRK_LD_MISS_EXPOSED_CYC_COUNT | ||
513 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L2 | ||
514 | /sys/devices/cpu/events/PM_LSU_DCACHE_RELOAD_VALID | ||
515 | /sys/devices/cpu/events/PM_VSU_FMA | ||
516 | /sys/devices/cpu/events/PM_LSU0_FLUSH_SRQ | ||
517 | /sys/devices/cpu/events/PM_LSU1_L1_PREF | ||
518 | /sys/devices/cpu/events/PM_IOPS_CMPL | ||
519 | /sys/devices/cpu/events/PM_L2_SYS_PUMP | ||
520 | /sys/devices/cpu/events/PM_L2_RCLD_BUSY_RC_FULL | ||
521 | /sys/devices/cpu/events/PM_LSU_LMQ_S0_ALLOC | ||
522 | /sys/devices/cpu/events/PM_FLUSH_DISP_SYNC | ||
523 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_DL2L3_MOD_CYC | ||
524 | /sys/devices/cpu/events/PM_L2_IC_INV | ||
525 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L21_MOD_CYC | ||
526 | /sys/devices/cpu/events/PM_L3_PREF_LDST | ||
527 | /sys/devices/cpu/events/PM_LSU_SRQ_EMPTY_CYC | ||
528 | /sys/devices/cpu/events/PM_LSU_LMQ_S0_VALID | ||
529 | /sys/devices/cpu/events/PM_FLUSH_PARTIAL | ||
530 | /sys/devices/cpu/events/PM_VSU1_FMA_DOUBLE | ||
531 | /sys/devices/cpu/events/PM_1PLUS_PPC_DISP | ||
532 | /sys/devices/cpu/events/PM_DATA_FROM_L2MISS | ||
533 | /sys/devices/cpu/events/PM_SUSPENDED | ||
534 | /sys/devices/cpu/events/PM_VSU0_FMA | ||
535 | /sys/devices/cpu/events/PM_STCX_FAIL | ||
536 | /sys/devices/cpu/events/PM_VSU0_FSQRT_FDIV_DOUBLE | ||
537 | /sys/devices/cpu/events/PM_DC_PREF_DST | ||
538 | /sys/devices/cpu/events/PM_VSU1_SCAL_SINGLE_ISSUED | ||
539 | /sys/devices/cpu/events/PM_L3_HIT | ||
540 | /sys/devices/cpu/events/PM_L2_GLOB_GUESS_WRONG | ||
541 | /sys/devices/cpu/events/PM_MRK_DFU_FIN | ||
542 | /sys/devices/cpu/events/PM_INST_FROM_L1 | ||
543 | /sys/devices/cpu/events/PM_IC_DEMAND_REQ | ||
544 | /sys/devices/cpu/events/PM_VSU1_FSQRT_FDIV_DOUBLE | ||
545 | /sys/devices/cpu/events/PM_VSU1_FMA | ||
546 | /sys/devices/cpu/events/PM_MRK_LD_MISS_L1 | ||
547 | /sys/devices/cpu/events/PM_VSU0_2FLOP_DOUBLE | ||
548 | /sys/devices/cpu/events/PM_LSU_DC_PREF_STRIDED_STREAM_CONFIRM | ||
549 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_L31_SHR | ||
550 | /sys/devices/cpu/events/PM_MRK_LSU_REJECT_ERAT_MISS | ||
551 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_L2MISS | ||
552 | /sys/devices/cpu/events/PM_DATA_FROM_RL2L3_SHR | ||
553 | /sys/devices/cpu/events/PM_INST_FROM_PREF | ||
554 | /sys/devices/cpu/events/PM_VSU1_SQ | ||
555 | /sys/devices/cpu/events/PM_L2_LD_DISP | ||
556 | /sys/devices/cpu/events/PM_L2_DISP_ALL | ||
557 | /sys/devices/cpu/events/PM_THRD_GRP_CMPL_BOTH_CYC | ||
558 | /sys/devices/cpu/events/PM_VSU_FSQRT_FDIV_DOUBLE | ||
559 | /sys/devices/cpu/events/PM_INST_PTEG_FROM_DL2L3_SHR | ||
560 | /sys/devices/cpu/events/PM_VSU_1FLOP | ||
561 | /sys/devices/cpu/events/PM_HV_CYC | ||
562 | /sys/devices/cpu/events/PM_MRK_LSU_FIN | ||
563 | /sys/devices/cpu/events/PM_MRK_DATA_FROM_RL2L3_SHR | ||
564 | /sys/devices/cpu/events/PM_DTLB_MISS_16M | ||
565 | /sys/devices/cpu/events/PM_LSU1_LMQ_LHR_MERGE | ||
566 | /sys/devices/cpu/events/PM_IFU_FIN | ||
567 | /sys/devices/cpu/events/PM_1THRD_CON_RUN_INSTR | ||
568 | /sys/devices/cpu/events/PM_CMPLU_STALL_COUNT | ||
569 | /sys/devices/cpu/events/PM_MEM0_PB_RD_CL | ||
570 | /sys/devices/cpu/events/PM_THRD_1_RUN_CYC | ||
571 | /sys/devices/cpu/events/PM_THRD_2_CONC_RUN_INSTR | ||
572 | /sys/devices/cpu/events/PM_THRD_2_RUN_CYC | ||
573 | /sys/devices/cpu/events/PM_THRD_3_CONC_RUN_INST | ||
574 | /sys/devices/cpu/events/PM_THRD_3_RUN_CYC | ||
575 | /sys/devices/cpu/events/PM_THRD_4_CONC_RUN_INST | ||
576 | /sys/devices/cpu/events/PM_THRD_4_RUN_CYC | ||
60 | 577 | ||
61 | Date: 2013/01/08 | 578 | Date: 2013/01/08 |
62 | 579 | ||
diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7 b/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7 new file mode 100644 index 000000000000..e78ee798d7bd --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7 | |||
@@ -0,0 +1,23 @@ | |||
1 | What: /sys/bus/event_source/devices/hv_24x7/interface/catalog | ||
2 | Date: February 2014 | ||
3 | Contact: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
4 | Description: | ||
5 | Provides access to the binary "24x7 catalog" provided by the | ||
6 | hypervisor on POWER7 and 8 systems. This catalog lists events | ||
7 | avaliable from the powerpc "hv_24x7" pmu. Its format is | ||
8 | documented here: | ||
9 | https://raw.githubusercontent.com/jmesmon/catalog-24x7/master/hv-24x7-catalog.h | ||
10 | |||
11 | What: /sys/bus/event_source/devices/hv_24x7/interface/catalog_length | ||
12 | Date: February 2014 | ||
13 | Contact: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
14 | Description: | ||
15 | A number equal to the length in bytes of the catalog. This is | ||
16 | also extractable from the provided binary "catalog" sysfs entry. | ||
17 | |||
18 | What: /sys/bus/event_source/devices/hv_24x7/interface/catalog_version | ||
19 | Date: February 2014 | ||
20 | Contact: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
21 | Description: | ||
22 | Exposes the "version" field of the 24x7 catalog. This is also | ||
23 | extractable from the provided binary "catalog" sysfs entry. | ||
diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_gpci b/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_gpci new file mode 100644 index 000000000000..3fa58c23f13b --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_gpci | |||
@@ -0,0 +1,43 @@ | |||
1 | What: /sys/bus/event_source/devices/hv_gpci/interface/collect_privileged | ||
2 | Date: February 2014 | ||
3 | Contact: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
4 | Description: | ||
5 | '0' if the hypervisor is configured to forbid access to event | ||
6 | counters being accumulated by other guests and to physical | ||
7 | domain event counters. | ||
8 | '1' if that access is allowed. | ||
9 | |||
10 | What: /sys/bus/event_source/devices/hv_gpci/interface/ga | ||
11 | Date: February 2014 | ||
12 | Contact: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
13 | Description: | ||
14 | 0 or 1. Indicates whether we have access to "GA" events (listed | ||
15 | in arch/powerpc/perf/hv-gpci.h). | ||
16 | |||
17 | What: /sys/bus/event_source/devices/hv_gpci/interface/expanded | ||
18 | Date: February 2014 | ||
19 | Contact: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
20 | Description: | ||
21 | 0 or 1. Indicates whether we have access to "EXPANDED" events (listed | ||
22 | in arch/powerpc/perf/hv-gpci.h). | ||
23 | |||
24 | What: /sys/bus/event_source/devices/hv_gpci/interface/lab | ||
25 | Date: February 2014 | ||
26 | Contact: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
27 | Description: | ||
28 | 0 or 1. Indicates whether we have access to "LAB" events (listed | ||
29 | in arch/powerpc/perf/hv-gpci.h). | ||
30 | |||
31 | What: /sys/bus/event_source/devices/hv_gpci/interface/version | ||
32 | Date: February 2014 | ||
33 | Contact: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
34 | Description: | ||
35 | A number indicating the version of the gpci interface that the | ||
36 | hypervisor reports supporting. | ||
37 | |||
38 | What: /sys/bus/event_source/devices/hv_gpci/interface/kernel_version | ||
39 | Date: February 2014 | ||
40 | Contact: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
41 | Description: | ||
42 | A number indicating the latest version of the gpci interface | ||
43 | that the kernel is aware of. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index b2cf5cfb4d29..27030d573d88 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5216,11 +5216,10 @@ F: arch/powerpc/platforms/512x/ | |||
5216 | F: arch/powerpc/platforms/52xx/ | 5216 | F: arch/powerpc/platforms/52xx/ |
5217 | 5217 | ||
5218 | LINUX FOR POWERPC EMBEDDED PPC4XX | 5218 | LINUX FOR POWERPC EMBEDDED PPC4XX |
5219 | M: Josh Boyer <jwboyer@gmail.com> | 5219 | M: Alistair Popple <alistair@popple.id.au> |
5220 | M: Matt Porter <mporter@kernel.crashing.org> | 5220 | M: Matt Porter <mporter@kernel.crashing.org> |
5221 | W: http://www.penguinppc.org/ | 5221 | W: http://www.penguinppc.org/ |
5222 | L: linuxppc-dev@lists.ozlabs.org | 5222 | L: linuxppc-dev@lists.ozlabs.org |
5223 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git | ||
5224 | S: Maintained | 5223 | S: Maintained |
5225 | F: arch/powerpc/platforms/40x/ | 5224 | F: arch/powerpc/platforms/40x/ |
5226 | F: arch/powerpc/platforms/44x/ | 5225 | F: arch/powerpc/platforms/44x/ |
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index e015896b7e5c..f26b267eb71f 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig | |||
@@ -73,74 +73,8 @@ CONFIG_INET_ESP=m | |||
73 | CONFIG_INET_IPCOMP=m | 73 | CONFIG_INET_IPCOMP=m |
74 | # CONFIG_IPV6 is not set | 74 | # CONFIG_IPV6 is not set |
75 | CONFIG_NETFILTER=y | 75 | CONFIG_NETFILTER=y |
76 | CONFIG_NF_CONNTRACK=m | 76 | # CONFIG_NETFILTER_ADVANCED is not set |
77 | CONFIG_NF_CONNTRACK_EVENTS=y | 77 | CONFIG_BRIDGE=m |
78 | CONFIG_NF_CT_PROTO_SCTP=m | ||
79 | CONFIG_NF_CONNTRACK_AMANDA=m | ||
80 | CONFIG_NF_CONNTRACK_FTP=m | ||
81 | CONFIG_NF_CONNTRACK_H323=m | ||
82 | CONFIG_NF_CONNTRACK_IRC=m | ||
83 | CONFIG_NF_CONNTRACK_NETBIOS_NS=m | ||
84 | CONFIG_NF_CONNTRACK_PPTP=m | ||
85 | CONFIG_NF_CONNTRACK_SIP=m | ||
86 | CONFIG_NF_CONNTRACK_TFTP=m | ||
87 | CONFIG_NF_CT_NETLINK=m | ||
88 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | ||
89 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m | ||
90 | CONFIG_NETFILTER_XT_TARGET_DSCP=m | ||
91 | CONFIG_NETFILTER_XT_TARGET_MARK=m | ||
92 | CONFIG_NETFILTER_XT_TARGET_NFLOG=m | ||
93 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | ||
94 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
95 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | ||
96 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | ||
97 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | ||
98 | CONFIG_NETFILTER_XT_MATCH_COMMENT=m | ||
99 | CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m | ||
100 | CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m | ||
101 | CONFIG_NETFILTER_XT_MATCH_CONNMARK=m | ||
102 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m | ||
103 | CONFIG_NETFILTER_XT_MATCH_DCCP=m | ||
104 | CONFIG_NETFILTER_XT_MATCH_DSCP=m | ||
105 | CONFIG_NETFILTER_XT_MATCH_ESP=m | ||
106 | CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m | ||
107 | CONFIG_NETFILTER_XT_MATCH_HELPER=m | ||
108 | CONFIG_NETFILTER_XT_MATCH_IPRANGE=m | ||
109 | CONFIG_NETFILTER_XT_MATCH_LENGTH=m | ||
110 | CONFIG_NETFILTER_XT_MATCH_LIMIT=m | ||
111 | CONFIG_NETFILTER_XT_MATCH_MAC=m | ||
112 | CONFIG_NETFILTER_XT_MATCH_MARK=m | ||
113 | CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m | ||
114 | CONFIG_NETFILTER_XT_MATCH_OWNER=m | ||
115 | CONFIG_NETFILTER_XT_MATCH_POLICY=m | ||
116 | CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m | ||
117 | CONFIG_NETFILTER_XT_MATCH_QUOTA=m | ||
118 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | ||
119 | CONFIG_NETFILTER_XT_MATCH_REALM=m | ||
120 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | ||
121 | CONFIG_NETFILTER_XT_MATCH_SCTP=m | ||
122 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
123 | CONFIG_NETFILTER_XT_MATCH_STATE=m | ||
124 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | ||
125 | CONFIG_NETFILTER_XT_MATCH_STRING=m | ||
126 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | ||
127 | CONFIG_NETFILTER_XT_MATCH_U32=m | ||
128 | CONFIG_NF_CONNTRACK_IPV4=m | ||
129 | CONFIG_IP_NF_IPTABLES=m | ||
130 | CONFIG_IP_NF_MATCH_AH=m | ||
131 | CONFIG_IP_NF_MATCH_ECN=m | ||
132 | CONFIG_IP_NF_MATCH_TTL=m | ||
133 | CONFIG_IP_NF_FILTER=m | ||
134 | CONFIG_IP_NF_TARGET_REJECT=m | ||
135 | CONFIG_IP_NF_TARGET_ULOG=m | ||
136 | CONFIG_IP_NF_MANGLE=m | ||
137 | CONFIG_IP_NF_TARGET_CLUSTERIP=m | ||
138 | CONFIG_IP_NF_TARGET_ECN=m | ||
139 | CONFIG_IP_NF_TARGET_TTL=m | ||
140 | CONFIG_IP_NF_RAW=m | ||
141 | CONFIG_IP_NF_ARPTABLES=m | ||
142 | CONFIG_IP_NF_ARPFILTER=m | ||
143 | CONFIG_IP_NF_ARP_MANGLE=m | ||
144 | CONFIG_BPF_JIT=y | 78 | CONFIG_BPF_JIT=y |
145 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 79 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
146 | CONFIG_DEVTMPFS=y | 80 | CONFIG_DEVTMPFS=y |
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index f627fda08953..438e813dc9cb 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig | |||
@@ -48,74 +48,8 @@ CONFIG_INET_ESP=m | |||
48 | CONFIG_INET_IPCOMP=m | 48 | CONFIG_INET_IPCOMP=m |
49 | # CONFIG_IPV6 is not set | 49 | # CONFIG_IPV6 is not set |
50 | CONFIG_NETFILTER=y | 50 | CONFIG_NETFILTER=y |
51 | CONFIG_NF_CONNTRACK=m | 51 | # CONFIG_NETFILTER_ADVANCED is not set |
52 | CONFIG_NF_CONNTRACK_EVENTS=y | 52 | CONFIG_BRIDGE=m |
53 | CONFIG_NF_CT_PROTO_SCTP=m | ||
54 | CONFIG_NF_CONNTRACK_AMANDA=m | ||
55 | CONFIG_NF_CONNTRACK_FTP=m | ||
56 | CONFIG_NF_CONNTRACK_H323=m | ||
57 | CONFIG_NF_CONNTRACK_IRC=m | ||
58 | CONFIG_NF_CONNTRACK_NETBIOS_NS=m | ||
59 | CONFIG_NF_CONNTRACK_PPTP=m | ||
60 | CONFIG_NF_CONNTRACK_SIP=m | ||
61 | CONFIG_NF_CONNTRACK_TFTP=m | ||
62 | CONFIG_NF_CT_NETLINK=m | ||
63 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | ||
64 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m | ||
65 | CONFIG_NETFILTER_XT_TARGET_DSCP=m | ||
66 | CONFIG_NETFILTER_XT_TARGET_MARK=m | ||
67 | CONFIG_NETFILTER_XT_TARGET_NFLOG=m | ||
68 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | ||
69 | CONFIG_NETFILTER_XT_TARGET_TPROXY=m | ||
70 | CONFIG_NETFILTER_XT_TARGET_TRACE=m | ||
71 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | ||
72 | CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m | ||
73 | CONFIG_NETFILTER_XT_MATCH_COMMENT=m | ||
74 | CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m | ||
75 | CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m | ||
76 | CONFIG_NETFILTER_XT_MATCH_CONNMARK=m | ||
77 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m | ||
78 | CONFIG_NETFILTER_XT_MATCH_DCCP=m | ||
79 | CONFIG_NETFILTER_XT_MATCH_DSCP=m | ||
80 | CONFIG_NETFILTER_XT_MATCH_ESP=m | ||
81 | CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m | ||
82 | CONFIG_NETFILTER_XT_MATCH_HELPER=m | ||
83 | CONFIG_NETFILTER_XT_MATCH_IPRANGE=m | ||
84 | CONFIG_NETFILTER_XT_MATCH_LENGTH=m | ||
85 | CONFIG_NETFILTER_XT_MATCH_LIMIT=m | ||
86 | CONFIG_NETFILTER_XT_MATCH_MAC=m | ||
87 | CONFIG_NETFILTER_XT_MATCH_MARK=m | ||
88 | CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m | ||
89 | CONFIG_NETFILTER_XT_MATCH_OWNER=m | ||
90 | CONFIG_NETFILTER_XT_MATCH_POLICY=m | ||
91 | CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m | ||
92 | CONFIG_NETFILTER_XT_MATCH_QUOTA=m | ||
93 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | ||
94 | CONFIG_NETFILTER_XT_MATCH_REALM=m | ||
95 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | ||
96 | CONFIG_NETFILTER_XT_MATCH_SCTP=m | ||
97 | CONFIG_NETFILTER_XT_MATCH_SOCKET=m | ||
98 | CONFIG_NETFILTER_XT_MATCH_STATE=m | ||
99 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | ||
100 | CONFIG_NETFILTER_XT_MATCH_STRING=m | ||
101 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | ||
102 | CONFIG_NETFILTER_XT_MATCH_U32=m | ||
103 | CONFIG_NF_CONNTRACK_IPV4=m | ||
104 | CONFIG_IP_NF_IPTABLES=m | ||
105 | CONFIG_IP_NF_MATCH_AH=m | ||
106 | CONFIG_IP_NF_MATCH_ECN=m | ||
107 | CONFIG_IP_NF_MATCH_TTL=m | ||
108 | CONFIG_IP_NF_FILTER=m | ||
109 | CONFIG_IP_NF_TARGET_REJECT=m | ||
110 | CONFIG_IP_NF_TARGET_ULOG=m | ||
111 | CONFIG_IP_NF_MANGLE=m | ||
112 | CONFIG_IP_NF_TARGET_CLUSTERIP=m | ||
113 | CONFIG_IP_NF_TARGET_ECN=m | ||
114 | CONFIG_IP_NF_TARGET_TTL=m | ||
115 | CONFIG_IP_NF_RAW=m | ||
116 | CONFIG_IP_NF_ARPTABLES=m | ||
117 | CONFIG_IP_NF_ARPFILTER=m | ||
118 | CONFIG_IP_NF_ARP_MANGLE=m | ||
119 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 53 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
120 | CONFIG_DEVTMPFS=y | 54 | CONFIG_DEVTMPFS=y |
121 | CONFIG_DEVTMPFS_MOUNT=y | 55 | CONFIG_DEVTMPFS_MOUNT=y |
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index e9a8b4e0a0f6..9ea8342bd219 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig | |||
@@ -65,57 +65,8 @@ CONFIG_INET_ESP=m | |||
65 | CONFIG_INET_IPCOMP=m | 65 | CONFIG_INET_IPCOMP=m |
66 | # CONFIG_IPV6 is not set | 66 | # CONFIG_IPV6 is not set |
67 | CONFIG_NETFILTER=y | 67 | CONFIG_NETFILTER=y |
68 | CONFIG_NF_CONNTRACK=m | 68 | # CONFIG_NETFILTER_ADVANCED is not set |
69 | CONFIG_NF_CONNTRACK_EVENTS=y | 69 | CONFIG_BRIDGE=m |
70 | CONFIG_NF_CT_PROTO_UDPLITE=m | ||
71 | CONFIG_NF_CONNTRACK_FTP=m | ||
72 | CONFIG_NF_CONNTRACK_IRC=m | ||
73 | CONFIG_NF_CONNTRACK_TFTP=m | ||
74 | CONFIG_NF_CT_NETLINK=m | ||
75 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | ||
76 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m | ||
77 | CONFIG_NETFILTER_XT_TARGET_MARK=m | ||
78 | CONFIG_NETFILTER_XT_TARGET_NFLOG=m | ||
79 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | ||
80 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | ||
81 | CONFIG_NETFILTER_XT_MATCH_COMMENT=m | ||
82 | CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m | ||
83 | CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m | ||
84 | CONFIG_NETFILTER_XT_MATCH_CONNMARK=m | ||
85 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m | ||
86 | CONFIG_NETFILTER_XT_MATCH_DCCP=m | ||
87 | CONFIG_NETFILTER_XT_MATCH_DSCP=m | ||
88 | CONFIG_NETFILTER_XT_MATCH_ESP=m | ||
89 | CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m | ||
90 | CONFIG_NETFILTER_XT_MATCH_HELPER=m | ||
91 | CONFIG_NETFILTER_XT_MATCH_IPRANGE=m | ||
92 | CONFIG_NETFILTER_XT_MATCH_LENGTH=m | ||
93 | CONFIG_NETFILTER_XT_MATCH_LIMIT=m | ||
94 | CONFIG_NETFILTER_XT_MATCH_MAC=m | ||
95 | CONFIG_NETFILTER_XT_MATCH_MARK=m | ||
96 | CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m | ||
97 | CONFIG_NETFILTER_XT_MATCH_OWNER=m | ||
98 | CONFIG_NETFILTER_XT_MATCH_POLICY=m | ||
99 | CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m | ||
100 | CONFIG_NETFILTER_XT_MATCH_QUOTA=m | ||
101 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | ||
102 | CONFIG_NETFILTER_XT_MATCH_REALM=m | ||
103 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | ||
104 | CONFIG_NETFILTER_XT_MATCH_SCTP=m | ||
105 | CONFIG_NETFILTER_XT_MATCH_STATE=m | ||
106 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | ||
107 | CONFIG_NETFILTER_XT_MATCH_STRING=m | ||
108 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | ||
109 | CONFIG_NETFILTER_XT_MATCH_TIME=m | ||
110 | CONFIG_NETFILTER_XT_MATCH_U32=m | ||
111 | CONFIG_NF_CONNTRACK_IPV4=m | ||
112 | CONFIG_IP_NF_IPTABLES=m | ||
113 | CONFIG_IP_NF_MATCH_AH=m | ||
114 | CONFIG_IP_NF_MATCH_ECN=m | ||
115 | CONFIG_IP_NF_MATCH_TTL=m | ||
116 | CONFIG_IP_NF_FILTER=m | ||
117 | CONFIG_IP_NF_TARGET_REJECT=m | ||
118 | CONFIG_IP_NF_TARGET_ULOG=m | ||
119 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 70 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
120 | CONFIG_DEVTMPFS=y | 71 | CONFIG_DEVTMPFS=y |
121 | CONFIG_DEVTMPFS_MOUNT=y | 72 | CONFIG_DEVTMPFS_MOUNT=y |
@@ -353,3 +304,5 @@ CONFIG_CRYPTO_DEV_NX_ENCRYPT=m | |||
353 | CONFIG_VIRTUALIZATION=y | 304 | CONFIG_VIRTUALIZATION=y |
354 | CONFIG_KVM_BOOK3S_64=m | 305 | CONFIG_KVM_BOOK3S_64=m |
355 | CONFIG_KVM_BOOK3S_64_HV=y | 306 | CONFIG_KVM_BOOK3S_64_HV=y |
307 | CONFIG_TRANSPARENT_HUGEPAGE=y | ||
308 | CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y | ||
diff --git a/arch/powerpc/configs/pseries_le_defconfig b/arch/powerpc/configs/pseries_le_defconfig index 62771e0adb7c..3c84f9d87980 100644 --- a/arch/powerpc/configs/pseries_le_defconfig +++ b/arch/powerpc/configs/pseries_le_defconfig | |||
@@ -67,57 +67,8 @@ CONFIG_INET_ESP=m | |||
67 | CONFIG_INET_IPCOMP=m | 67 | CONFIG_INET_IPCOMP=m |
68 | # CONFIG_IPV6 is not set | 68 | # CONFIG_IPV6 is not set |
69 | CONFIG_NETFILTER=y | 69 | CONFIG_NETFILTER=y |
70 | CONFIG_NF_CONNTRACK=m | 70 | # CONFIG_NETFILTER_ADVANCED is not set |
71 | CONFIG_NF_CONNTRACK_EVENTS=y | 71 | CONFIG_BRIDGE=m |
72 | CONFIG_NF_CT_PROTO_UDPLITE=m | ||
73 | CONFIG_NF_CONNTRACK_FTP=m | ||
74 | CONFIG_NF_CONNTRACK_IRC=m | ||
75 | CONFIG_NF_CONNTRACK_TFTP=m | ||
76 | CONFIG_NF_CT_NETLINK=m | ||
77 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | ||
78 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m | ||
79 | CONFIG_NETFILTER_XT_TARGET_MARK=m | ||
80 | CONFIG_NETFILTER_XT_TARGET_NFLOG=m | ||
81 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | ||
82 | CONFIG_NETFILTER_XT_TARGET_TCPMSS=m | ||
83 | CONFIG_NETFILTER_XT_MATCH_COMMENT=m | ||
84 | CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m | ||
85 | CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m | ||
86 | CONFIG_NETFILTER_XT_MATCH_CONNMARK=m | ||
87 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m | ||
88 | CONFIG_NETFILTER_XT_MATCH_DCCP=m | ||
89 | CONFIG_NETFILTER_XT_MATCH_DSCP=m | ||
90 | CONFIG_NETFILTER_XT_MATCH_ESP=m | ||
91 | CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m | ||
92 | CONFIG_NETFILTER_XT_MATCH_HELPER=m | ||
93 | CONFIG_NETFILTER_XT_MATCH_IPRANGE=m | ||
94 | CONFIG_NETFILTER_XT_MATCH_LENGTH=m | ||
95 | CONFIG_NETFILTER_XT_MATCH_LIMIT=m | ||
96 | CONFIG_NETFILTER_XT_MATCH_MAC=m | ||
97 | CONFIG_NETFILTER_XT_MATCH_MARK=m | ||
98 | CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m | ||
99 | CONFIG_NETFILTER_XT_MATCH_OWNER=m | ||
100 | CONFIG_NETFILTER_XT_MATCH_POLICY=m | ||
101 | CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m | ||
102 | CONFIG_NETFILTER_XT_MATCH_QUOTA=m | ||
103 | CONFIG_NETFILTER_XT_MATCH_RATEEST=m | ||
104 | CONFIG_NETFILTER_XT_MATCH_REALM=m | ||
105 | CONFIG_NETFILTER_XT_MATCH_RECENT=m | ||
106 | CONFIG_NETFILTER_XT_MATCH_SCTP=m | ||
107 | CONFIG_NETFILTER_XT_MATCH_STATE=m | ||
108 | CONFIG_NETFILTER_XT_MATCH_STATISTIC=m | ||
109 | CONFIG_NETFILTER_XT_MATCH_STRING=m | ||
110 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | ||
111 | CONFIG_NETFILTER_XT_MATCH_TIME=m | ||
112 | CONFIG_NETFILTER_XT_MATCH_U32=m | ||
113 | CONFIG_NF_CONNTRACK_IPV4=m | ||
114 | CONFIG_IP_NF_IPTABLES=m | ||
115 | CONFIG_IP_NF_MATCH_AH=m | ||
116 | CONFIG_IP_NF_MATCH_ECN=m | ||
117 | CONFIG_IP_NF_MATCH_TTL=m | ||
118 | CONFIG_IP_NF_FILTER=m | ||
119 | CONFIG_IP_NF_TARGET_REJECT=m | ||
120 | CONFIG_IP_NF_TARGET_ULOG=m | ||
121 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 72 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
122 | CONFIG_DEVTMPFS=y | 73 | CONFIG_DEVTMPFS=y |
123 | CONFIG_DEVTMPFS_MOUNT=y | 74 | CONFIG_DEVTMPFS_MOUNT=y |
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index a613d2c82fd9..b142b8e0ed9e 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h | |||
@@ -8,7 +8,11 @@ | |||
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | 9 | ||
10 | #define COMPAT_USER_HZ 100 | 10 | #define COMPAT_USER_HZ 100 |
11 | #ifdef __BIG_ENDIAN__ | ||
11 | #define COMPAT_UTS_MACHINE "ppc\0\0" | 12 | #define COMPAT_UTS_MACHINE "ppc\0\0" |
13 | #else | ||
14 | #define COMPAT_UTS_MACHINE "ppcle\0\0" | ||
15 | #endif | ||
12 | 16 | ||
13 | typedef u32 compat_size_t; | 17 | typedef u32 compat_size_t; |
14 | typedef s32 compat_ssize_t; | 18 | typedef s32 compat_ssize_t; |
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 617cc767c076..bc2347774f0a 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
@@ -189,6 +189,7 @@ extern const char *powerpc_base_platform; | |||
189 | #define CPU_FTR_HAS_PPR LONG_ASM_CONST(0x0200000000000000) | 189 | #define CPU_FTR_HAS_PPR LONG_ASM_CONST(0x0200000000000000) |
190 | #define CPU_FTR_DAWR LONG_ASM_CONST(0x0400000000000000) | 190 | #define CPU_FTR_DAWR LONG_ASM_CONST(0x0400000000000000) |
191 | #define CPU_FTR_DABRX LONG_ASM_CONST(0x0800000000000000) | 191 | #define CPU_FTR_DABRX LONG_ASM_CONST(0x0800000000000000) |
192 | #define CPU_FTR_PMAO_BUG LONG_ASM_CONST(0x1000000000000000) | ||
192 | 193 | ||
193 | #ifndef __ASSEMBLY__ | 194 | #ifndef __ASSEMBLY__ |
194 | 195 | ||
@@ -445,6 +446,7 @@ extern const char *powerpc_base_platform; | |||
445 | CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ | 446 | CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ |
446 | CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \ | 447 | CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \ |
447 | CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP) | 448 | CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP) |
449 | #define CPU_FTRS_POWER8E (CPU_FTRS_POWER8 | CPU_FTR_PMAO_BUG) | ||
448 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 450 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
449 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 451 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
450 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 452 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
@@ -466,8 +468,8 @@ extern const char *powerpc_base_platform; | |||
466 | #define CPU_FTRS_POSSIBLE \ | 468 | #define CPU_FTRS_POSSIBLE \ |
467 | (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \ | 469 | (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \ |
468 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 | \ | 470 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 | \ |
469 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8 | CPU_FTRS_CELL | \ | 471 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \ |
470 | CPU_FTRS_PA6T | CPU_FTR_VSX) | 472 | CPU_FTRS_CELL | CPU_FTRS_PA6T | CPU_FTR_VSX) |
471 | #endif | 473 | #endif |
472 | #else | 474 | #else |
473 | enum { | 475 | enum { |
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 66830618cc19..aeaa56cd9b54 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -147,6 +147,14 @@ BEGIN_FTR_SECTION_NESTED(943) \ | |||
147 | END_FTR_SECTION_NESTED(ftr,ftr,943) | 147 | END_FTR_SECTION_NESTED(ftr,ftr,943) |
148 | 148 | ||
149 | /* | 149 | /* |
150 | * Set an SPR from a register if the CPU has the given feature | ||
151 | */ | ||
152 | #define OPT_SET_SPR(ra, spr, ftr) \ | ||
153 | BEGIN_FTR_SECTION_NESTED(943) \ | ||
154 | mtspr spr,ra; \ | ||
155 | END_FTR_SECTION_NESTED(ftr,ftr,943) | ||
156 | |||
157 | /* | ||
150 | * Save a register to the PACA if the CPU has the given feature | 158 | * Save a register to the PACA if the CPU has the given feature |
151 | */ | 159 | */ |
152 | #define OPT_SAVE_REG_TO_PACA(offset, ra, ftr) \ | 160 | #define OPT_SAVE_REG_TO_PACA(offset, ra, ftr) \ |
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index d8b600b3f058..5dbbb29f5c3e 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h | |||
@@ -274,6 +274,11 @@ | |||
274 | /* Platform specific hcalls, used by KVM */ | 274 | /* Platform specific hcalls, used by KVM */ |
275 | #define H_RTAS 0xf000 | 275 | #define H_RTAS 0xf000 |
276 | 276 | ||
277 | /* "Platform specific hcalls", provided by PHYP */ | ||
278 | #define H_GET_24X7_CATALOG_PAGE 0xF078 | ||
279 | #define H_GET_24X7_DATA 0xF07C | ||
280 | #define H_GET_PERF_COUNTER_INFO 0xF080 | ||
281 | |||
277 | #ifndef __ASSEMBLY__ | 282 | #ifndef __ASSEMBLY__ |
278 | 283 | ||
279 | /** | 284 | /** |
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 2636acfcd340..ffafab037ba8 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h | |||
@@ -83,6 +83,8 @@ extern int opal_enter_rtas(struct rtas_args *args, | |||
83 | #define OPAL_INTERNAL_ERROR -11 | 83 | #define OPAL_INTERNAL_ERROR -11 |
84 | #define OPAL_BUSY_EVENT -12 | 84 | #define OPAL_BUSY_EVENT -12 |
85 | #define OPAL_HARDWARE_FROZEN -13 | 85 | #define OPAL_HARDWARE_FROZEN -13 |
86 | #define OPAL_WRONG_STATE -14 | ||
87 | #define OPAL_ASYNC_COMPLETION -15 | ||
86 | 88 | ||
87 | /* API Tokens (in r0) */ | 89 | /* API Tokens (in r0) */ |
88 | #define OPAL_CONSOLE_WRITE 1 | 90 | #define OPAL_CONSOLE_WRITE 1 |
@@ -165,8 +167,11 @@ extern int opal_enter_rtas(struct rtas_args *args, | |||
165 | #define OPAL_DUMP_ACK 84 | 167 | #define OPAL_DUMP_ACK 84 |
166 | #define OPAL_GET_MSG 85 | 168 | #define OPAL_GET_MSG 85 |
167 | #define OPAL_CHECK_ASYNC_COMPLETION 86 | 169 | #define OPAL_CHECK_ASYNC_COMPLETION 86 |
168 | #define OPAL_DUMP_RESEND 91 | ||
169 | #define OPAL_SYNC_HOST_REBOOT 87 | 170 | #define OPAL_SYNC_HOST_REBOOT 87 |
171 | #define OPAL_SENSOR_READ 88 | ||
172 | #define OPAL_GET_PARAM 89 | ||
173 | #define OPAL_SET_PARAM 90 | ||
174 | #define OPAL_DUMP_RESEND 91 | ||
170 | #define OPAL_DUMP_INFO2 94 | 175 | #define OPAL_DUMP_INFO2 94 |
171 | 176 | ||
172 | #ifndef __ASSEMBLY__ | 177 | #ifndef __ASSEMBLY__ |
@@ -253,7 +258,9 @@ enum OpalPendingState { | |||
253 | }; | 258 | }; |
254 | 259 | ||
255 | enum OpalMessageType { | 260 | enum OpalMessageType { |
256 | OPAL_MSG_ASYNC_COMP = 0, | 261 | OPAL_MSG_ASYNC_COMP = 0, /* params[0] = token, params[1] = rc, |
262 | * additional params function-specific | ||
263 | */ | ||
257 | OPAL_MSG_MEM_ERR, | 264 | OPAL_MSG_MEM_ERR, |
258 | OPAL_MSG_EPOW, | 265 | OPAL_MSG_EPOW, |
259 | OPAL_MSG_SHUTDOWN, | 266 | OPAL_MSG_SHUTDOWN, |
@@ -406,6 +413,13 @@ enum OpalLPCAddressType { | |||
406 | OPAL_LPC_FW = 2, | 413 | OPAL_LPC_FW = 2, |
407 | }; | 414 | }; |
408 | 415 | ||
416 | /* System parameter permission */ | ||
417 | enum OpalSysparamPerm { | ||
418 | OPAL_SYSPARAM_READ = 0x1, | ||
419 | OPAL_SYSPARAM_WRITE = 0x2, | ||
420 | OPAL_SYSPARAM_RW = (OPAL_SYSPARAM_READ | OPAL_SYSPARAM_WRITE), | ||
421 | }; | ||
422 | |||
409 | struct opal_msg { | 423 | struct opal_msg { |
410 | uint32_t msg_type; | 424 | uint32_t msg_type; |
411 | uint32_t reserved; | 425 | uint32_t reserved; |
@@ -855,6 +869,12 @@ int64_t opal_dump_resend_notification(void); | |||
855 | int64_t opal_get_msg(uint64_t buffer, size_t size); | 869 | int64_t opal_get_msg(uint64_t buffer, size_t size); |
856 | int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token); | 870 | int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token); |
857 | int64_t opal_sync_host_reboot(void); | 871 | int64_t opal_sync_host_reboot(void); |
872 | int64_t opal_get_param(uint64_t token, uint32_t param_id, uint64_t buffer, | ||
873 | size_t length); | ||
874 | int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer, | ||
875 | size_t length); | ||
876 | int64_t opal_sensor_read(uint32_t sensor_hndl, int token, | ||
877 | uint32_t *sensor_data); | ||
858 | 878 | ||
859 | /* Internal functions */ | 879 | /* Internal functions */ |
860 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); | 880 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); |
@@ -880,6 +900,13 @@ extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val); | |||
880 | extern int opal_get_chars(uint32_t vtermno, char *buf, int count); | 900 | extern int opal_get_chars(uint32_t vtermno, char *buf, int count); |
881 | extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len); | 901 | extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len); |
882 | 902 | ||
903 | extern int __opal_async_get_token(void); | ||
904 | extern int opal_async_get_token_interruptible(void); | ||
905 | extern int __opal_async_release_token(int token); | ||
906 | extern int opal_async_release_token(int token); | ||
907 | extern int opal_async_wait_response(uint64_t token, struct opal_msg *msg); | ||
908 | extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data); | ||
909 | |||
883 | extern void hvc_opal_init_early(void); | 910 | extern void hvc_opal_init_early(void); |
884 | 911 | ||
885 | struct rtc_time; | 912 | struct rtc_time; |
@@ -890,6 +917,7 @@ extern void opal_nvram_init(void); | |||
890 | extern void opal_flash_init(void); | 917 | extern void opal_flash_init(void); |
891 | extern int opal_elog_init(void); | 918 | extern int opal_elog_init(void); |
892 | extern void opal_platform_dump_init(void); | 919 | extern void opal_platform_dump_init(void); |
920 | extern void opal_sys_param_init(void); | ||
893 | 921 | ||
894 | extern int opal_machine_check(struct pt_regs *regs); | 922 | extern int opal_machine_check(struct pt_regs *regs); |
895 | extern bool opal_mce_check_early_recovery(struct pt_regs *regs); | 923 | extern bool opal_mce_check_early_recovery(struct pt_regs *regs); |
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index 3fd2f1b6f906..9ed737146dbb 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <uapi/asm/perf_event.h> | 15 | #include <uapi/asm/perf_event.h> |
16 | 16 | ||
17 | /* Update perf_event_print_debug() if this changes */ | ||
17 | #define MAX_HWEVENTS 8 | 18 | #define MAX_HWEVENTS 8 |
18 | #define MAX_EVENT_ALTERNATIVES 8 | 19 | #define MAX_EVENT_ALTERNATIVES 8 |
19 | #define MAX_LIMITED_HWCOUNTERS 2 | 20 | #define MAX_LIMITED_HWCOUNTERS 2 |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index f7251c2dc049..1a36b8ede417 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -668,12 +668,14 @@ | |||
668 | #define MMCR0_PMXE 0x04000000UL /* performance monitor exception enable */ | 668 | #define MMCR0_PMXE 0x04000000UL /* performance monitor exception enable */ |
669 | #define MMCR0_FCECE 0x02000000UL /* freeze ctrs on enabled cond or event */ | 669 | #define MMCR0_FCECE 0x02000000UL /* freeze ctrs on enabled cond or event */ |
670 | #define MMCR0_TBEE 0x00400000UL /* time base exception enable */ | 670 | #define MMCR0_TBEE 0x00400000UL /* time base exception enable */ |
671 | #define MMCR0_BHRBA 0x00200000UL /* BHRB Access allowed in userspace */ | ||
671 | #define MMCR0_EBE 0x00100000UL /* Event based branch enable */ | 672 | #define MMCR0_EBE 0x00100000UL /* Event based branch enable */ |
672 | #define MMCR0_PMCC 0x000c0000UL /* PMC control */ | 673 | #define MMCR0_PMCC 0x000c0000UL /* PMC control */ |
673 | #define MMCR0_PMCC_U6 0x00080000UL /* PMC1-6 are R/W by user (PR) */ | 674 | #define MMCR0_PMCC_U6 0x00080000UL /* PMC1-6 are R/W by user (PR) */ |
674 | #define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/ | 675 | #define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/ |
675 | #define MMCR0_PMCjCE 0x00004000UL /* PMCj count enable*/ | 676 | #define MMCR0_PMCjCE 0x00004000UL /* PMCj count enable*/ |
676 | #define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */ | 677 | #define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */ |
678 | #define MMCR0_PMAO_SYNC 0x00000800UL /* PMU interrupt is synchronous */ | ||
677 | #define MMCR0_PMAO 0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */ | 679 | #define MMCR0_PMAO 0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */ |
678 | #define MMCR0_SHRFC 0x00000040UL /* SHRre freeze conditions between threads */ | 680 | #define MMCR0_SHRFC 0x00000040UL /* SHRre freeze conditions between threads */ |
679 | #define MMCR0_FC56 0x00000010UL /* freeze counters 5 and 6 */ | 681 | #define MMCR0_FC56 0x00000010UL /* freeze counters 5 and 6 */ |
@@ -707,6 +709,7 @@ | |||
707 | #define SPRN_EBBHR 804 /* Event based branch handler register */ | 709 | #define SPRN_EBBHR 804 /* Event based branch handler register */ |
708 | #define SPRN_EBBRR 805 /* Event based branch return register */ | 710 | #define SPRN_EBBRR 805 /* Event based branch return register */ |
709 | #define SPRN_BESCR 806 /* Branch event status and control register */ | 711 | #define SPRN_BESCR 806 /* Branch event status and control register */ |
712 | #define BESCR_GE 0x8000000000000000ULL /* Global Enable */ | ||
710 | #define SPRN_WORT 895 /* Workload optimization register - thread */ | 713 | #define SPRN_WORT 895 /* Workload optimization register - thread */ |
711 | 714 | ||
712 | #define SPRN_PMC1 787 | 715 | #define SPRN_PMC1 787 |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 6c8dd5da4de5..c1faade6506d 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -510,7 +510,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
510 | .pvr_mask = 0xffff0000, | 510 | .pvr_mask = 0xffff0000, |
511 | .pvr_value = 0x004b0000, | 511 | .pvr_value = 0x004b0000, |
512 | .cpu_name = "POWER8E (raw)", | 512 | .cpu_name = "POWER8E (raw)", |
513 | .cpu_features = CPU_FTRS_POWER8, | 513 | .cpu_features = CPU_FTRS_POWER8E, |
514 | .cpu_user_features = COMMON_USER_POWER8, | 514 | .cpu_user_features = COMMON_USER_POWER8, |
515 | .cpu_user_features2 = COMMON_USER2_POWER8, | 515 | .cpu_user_features2 = COMMON_USER2_POWER8, |
516 | .mmu_features = MMU_FTRS_POWER8, | 516 | .mmu_features = MMU_FTRS_POWER8, |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 38d507306a11..4c34c3c827ad 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -164,13 +164,18 @@ BEGIN_FTR_SECTION | |||
164 | */ | 164 | */ |
165 | mfspr r13,SPRN_SRR1 | 165 | mfspr r13,SPRN_SRR1 |
166 | rlwinm. r13,r13,47-31,30,31 | 166 | rlwinm. r13,r13,47-31,30,31 |
167 | OPT_GET_SPR(r13, SPRN_CFAR, CPU_FTR_CFAR) | ||
167 | beq 9f | 168 | beq 9f |
168 | 169 | ||
170 | mfspr r13,SPRN_SRR1 | ||
171 | rlwinm. r13,r13,47-31,30,31 | ||
169 | /* waking up from powersave (nap) state */ | 172 | /* waking up from powersave (nap) state */ |
170 | cmpwi cr1,r13,2 | 173 | cmpwi cr1,r13,2 |
171 | /* Total loss of HV state is fatal. let's just stay stuck here */ | 174 | /* Total loss of HV state is fatal. let's just stay stuck here */ |
175 | OPT_GET_SPR(r13, SPRN_CFAR, CPU_FTR_CFAR) | ||
172 | bgt cr1,. | 176 | bgt cr1,. |
173 | 9: | 177 | 9: |
178 | OPT_SET_SPR(r13, SPRN_CFAR, CPU_FTR_CFAR) | ||
174 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206) | 179 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206) |
175 | #endif /* CONFIG_PPC_P7_NAP */ | 180 | #endif /* CONFIG_PPC_P7_NAP */ |
176 | EXCEPTION_PROLOG_0(PACA_EXMC) | 181 | EXCEPTION_PROLOG_0(PACA_EXMC) |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4cf674d7d5ae..f386296ff378 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -1013,12 +1013,13 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log, | |||
1013 | return NULL; | 1013 | return NULL; |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | /* We assume to be passed big endian arguments */ | ||
1016 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | 1017 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs) |
1017 | { | 1018 | { |
1018 | struct rtas_args args; | 1019 | struct rtas_args args; |
1019 | unsigned long flags; | 1020 | unsigned long flags; |
1020 | char *buff_copy, *errbuf = NULL; | 1021 | char *buff_copy, *errbuf = NULL; |
1021 | int nargs; | 1022 | int nargs, nret, token; |
1022 | int rc; | 1023 | int rc; |
1023 | 1024 | ||
1024 | if (!capable(CAP_SYS_ADMIN)) | 1025 | if (!capable(CAP_SYS_ADMIN)) |
@@ -1027,10 +1028,13 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
1027 | if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0) | 1028 | if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0) |
1028 | return -EFAULT; | 1029 | return -EFAULT; |
1029 | 1030 | ||
1030 | nargs = args.nargs; | 1031 | nargs = be32_to_cpu(args.nargs); |
1032 | nret = be32_to_cpu(args.nret); | ||
1033 | token = be32_to_cpu(args.token); | ||
1034 | |||
1031 | if (nargs > ARRAY_SIZE(args.args) | 1035 | if (nargs > ARRAY_SIZE(args.args) |
1032 | || args.nret > ARRAY_SIZE(args.args) | 1036 | || nret > ARRAY_SIZE(args.args) |
1033 | || nargs + args.nret > ARRAY_SIZE(args.args)) | 1037 | || nargs + nret > ARRAY_SIZE(args.args)) |
1034 | return -EINVAL; | 1038 | return -EINVAL; |
1035 | 1039 | ||
1036 | /* Copy in args. */ | 1040 | /* Copy in args. */ |
@@ -1038,14 +1042,14 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
1038 | nargs * sizeof(rtas_arg_t)) != 0) | 1042 | nargs * sizeof(rtas_arg_t)) != 0) |
1039 | return -EFAULT; | 1043 | return -EFAULT; |
1040 | 1044 | ||
1041 | if (args.token == RTAS_UNKNOWN_SERVICE) | 1045 | if (token == RTAS_UNKNOWN_SERVICE) |
1042 | return -EINVAL; | 1046 | return -EINVAL; |
1043 | 1047 | ||
1044 | args.rets = &args.args[nargs]; | 1048 | args.rets = &args.args[nargs]; |
1045 | memset(args.rets, 0, args.nret * sizeof(rtas_arg_t)); | 1049 | memset(args.rets, 0, nret * sizeof(rtas_arg_t)); |
1046 | 1050 | ||
1047 | /* Need to handle ibm,suspend_me call specially */ | 1051 | /* Need to handle ibm,suspend_me call specially */ |
1048 | if (args.token == ibm_suspend_me_token) { | 1052 | if (token == ibm_suspend_me_token) { |
1049 | rc = rtas_ibm_suspend_me(&args); | 1053 | rc = rtas_ibm_suspend_me(&args); |
1050 | if (rc) | 1054 | if (rc) |
1051 | return rc; | 1055 | return rc; |
@@ -1062,7 +1066,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
1062 | 1066 | ||
1063 | /* A -1 return code indicates that the last command couldn't | 1067 | /* A -1 return code indicates that the last command couldn't |
1064 | be completed due to a hardware error. */ | 1068 | be completed due to a hardware error. */ |
1065 | if (args.rets[0] == -1) | 1069 | if (be32_to_cpu(args.rets[0]) == -1) |
1066 | errbuf = __fetch_rtas_last_error(buff_copy); | 1070 | errbuf = __fetch_rtas_last_error(buff_copy); |
1067 | 1071 | ||
1068 | unlock_rtas(flags); | 1072 | unlock_rtas(flags); |
@@ -1077,7 +1081,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
1077 | /* Copy out args. */ | 1081 | /* Copy out args. */ |
1078 | if (copy_to_user(uargs->args + nargs, | 1082 | if (copy_to_user(uargs->args + nargs, |
1079 | args.args + nargs, | 1083 | args.args + nargs, |
1080 | args.nret * sizeof(rtas_arg_t)) != 0) | 1084 | nret * sizeof(rtas_arg_t)) != 0) |
1081 | return -EFAULT; | 1085 | return -EFAULT; |
1082 | 1086 | ||
1083 | return 0; | 1087 | return 0; |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 33cd7a0b8e73..df86f0ce2d36 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -1379,8 +1379,9 @@ void facility_unavailable_exception(struct pt_regs *regs) | |||
1379 | if (!arch_irq_disabled_regs(regs)) | 1379 | if (!arch_irq_disabled_regs(regs)) |
1380 | local_irq_enable(); | 1380 | local_irq_enable(); |
1381 | 1381 | ||
1382 | pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n", | 1382 | pr_err_ratelimited( |
1383 | hv ? "Hypervisor " : "", facility, regs->nip, regs->msr); | 1383 | "%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n", |
1384 | hv ? "Hypervisor " : "", facility, regs->nip, regs->msr); | ||
1384 | 1385 | ||
1385 | if (user_mode(regs)) { | 1386 | if (user_mode(regs)) { |
1386 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); | 1387 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 62bf5e8e78da..f6ce1f111f5b 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -647,6 +647,11 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, | |||
647 | if (old & _PAGE_HASHPTE) | 647 | if (old & _PAGE_HASHPTE) |
648 | hpte_do_hugepage_flush(vma->vm_mm, address, pmdp); | 648 | hpte_do_hugepage_flush(vma->vm_mm, address, pmdp); |
649 | } | 649 | } |
650 | /* | ||
651 | * This ensures that generic code that rely on IRQ disabling | ||
652 | * to prevent a parallel THP split work as expected. | ||
653 | */ | ||
654 | kick_all_cpus_sync(); | ||
650 | } | 655 | } |
651 | 656 | ||
652 | /* | 657 | /* |
diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile index 60d71eea919c..f9c083a5652a 100644 --- a/arch/powerpc/perf/Makefile +++ b/arch/powerpc/perf/Makefile | |||
@@ -11,5 +11,7 @@ obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o | |||
11 | obj-$(CONFIG_FSL_EMB_PERF_EVENT) += core-fsl-emb.o | 11 | obj-$(CONFIG_FSL_EMB_PERF_EVENT) += core-fsl-emb.o |
12 | obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o e6500-pmu.o | 12 | obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o e6500-pmu.o |
13 | 13 | ||
14 | obj-$(CONFIG_HV_PERF_CTRS) += hv-24x7.o hv-gpci.o hv-common.o | ||
15 | |||
14 | obj-$(CONFIG_PPC64) += $(obj64-y) | 16 | obj-$(CONFIG_PPC64) += $(obj64-y) |
15 | obj-$(CONFIG_PPC32) += $(obj32-y) | 17 | obj-$(CONFIG_PPC32) += $(obj32-y) |
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 67cf22083f4c..4520c9356b54 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c | |||
@@ -78,6 +78,7 @@ static unsigned int freeze_events_kernel = MMCR0_FCS; | |||
78 | #define MMCR0_FC56 0 | 78 | #define MMCR0_FC56 0 |
79 | #define MMCR0_PMAO 0 | 79 | #define MMCR0_PMAO 0 |
80 | #define MMCR0_EBE 0 | 80 | #define MMCR0_EBE 0 |
81 | #define MMCR0_BHRBA 0 | ||
81 | #define MMCR0_PMCC 0 | 82 | #define MMCR0_PMCC 0 |
82 | #define MMCR0_PMCC_U6 0 | 83 | #define MMCR0_PMCC_U6 0 |
83 | 84 | ||
@@ -120,6 +121,7 @@ static inline void power_pmu_bhrb_enable(struct perf_event *event) {} | |||
120 | static inline void power_pmu_bhrb_disable(struct perf_event *event) {} | 121 | static inline void power_pmu_bhrb_disable(struct perf_event *event) {} |
121 | void power_pmu_flush_branch_stack(void) {} | 122 | void power_pmu_flush_branch_stack(void) {} |
122 | static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {} | 123 | static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {} |
124 | static void pmao_restore_workaround(bool ebb) { } | ||
123 | #endif /* CONFIG_PPC32 */ | 125 | #endif /* CONFIG_PPC32 */ |
124 | 126 | ||
125 | static bool regs_use_siar(struct pt_regs *regs) | 127 | static bool regs_use_siar(struct pt_regs *regs) |
@@ -502,8 +504,11 @@ static int ebb_event_check(struct perf_event *event) | |||
502 | if (!leader->attr.pinned || !leader->attr.exclusive) | 504 | if (!leader->attr.pinned || !leader->attr.exclusive) |
503 | return -EINVAL; | 505 | return -EINVAL; |
504 | 506 | ||
505 | if (event->attr.inherit || event->attr.sample_period || | 507 | if (event->attr.freq || |
506 | event->attr.enable_on_exec || event->attr.freq) | 508 | event->attr.inherit || |
509 | event->attr.sample_type || | ||
510 | event->attr.sample_period || | ||
511 | event->attr.enable_on_exec) | ||
507 | return -EINVAL; | 512 | return -EINVAL; |
508 | } | 513 | } |
509 | 514 | ||
@@ -542,13 +547,21 @@ static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0) | |||
542 | if (!ebb) | 547 | if (!ebb) |
543 | goto out; | 548 | goto out; |
544 | 549 | ||
545 | /* Enable EBB and read/write to all 6 PMCs for userspace */ | 550 | /* Enable EBB and read/write to all 6 PMCs and BHRB for userspace */ |
546 | mmcr0 |= MMCR0_EBE | MMCR0_PMCC_U6; | 551 | mmcr0 |= MMCR0_EBE | MMCR0_BHRBA | MMCR0_PMCC_U6; |
547 | 552 | ||
548 | /* Add any bits from the user reg, FC or PMAO */ | 553 | /* |
554 | * Add any bits from the user MMCR0, FC or PMAO. This is compatible | ||
555 | * with pmao_restore_workaround() because we may add PMAO but we never | ||
556 | * clear it here. | ||
557 | */ | ||
549 | mmcr0 |= current->thread.mmcr0; | 558 | mmcr0 |= current->thread.mmcr0; |
550 | 559 | ||
551 | /* Be careful not to set PMXE if userspace had it cleared */ | 560 | /* |
561 | * Be careful not to set PMXE if userspace had it cleared. This is also | ||
562 | * compatible with pmao_restore_workaround() because it has already | ||
563 | * cleared PMXE and we leave PMAO alone. | ||
564 | */ | ||
552 | if (!(current->thread.mmcr0 & MMCR0_PMXE)) | 565 | if (!(current->thread.mmcr0 & MMCR0_PMXE)) |
553 | mmcr0 &= ~MMCR0_PMXE; | 566 | mmcr0 &= ~MMCR0_PMXE; |
554 | 567 | ||
@@ -559,13 +572,94 @@ static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0) | |||
559 | out: | 572 | out: |
560 | return mmcr0; | 573 | return mmcr0; |
561 | } | 574 | } |
562 | #endif /* CONFIG_PPC64 */ | ||
563 | |||
564 | static void perf_event_interrupt(struct pt_regs *regs); | ||
565 | 575 | ||
566 | void perf_event_print_debug(void) | 576 | static void pmao_restore_workaround(bool ebb) |
567 | { | 577 | { |
578 | unsigned pmcs[6]; | ||
579 | |||
580 | if (!cpu_has_feature(CPU_FTR_PMAO_BUG)) | ||
581 | return; | ||
582 | |||
583 | /* | ||
584 | * On POWER8E there is a hardware defect which affects the PMU context | ||
585 | * switch logic, ie. power_pmu_disable/enable(). | ||
586 | * | ||
587 | * When a counter overflows PMXE is cleared and FC/PMAO is set in MMCR0 | ||
588 | * by the hardware. Sometime later the actual PMU exception is | ||
589 | * delivered. | ||
590 | * | ||
591 | * If we context switch, or simply disable/enable, the PMU prior to the | ||
592 | * exception arriving, the exception will be lost when we clear PMAO. | ||
593 | * | ||
594 | * When we reenable the PMU, we will write the saved MMCR0 with PMAO | ||
595 | * set, and this _should_ generate an exception. However because of the | ||
596 | * defect no exception is generated when we write PMAO, and we get | ||
597 | * stuck with no counters counting but no exception delivered. | ||
598 | * | ||
599 | * The workaround is to detect this case and tweak the hardware to | ||
600 | * create another pending PMU exception. | ||
601 | * | ||
602 | * We do that by setting up PMC6 (cycles) for an imminent overflow and | ||
603 | * enabling the PMU. That causes a new exception to be generated in the | ||
604 | * chip, but we don't take it yet because we have interrupts hard | ||
605 | * disabled. We then write back the PMU state as we want it to be seen | ||
606 | * by the exception handler. When we reenable interrupts the exception | ||
607 | * handler will be called and see the correct state. | ||
608 | * | ||
609 | * The logic is the same for EBB, except that the exception is gated by | ||
610 | * us having interrupts hard disabled as well as the fact that we are | ||
611 | * not in userspace. The exception is finally delivered when we return | ||
612 | * to userspace. | ||
613 | */ | ||
614 | |||
615 | /* Only if PMAO is set and PMAO_SYNC is clear */ | ||
616 | if ((current->thread.mmcr0 & (MMCR0_PMAO | MMCR0_PMAO_SYNC)) != MMCR0_PMAO) | ||
617 | return; | ||
618 | |||
619 | /* If we're doing EBB, only if BESCR[GE] is set */ | ||
620 | if (ebb && !(current->thread.bescr & BESCR_GE)) | ||
621 | return; | ||
622 | |||
623 | /* | ||
624 | * We are already soft-disabled in power_pmu_enable(). We need to hard | ||
625 | * enable to actually prevent the PMU exception from firing. | ||
626 | */ | ||
627 | hard_irq_disable(); | ||
628 | |||
629 | /* | ||
630 | * This is a bit gross, but we know we're on POWER8E and have 6 PMCs. | ||
631 | * Using read/write_pmc() in a for loop adds 12 function calls and | ||
632 | * almost doubles our code size. | ||
633 | */ | ||
634 | pmcs[0] = mfspr(SPRN_PMC1); | ||
635 | pmcs[1] = mfspr(SPRN_PMC2); | ||
636 | pmcs[2] = mfspr(SPRN_PMC3); | ||
637 | pmcs[3] = mfspr(SPRN_PMC4); | ||
638 | pmcs[4] = mfspr(SPRN_PMC5); | ||
639 | pmcs[5] = mfspr(SPRN_PMC6); | ||
640 | |||
641 | /* Ensure all freeze bits are unset */ | ||
642 | mtspr(SPRN_MMCR2, 0); | ||
643 | |||
644 | /* Set up PMC6 to overflow in one cycle */ | ||
645 | mtspr(SPRN_PMC6, 0x7FFFFFFE); | ||
646 | |||
647 | /* Enable exceptions and unfreeze PMC6 */ | ||
648 | mtspr(SPRN_MMCR0, MMCR0_PMXE | MMCR0_PMCjCE | MMCR0_PMAO); | ||
649 | |||
650 | /* Now we need to refreeze and restore the PMCs */ | ||
651 | mtspr(SPRN_MMCR0, MMCR0_FC | MMCR0_PMAO); | ||
652 | |||
653 | mtspr(SPRN_PMC1, pmcs[0]); | ||
654 | mtspr(SPRN_PMC2, pmcs[1]); | ||
655 | mtspr(SPRN_PMC3, pmcs[2]); | ||
656 | mtspr(SPRN_PMC4, pmcs[3]); | ||
657 | mtspr(SPRN_PMC5, pmcs[4]); | ||
658 | mtspr(SPRN_PMC6, pmcs[5]); | ||
568 | } | 659 | } |
660 | #endif /* CONFIG_PPC64 */ | ||
661 | |||
662 | static void perf_event_interrupt(struct pt_regs *regs); | ||
569 | 663 | ||
570 | /* | 664 | /* |
571 | * Read one performance monitor counter (PMC). | 665 | * Read one performance monitor counter (PMC). |
@@ -645,6 +739,57 @@ static void write_pmc(int idx, unsigned long val) | |||
645 | } | 739 | } |
646 | } | 740 | } |
647 | 741 | ||
742 | /* Called from sysrq_handle_showregs() */ | ||
743 | void perf_event_print_debug(void) | ||
744 | { | ||
745 | unsigned long sdar, sier, flags; | ||
746 | u32 pmcs[MAX_HWEVENTS]; | ||
747 | int i; | ||
748 | |||
749 | if (!ppmu->n_counter) | ||
750 | return; | ||
751 | |||
752 | local_irq_save(flags); | ||
753 | |||
754 | pr_info("CPU: %d PMU registers, ppmu = %s n_counters = %d", | ||
755 | smp_processor_id(), ppmu->name, ppmu->n_counter); | ||
756 | |||
757 | for (i = 0; i < ppmu->n_counter; i++) | ||
758 | pmcs[i] = read_pmc(i + 1); | ||
759 | |||
760 | for (; i < MAX_HWEVENTS; i++) | ||
761 | pmcs[i] = 0xdeadbeef; | ||
762 | |||
763 | pr_info("PMC1: %08x PMC2: %08x PMC3: %08x PMC4: %08x\n", | ||
764 | pmcs[0], pmcs[1], pmcs[2], pmcs[3]); | ||
765 | |||
766 | if (ppmu->n_counter > 4) | ||
767 | pr_info("PMC5: %08x PMC6: %08x PMC7: %08x PMC8: %08x\n", | ||
768 | pmcs[4], pmcs[5], pmcs[6], pmcs[7]); | ||
769 | |||
770 | pr_info("MMCR0: %016lx MMCR1: %016lx MMCRA: %016lx\n", | ||
771 | mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1), mfspr(SPRN_MMCRA)); | ||
772 | |||
773 | sdar = sier = 0; | ||
774 | #ifdef CONFIG_PPC64 | ||
775 | sdar = mfspr(SPRN_SDAR); | ||
776 | |||
777 | if (ppmu->flags & PPMU_HAS_SIER) | ||
778 | sier = mfspr(SPRN_SIER); | ||
779 | |||
780 | if (ppmu->flags & PPMU_EBB) { | ||
781 | pr_info("MMCR2: %016lx EBBHR: %016lx\n", | ||
782 | mfspr(SPRN_MMCR2), mfspr(SPRN_EBBHR)); | ||
783 | pr_info("EBBRR: %016lx BESCR: %016lx\n", | ||
784 | mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR)); | ||
785 | } | ||
786 | #endif | ||
787 | pr_info("SIAR: %016lx SDAR: %016lx SIER: %016lx\n", | ||
788 | mfspr(SPRN_SIAR), sdar, sier); | ||
789 | |||
790 | local_irq_restore(flags); | ||
791 | } | ||
792 | |||
648 | /* | 793 | /* |
649 | * Check if a set of events can all go on the PMU at once. | 794 | * Check if a set of events can all go on the PMU at once. |
650 | * If they can't, this will look at alternative codes for the events | 795 | * If they can't, this will look at alternative codes for the events |
@@ -973,11 +1118,12 @@ static void power_pmu_disable(struct pmu *pmu) | |||
973 | } | 1118 | } |
974 | 1119 | ||
975 | /* | 1120 | /* |
976 | * Set the 'freeze counters' bit, clear EBE/PMCC/PMAO/FC56. | 1121 | * Set the 'freeze counters' bit, clear EBE/BHRBA/PMCC/PMAO/FC56 |
977 | */ | 1122 | */ |
978 | val = mmcr0 = mfspr(SPRN_MMCR0); | 1123 | val = mmcr0 = mfspr(SPRN_MMCR0); |
979 | val |= MMCR0_FC; | 1124 | val |= MMCR0_FC; |
980 | val &= ~(MMCR0_EBE | MMCR0_PMCC | MMCR0_PMAO | MMCR0_FC56); | 1125 | val &= ~(MMCR0_EBE | MMCR0_BHRBA | MMCR0_PMCC | MMCR0_PMAO | |
1126 | MMCR0_FC56); | ||
981 | 1127 | ||
982 | /* | 1128 | /* |
983 | * The barrier is to make sure the mtspr has been | 1129 | * The barrier is to make sure the mtspr has been |
@@ -1144,6 +1290,8 @@ static void power_pmu_enable(struct pmu *pmu) | |||
1144 | cpuhw->mmcr[0] |= MMCR0_PMXE | MMCR0_FCECE; | 1290 | cpuhw->mmcr[0] |= MMCR0_PMXE | MMCR0_FCECE; |
1145 | 1291 | ||
1146 | out_enable: | 1292 | out_enable: |
1293 | pmao_restore_workaround(ebb); | ||
1294 | |||
1147 | mmcr0 = ebb_switch_in(ebb, cpuhw->mmcr[0]); | 1295 | mmcr0 = ebb_switch_in(ebb, cpuhw->mmcr[0]); |
1148 | 1296 | ||
1149 | mb(); | 1297 | mb(); |
diff --git a/arch/powerpc/perf/hv-24x7-catalog.h b/arch/powerpc/perf/hv-24x7-catalog.h new file mode 100644 index 000000000000..21b19dd86d9c --- /dev/null +++ b/arch/powerpc/perf/hv-24x7-catalog.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #ifndef LINUX_POWERPC_PERF_HV_24X7_CATALOG_H_ | ||
2 | #define LINUX_POWERPC_PERF_HV_24X7_CATALOG_H_ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | /* From document "24x7 Event and Group Catalog Formats Proposal" v0.15 */ | ||
7 | |||
8 | struct hv_24x7_catalog_page_0 { | ||
9 | #define HV_24X7_CATALOG_MAGIC 0x32347837 /* "24x7" in ASCII */ | ||
10 | __be32 magic; | ||
11 | __be32 length; /* In 4096 byte pages */ | ||
12 | __be64 version; /* XXX: arbitrary? what's the meaning/useage/purpose? */ | ||
13 | __u8 build_time_stamp[16]; /* "YYYYMMDDHHMMSS\0\0" */ | ||
14 | __u8 reserved2[32]; | ||
15 | __be16 schema_data_offs; /* in 4096 byte pages */ | ||
16 | __be16 schema_data_len; /* in 4096 byte pages */ | ||
17 | __be16 schema_entry_count; | ||
18 | __u8 reserved3[2]; | ||
19 | __be16 event_data_offs; | ||
20 | __be16 event_data_len; | ||
21 | __be16 event_entry_count; | ||
22 | __u8 reserved4[2]; | ||
23 | __be16 group_data_offs; /* in 4096 byte pages */ | ||
24 | __be16 group_data_len; /* in 4096 byte pages */ | ||
25 | __be16 group_entry_count; | ||
26 | __u8 reserved5[2]; | ||
27 | __be16 formula_data_offs; /* in 4096 byte pages */ | ||
28 | __be16 formula_data_len; /* in 4096 byte pages */ | ||
29 | __be16 formula_entry_count; | ||
30 | __u8 reserved6[2]; | ||
31 | } __packed; | ||
32 | |||
33 | #endif | ||
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c new file mode 100644 index 000000000000..297c91051413 --- /dev/null +++ b/arch/powerpc/perf/hv-24x7.c | |||
@@ -0,0 +1,510 @@ | |||
1 | /* | ||
2 | * Hypervisor supplied "24x7" performance counter support | ||
3 | * | ||
4 | * Author: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
5 | * Copyright 2014 IBM Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #define pr_fmt(fmt) "hv-24x7: " fmt | ||
14 | |||
15 | #include <linux/perf_event.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <asm/firmware.h> | ||
19 | #include <asm/hvcall.h> | ||
20 | #include <asm/io.h> | ||
21 | |||
22 | #include "hv-24x7.h" | ||
23 | #include "hv-24x7-catalog.h" | ||
24 | #include "hv-common.h" | ||
25 | |||
26 | /* | ||
27 | * TODO: Merging events: | ||
28 | * - Think of the hcall as an interface to a 4d array of counters: | ||
29 | * - x = domains | ||
30 | * - y = indexes in the domain (core, chip, vcpu, node, etc) | ||
31 | * - z = offset into the counter space | ||
32 | * - w = lpars (guest vms, "logical partitions") | ||
33 | * - A single request is: x,y,y_last,z,z_last,w,w_last | ||
34 | * - this means we can retrieve a rectangle of counters in y,z for a single x. | ||
35 | * | ||
36 | * - Things to consider (ignoring w): | ||
37 | * - input cost_per_request = 16 | ||
38 | * - output cost_per_result(ys,zs) = 8 + 8 * ys + ys * zs | ||
39 | * - limited number of requests per hcall (must fit into 4K bytes) | ||
40 | * - 4k = 16 [buffer header] - 16 [request size] * request_count | ||
41 | * - 255 requests per hcall | ||
42 | * - sometimes it will be more efficient to read extra data and discard | ||
43 | */ | ||
44 | |||
45 | /* | ||
46 | * Example usage: | ||
47 | * perf stat -e 'hv_24x7/domain=2,offset=8,starting_index=0,lpar=0xffffffff/' | ||
48 | */ | ||
49 | |||
50 | /* u3 0-6, one of HV_24X7_PERF_DOMAIN */ | ||
51 | EVENT_DEFINE_RANGE_FORMAT(domain, config, 0, 3); | ||
52 | /* u16 */ | ||
53 | EVENT_DEFINE_RANGE_FORMAT(starting_index, config, 16, 31); | ||
54 | /* u32, see "data_offset" */ | ||
55 | EVENT_DEFINE_RANGE_FORMAT(offset, config, 32, 63); | ||
56 | /* u16 */ | ||
57 | EVENT_DEFINE_RANGE_FORMAT(lpar, config1, 0, 15); | ||
58 | |||
59 | EVENT_DEFINE_RANGE(reserved1, config, 4, 15); | ||
60 | EVENT_DEFINE_RANGE(reserved2, config1, 16, 63); | ||
61 | EVENT_DEFINE_RANGE(reserved3, config2, 0, 63); | ||
62 | |||
63 | static struct attribute *format_attrs[] = { | ||
64 | &format_attr_domain.attr, | ||
65 | &format_attr_offset.attr, | ||
66 | &format_attr_starting_index.attr, | ||
67 | &format_attr_lpar.attr, | ||
68 | NULL, | ||
69 | }; | ||
70 | |||
71 | static struct attribute_group format_group = { | ||
72 | .name = "format", | ||
73 | .attrs = format_attrs, | ||
74 | }; | ||
75 | |||
76 | static struct kmem_cache *hv_page_cache; | ||
77 | |||
78 | /* | ||
79 | * read_offset_data - copy data from one buffer to another while treating the | ||
80 | * source buffer as a small view on the total avaliable | ||
81 | * source data. | ||
82 | * | ||
83 | * @dest: buffer to copy into | ||
84 | * @dest_len: length of @dest in bytes | ||
85 | * @requested_offset: the offset within the source data we want. Must be > 0 | ||
86 | * @src: buffer to copy data from | ||
87 | * @src_len: length of @src in bytes | ||
88 | * @source_offset: the offset in the sorce data that (src,src_len) refers to. | ||
89 | * Must be > 0 | ||
90 | * | ||
91 | * returns the number of bytes copied. | ||
92 | * | ||
93 | * The following ascii art shows the various buffer possitioning we need to | ||
94 | * handle, assigns some arbitrary varibles to points on the buffer, and then | ||
95 | * shows how we fiddle with those values to get things we care about (copy | ||
96 | * start in src and copy len) | ||
97 | * | ||
98 | * s = @src buffer | ||
99 | * d = @dest buffer | ||
100 | * '.' areas in d are written to. | ||
101 | * | ||
102 | * u | ||
103 | * x w v z | ||
104 | * d |.........| | ||
105 | * s |----------------------| | ||
106 | * | ||
107 | * u | ||
108 | * x w z v | ||
109 | * d |........------| | ||
110 | * s |------------------| | ||
111 | * | ||
112 | * x w u,z,v | ||
113 | * d |........| | ||
114 | * s |------------------| | ||
115 | * | ||
116 | * x,w u,v,z | ||
117 | * d |..................| | ||
118 | * s |------------------| | ||
119 | * | ||
120 | * x u | ||
121 | * w v z | ||
122 | * d |........| | ||
123 | * s |------------------| | ||
124 | * | ||
125 | * x z w v | ||
126 | * d |------| | ||
127 | * s |------| | ||
128 | * | ||
129 | * x = source_offset | ||
130 | * w = requested_offset | ||
131 | * z = source_offset + src_len | ||
132 | * v = requested_offset + dest_len | ||
133 | * | ||
134 | * w_offset_in_s = w - x = requested_offset - source_offset | ||
135 | * z_offset_in_s = z - x = src_len | ||
136 | * v_offset_in_s = v - x = request_offset + dest_len - src_len | ||
137 | */ | ||
138 | static ssize_t read_offset_data(void *dest, size_t dest_len, | ||
139 | loff_t requested_offset, void *src, | ||
140 | size_t src_len, loff_t source_offset) | ||
141 | { | ||
142 | size_t w_offset_in_s = requested_offset - source_offset; | ||
143 | size_t z_offset_in_s = src_len; | ||
144 | size_t v_offset_in_s = requested_offset + dest_len - src_len; | ||
145 | size_t u_offset_in_s = min(z_offset_in_s, v_offset_in_s); | ||
146 | size_t copy_len = u_offset_in_s - w_offset_in_s; | ||
147 | |||
148 | if (requested_offset < 0 || source_offset < 0) | ||
149 | return -EINVAL; | ||
150 | |||
151 | if (z_offset_in_s <= w_offset_in_s) | ||
152 | return 0; | ||
153 | |||
154 | memcpy(dest, src + w_offset_in_s, copy_len); | ||
155 | return copy_len; | ||
156 | } | ||
157 | |||
158 | static unsigned long h_get_24x7_catalog_page(char page[static 4096], | ||
159 | u32 version, u32 index) | ||
160 | { | ||
161 | WARN_ON(!IS_ALIGNED((unsigned long)page, 4096)); | ||
162 | return plpar_hcall_norets(H_GET_24X7_CATALOG_PAGE, | ||
163 | virt_to_phys(page), | ||
164 | version, | ||
165 | index); | ||
166 | } | ||
167 | |||
168 | static ssize_t catalog_read(struct file *filp, struct kobject *kobj, | ||
169 | struct bin_attribute *bin_attr, char *buf, | ||
170 | loff_t offset, size_t count) | ||
171 | { | ||
172 | unsigned long hret; | ||
173 | ssize_t ret = 0; | ||
174 | size_t catalog_len = 0, catalog_page_len = 0, page_count = 0; | ||
175 | loff_t page_offset = 0; | ||
176 | uint32_t catalog_version_num = 0; | ||
177 | void *page = kmem_cache_alloc(hv_page_cache, GFP_USER); | ||
178 | struct hv_24x7_catalog_page_0 *page_0 = page; | ||
179 | if (!page) | ||
180 | return -ENOMEM; | ||
181 | |||
182 | hret = h_get_24x7_catalog_page(page, 0, 0); | ||
183 | if (hret) { | ||
184 | ret = -EIO; | ||
185 | goto e_free; | ||
186 | } | ||
187 | |||
188 | catalog_version_num = be32_to_cpu(page_0->version); | ||
189 | catalog_page_len = be32_to_cpu(page_0->length); | ||
190 | catalog_len = catalog_page_len * 4096; | ||
191 | |||
192 | page_offset = offset / 4096; | ||
193 | page_count = count / 4096; | ||
194 | |||
195 | if (page_offset >= catalog_page_len) | ||
196 | goto e_free; | ||
197 | |||
198 | if (page_offset != 0) { | ||
199 | hret = h_get_24x7_catalog_page(page, catalog_version_num, | ||
200 | page_offset); | ||
201 | if (hret) { | ||
202 | ret = -EIO; | ||
203 | goto e_free; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | ret = read_offset_data(buf, count, offset, | ||
208 | page, 4096, page_offset * 4096); | ||
209 | e_free: | ||
210 | if (hret) | ||
211 | pr_err("h_get_24x7_catalog_page(ver=%d, page=%lld) failed: rc=%ld\n", | ||
212 | catalog_version_num, page_offset, hret); | ||
213 | kfree(page); | ||
214 | |||
215 | pr_devel("catalog_read: offset=%lld(%lld) count=%zu(%zu) catalog_len=%zu(%zu) => %zd\n", | ||
216 | offset, page_offset, count, page_count, catalog_len, | ||
217 | catalog_page_len, ret); | ||
218 | |||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | #define PAGE_0_ATTR(_name, _fmt, _expr) \ | ||
223 | static ssize_t _name##_show(struct device *dev, \ | ||
224 | struct device_attribute *dev_attr, \ | ||
225 | char *buf) \ | ||
226 | { \ | ||
227 | unsigned long hret; \ | ||
228 | ssize_t ret = 0; \ | ||
229 | void *page = kmem_cache_alloc(hv_page_cache, GFP_USER); \ | ||
230 | struct hv_24x7_catalog_page_0 *page_0 = page; \ | ||
231 | if (!page) \ | ||
232 | return -ENOMEM; \ | ||
233 | hret = h_get_24x7_catalog_page(page, 0, 0); \ | ||
234 | if (hret) { \ | ||
235 | ret = -EIO; \ | ||
236 | goto e_free; \ | ||
237 | } \ | ||
238 | ret = sprintf(buf, _fmt, _expr); \ | ||
239 | e_free: \ | ||
240 | kfree(page); \ | ||
241 | return ret; \ | ||
242 | } \ | ||
243 | static DEVICE_ATTR_RO(_name) | ||
244 | |||
245 | PAGE_0_ATTR(catalog_version, "%lld\n", | ||
246 | (unsigned long long)be32_to_cpu(page_0->version)); | ||
247 | PAGE_0_ATTR(catalog_len, "%lld\n", | ||
248 | (unsigned long long)be32_to_cpu(page_0->length) * 4096); | ||
249 | static BIN_ATTR_RO(catalog, 0/* real length varies */); | ||
250 | |||
251 | static struct bin_attribute *if_bin_attrs[] = { | ||
252 | &bin_attr_catalog, | ||
253 | NULL, | ||
254 | }; | ||
255 | |||
256 | static struct attribute *if_attrs[] = { | ||
257 | &dev_attr_catalog_len.attr, | ||
258 | &dev_attr_catalog_version.attr, | ||
259 | NULL, | ||
260 | }; | ||
261 | |||
262 | static struct attribute_group if_group = { | ||
263 | .name = "interface", | ||
264 | .bin_attrs = if_bin_attrs, | ||
265 | .attrs = if_attrs, | ||
266 | }; | ||
267 | |||
268 | static const struct attribute_group *attr_groups[] = { | ||
269 | &format_group, | ||
270 | &if_group, | ||
271 | NULL, | ||
272 | }; | ||
273 | |||
274 | static bool is_physical_domain(int domain) | ||
275 | { | ||
276 | return domain == HV_24X7_PERF_DOMAIN_PHYSICAL_CHIP || | ||
277 | domain == HV_24X7_PERF_DOMAIN_PHYSICAL_CORE; | ||
278 | } | ||
279 | |||
280 | static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, | ||
281 | u16 lpar, u64 *res, | ||
282 | bool success_expected) | ||
283 | { | ||
284 | unsigned long ret; | ||
285 | |||
286 | /* | ||
287 | * request_buffer and result_buffer are not required to be 4k aligned, | ||
288 | * but are not allowed to cross any 4k boundary. Aligning them to 4k is | ||
289 | * the simplest way to ensure that. | ||
290 | */ | ||
291 | struct reqb { | ||
292 | struct hv_24x7_request_buffer buf; | ||
293 | struct hv_24x7_request req; | ||
294 | } __packed __aligned(4096) request_buffer = { | ||
295 | .buf = { | ||
296 | .interface_version = HV_24X7_IF_VERSION_CURRENT, | ||
297 | .num_requests = 1, | ||
298 | }, | ||
299 | .req = { | ||
300 | .performance_domain = domain, | ||
301 | .data_size = cpu_to_be16(8), | ||
302 | .data_offset = cpu_to_be32(offset), | ||
303 | .starting_lpar_ix = cpu_to_be16(lpar), | ||
304 | .max_num_lpars = cpu_to_be16(1), | ||
305 | .starting_ix = cpu_to_be16(ix), | ||
306 | .max_ix = cpu_to_be16(1), | ||
307 | } | ||
308 | }; | ||
309 | |||
310 | struct resb { | ||
311 | struct hv_24x7_data_result_buffer buf; | ||
312 | struct hv_24x7_result res; | ||
313 | struct hv_24x7_result_element elem; | ||
314 | __be64 result; | ||
315 | } __packed __aligned(4096) result_buffer = {}; | ||
316 | |||
317 | ret = plpar_hcall_norets(H_GET_24X7_DATA, | ||
318 | virt_to_phys(&request_buffer), sizeof(request_buffer), | ||
319 | virt_to_phys(&result_buffer), sizeof(result_buffer)); | ||
320 | |||
321 | if (ret) { | ||
322 | if (success_expected) | ||
323 | pr_err_ratelimited("hcall failed: %d %#x %#x %d => 0x%lx (%ld) detail=0x%x failing ix=%x\n", | ||
324 | domain, offset, ix, lpar, | ||
325 | ret, ret, | ||
326 | result_buffer.buf.detailed_rc, | ||
327 | result_buffer.buf.failing_request_ix); | ||
328 | return ret; | ||
329 | } | ||
330 | |||
331 | *res = be64_to_cpu(result_buffer.result); | ||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | static unsigned long event_24x7_request(struct perf_event *event, u64 *res, | ||
336 | bool success_expected) | ||
337 | { | ||
338 | return single_24x7_request(event_get_domain(event), | ||
339 | event_get_offset(event), | ||
340 | event_get_starting_index(event), | ||
341 | event_get_lpar(event), | ||
342 | res, | ||
343 | success_expected); | ||
344 | } | ||
345 | |||
346 | static int h_24x7_event_init(struct perf_event *event) | ||
347 | { | ||
348 | struct hv_perf_caps caps; | ||
349 | unsigned domain; | ||
350 | unsigned long hret; | ||
351 | u64 ct; | ||
352 | |||
353 | /* Not our event */ | ||
354 | if (event->attr.type != event->pmu->type) | ||
355 | return -ENOENT; | ||
356 | |||
357 | /* Unused areas must be 0 */ | ||
358 | if (event_get_reserved1(event) || | ||
359 | event_get_reserved2(event) || | ||
360 | event_get_reserved3(event)) { | ||
361 | pr_devel("reserved set when forbidden 0x%llx(0x%llx) 0x%llx(0x%llx) 0x%llx(0x%llx)\n", | ||
362 | event->attr.config, | ||
363 | event_get_reserved1(event), | ||
364 | event->attr.config1, | ||
365 | event_get_reserved2(event), | ||
366 | event->attr.config2, | ||
367 | event_get_reserved3(event)); | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | |||
371 | /* unsupported modes and filters */ | ||
372 | if (event->attr.exclude_user || | ||
373 | event->attr.exclude_kernel || | ||
374 | event->attr.exclude_hv || | ||
375 | event->attr.exclude_idle || | ||
376 | event->attr.exclude_host || | ||
377 | event->attr.exclude_guest || | ||
378 | is_sampling_event(event)) /* no sampling */ | ||
379 | return -EINVAL; | ||
380 | |||
381 | /* no branch sampling */ | ||
382 | if (has_branch_stack(event)) | ||
383 | return -EOPNOTSUPP; | ||
384 | |||
385 | /* offset must be 8 byte aligned */ | ||
386 | if (event_get_offset(event) % 8) { | ||
387 | pr_devel("bad alignment\n"); | ||
388 | return -EINVAL; | ||
389 | } | ||
390 | |||
391 | /* Domains above 6 are invalid */ | ||
392 | domain = event_get_domain(event); | ||
393 | if (domain > 6) { | ||
394 | pr_devel("invalid domain %d\n", domain); | ||
395 | return -EINVAL; | ||
396 | } | ||
397 | |||
398 | hret = hv_perf_caps_get(&caps); | ||
399 | if (hret) { | ||
400 | pr_devel("could not get capabilities: rc=%ld\n", hret); | ||
401 | return -EIO; | ||
402 | } | ||
403 | |||
404 | /* PHYSICAL domains & other lpars require extra capabilities */ | ||
405 | if (!caps.collect_privileged && (is_physical_domain(domain) || | ||
406 | (event_get_lpar(event) != event_get_lpar_max()))) { | ||
407 | pr_devel("hv permisions disallow: is_physical_domain:%d, lpar=0x%llx\n", | ||
408 | is_physical_domain(domain), | ||
409 | event_get_lpar(event)); | ||
410 | return -EACCES; | ||
411 | } | ||
412 | |||
413 | /* see if the event complains */ | ||
414 | if (event_24x7_request(event, &ct, false)) { | ||
415 | pr_devel("test hcall failed\n"); | ||
416 | return -EIO; | ||
417 | } | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static u64 h_24x7_get_value(struct perf_event *event) | ||
423 | { | ||
424 | unsigned long ret; | ||
425 | u64 ct; | ||
426 | ret = event_24x7_request(event, &ct, true); | ||
427 | if (ret) | ||
428 | /* We checked this in event init, shouldn't fail here... */ | ||
429 | return 0; | ||
430 | |||
431 | return ct; | ||
432 | } | ||
433 | |||
434 | static void h_24x7_event_update(struct perf_event *event) | ||
435 | { | ||
436 | s64 prev; | ||
437 | u64 now; | ||
438 | now = h_24x7_get_value(event); | ||
439 | prev = local64_xchg(&event->hw.prev_count, now); | ||
440 | local64_add(now - prev, &event->count); | ||
441 | } | ||
442 | |||
443 | static void h_24x7_event_start(struct perf_event *event, int flags) | ||
444 | { | ||
445 | if (flags & PERF_EF_RELOAD) | ||
446 | local64_set(&event->hw.prev_count, h_24x7_get_value(event)); | ||
447 | } | ||
448 | |||
449 | static void h_24x7_event_stop(struct perf_event *event, int flags) | ||
450 | { | ||
451 | h_24x7_event_update(event); | ||
452 | } | ||
453 | |||
454 | static int h_24x7_event_add(struct perf_event *event, int flags) | ||
455 | { | ||
456 | if (flags & PERF_EF_START) | ||
457 | h_24x7_event_start(event, flags); | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static int h_24x7_event_idx(struct perf_event *event) | ||
463 | { | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static struct pmu h_24x7_pmu = { | ||
468 | .task_ctx_nr = perf_invalid_context, | ||
469 | |||
470 | .name = "hv_24x7", | ||
471 | .attr_groups = attr_groups, | ||
472 | .event_init = h_24x7_event_init, | ||
473 | .add = h_24x7_event_add, | ||
474 | .del = h_24x7_event_stop, | ||
475 | .start = h_24x7_event_start, | ||
476 | .stop = h_24x7_event_stop, | ||
477 | .read = h_24x7_event_update, | ||
478 | .event_idx = h_24x7_event_idx, | ||
479 | }; | ||
480 | |||
481 | static int hv_24x7_init(void) | ||
482 | { | ||
483 | int r; | ||
484 | unsigned long hret; | ||
485 | struct hv_perf_caps caps; | ||
486 | |||
487 | if (!firmware_has_feature(FW_FEATURE_LPAR)) { | ||
488 | pr_info("not a virtualized system, not enabling\n"); | ||
489 | return -ENODEV; | ||
490 | } | ||
491 | |||
492 | hret = hv_perf_caps_get(&caps); | ||
493 | if (hret) { | ||
494 | pr_info("could not obtain capabilities, error 0x%80lx, not enabling\n", | ||
495 | hret); | ||
496 | return -ENODEV; | ||
497 | } | ||
498 | |||
499 | hv_page_cache = kmem_cache_create("hv-page-4096", 4096, 4096, 0, NULL); | ||
500 | if (!hv_page_cache) | ||
501 | return -ENOMEM; | ||
502 | |||
503 | r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1); | ||
504 | if (r) | ||
505 | return r; | ||
506 | |||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | device_initcall(hv_24x7_init); | ||
diff --git a/arch/powerpc/perf/hv-24x7.h b/arch/powerpc/perf/hv-24x7.h new file mode 100644 index 000000000000..720ebce4b435 --- /dev/null +++ b/arch/powerpc/perf/hv-24x7.h | |||
@@ -0,0 +1,109 @@ | |||
1 | #ifndef LINUX_POWERPC_PERF_HV_24X7_H_ | ||
2 | #define LINUX_POWERPC_PERF_HV_24X7_H_ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | struct hv_24x7_request { | ||
7 | /* PHYSICAL domains require enabling via phyp/hmc. */ | ||
8 | #define HV_24X7_PERF_DOMAIN_PHYSICAL_CHIP 0x01 | ||
9 | #define HV_24X7_PERF_DOMAIN_PHYSICAL_CORE 0x02 | ||
10 | #define HV_24X7_PERF_DOMAIN_VIRTUAL_PROCESSOR_HOME_CORE 0x03 | ||
11 | #define HV_24X7_PERF_DOMAIN_VIRTUAL_PROCESSOR_HOME_CHIP 0x04 | ||
12 | #define HV_24X7_PERF_DOMAIN_VIRTUAL_PROCESSOR_HOME_NODE 0x05 | ||
13 | #define HV_24X7_PERF_DOMAIN_VIRTUAL_PROCESSOR_REMOTE_NODE 0x06 | ||
14 | __u8 performance_domain; | ||
15 | __u8 reserved[0x1]; | ||
16 | |||
17 | /* bytes to read starting at @data_offset. must be a multiple of 8 */ | ||
18 | __be16 data_size; | ||
19 | |||
20 | /* | ||
21 | * byte offset within the perf domain to read from. must be 8 byte | ||
22 | * aligned | ||
23 | */ | ||
24 | __be32 data_offset; | ||
25 | |||
26 | /* | ||
27 | * only valid for VIRTUAL_PROCESSOR domains, ignored for others. | ||
28 | * -1 means "current partition only" | ||
29 | * Enabling via phyp/hmc required for non-"-1" values. 0 forbidden | ||
30 | * unless requestor is 0. | ||
31 | */ | ||
32 | __be16 starting_lpar_ix; | ||
33 | |||
34 | /* | ||
35 | * Ignored when @starting_lpar_ix == -1 | ||
36 | * Ignored when @performance_domain is not VIRTUAL_PROCESSOR_* | ||
37 | * -1 means "infinite" or all | ||
38 | */ | ||
39 | __be16 max_num_lpars; | ||
40 | |||
41 | /* chip, core, or virtual processor based on @performance_domain */ | ||
42 | __be16 starting_ix; | ||
43 | __be16 max_ix; | ||
44 | } __packed; | ||
45 | |||
46 | struct hv_24x7_request_buffer { | ||
47 | /* 0 - ? */ | ||
48 | /* 1 - ? */ | ||
49 | #define HV_24X7_IF_VERSION_CURRENT 0x01 | ||
50 | __u8 interface_version; | ||
51 | __u8 num_requests; | ||
52 | __u8 reserved[0xE]; | ||
53 | struct hv_24x7_request requests[]; | ||
54 | } __packed; | ||
55 | |||
56 | struct hv_24x7_result_element { | ||
57 | __be16 lpar_ix; | ||
58 | |||
59 | /* | ||
60 | * represents the core, chip, or virtual processor based on the | ||
61 | * request's @performance_domain | ||
62 | */ | ||
63 | __be16 domain_ix; | ||
64 | |||
65 | /* -1 if @performance_domain does not refer to a virtual processor */ | ||
66 | __be32 lpar_cfg_instance_id; | ||
67 | |||
68 | /* size = @result_element_data_size of cointaining result. */ | ||
69 | __u8 element_data[]; | ||
70 | } __packed; | ||
71 | |||
72 | struct hv_24x7_result { | ||
73 | __u8 result_ix; | ||
74 | |||
75 | /* | ||
76 | * 0 = not all result elements fit into the buffer, additional requests | ||
77 | * required | ||
78 | * 1 = all result elements were returned | ||
79 | */ | ||
80 | __u8 results_complete; | ||
81 | __be16 num_elements_returned; | ||
82 | |||
83 | /* This is a copy of @data_size from the coresponding hv_24x7_request */ | ||
84 | __be16 result_element_data_size; | ||
85 | __u8 reserved[0x2]; | ||
86 | |||
87 | /* WARNING: only valid for first result element due to variable sizes | ||
88 | * of result elements */ | ||
89 | /* struct hv_24x7_result_element[@num_elements_returned] */ | ||
90 | struct hv_24x7_result_element elements[]; | ||
91 | } __packed; | ||
92 | |||
93 | struct hv_24x7_data_result_buffer { | ||
94 | /* See versioning for request buffer */ | ||
95 | __u8 interface_version; | ||
96 | |||
97 | __u8 num_results; | ||
98 | __u8 reserved[0x1]; | ||
99 | __u8 failing_request_ix; | ||
100 | __be32 detailed_rc; | ||
101 | __be64 cec_cfg_instance_id; | ||
102 | __be64 catalog_version_num; | ||
103 | __u8 reserved2[0x8]; | ||
104 | /* WARNING: only valid for the first result due to variable sizes of | ||
105 | * results */ | ||
106 | struct hv_24x7_result results[]; /* [@num_results] */ | ||
107 | } __packed; | ||
108 | |||
109 | #endif | ||
diff --git a/arch/powerpc/perf/hv-common.c b/arch/powerpc/perf/hv-common.c new file mode 100644 index 000000000000..47e02b366f58 --- /dev/null +++ b/arch/powerpc/perf/hv-common.c | |||
@@ -0,0 +1,39 @@ | |||
1 | #include <asm/io.h> | ||
2 | #include <asm/hvcall.h> | ||
3 | |||
4 | #include "hv-gpci.h" | ||
5 | #include "hv-common.h" | ||
6 | |||
7 | unsigned long hv_perf_caps_get(struct hv_perf_caps *caps) | ||
8 | { | ||
9 | unsigned long r; | ||
10 | struct p { | ||
11 | struct hv_get_perf_counter_info_params params; | ||
12 | struct cv_system_performance_capabilities caps; | ||
13 | } __packed __aligned(sizeof(uint64_t)); | ||
14 | |||
15 | struct p arg = { | ||
16 | .params = { | ||
17 | .counter_request = cpu_to_be32( | ||
18 | CIR_SYSTEM_PERFORMANCE_CAPABILITIES), | ||
19 | .starting_index = cpu_to_be32(-1), | ||
20 | .counter_info_version_in = 0, | ||
21 | } | ||
22 | }; | ||
23 | |||
24 | r = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, | ||
25 | virt_to_phys(&arg), sizeof(arg)); | ||
26 | |||
27 | if (r) | ||
28 | return r; | ||
29 | |||
30 | pr_devel("capability_mask: 0x%x\n", arg.caps.capability_mask); | ||
31 | |||
32 | caps->version = arg.params.counter_info_version_out; | ||
33 | caps->collect_privileged = !!arg.caps.perf_collect_privileged; | ||
34 | caps->ga = !!(arg.caps.capability_mask & CV_CM_GA); | ||
35 | caps->expanded = !!(arg.caps.capability_mask & CV_CM_EXPANDED); | ||
36 | caps->lab = !!(arg.caps.capability_mask & CV_CM_LAB); | ||
37 | |||
38 | return r; | ||
39 | } | ||
diff --git a/arch/powerpc/perf/hv-common.h b/arch/powerpc/perf/hv-common.h new file mode 100644 index 000000000000..5d79cecbd73d --- /dev/null +++ b/arch/powerpc/perf/hv-common.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef LINUX_POWERPC_PERF_HV_COMMON_H_ | ||
2 | #define LINUX_POWERPC_PERF_HV_COMMON_H_ | ||
3 | |||
4 | #include <linux/perf_event.h> | ||
5 | #include <linux/types.h> | ||
6 | |||
7 | struct hv_perf_caps { | ||
8 | u16 version; | ||
9 | u16 collect_privileged:1, | ||
10 | ga:1, | ||
11 | expanded:1, | ||
12 | lab:1, | ||
13 | unused:12; | ||
14 | }; | ||
15 | |||
16 | unsigned long hv_perf_caps_get(struct hv_perf_caps *caps); | ||
17 | |||
18 | |||
19 | #define EVENT_DEFINE_RANGE_FORMAT(name, attr_var, bit_start, bit_end) \ | ||
20 | PMU_FORMAT_ATTR(name, #attr_var ":" #bit_start "-" #bit_end); \ | ||
21 | EVENT_DEFINE_RANGE(name, attr_var, bit_start, bit_end) | ||
22 | |||
23 | #define EVENT_DEFINE_RANGE(name, attr_var, bit_start, bit_end) \ | ||
24 | static u64 event_get_##name##_max(void) \ | ||
25 | { \ | ||
26 | BUILD_BUG_ON((bit_start > bit_end) \ | ||
27 | || (bit_end >= (sizeof(1ull) * 8))); \ | ||
28 | return (((1ull << (bit_end - bit_start)) - 1) << 1) + 1; \ | ||
29 | } \ | ||
30 | static u64 event_get_##name(struct perf_event *event) \ | ||
31 | { \ | ||
32 | return (event->attr.attr_var >> (bit_start)) & \ | ||
33 | event_get_##name##_max(); \ | ||
34 | } | ||
35 | |||
36 | #endif | ||
diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c new file mode 100644 index 000000000000..278ba7b9c2b5 --- /dev/null +++ b/arch/powerpc/perf/hv-gpci.c | |||
@@ -0,0 +1,294 @@ | |||
1 | /* | ||
2 | * Hypervisor supplied "gpci" ("get performance counter info") performance | ||
3 | * counter support | ||
4 | * | ||
5 | * Author: Cody P Schafer <cody@linux.vnet.ibm.com> | ||
6 | * Copyright 2014 IBM Corporation. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #define pr_fmt(fmt) "hv-gpci: " fmt | ||
15 | |||
16 | #include <linux/init.h> | ||
17 | #include <linux/perf_event.h> | ||
18 | #include <asm/firmware.h> | ||
19 | #include <asm/hvcall.h> | ||
20 | #include <asm/io.h> | ||
21 | |||
22 | #include "hv-gpci.h" | ||
23 | #include "hv-common.h" | ||
24 | |||
25 | /* | ||
26 | * Example usage: | ||
27 | * perf stat -e 'hv_gpci/counter_info_version=3,offset=0,length=8, | ||
28 | * secondary_index=0,starting_index=0xffffffff,request=0x10/' ... | ||
29 | */ | ||
30 | |||
31 | /* u32 */ | ||
32 | EVENT_DEFINE_RANGE_FORMAT(request, config, 0, 31); | ||
33 | /* u32 */ | ||
34 | EVENT_DEFINE_RANGE_FORMAT(starting_index, config, 32, 63); | ||
35 | /* u16 */ | ||
36 | EVENT_DEFINE_RANGE_FORMAT(secondary_index, config1, 0, 15); | ||
37 | /* u8 */ | ||
38 | EVENT_DEFINE_RANGE_FORMAT(counter_info_version, config1, 16, 23); | ||
39 | /* u8, bytes of data (1-8) */ | ||
40 | EVENT_DEFINE_RANGE_FORMAT(length, config1, 24, 31); | ||
41 | /* u32, byte offset */ | ||
42 | EVENT_DEFINE_RANGE_FORMAT(offset, config1, 32, 63); | ||
43 | |||
44 | static struct attribute *format_attrs[] = { | ||
45 | &format_attr_request.attr, | ||
46 | &format_attr_starting_index.attr, | ||
47 | &format_attr_secondary_index.attr, | ||
48 | &format_attr_counter_info_version.attr, | ||
49 | |||
50 | &format_attr_offset.attr, | ||
51 | &format_attr_length.attr, | ||
52 | NULL, | ||
53 | }; | ||
54 | |||
55 | static struct attribute_group format_group = { | ||
56 | .name = "format", | ||
57 | .attrs = format_attrs, | ||
58 | }; | ||
59 | |||
60 | #define HV_CAPS_ATTR(_name, _format) \ | ||
61 | static ssize_t _name##_show(struct device *dev, \ | ||
62 | struct device_attribute *attr, \ | ||
63 | char *page) \ | ||
64 | { \ | ||
65 | struct hv_perf_caps caps; \ | ||
66 | unsigned long hret = hv_perf_caps_get(&caps); \ | ||
67 | if (hret) \ | ||
68 | return -EIO; \ | ||
69 | \ | ||
70 | return sprintf(page, _format, caps._name); \ | ||
71 | } \ | ||
72 | static struct device_attribute hv_caps_attr_##_name = __ATTR_RO(_name) | ||
73 | |||
74 | static ssize_t kernel_version_show(struct device *dev, | ||
75 | struct device_attribute *attr, | ||
76 | char *page) | ||
77 | { | ||
78 | return sprintf(page, "0x%x\n", COUNTER_INFO_VERSION_CURRENT); | ||
79 | } | ||
80 | |||
81 | DEVICE_ATTR_RO(kernel_version); | ||
82 | HV_CAPS_ATTR(version, "0x%x\n"); | ||
83 | HV_CAPS_ATTR(ga, "%d\n"); | ||
84 | HV_CAPS_ATTR(expanded, "%d\n"); | ||
85 | HV_CAPS_ATTR(lab, "%d\n"); | ||
86 | HV_CAPS_ATTR(collect_privileged, "%d\n"); | ||
87 | |||
88 | static struct attribute *interface_attrs[] = { | ||
89 | &dev_attr_kernel_version.attr, | ||
90 | &hv_caps_attr_version.attr, | ||
91 | &hv_caps_attr_ga.attr, | ||
92 | &hv_caps_attr_expanded.attr, | ||
93 | &hv_caps_attr_lab.attr, | ||
94 | &hv_caps_attr_collect_privileged.attr, | ||
95 | NULL, | ||
96 | }; | ||
97 | |||
98 | static struct attribute_group interface_group = { | ||
99 | .name = "interface", | ||
100 | .attrs = interface_attrs, | ||
101 | }; | ||
102 | |||
103 | static const struct attribute_group *attr_groups[] = { | ||
104 | &format_group, | ||
105 | &interface_group, | ||
106 | NULL, | ||
107 | }; | ||
108 | |||
109 | #define GPCI_MAX_DATA_BYTES \ | ||
110 | (1024 - sizeof(struct hv_get_perf_counter_info_params)) | ||
111 | |||
112 | static unsigned long single_gpci_request(u32 req, u32 starting_index, | ||
113 | u16 secondary_index, u8 version_in, u32 offset, u8 length, | ||
114 | u64 *value) | ||
115 | { | ||
116 | unsigned long ret; | ||
117 | size_t i; | ||
118 | u64 count; | ||
119 | |||
120 | struct { | ||
121 | struct hv_get_perf_counter_info_params params; | ||
122 | uint8_t bytes[GPCI_MAX_DATA_BYTES]; | ||
123 | } __packed __aligned(sizeof(uint64_t)) arg = { | ||
124 | .params = { | ||
125 | .counter_request = cpu_to_be32(req), | ||
126 | .starting_index = cpu_to_be32(starting_index), | ||
127 | .secondary_index = cpu_to_be16(secondary_index), | ||
128 | .counter_info_version_in = version_in, | ||
129 | } | ||
130 | }; | ||
131 | |||
132 | ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, | ||
133 | virt_to_phys(&arg), sizeof(arg)); | ||
134 | if (ret) { | ||
135 | pr_devel("hcall failed: 0x%lx\n", ret); | ||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * we verify offset and length are within the zeroed buffer at event | ||
141 | * init. | ||
142 | */ | ||
143 | count = 0; | ||
144 | for (i = offset; i < offset + length; i++) | ||
145 | count |= arg.bytes[i] << (i - offset); | ||
146 | |||
147 | *value = count; | ||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | static u64 h_gpci_get_value(struct perf_event *event) | ||
152 | { | ||
153 | u64 count; | ||
154 | unsigned long ret = single_gpci_request(event_get_request(event), | ||
155 | event_get_starting_index(event), | ||
156 | event_get_secondary_index(event), | ||
157 | event_get_counter_info_version(event), | ||
158 | event_get_offset(event), | ||
159 | event_get_length(event), | ||
160 | &count); | ||
161 | if (ret) | ||
162 | return 0; | ||
163 | return count; | ||
164 | } | ||
165 | |||
166 | static void h_gpci_event_update(struct perf_event *event) | ||
167 | { | ||
168 | s64 prev; | ||
169 | u64 now = h_gpci_get_value(event); | ||
170 | prev = local64_xchg(&event->hw.prev_count, now); | ||
171 | local64_add(now - prev, &event->count); | ||
172 | } | ||
173 | |||
174 | static void h_gpci_event_start(struct perf_event *event, int flags) | ||
175 | { | ||
176 | local64_set(&event->hw.prev_count, h_gpci_get_value(event)); | ||
177 | } | ||
178 | |||
179 | static void h_gpci_event_stop(struct perf_event *event, int flags) | ||
180 | { | ||
181 | h_gpci_event_update(event); | ||
182 | } | ||
183 | |||
184 | static int h_gpci_event_add(struct perf_event *event, int flags) | ||
185 | { | ||
186 | if (flags & PERF_EF_START) | ||
187 | h_gpci_event_start(event, flags); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int h_gpci_event_init(struct perf_event *event) | ||
193 | { | ||
194 | u64 count; | ||
195 | u8 length; | ||
196 | |||
197 | /* Not our event */ | ||
198 | if (event->attr.type != event->pmu->type) | ||
199 | return -ENOENT; | ||
200 | |||
201 | /* config2 is unused */ | ||
202 | if (event->attr.config2) { | ||
203 | pr_devel("config2 set when reserved\n"); | ||
204 | return -EINVAL; | ||
205 | } | ||
206 | |||
207 | /* unsupported modes and filters */ | ||
208 | if (event->attr.exclude_user || | ||
209 | event->attr.exclude_kernel || | ||
210 | event->attr.exclude_hv || | ||
211 | event->attr.exclude_idle || | ||
212 | event->attr.exclude_host || | ||
213 | event->attr.exclude_guest || | ||
214 | is_sampling_event(event)) /* no sampling */ | ||
215 | return -EINVAL; | ||
216 | |||
217 | /* no branch sampling */ | ||
218 | if (has_branch_stack(event)) | ||
219 | return -EOPNOTSUPP; | ||
220 | |||
221 | length = event_get_length(event); | ||
222 | if (length < 1 || length > 8) { | ||
223 | pr_devel("length invalid\n"); | ||
224 | return -EINVAL; | ||
225 | } | ||
226 | |||
227 | /* last byte within the buffer? */ | ||
228 | if ((event_get_offset(event) + length) > GPCI_MAX_DATA_BYTES) { | ||
229 | pr_devel("request outside of buffer: %zu > %zu\n", | ||
230 | (size_t)event_get_offset(event) + length, | ||
231 | GPCI_MAX_DATA_BYTES); | ||
232 | return -EINVAL; | ||
233 | } | ||
234 | |||
235 | /* check if the request works... */ | ||
236 | if (single_gpci_request(event_get_request(event), | ||
237 | event_get_starting_index(event), | ||
238 | event_get_secondary_index(event), | ||
239 | event_get_counter_info_version(event), | ||
240 | event_get_offset(event), | ||
241 | length, | ||
242 | &count)) { | ||
243 | pr_devel("gpci hcall failed\n"); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static int h_gpci_event_idx(struct perf_event *event) | ||
251 | { | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static struct pmu h_gpci_pmu = { | ||
256 | .task_ctx_nr = perf_invalid_context, | ||
257 | |||
258 | .name = "hv_gpci", | ||
259 | .attr_groups = attr_groups, | ||
260 | .event_init = h_gpci_event_init, | ||
261 | .add = h_gpci_event_add, | ||
262 | .del = h_gpci_event_stop, | ||
263 | .start = h_gpci_event_start, | ||
264 | .stop = h_gpci_event_stop, | ||
265 | .read = h_gpci_event_update, | ||
266 | .event_idx = h_gpci_event_idx, | ||
267 | }; | ||
268 | |||
269 | static int hv_gpci_init(void) | ||
270 | { | ||
271 | int r; | ||
272 | unsigned long hret; | ||
273 | struct hv_perf_caps caps; | ||
274 | |||
275 | if (!firmware_has_feature(FW_FEATURE_LPAR)) { | ||
276 | pr_info("not a virtualized system, not enabling\n"); | ||
277 | return -ENODEV; | ||
278 | } | ||
279 | |||
280 | hret = hv_perf_caps_get(&caps); | ||
281 | if (hret) { | ||
282 | pr_info("could not obtain capabilities, error 0x%80lx, not enabling\n", | ||
283 | hret); | ||
284 | return -ENODEV; | ||
285 | } | ||
286 | |||
287 | r = perf_pmu_register(&h_gpci_pmu, h_gpci_pmu.name, -1); | ||
288 | if (r) | ||
289 | return r; | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | device_initcall(hv_gpci_init); | ||
diff --git a/arch/powerpc/perf/hv-gpci.h b/arch/powerpc/perf/hv-gpci.h new file mode 100644 index 000000000000..b25f460c9cce --- /dev/null +++ b/arch/powerpc/perf/hv-gpci.h | |||
@@ -0,0 +1,73 @@ | |||
1 | #ifndef LINUX_POWERPC_PERF_HV_GPCI_H_ | ||
2 | #define LINUX_POWERPC_PERF_HV_GPCI_H_ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | /* From the document "H_GetPerformanceCounterInfo Interface" v1.07 */ | ||
7 | |||
8 | /* H_GET_PERF_COUNTER_INFO argument */ | ||
9 | struct hv_get_perf_counter_info_params { | ||
10 | __be32 counter_request; /* I */ | ||
11 | __be32 starting_index; /* IO */ | ||
12 | __be16 secondary_index; /* IO */ | ||
13 | __be16 returned_values; /* O */ | ||
14 | __be32 detail_rc; /* O, only needed when called via *_norets() */ | ||
15 | |||
16 | /* | ||
17 | * O, size each of counter_value element in bytes, only set for version | ||
18 | * >= 0x3 | ||
19 | */ | ||
20 | __be16 cv_element_size; | ||
21 | |||
22 | /* I, 0 (zero) for versions < 0x3 */ | ||
23 | __u8 counter_info_version_in; | ||
24 | |||
25 | /* O, 0 (zero) if version < 0x3. Must be set to 0 when making hcall */ | ||
26 | __u8 counter_info_version_out; | ||
27 | __u8 reserved[0xC]; | ||
28 | __u8 counter_value[]; | ||
29 | } __packed; | ||
30 | |||
31 | /* | ||
32 | * counter info version => fw version/reference (spec version) | ||
33 | * | ||
34 | * 8 => power8 (1.07) | ||
35 | * [7 is skipped by spec 1.07] | ||
36 | * 6 => TLBIE (1.07) | ||
37 | * 5 => v7r7m0.phyp (1.05) | ||
38 | * [4 skipped] | ||
39 | * 3 => v7r6m0.phyp (?) | ||
40 | * [1,2 skipped] | ||
41 | * 0 => v7r{2,3,4}m0.phyp (?) | ||
42 | */ | ||
43 | #define COUNTER_INFO_VERSION_CURRENT 0x8 | ||
44 | |||
45 | /* | ||
46 | * These determine the counter_value[] layout and the meaning of starting_index | ||
47 | * and secondary_index. | ||
48 | * | ||
49 | * Unless otherwise noted, @secondary_index is unused and ignored. | ||
50 | */ | ||
51 | enum counter_info_requests { | ||
52 | |||
53 | /* GENERAL */ | ||
54 | |||
55 | /* @starting_index: must be -1 (to refer to the current partition) | ||
56 | */ | ||
57 | CIR_SYSTEM_PERFORMANCE_CAPABILITIES = 0X40, | ||
58 | }; | ||
59 | |||
60 | struct cv_system_performance_capabilities { | ||
61 | /* If != 0, allowed to collect data from other partitions */ | ||
62 | __u8 perf_collect_privileged; | ||
63 | |||
64 | /* These following are only valid if counter_info_version >= 0x3 */ | ||
65 | #define CV_CM_GA (1 << 7) | ||
66 | #define CV_CM_EXPANDED (1 << 6) | ||
67 | #define CV_CM_LAB (1 << 5) | ||
68 | /* remaining bits are reserved */ | ||
69 | __u8 capability_mask; | ||
70 | __u8 reserved[0xE]; | ||
71 | } __packed; | ||
72 | |||
73 | #endif | ||
diff --git a/arch/powerpc/perf/power7-events-list.h b/arch/powerpc/perf/power7-events-list.h index 687790a2c0b8..64f13d9260a6 100644 --- a/arch/powerpc/perf/power7-events-list.h +++ b/arch/powerpc/perf/power7-events-list.h | |||
@@ -546,3 +546,13 @@ EVENT(PM_MRK_DATA_FROM_RL2L3_SHR, 0x1d04c) | |||
546 | EVENT(PM_DTLB_MISS_16M, 0x4c05e) | 546 | EVENT(PM_DTLB_MISS_16M, 0x4c05e) |
547 | EVENT(PM_LSU1_LMQ_LHR_MERGE, 0x0d09a) | 547 | EVENT(PM_LSU1_LMQ_LHR_MERGE, 0x0d09a) |
548 | EVENT(PM_IFU_FIN, 0x40066) | 548 | EVENT(PM_IFU_FIN, 0x40066) |
549 | EVENT(PM_1THRD_CON_RUN_INSTR, 0x30062) | ||
550 | EVENT(PM_CMPLU_STALL_COUNT, 0x4000B) | ||
551 | EVENT(PM_MEM0_PB_RD_CL, 0x30083) | ||
552 | EVENT(PM_THRD_1_RUN_CYC, 0x10060) | ||
553 | EVENT(PM_THRD_2_CONC_RUN_INSTR, 0x40062) | ||
554 | EVENT(PM_THRD_2_RUN_CYC, 0x20060) | ||
555 | EVENT(PM_THRD_3_CONC_RUN_INST, 0x10062) | ||
556 | EVENT(PM_THRD_3_RUN_CYC, 0x30060) | ||
557 | EVENT(PM_THRD_4_CONC_RUN_INST, 0x20062) | ||
558 | EVENT(PM_THRD_4_RUN_CYC, 0x40060) | ||
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index 96cee20dcd34..fe2763b6e039 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define pr_fmt(fmt) "power8-pmu: " fmt | ||
14 | |||
13 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
14 | #include <linux/perf_event.h> | 16 | #include <linux/perf_event.h> |
15 | #include <asm/firmware.h> | 17 | #include <asm/firmware.h> |
@@ -62,9 +64,11 @@ | |||
62 | * | 64 | * |
63 | * 60 56 52 48 44 40 36 32 | 65 | * 60 56 52 48 44 40 36 32 |
64 | * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | | 66 | * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | |
65 | * | [ thresh_cmp ] [ thresh_ctl ] | 67 | * | | [ ] [ thresh_cmp ] [ thresh_ctl ] |
66 | * | | | 68 | * | | | | |
67 | * *- EBB (Linux) thresh start/stop OR FAB match -* | 69 | * | | *- IFM (Linux) thresh start/stop OR FAB match -* |
70 | * | *- BHRB (Linux) | ||
71 | * *- EBB (Linux) | ||
68 | * | 72 | * |
69 | * 28 24 20 16 12 8 4 0 | 73 | * 28 24 20 16 12 8 4 0 |
70 | * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | | 74 | * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | |
@@ -114,9 +118,18 @@ | |||
114 | * MMCRA[57:59] = sample[0:2] (RAND_SAMP_ELIG) | 118 | * MMCRA[57:59] = sample[0:2] (RAND_SAMP_ELIG) |
115 | Â * MMCRA[61:62] = sample[3:4] (RAND_SAMP_MODE) | 119 | Â * MMCRA[61:62] = sample[3:4] (RAND_SAMP_MODE) |
116 | * | 120 | * |
121 | * if EBB and BHRB: | ||
122 | * MMCRA[32:33] = IFM | ||
123 | * | ||
117 | */ | 124 | */ |
118 | 125 | ||
119 | #define EVENT_EBB_MASK 1ull | 126 | #define EVENT_EBB_MASK 1ull |
127 | #define EVENT_EBB_SHIFT PERF_EVENT_CONFIG_EBB_SHIFT | ||
128 | #define EVENT_BHRB_MASK 1ull | ||
129 | #define EVENT_BHRB_SHIFT 62 | ||
130 | #define EVENT_WANTS_BHRB (EVENT_BHRB_MASK << EVENT_BHRB_SHIFT) | ||
131 | #define EVENT_IFM_MASK 3ull | ||
132 | #define EVENT_IFM_SHIFT 60 | ||
120 | #define EVENT_THR_CMP_SHIFT 40 /* Threshold CMP value */ | 133 | #define EVENT_THR_CMP_SHIFT 40 /* Threshold CMP value */ |
121 | #define EVENT_THR_CMP_MASK 0x3ff | 134 | #define EVENT_THR_CMP_MASK 0x3ff |
122 | #define EVENT_THR_CTL_SHIFT 32 /* Threshold control value (start/stop) */ | 135 | #define EVENT_THR_CTL_SHIFT 32 /* Threshold control value (start/stop) */ |
@@ -141,6 +154,12 @@ | |||
141 | #define EVENT_IS_MARKED (EVENT_MARKED_MASK << EVENT_MARKED_SHIFT) | 154 | #define EVENT_IS_MARKED (EVENT_MARKED_MASK << EVENT_MARKED_SHIFT) |
142 | #define EVENT_PSEL_MASK 0xff /* PMCxSEL value */ | 155 | #define EVENT_PSEL_MASK 0xff /* PMCxSEL value */ |
143 | 156 | ||
157 | /* Bits defined by Linux */ | ||
158 | #define EVENT_LINUX_MASK \ | ||
159 | ((EVENT_EBB_MASK << EVENT_EBB_SHIFT) | \ | ||
160 | (EVENT_BHRB_MASK << EVENT_BHRB_SHIFT) | \ | ||
161 | (EVENT_IFM_MASK << EVENT_IFM_SHIFT)) | ||
162 | |||
144 | #define EVENT_VALID_MASK \ | 163 | #define EVENT_VALID_MASK \ |
145 | ((EVENT_THRESH_MASK << EVENT_THRESH_SHIFT) | \ | 164 | ((EVENT_THRESH_MASK << EVENT_THRESH_SHIFT) | \ |
146 | (EVENT_SAMPLE_MASK << EVENT_SAMPLE_SHIFT) | \ | 165 | (EVENT_SAMPLE_MASK << EVENT_SAMPLE_SHIFT) | \ |
@@ -149,7 +168,7 @@ | |||
149 | (EVENT_UNIT_MASK << EVENT_UNIT_SHIFT) | \ | 168 | (EVENT_UNIT_MASK << EVENT_UNIT_SHIFT) | \ |
150 | (EVENT_COMBINE_MASK << EVENT_COMBINE_SHIFT) | \ | 169 | (EVENT_COMBINE_MASK << EVENT_COMBINE_SHIFT) | \ |
151 | (EVENT_MARKED_MASK << EVENT_MARKED_SHIFT) | \ | 170 | (EVENT_MARKED_MASK << EVENT_MARKED_SHIFT) | \ |
152 | (EVENT_EBB_MASK << PERF_EVENT_CONFIG_EBB_SHIFT) | \ | 171 | EVENT_LINUX_MASK | \ |
153 | EVENT_PSEL_MASK) | 172 | EVENT_PSEL_MASK) |
154 | 173 | ||
155 | /* MMCRA IFM bits - POWER8 */ | 174 | /* MMCRA IFM bits - POWER8 */ |
@@ -173,10 +192,11 @@ | |||
173 | * | 192 | * |
174 | * 28 24 20 16 12 8 4 0 | 193 | * 28 24 20 16 12 8 4 0 |
175 | * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | | 194 | * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | |
176 | * | [ ] [ sample ] [ ] [6] [5] [4] [3] [2] [1] | 195 | * [ ] | [ ] [ sample ] [ ] [6] [5] [4] [3] [2] [1] |
177 | * EBB -* | | | 196 | * | | | | |
178 | * | | Count of events for each PMC. | 197 | * BHRB IFM -* | | | Count of events for each PMC. |
179 | * L1 I/D qualifier -* | p1, p2, p3, p4, p5, p6. | 198 | * EBB -* | | p1, p2, p3, p4, p5, p6. |
199 | * L1 I/D qualifier -* | | ||
180 | * nc - number of counters -* | 200 | * nc - number of counters -* |
181 | * | 201 | * |
182 | * The PMC fields P1..P6, and NC, are adder fields. As we accumulate constraints | 202 | * The PMC fields P1..P6, and NC, are adder fields. As we accumulate constraints |
@@ -195,6 +215,9 @@ | |||
195 | #define CNST_EBB_VAL(v) (((v) & EVENT_EBB_MASK) << 24) | 215 | #define CNST_EBB_VAL(v) (((v) & EVENT_EBB_MASK) << 24) |
196 | #define CNST_EBB_MASK CNST_EBB_VAL(EVENT_EBB_MASK) | 216 | #define CNST_EBB_MASK CNST_EBB_VAL(EVENT_EBB_MASK) |
197 | 217 | ||
218 | #define CNST_IFM_VAL(v) (((v) & EVENT_IFM_MASK) << 25) | ||
219 | #define CNST_IFM_MASK CNST_IFM_VAL(EVENT_IFM_MASK) | ||
220 | |||
198 | #define CNST_L1_QUAL_VAL(v) (((v) & 3) << 22) | 221 | #define CNST_L1_QUAL_VAL(v) (((v) & 3) << 22) |
199 | #define CNST_L1_QUAL_MASK CNST_L1_QUAL_VAL(3) | 222 | #define CNST_L1_QUAL_MASK CNST_L1_QUAL_VAL(3) |
200 | 223 | ||
@@ -241,6 +264,7 @@ | |||
241 | #define MMCRA_THR_SEL_SHIFT 16 | 264 | #define MMCRA_THR_SEL_SHIFT 16 |
242 | #define MMCRA_THR_CMP_SHIFT 32 | 265 | #define MMCRA_THR_CMP_SHIFT 32 |
243 | #define MMCRA_SDAR_MODE_TLB (1ull << 42) | 266 | #define MMCRA_SDAR_MODE_TLB (1ull << 42) |
267 | #define MMCRA_IFM_SHIFT 30 | ||
244 | 268 | ||
245 | 269 | ||
246 | static inline bool event_is_fab_match(u64 event) | 270 | static inline bool event_is_fab_match(u64 event) |
@@ -265,20 +289,22 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long | |||
265 | pmc = (event >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; | 289 | pmc = (event >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; |
266 | unit = (event >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK; | 290 | unit = (event >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK; |
267 | cache = (event >> EVENT_CACHE_SEL_SHIFT) & EVENT_CACHE_SEL_MASK; | 291 | cache = (event >> EVENT_CACHE_SEL_SHIFT) & EVENT_CACHE_SEL_MASK; |
268 | ebb = (event >> PERF_EVENT_CONFIG_EBB_SHIFT) & EVENT_EBB_MASK; | 292 | ebb = (event >> EVENT_EBB_SHIFT) & EVENT_EBB_MASK; |
269 | |||
270 | /* Clear the EBB bit in the event, so event checks work below */ | ||
271 | event &= ~(EVENT_EBB_MASK << PERF_EVENT_CONFIG_EBB_SHIFT); | ||
272 | 293 | ||
273 | if (pmc) { | 294 | if (pmc) { |
295 | u64 base_event; | ||
296 | |||
274 | if (pmc > 6) | 297 | if (pmc > 6) |
275 | return -1; | 298 | return -1; |
276 | 299 | ||
277 | mask |= CNST_PMC_MASK(pmc); | 300 | /* Ignore Linux defined bits when checking event below */ |
278 | value |= CNST_PMC_VAL(pmc); | 301 | base_event = event & ~EVENT_LINUX_MASK; |
279 | 302 | ||
280 | if (pmc >= 5 && event != 0x500fa && event != 0x600f4) | 303 | if (pmc >= 5 && base_event != 0x500fa && base_event != 0x600f4) |
281 | return -1; | 304 | return -1; |
305 | |||
306 | mask |= CNST_PMC_MASK(pmc); | ||
307 | value |= CNST_PMC_VAL(pmc); | ||
282 | } | 308 | } |
283 | 309 | ||
284 | if (pmc <= 4) { | 310 | if (pmc <= 4) { |
@@ -299,9 +325,10 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long | |||
299 | * HV writable, and there is no API for guest kernels to modify | 325 | * HV writable, and there is no API for guest kernels to modify |
300 | * it. The solution is for the hypervisor to initialise the | 326 | * it. The solution is for the hypervisor to initialise the |
301 | * field to zeroes, and for us to only ever allow events that | 327 | * field to zeroes, and for us to only ever allow events that |
302 | * have a cache selector of zero. | 328 | * have a cache selector of zero. The bank selector (bit 3) is |
329 | * irrelevant, as long as the rest of the value is 0. | ||
303 | */ | 330 | */ |
304 | if (cache) | 331 | if (cache & 0x7) |
305 | return -1; | 332 | return -1; |
306 | 333 | ||
307 | } else if (event & EVENT_IS_L1) { | 334 | } else if (event & EVENT_IS_L1) { |
@@ -342,6 +369,15 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long | |||
342 | /* EBB events must specify the PMC */ | 369 | /* EBB events must specify the PMC */ |
343 | return -1; | 370 | return -1; |
344 | 371 | ||
372 | if (event & EVENT_WANTS_BHRB) { | ||
373 | if (!ebb) | ||
374 | /* Only EBB events can request BHRB */ | ||
375 | return -1; | ||
376 | |||
377 | mask |= CNST_IFM_MASK; | ||
378 | value |= CNST_IFM_VAL(event >> EVENT_IFM_SHIFT); | ||
379 | } | ||
380 | |||
345 | /* | 381 | /* |
346 | * All events must agree on EBB, either all request it or none. | 382 | * All events must agree on EBB, either all request it or none. |
347 | * EBB events are pinned & exclusive, so this should never actually | 383 | * EBB events are pinned & exclusive, so this should never actually |
@@ -431,6 +467,11 @@ static int power8_compute_mmcr(u64 event[], int n_ev, | |||
431 | mmcra |= val << MMCRA_THR_CMP_SHIFT; | 467 | mmcra |= val << MMCRA_THR_CMP_SHIFT; |
432 | } | 468 | } |
433 | 469 | ||
470 | if (event[i] & EVENT_WANTS_BHRB) { | ||
471 | val = (event[i] >> EVENT_IFM_SHIFT) & EVENT_IFM_MASK; | ||
472 | mmcra |= val << MMCRA_IFM_SHIFT; | ||
473 | } | ||
474 | |||
434 | hwc[i] = pmc - 1; | 475 | hwc[i] = pmc - 1; |
435 | } | 476 | } |
436 | 477 | ||
@@ -774,6 +815,9 @@ static int __init init_power8_pmu(void) | |||
774 | /* Tell userspace that EBB is supported */ | 815 | /* Tell userspace that EBB is supported */ |
775 | cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB; | 816 | cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB; |
776 | 817 | ||
818 | if (cpu_has_feature(CPU_FTR_PMAO_BUG)) | ||
819 | pr_info("PMAO restore workaround active.\n"); | ||
820 | |||
777 | return 0; | 821 | return 0; |
778 | } | 822 | } |
779 | early_initcall(init_power8_pmu); | 823 | early_initcall(init_power8_pmu); |
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile index 5125caeb40f4..f324ea099503 100644 --- a/arch/powerpc/platforms/powernv/Makefile +++ b/arch/powerpc/platforms/powernv/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o | 1 | obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o opal-async.o |
2 | obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o | 2 | obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o |
3 | obj-y += rng.o opal-elog.o opal-dump.o | 3 | obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o |
4 | 4 | ||
5 | obj-$(CONFIG_SMP) += smp.o | 5 | obj-$(CONFIG_SMP) += smp.o |
6 | obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o | 6 | obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o |
diff --git a/arch/powerpc/platforms/powernv/opal-async.c b/arch/powerpc/platforms/powernv/opal-async.c new file mode 100644 index 000000000000..cd0c1354d404 --- /dev/null +++ b/arch/powerpc/platforms/powernv/opal-async.c | |||
@@ -0,0 +1,203 @@ | |||
1 | /* | ||
2 | * PowerNV OPAL asynchronous completion interfaces | ||
3 | * | ||
4 | * Copyright 2013 IBM Corp. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #undef DEBUG | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/semaphore.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/wait.h> | ||
21 | #include <linux/gfp.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <asm/opal.h> | ||
24 | |||
25 | #define N_ASYNC_COMPLETIONS 64 | ||
26 | |||
27 | static DECLARE_BITMAP(opal_async_complete_map, N_ASYNC_COMPLETIONS) = {~0UL}; | ||
28 | static DECLARE_BITMAP(opal_async_token_map, N_ASYNC_COMPLETIONS); | ||
29 | static DECLARE_WAIT_QUEUE_HEAD(opal_async_wait); | ||
30 | static DEFINE_SPINLOCK(opal_async_comp_lock); | ||
31 | static struct semaphore opal_async_sem; | ||
32 | static struct opal_msg *opal_async_responses; | ||
33 | static unsigned int opal_max_async_tokens; | ||
34 | |||
35 | int __opal_async_get_token(void) | ||
36 | { | ||
37 | unsigned long flags; | ||
38 | int token; | ||
39 | |||
40 | spin_lock_irqsave(&opal_async_comp_lock, flags); | ||
41 | token = find_first_bit(opal_async_complete_map, opal_max_async_tokens); | ||
42 | if (token >= opal_max_async_tokens) { | ||
43 | token = -EBUSY; | ||
44 | goto out; | ||
45 | } | ||
46 | |||
47 | if (__test_and_set_bit(token, opal_async_token_map)) { | ||
48 | token = -EBUSY; | ||
49 | goto out; | ||
50 | } | ||
51 | |||
52 | __clear_bit(token, opal_async_complete_map); | ||
53 | |||
54 | out: | ||
55 | spin_unlock_irqrestore(&opal_async_comp_lock, flags); | ||
56 | return token; | ||
57 | } | ||
58 | |||
59 | int opal_async_get_token_interruptible(void) | ||
60 | { | ||
61 | int token; | ||
62 | |||
63 | /* Wait until a token is available */ | ||
64 | if (down_interruptible(&opal_async_sem)) | ||
65 | return -ERESTARTSYS; | ||
66 | |||
67 | token = __opal_async_get_token(); | ||
68 | if (token < 0) | ||
69 | up(&opal_async_sem); | ||
70 | |||
71 | return token; | ||
72 | } | ||
73 | |||
74 | int __opal_async_release_token(int token) | ||
75 | { | ||
76 | unsigned long flags; | ||
77 | |||
78 | if (token < 0 || token >= opal_max_async_tokens) { | ||
79 | pr_err("%s: Passed token is out of range, token %d\n", | ||
80 | __func__, token); | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | |||
84 | spin_lock_irqsave(&opal_async_comp_lock, flags); | ||
85 | __set_bit(token, opal_async_complete_map); | ||
86 | __clear_bit(token, opal_async_token_map); | ||
87 | spin_unlock_irqrestore(&opal_async_comp_lock, flags); | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | int opal_async_release_token(int token) | ||
93 | { | ||
94 | int ret; | ||
95 | |||
96 | ret = __opal_async_release_token(token); | ||
97 | if (ret) | ||
98 | return ret; | ||
99 | |||
100 | up(&opal_async_sem); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | int opal_async_wait_response(uint64_t token, struct opal_msg *msg) | ||
106 | { | ||
107 | if (token >= opal_max_async_tokens) { | ||
108 | pr_err("%s: Invalid token passed\n", __func__); | ||
109 | return -EINVAL; | ||
110 | } | ||
111 | |||
112 | if (!msg) { | ||
113 | pr_err("%s: Invalid message pointer passed\n", __func__); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | |||
117 | wait_event(opal_async_wait, test_bit(token, opal_async_complete_map)); | ||
118 | memcpy(msg, &opal_async_responses[token], sizeof(*msg)); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int opal_async_comp_event(struct notifier_block *nb, | ||
124 | unsigned long msg_type, void *msg) | ||
125 | { | ||
126 | struct opal_msg *comp_msg = msg; | ||
127 | unsigned long flags; | ||
128 | |||
129 | if (msg_type != OPAL_MSG_ASYNC_COMP) | ||
130 | return 0; | ||
131 | |||
132 | memcpy(&opal_async_responses[comp_msg->params[0]], comp_msg, | ||
133 | sizeof(*comp_msg)); | ||
134 | spin_lock_irqsave(&opal_async_comp_lock, flags); | ||
135 | __set_bit(comp_msg->params[0], opal_async_complete_map); | ||
136 | spin_unlock_irqrestore(&opal_async_comp_lock, flags); | ||
137 | |||
138 | wake_up(&opal_async_wait); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static struct notifier_block opal_async_comp_nb = { | ||
144 | .notifier_call = opal_async_comp_event, | ||
145 | .next = NULL, | ||
146 | .priority = 0, | ||
147 | }; | ||
148 | |||
149 | static int __init opal_async_comp_init(void) | ||
150 | { | ||
151 | struct device_node *opal_node; | ||
152 | const __be32 *async; | ||
153 | int err; | ||
154 | |||
155 | opal_node = of_find_node_by_path("/ibm,opal"); | ||
156 | if (!opal_node) { | ||
157 | pr_err("%s: Opal node not found\n", __func__); | ||
158 | err = -ENOENT; | ||
159 | goto out; | ||
160 | } | ||
161 | |||
162 | async = of_get_property(opal_node, "opal-msg-async-num", NULL); | ||
163 | if (!async) { | ||
164 | pr_err("%s: %s has no opal-msg-async-num\n", | ||
165 | __func__, opal_node->full_name); | ||
166 | err = -ENOENT; | ||
167 | goto out_opal_node; | ||
168 | } | ||
169 | |||
170 | opal_max_async_tokens = be32_to_cpup(async); | ||
171 | if (opal_max_async_tokens > N_ASYNC_COMPLETIONS) | ||
172 | opal_max_async_tokens = N_ASYNC_COMPLETIONS; | ||
173 | |||
174 | err = opal_message_notifier_register(OPAL_MSG_ASYNC_COMP, | ||
175 | &opal_async_comp_nb); | ||
176 | if (err) { | ||
177 | pr_err("%s: Can't register OPAL event notifier (%d)\n", | ||
178 | __func__, err); | ||
179 | goto out_opal_node; | ||
180 | } | ||
181 | |||
182 | opal_async_responses = kzalloc( | ||
183 | sizeof(*opal_async_responses) * opal_max_async_tokens, | ||
184 | GFP_KERNEL); | ||
185 | if (!opal_async_responses) { | ||
186 | pr_err("%s: Out of memory, failed to do asynchronous " | ||
187 | "completion init\n", __func__); | ||
188 | err = -ENOMEM; | ||
189 | goto out_opal_node; | ||
190 | } | ||
191 | |||
192 | /* Initialize to 1 less than the maximum tokens available, as we may | ||
193 | * require to pop one during emergency through synchronous call to | ||
194 | * __opal_async_get_token() | ||
195 | */ | ||
196 | sema_init(&opal_async_sem, opal_max_async_tokens - 1); | ||
197 | |||
198 | out_opal_node: | ||
199 | of_node_put(opal_node); | ||
200 | out: | ||
201 | return err; | ||
202 | } | ||
203 | subsys_initcall(opal_async_comp_init); | ||
diff --git a/arch/powerpc/platforms/powernv/opal-sensor.c b/arch/powerpc/platforms/powernv/opal-sensor.c new file mode 100644 index 000000000000..663cc9c65613 --- /dev/null +++ b/arch/powerpc/platforms/powernv/opal-sensor.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * PowerNV sensor code | ||
3 | * | ||
4 | * Copyright (C) 2013 IBM | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/delay.h> | ||
22 | #include <linux/mutex.h> | ||
23 | #include <asm/opal.h> | ||
24 | |||
25 | static DEFINE_MUTEX(opal_sensor_mutex); | ||
26 | |||
27 | /* | ||
28 | * This will return sensor information to driver based on the requested sensor | ||
29 | * handle. A handle is an opaque id for the powernv, read by the driver from the | ||
30 | * device tree.. | ||
31 | */ | ||
32 | int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data) | ||
33 | { | ||
34 | int ret, token; | ||
35 | struct opal_msg msg; | ||
36 | |||
37 | token = opal_async_get_token_interruptible(); | ||
38 | if (token < 0) { | ||
39 | pr_err("%s: Couldn't get the token, returning\n", __func__); | ||
40 | ret = token; | ||
41 | goto out; | ||
42 | } | ||
43 | |||
44 | mutex_lock(&opal_sensor_mutex); | ||
45 | ret = opal_sensor_read(sensor_hndl, token, sensor_data); | ||
46 | if (ret != OPAL_ASYNC_COMPLETION) | ||
47 | goto out_token; | ||
48 | |||
49 | ret = opal_async_wait_response(token, &msg); | ||
50 | if (ret) { | ||
51 | pr_err("%s: Failed to wait for the async response, %d\n", | ||
52 | __func__, ret); | ||
53 | goto out_token; | ||
54 | } | ||
55 | |||
56 | ret = msg.params[1]; | ||
57 | |||
58 | out_token: | ||
59 | mutex_unlock(&opal_sensor_mutex); | ||
60 | opal_async_release_token(token); | ||
61 | out: | ||
62 | return ret; | ||
63 | } | ||
64 | EXPORT_SYMBOL_GPL(opal_get_sensor_data); | ||
diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c b/arch/powerpc/platforms/powernv/opal-sysparam.c new file mode 100644 index 000000000000..0bd249a26f30 --- /dev/null +++ b/arch/powerpc/platforms/powernv/opal-sysparam.c | |||
@@ -0,0 +1,290 @@ | |||
1 | /* | ||
2 | * PowerNV system parameter code | ||
3 | * | ||
4 | * Copyright (C) 2013 IBM | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kobject.h> | ||
22 | #include <linux/mutex.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/of.h> | ||
25 | #include <linux/gfp.h> | ||
26 | #include <linux/stat.h> | ||
27 | #include <asm/opal.h> | ||
28 | |||
29 | #define MAX_PARAM_DATA_LEN 64 | ||
30 | |||
31 | static DEFINE_MUTEX(opal_sysparam_mutex); | ||
32 | static struct kobject *sysparam_kobj; | ||
33 | static void *param_data_buf; | ||
34 | |||
35 | struct param_attr { | ||
36 | struct list_head list; | ||
37 | u32 param_id; | ||
38 | u32 param_size; | ||
39 | struct kobj_attribute kobj_attr; | ||
40 | }; | ||
41 | |||
42 | static int opal_get_sys_param(u32 param_id, u32 length, void *buffer) | ||
43 | { | ||
44 | struct opal_msg msg; | ||
45 | int ret, token; | ||
46 | |||
47 | token = opal_async_get_token_interruptible(); | ||
48 | if (token < 0) { | ||
49 | if (token != -ERESTARTSYS) | ||
50 | pr_err("%s: Couldn't get the token, returning\n", | ||
51 | __func__); | ||
52 | ret = token; | ||
53 | goto out; | ||
54 | } | ||
55 | |||
56 | ret = opal_get_param(token, param_id, (u64)buffer, length); | ||
57 | if (ret != OPAL_ASYNC_COMPLETION) | ||
58 | goto out_token; | ||
59 | |||
60 | ret = opal_async_wait_response(token, &msg); | ||
61 | if (ret) { | ||
62 | pr_err("%s: Failed to wait for the async response, %d\n", | ||
63 | __func__, ret); | ||
64 | goto out_token; | ||
65 | } | ||
66 | |||
67 | ret = msg.params[1]; | ||
68 | |||
69 | out_token: | ||
70 | opal_async_release_token(token); | ||
71 | out: | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | static int opal_set_sys_param(u32 param_id, u32 length, void *buffer) | ||
76 | { | ||
77 | struct opal_msg msg; | ||
78 | int ret, token; | ||
79 | |||
80 | token = opal_async_get_token_interruptible(); | ||
81 | if (token < 0) { | ||
82 | if (token != -ERESTARTSYS) | ||
83 | pr_err("%s: Couldn't get the token, returning\n", | ||
84 | __func__); | ||
85 | ret = token; | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | ret = opal_set_param(token, param_id, (u64)buffer, length); | ||
90 | |||
91 | if (ret != OPAL_ASYNC_COMPLETION) | ||
92 | goto out_token; | ||
93 | |||
94 | ret = opal_async_wait_response(token, &msg); | ||
95 | if (ret) { | ||
96 | pr_err("%s: Failed to wait for the async response, %d\n", | ||
97 | __func__, ret); | ||
98 | goto out_token; | ||
99 | } | ||
100 | |||
101 | ret = msg.params[1]; | ||
102 | |||
103 | out_token: | ||
104 | opal_async_release_token(token); | ||
105 | out: | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | static ssize_t sys_param_show(struct kobject *kobj, | ||
110 | struct kobj_attribute *kobj_attr, char *buf) | ||
111 | { | ||
112 | struct param_attr *attr = container_of(kobj_attr, struct param_attr, | ||
113 | kobj_attr); | ||
114 | int ret; | ||
115 | |||
116 | mutex_lock(&opal_sysparam_mutex); | ||
117 | ret = opal_get_sys_param(attr->param_id, attr->param_size, | ||
118 | param_data_buf); | ||
119 | if (ret) | ||
120 | goto out; | ||
121 | |||
122 | memcpy(buf, param_data_buf, attr->param_size); | ||
123 | |||
124 | out: | ||
125 | mutex_unlock(&opal_sysparam_mutex); | ||
126 | return ret ? ret : attr->param_size; | ||
127 | } | ||
128 | |||
129 | static ssize_t sys_param_store(struct kobject *kobj, | ||
130 | struct kobj_attribute *kobj_attr, const char *buf, size_t count) | ||
131 | { | ||
132 | struct param_attr *attr = container_of(kobj_attr, struct param_attr, | ||
133 | kobj_attr); | ||
134 | int ret; | ||
135 | |||
136 | mutex_lock(&opal_sysparam_mutex); | ||
137 | memcpy(param_data_buf, buf, count); | ||
138 | ret = opal_set_sys_param(attr->param_id, attr->param_size, | ||
139 | param_data_buf); | ||
140 | mutex_unlock(&opal_sysparam_mutex); | ||
141 | return ret ? ret : count; | ||
142 | } | ||
143 | |||
144 | void __init opal_sys_param_init(void) | ||
145 | { | ||
146 | struct device_node *sysparam; | ||
147 | struct param_attr *attr; | ||
148 | u32 *id, *size; | ||
149 | int count, i; | ||
150 | u8 *perm; | ||
151 | |||
152 | if (!opal_kobj) { | ||
153 | pr_warn("SYSPARAM: opal kobject is not available\n"); | ||
154 | goto out; | ||
155 | } | ||
156 | |||
157 | sysparam_kobj = kobject_create_and_add("sysparams", opal_kobj); | ||
158 | if (!sysparam_kobj) { | ||
159 | pr_err("SYSPARAM: Failed to create sysparam kobject\n"); | ||
160 | goto out; | ||
161 | } | ||
162 | |||
163 | /* Allocate big enough buffer for any get/set transactions */ | ||
164 | param_data_buf = kzalloc(MAX_PARAM_DATA_LEN, GFP_KERNEL); | ||
165 | if (!param_data_buf) { | ||
166 | pr_err("SYSPARAM: Failed to allocate memory for param data " | ||
167 | "buf\n"); | ||
168 | goto out_kobj_put; | ||
169 | } | ||
170 | |||
171 | sysparam = of_find_node_by_path("/ibm,opal/sysparams"); | ||
172 | if (!sysparam) { | ||
173 | pr_err("SYSPARAM: Opal sysparam node not found\n"); | ||
174 | goto out_param_buf; | ||
175 | } | ||
176 | |||
177 | if (!of_device_is_compatible(sysparam, "ibm,opal-sysparams")) { | ||
178 | pr_err("SYSPARAM: Opal sysparam node not compatible\n"); | ||
179 | goto out_node_put; | ||
180 | } | ||
181 | |||
182 | /* Number of parameters exposed through DT */ | ||
183 | count = of_property_count_strings(sysparam, "param-name"); | ||
184 | if (count < 0) { | ||
185 | pr_err("SYSPARAM: No string found of property param-name in " | ||
186 | "the node %s\n", sysparam->name); | ||
187 | goto out_node_put; | ||
188 | } | ||
189 | |||
190 | id = kzalloc(sizeof(*id) * count, GFP_KERNEL); | ||
191 | if (!id) { | ||
192 | pr_err("SYSPARAM: Failed to allocate memory to read parameter " | ||
193 | "id\n"); | ||
194 | goto out_node_put; | ||
195 | } | ||
196 | |||
197 | size = kzalloc(sizeof(*size) * count, GFP_KERNEL); | ||
198 | if (!size) { | ||
199 | pr_err("SYSPARAM: Failed to allocate memory to read parameter " | ||
200 | "size\n"); | ||
201 | goto out_free_id; | ||
202 | } | ||
203 | |||
204 | perm = kzalloc(sizeof(*perm) * count, GFP_KERNEL); | ||
205 | if (!perm) { | ||
206 | pr_err("SYSPARAM: Failed to allocate memory to read supported " | ||
207 | "action on the parameter"); | ||
208 | goto out_free_size; | ||
209 | } | ||
210 | |||
211 | if (of_property_read_u32_array(sysparam, "param-id", id, count)) { | ||
212 | pr_err("SYSPARAM: Missing property param-id in the DT\n"); | ||
213 | goto out_free_perm; | ||
214 | } | ||
215 | |||
216 | if (of_property_read_u32_array(sysparam, "param-len", size, count)) { | ||
217 | pr_err("SYSPARAM: Missing propery param-len in the DT\n"); | ||
218 | goto out_free_perm; | ||
219 | } | ||
220 | |||
221 | |||
222 | if (of_property_read_u8_array(sysparam, "param-perm", perm, count)) { | ||
223 | pr_err("SYSPARAM: Missing propery param-perm in the DT\n"); | ||
224 | goto out_free_perm; | ||
225 | } | ||
226 | |||
227 | attr = kzalloc(sizeof(*attr) * count, GFP_KERNEL); | ||
228 | if (!attr) { | ||
229 | pr_err("SYSPARAM: Failed to allocate memory for parameter " | ||
230 | "attributes\n"); | ||
231 | goto out_free_perm; | ||
232 | } | ||
233 | |||
234 | /* For each of the parameters, populate the parameter attributes */ | ||
235 | for (i = 0; i < count; i++) { | ||
236 | sysfs_attr_init(&attr[i].kobj_attr.attr); | ||
237 | attr[i].param_id = id[i]; | ||
238 | attr[i].param_size = size[i]; | ||
239 | if (of_property_read_string_index(sysparam, "param-name", i, | ||
240 | &attr[i].kobj_attr.attr.name)) | ||
241 | continue; | ||
242 | |||
243 | /* If the parameter is read-only or read-write */ | ||
244 | switch (perm[i] & 3) { | ||
245 | case OPAL_SYSPARAM_READ: | ||
246 | attr[i].kobj_attr.attr.mode = S_IRUGO; | ||
247 | break; | ||
248 | case OPAL_SYSPARAM_WRITE: | ||
249 | attr[i].kobj_attr.attr.mode = S_IWUGO; | ||
250 | break; | ||
251 | case OPAL_SYSPARAM_RW: | ||
252 | attr[i].kobj_attr.attr.mode = S_IRUGO | S_IWUGO; | ||
253 | break; | ||
254 | default: | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | attr[i].kobj_attr.show = sys_param_show; | ||
259 | attr[i].kobj_attr.store = sys_param_store; | ||
260 | |||
261 | if (sysfs_create_file(sysparam_kobj, &attr[i].kobj_attr.attr)) { | ||
262 | pr_err("SYSPARAM: Failed to create sysfs file %s\n", | ||
263 | attr[i].kobj_attr.attr.name); | ||
264 | goto out_free_attr; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | kfree(perm); | ||
269 | kfree(size); | ||
270 | kfree(id); | ||
271 | of_node_put(sysparam); | ||
272 | return; | ||
273 | |||
274 | out_free_attr: | ||
275 | kfree(attr); | ||
276 | out_free_perm: | ||
277 | kfree(perm); | ||
278 | out_free_size: | ||
279 | kfree(size); | ||
280 | out_free_id: | ||
281 | kfree(id); | ||
282 | out_node_put: | ||
283 | of_node_put(sysparam); | ||
284 | out_param_buf: | ||
285 | kfree(param_data_buf); | ||
286 | out_kobj_put: | ||
287 | kobject_put(sysparam_kobj); | ||
288 | out: | ||
289 | return; | ||
290 | } | ||
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 47ec3f738062..75c89df8d71e 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S | |||
@@ -140,3 +140,6 @@ OPAL_CALL(opal_get_msg, OPAL_GET_MSG); | |||
140 | OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION); | 140 | OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION); |
141 | OPAL_CALL(opal_dump_resend_notification, OPAL_DUMP_RESEND); | 141 | OPAL_CALL(opal_dump_resend_notification, OPAL_DUMP_RESEND); |
142 | OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT); | 142 | OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT); |
143 | OPAL_CALL(opal_sensor_read, OPAL_SENSOR_READ); | ||
144 | OPAL_CALL(opal_get_param, OPAL_GET_PARAM); | ||
145 | OPAL_CALL(opal_set_param, OPAL_SET_PARAM); | ||
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 2e269c27dd23..e92f2f67640f 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -572,6 +572,8 @@ static int __init opal_init(void) | |||
572 | opal_flash_init(); | 572 | opal_flash_init(); |
573 | /* Setup platform dump extract interface */ | 573 | /* Setup platform dump extract interface */ |
574 | opal_platform_dump_init(); | 574 | opal_platform_dump_init(); |
575 | /* Setup system parameters interface */ | ||
576 | opal_sys_param_init(); | ||
575 | } | 577 | } |
576 | 578 | ||
577 | return 0; | 579 | return 0; |
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 80b1d57c306a..2cb8b776c84a 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
@@ -111,6 +111,18 @@ config CMM | |||
111 | will be reused for other LPARs. The interface allows firmware to | 111 | will be reused for other LPARs. The interface allows firmware to |
112 | balance memory across many LPARs. | 112 | balance memory across many LPARs. |
113 | 113 | ||
114 | config HV_PERF_CTRS | ||
115 | bool "Hypervisor supplied PMU events (24x7 & GPCI)" | ||
116 | default y | ||
117 | depends on PERF_EVENTS && PPC_PSERIES | ||
118 | help | ||
119 | Enable access to hypervisor supplied counters in perf. Currently, | ||
120 | this enables code that uses the hcall GetPerfCounterInfo and 24x7 | ||
121 | interfaces to retrieve counters. GPCI exists on Power 6 and later | ||
122 | systems. 24x7 is available on Power 8 systems. | ||
123 | |||
124 | If unsure, select Y. | ||
125 | |||
114 | config DTL | 126 | config DTL |
115 | bool "Dispatch Trace Log" | 127 | bool "Dispatch Trace Log" |
116 | depends on PPC_SPLPAR && DEBUG_FS | 128 | depends on PPC_SPLPAR && DEBUG_FS |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 5ce43d8dfa98..ad4cdcbc618b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -557,6 +557,14 @@ config SENSORS_IBMPEX | |||
557 | This driver can also be built as a module. If so, the module | 557 | This driver can also be built as a module. If so, the module |
558 | will be called ibmpex. | 558 | will be called ibmpex. |
559 | 559 | ||
560 | config SENSORS_IBMPOWERNV | ||
561 | tristate "IBM PowerNv Platform temperature/power/fan sensor" | ||
562 | depends on PPC_POWERNV | ||
563 | default y | ||
564 | help | ||
565 | If you say yes here you get support for the temperature/fan/power | ||
566 | sensors on your platform. | ||
567 | |||
560 | config SENSORS_IIO_HWMON | 568 | config SENSORS_IIO_HWMON |
561 | tristate "Hwmon driver that uses channels specified via iio maps" | 569 | tristate "Hwmon driver that uses channels specified via iio maps" |
562 | depends on IIO | 570 | depends on IIO |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index ec7cde06eb52..807e1721ed79 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -70,6 +70,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o | |||
70 | obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o | 70 | obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o |
71 | obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o | 71 | obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o |
72 | obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o | 72 | obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o |
73 | obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o | ||
73 | obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o | 74 | obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o |
74 | obj-$(CONFIG_SENSORS_INA209) += ina209.o | 75 | obj-$(CONFIG_SENSORS_INA209) += ina209.o |
75 | obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o | 76 | obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o |
diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c new file mode 100644 index 000000000000..b7b1297a9b02 --- /dev/null +++ b/drivers/hwmon/ibmpowernv.c | |||
@@ -0,0 +1,529 @@ | |||
1 | /* | ||
2 | * hwmon driver for temperature/power/fan on IBM PowerNV platform | ||
3 | * Copyright (C) 2013 IBM | ||
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 as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/hwmon.h> | ||
24 | #include <linux/hwmon-sysfs.h> | ||
25 | #include <linux/of.h> | ||
26 | #include <linux/slab.h> | ||
27 | |||
28 | #include <linux/jiffies.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <asm/opal.h> | ||
31 | #include <linux/err.h> | ||
32 | |||
33 | MODULE_DESCRIPTION("IBM PowerNV Platform power/temp/fan sensor hwmon module"); | ||
34 | MODULE_LICENSE("GPL"); | ||
35 | |||
36 | #define MAX_ATTR_LENGTH 32 | ||
37 | |||
38 | /* Device tree sensor name prefixes. The device tree has the names in the | ||
39 | * format "cooling-fan#2-faulted" where the "cooling-fan" is the sensor type, | ||
40 | * 2 is the sensor count, and "faulted" is the sensor data attribute type. | ||
41 | */ | ||
42 | #define DT_FAULT_ATTR_SUFFIX "faulted" | ||
43 | #define DT_DATA_ATTR_SUFFIX "data" | ||
44 | #define DT_THRESHOLD_ATTR_SUFFIX "thrs" | ||
45 | |||
46 | enum sensors { | ||
47 | FAN, | ||
48 | TEMPERATURE, | ||
49 | POWERSUPPLY, | ||
50 | POWER, | ||
51 | MAX_SENSOR_TYPE, | ||
52 | }; | ||
53 | |||
54 | enum attributes { | ||
55 | INPUT, | ||
56 | MINIMUM, | ||
57 | MAXIMUM, | ||
58 | FAULT, | ||
59 | MAX_ATTR_TYPES | ||
60 | }; | ||
61 | |||
62 | static struct sensor_name { | ||
63 | char *name; | ||
64 | char *compaible; | ||
65 | } sensor_names[] = { | ||
66 | {"fan-sensor", "ibm,opal-sensor-cooling-fan"}, | ||
67 | {"amb-temp-sensor", "ibm,opal-sensor-amb-temp"}, | ||
68 | {"power-sensor", "ibm,opal-sensor-power-supply"}, | ||
69 | {"power", "ibm,opal-sensor-power"} | ||
70 | }; | ||
71 | |||
72 | static const char * const attribute_type_table[] = { | ||
73 | "input", | ||
74 | "min", | ||
75 | "max", | ||
76 | "fault", | ||
77 | NULL | ||
78 | }; | ||
79 | |||
80 | struct pdev_entry { | ||
81 | struct list_head list; | ||
82 | struct platform_device *pdev; | ||
83 | enum sensors type; | ||
84 | }; | ||
85 | |||
86 | static LIST_HEAD(pdev_list); | ||
87 | |||
88 | /* The sensors are categorised on type. | ||
89 | * | ||
90 | * The sensors of same type are categorised under a common platform device. | ||
91 | * So, The pdev is shared by all sensors of same type. | ||
92 | * Ex : temp1_input, temp1_max, temp2_input,temp2_max all share same platform | ||
93 | * device. | ||
94 | * | ||
95 | * "sensor_data" is the Platform device specific data. | ||
96 | * There is one hwmon_device instance for all the sensors of same type. | ||
97 | * This also holds the list of all sensors with same type but different | ||
98 | * attribute and index. | ||
99 | */ | ||
100 | struct sensor_specific_data { | ||
101 | u32 sensor_id; /* The hex value as in the device tree */ | ||
102 | u32 sensor_index; /* The sensor instance index */ | ||
103 | struct sensor_device_attribute sd_attr; | ||
104 | enum attributes attr_type; | ||
105 | char attr_name[64]; | ||
106 | }; | ||
107 | |||
108 | struct sensor_data { | ||
109 | struct device *hwmon_dev; | ||
110 | struct list_head sensor_list; | ||
111 | struct device_attribute name_attr; | ||
112 | }; | ||
113 | |||
114 | struct sensor_entry { | ||
115 | struct list_head list; | ||
116 | struct sensor_specific_data *sensor_data; | ||
117 | }; | ||
118 | |||
119 | static struct platform_device *powernv_sensor_get_pdev(enum sensors type) | ||
120 | { | ||
121 | struct pdev_entry *p; | ||
122 | list_for_each_entry(p, &pdev_list, list) | ||
123 | if (p->type == type) | ||
124 | return p->pdev; | ||
125 | |||
126 | return NULL; | ||
127 | } | ||
128 | |||
129 | static struct sensor_specific_data *powernv_sensor_get_sensor_data( | ||
130 | struct sensor_data *pdata, | ||
131 | int index, enum attributes attr_type) | ||
132 | { | ||
133 | struct sensor_entry *p; | ||
134 | list_for_each_entry(p, &pdata->sensor_list, list) | ||
135 | if ((p->sensor_data->sensor_index == index) && | ||
136 | (attr_type == p->sensor_data->attr_type)) | ||
137 | return p->sensor_data; | ||
138 | |||
139 | return NULL; | ||
140 | } | ||
141 | |||
142 | static ssize_t show_name(struct device *dev, | ||
143 | struct device_attribute *devattr, char *buf) | ||
144 | { | ||
145 | struct platform_device *pdev = to_platform_device(dev); | ||
146 | |||
147 | return sprintf(buf, "%s\n", pdev->name); | ||
148 | } | ||
149 | |||
150 | /* Note: Data from the sensors for each sensor type needs to be converted to | ||
151 | * the dimension appropriate. | ||
152 | */ | ||
153 | static ssize_t show_sensor(struct device *dev, | ||
154 | struct device_attribute *devattr, char *buf) | ||
155 | { | ||
156 | struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(devattr); | ||
157 | struct platform_device *pdev = to_platform_device(dev); | ||
158 | struct sensor_data *pdata = platform_get_drvdata(pdev); | ||
159 | struct sensor_specific_data *tdata = NULL; | ||
160 | enum sensors sensor_type = pdev->id; | ||
161 | u32 x = -1; | ||
162 | int ret; | ||
163 | |||
164 | if (sd_attr && sd_attr->dev_attr.attr.name) { | ||
165 | char *pos = strchr(sd_attr->dev_attr.attr.name, '_'); | ||
166 | int i; | ||
167 | |||
168 | for (i = 0; i < MAX_ATTR_TYPES; i++) { | ||
169 | if (strcmp(pos+1, attribute_type_table[i]) == 0) { | ||
170 | tdata = powernv_sensor_get_sensor_data(pdata, | ||
171 | sd_attr->index, i); | ||
172 | break; | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | if (tdata) { | ||
178 | ret = opal_get_sensor_data(tdata->sensor_id, &x); | ||
179 | if (ret) | ||
180 | x = -1; | ||
181 | } | ||
182 | |||
183 | if (sensor_type == TEMPERATURE && x > 0) { | ||
184 | /* Temperature comes in Degrees and convert it to | ||
185 | * milli-degrees. | ||
186 | */ | ||
187 | x = x*1000; | ||
188 | } else if (sensor_type == POWER && x > 0) { | ||
189 | /* Power value comes in watts, convert to micro-watts */ | ||
190 | x = x * 1000000; | ||
191 | } | ||
192 | |||
193 | return sprintf(buf, "%d\n", x); | ||
194 | } | ||
195 | |||
196 | static u32 get_sensor_index_from_name(const char *name) | ||
197 | { | ||
198 | char *hash_position = strchr(name, '#'); | ||
199 | u32 index = 0, copy_length; | ||
200 | char newbuf[8]; | ||
201 | |||
202 | if (hash_position) { | ||
203 | copy_length = strchr(hash_position, '-') - hash_position - 1; | ||
204 | if (copy_length < sizeof(newbuf)) { | ||
205 | strncpy(newbuf, hash_position + 1, copy_length); | ||
206 | sscanf(newbuf, "%d", &index); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | return index; | ||
211 | } | ||
212 | |||
213 | static inline void get_sensor_suffix_from_name(const char *name, char *suffix) | ||
214 | { | ||
215 | char *dash_position = strrchr(name, '-'); | ||
216 | if (dash_position) | ||
217 | strncpy(suffix, dash_position+1, MAX_ATTR_LENGTH); | ||
218 | else | ||
219 | strcpy(suffix,""); | ||
220 | } | ||
221 | |||
222 | static int get_sensor_attr_properties(const char *sensor_name, | ||
223 | enum sensors sensor_type, enum attributes *attr_type, | ||
224 | u32 *sensor_index) | ||
225 | { | ||
226 | char suffix[MAX_ATTR_LENGTH]; | ||
227 | |||
228 | *attr_type = MAX_ATTR_TYPES; | ||
229 | *sensor_index = get_sensor_index_from_name(sensor_name); | ||
230 | if (*sensor_index == 0) | ||
231 | return -EINVAL; | ||
232 | |||
233 | get_sensor_suffix_from_name(sensor_name, suffix); | ||
234 | if (strcmp(suffix, "") == 0) | ||
235 | return -EINVAL; | ||
236 | |||
237 | if (strcmp(suffix, DT_FAULT_ATTR_SUFFIX) == 0) | ||
238 | *attr_type = FAULT; | ||
239 | else if (strcmp(suffix, DT_DATA_ATTR_SUFFIX) == 0) | ||
240 | *attr_type = INPUT; | ||
241 | else if ((sensor_type == TEMPERATURE) && | ||
242 | (strcmp(suffix, DT_THRESHOLD_ATTR_SUFFIX) == 0)) | ||
243 | *attr_type = MAXIMUM; | ||
244 | else if ((sensor_type == FAN) && | ||
245 | (strcmp(suffix, DT_THRESHOLD_ATTR_SUFFIX) == 0)) | ||
246 | *attr_type = MINIMUM; | ||
247 | else | ||
248 | return -ENOENT; | ||
249 | |||
250 | if (((sensor_type == FAN) && ((*attr_type == INPUT) || | ||
251 | (*attr_type == MINIMUM))) | ||
252 | || ((sensor_type == TEMPERATURE) && ((*attr_type == INPUT) || | ||
253 | (*attr_type == MAXIMUM))) | ||
254 | || ((sensor_type == POWER) && ((*attr_type == INPUT)))) | ||
255 | return 0; | ||
256 | |||
257 | return -ENOENT; | ||
258 | } | ||
259 | |||
260 | static int create_sensor_attr(struct sensor_specific_data *tdata, | ||
261 | struct device *dev, enum sensors sensor_type, | ||
262 | enum attributes attr_type) | ||
263 | { | ||
264 | int err = 0; | ||
265 | char temp_file_prefix[50]; | ||
266 | static const char *const file_name_format = "%s%d_%s"; | ||
267 | |||
268 | tdata->attr_type = attr_type; | ||
269 | |||
270 | if (sensor_type == FAN) | ||
271 | strcpy(temp_file_prefix, "fan"); | ||
272 | else if (sensor_type == TEMPERATURE) | ||
273 | strcpy(temp_file_prefix, "temp"); | ||
274 | else if (sensor_type == POWERSUPPLY) | ||
275 | strcpy(temp_file_prefix, "powersupply"); | ||
276 | else if (sensor_type == POWER) | ||
277 | strcpy(temp_file_prefix, "power"); | ||
278 | |||
279 | snprintf(tdata->attr_name, sizeof(tdata->attr_name), file_name_format, | ||
280 | temp_file_prefix, tdata->sensor_index, | ||
281 | attribute_type_table[tdata->attr_type]); | ||
282 | |||
283 | sysfs_attr_init(&tdata->sd_attr.dev_attr.attr); | ||
284 | tdata->sd_attr.dev_attr.attr.name = tdata->attr_name; | ||
285 | tdata->sd_attr.dev_attr.attr.mode = S_IRUGO; | ||
286 | tdata->sd_attr.dev_attr.show = show_sensor; | ||
287 | |||
288 | tdata->sd_attr.index = tdata->sensor_index; | ||
289 | err = device_create_file(dev, &tdata->sd_attr.dev_attr); | ||
290 | |||
291 | return err; | ||
292 | } | ||
293 | |||
294 | static int create_name_attr(struct sensor_data *pdata, | ||
295 | struct device *dev) | ||
296 | { | ||
297 | sysfs_attr_init(&pdata->name_attr.attr); | ||
298 | pdata->name_attr.attr.name = "name"; | ||
299 | pdata->name_attr.attr.mode = S_IRUGO; | ||
300 | pdata->name_attr.show = show_name; | ||
301 | return device_create_file(dev, &pdata->name_attr); | ||
302 | } | ||
303 | |||
304 | static int create_platform_device(enum sensors sensor_type, | ||
305 | struct platform_device **pdev) | ||
306 | { | ||
307 | struct pdev_entry *pdev_entry = NULL; | ||
308 | int err; | ||
309 | |||
310 | *pdev = platform_device_alloc(sensor_names[sensor_type].name, | ||
311 | sensor_type); | ||
312 | if (!*pdev) { | ||
313 | pr_err("Device allocation failed\n"); | ||
314 | err = -ENOMEM; | ||
315 | goto exit; | ||
316 | } | ||
317 | |||
318 | pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL); | ||
319 | if (!pdev_entry) { | ||
320 | pr_err("Device allocation failed\n"); | ||
321 | err = -ENOMEM; | ||
322 | goto exit_device_put; | ||
323 | } | ||
324 | |||
325 | err = platform_device_add(*pdev); | ||
326 | if (err) { | ||
327 | pr_err("Device addition failed (%d)\n", err); | ||
328 | goto exit_device_free; | ||
329 | } | ||
330 | |||
331 | pdev_entry->pdev = *pdev; | ||
332 | pdev_entry->type = (*pdev)->id; | ||
333 | |||
334 | list_add_tail(&pdev_entry->list, &pdev_list); | ||
335 | |||
336 | return 0; | ||
337 | exit_device_free: | ||
338 | kfree(pdev_entry); | ||
339 | exit_device_put: | ||
340 | platform_device_put(*pdev); | ||
341 | exit: | ||
342 | return err; | ||
343 | } | ||
344 | |||
345 | static int create_sensor_data(struct platform_device *pdev) | ||
346 | { | ||
347 | struct sensor_data *pdata = NULL; | ||
348 | int err = 0; | ||
349 | |||
350 | pdata = kzalloc(sizeof(struct sensor_data), GFP_KERNEL); | ||
351 | if (!pdata) { | ||
352 | err = -ENOMEM; | ||
353 | goto exit; | ||
354 | } | ||
355 | |||
356 | err = create_name_attr(pdata, &pdev->dev); | ||
357 | if (err) | ||
358 | goto exit_free; | ||
359 | |||
360 | pdata->hwmon_dev = hwmon_device_register(&pdev->dev); | ||
361 | if (IS_ERR(pdata->hwmon_dev)) { | ||
362 | err = PTR_ERR(pdata->hwmon_dev); | ||
363 | dev_err(&pdev->dev, "Class registration failed (%d)\n", | ||
364 | err); | ||
365 | goto exit_name; | ||
366 | } | ||
367 | |||
368 | INIT_LIST_HEAD(&pdata->sensor_list); | ||
369 | platform_set_drvdata(pdev, pdata); | ||
370 | |||
371 | return 0; | ||
372 | |||
373 | exit_name: | ||
374 | device_remove_file(&pdev->dev, &pdata->name_attr); | ||
375 | exit_free: | ||
376 | kfree(pdata); | ||
377 | exit: | ||
378 | return err; | ||
379 | } | ||
380 | |||
381 | static void delete_sensor_attr(struct sensor_data *pdata) | ||
382 | { | ||
383 | struct sensor_entry *s, *l; | ||
384 | |||
385 | list_for_each_entry_safe(s, l, &pdata->sensor_list, list) { | ||
386 | struct sensor_specific_data *tdata = s->sensor_data; | ||
387 | kfree(tdata); | ||
388 | list_del(&s->list); | ||
389 | kfree(s); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | static int powernv_sensor_init(u32 sensor_id, const struct device_node *np, | ||
394 | enum sensors sensor_type, enum attributes attr_type, | ||
395 | u32 sensor_index) | ||
396 | { | ||
397 | struct platform_device *pdev = powernv_sensor_get_pdev(sensor_type); | ||
398 | struct sensor_specific_data *tdata; | ||
399 | struct sensor_entry *sensor_entry; | ||
400 | struct sensor_data *pdata; | ||
401 | int err = 0; | ||
402 | |||
403 | if (!pdev) { | ||
404 | err = create_platform_device(sensor_type, &pdev); | ||
405 | if (err) | ||
406 | goto exit; | ||
407 | |||
408 | err = create_sensor_data(pdev); | ||
409 | if (err) | ||
410 | goto exit; | ||
411 | } | ||
412 | |||
413 | pdata = platform_get_drvdata(pdev); | ||
414 | if (!pdata) { | ||
415 | err = -ENOMEM; | ||
416 | goto exit; | ||
417 | } | ||
418 | |||
419 | tdata = kzalloc(sizeof(struct sensor_specific_data), GFP_KERNEL); | ||
420 | if (!tdata) { | ||
421 | err = -ENOMEM; | ||
422 | goto exit; | ||
423 | } | ||
424 | |||
425 | tdata->sensor_id = sensor_id; | ||
426 | tdata->sensor_index = sensor_index; | ||
427 | |||
428 | err = create_sensor_attr(tdata, &pdev->dev, sensor_type, attr_type); | ||
429 | if (err) | ||
430 | goto exit_free; | ||
431 | |||
432 | sensor_entry = kzalloc(sizeof(struct sensor_entry), GFP_KERNEL); | ||
433 | if (!sensor_entry) { | ||
434 | err = -ENOMEM; | ||
435 | goto exit_attr; | ||
436 | } | ||
437 | |||
438 | sensor_entry->sensor_data = tdata; | ||
439 | |||
440 | list_add_tail(&sensor_entry->list, &pdata->sensor_list); | ||
441 | |||
442 | return 0; | ||
443 | exit_attr: | ||
444 | device_remove_file(&pdev->dev, &tdata->sd_attr.dev_attr); | ||
445 | exit_free: | ||
446 | kfree(tdata); | ||
447 | exit: | ||
448 | return err; | ||
449 | } | ||
450 | |||
451 | static void delete_unregister_sensors(void) | ||
452 | { | ||
453 | struct pdev_entry *p, *n; | ||
454 | |||
455 | list_for_each_entry_safe(p, n, &pdev_list, list) { | ||
456 | struct sensor_data *pdata = platform_get_drvdata(p->pdev); | ||
457 | if (pdata) { | ||
458 | delete_sensor_attr(pdata); | ||
459 | |||
460 | hwmon_device_unregister(pdata->hwmon_dev); | ||
461 | kfree(pdata); | ||
462 | } | ||
463 | platform_device_unregister(p->pdev); | ||
464 | list_del(&p->list); | ||
465 | kfree(p); | ||
466 | } | ||
467 | } | ||
468 | |||
469 | static int __init powernv_hwmon_init(void) | ||
470 | { | ||
471 | struct device_node *opal, *np = NULL; | ||
472 | enum attributes attr_type; | ||
473 | enum sensors type; | ||
474 | const u32 *sensor_id; | ||
475 | u32 sensor_index; | ||
476 | int err; | ||
477 | |||
478 | opal = of_find_node_by_path("/ibm,opal/sensors"); | ||
479 | if (!opal) { | ||
480 | pr_err("%s: Opal 'sensors' node not found\n", __func__); | ||
481 | return -ENXIO; | ||
482 | } | ||
483 | |||
484 | for_each_child_of_node(opal, np) { | ||
485 | if (np->name == NULL) | ||
486 | continue; | ||
487 | |||
488 | for (type = 0; type < MAX_SENSOR_TYPE; type++) | ||
489 | if (of_device_is_compatible(np, | ||
490 | sensor_names[type].compaible)) | ||
491 | break; | ||
492 | |||
493 | if (type == MAX_SENSOR_TYPE) | ||
494 | continue; | ||
495 | |||
496 | if (get_sensor_attr_properties(np->name, type, &attr_type, | ||
497 | &sensor_index)) | ||
498 | continue; | ||
499 | |||
500 | sensor_id = of_get_property(np, "sensor-id", NULL); | ||
501 | if (!sensor_id) { | ||
502 | pr_info("%s: %s doesn't have sensor-id\n", __func__, | ||
503 | np->name); | ||
504 | continue; | ||
505 | } | ||
506 | |||
507 | err = powernv_sensor_init(*sensor_id, np, type, attr_type, | ||
508 | sensor_index); | ||
509 | if (err) { | ||
510 | of_node_put(opal); | ||
511 | goto exit; | ||
512 | } | ||
513 | } | ||
514 | of_node_put(opal); | ||
515 | |||
516 | return 0; | ||
517 | exit: | ||
518 | delete_unregister_sensors(); | ||
519 | return err; | ||
520 | |||
521 | } | ||
522 | |||
523 | static void powernv_hwmon_exit(void) | ||
524 | { | ||
525 | delete_unregister_sensors(); | ||
526 | } | ||
527 | |||
528 | module_init(powernv_hwmon_init); | ||
529 | module_exit(powernv_hwmon_exit); | ||
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 6b579387c67a..aa0406895b53 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
@@ -70,8 +70,11 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj, | |||
70 | if (grp->bin_attrs) { | 70 | if (grp->bin_attrs) { |
71 | for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) { | 71 | for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) { |
72 | if (update) | 72 | if (update) |
73 | sysfs_remove_bin_file(kobj, *bin_attr); | 73 | kernfs_remove_by_name(parent, |
74 | error = sysfs_create_bin_file(kobj, *bin_attr); | 74 | (*bin_attr)->attr.name); |
75 | error = sysfs_add_file_mode_ns(parent, | ||
76 | &(*bin_attr)->attr, true, | ||
77 | (*bin_attr)->attr.mode, NULL); | ||
75 | if (error) | 78 | if (error) |
76 | break; | 79 | break; |
77 | } | 80 | } |