1 /*
2 * RISC-V PMU file.
3 *
4 * Copyright (c) 2021 Western Digital Corporation or its affiliates.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "qemu/osdep.h"
20 #include "qemu/log.h"
21 #include "qemu/error-report.h"
22 #include "cpu.h"
23 #include "pmu.h"
24 #include "sysemu/cpu-timers.h"
25 #include "sysemu/device_tree.h"
26
27 #define RISCV_TIMEBASE_FREQ 1000000000 /* 1Ghz */
28
29 /*
30 * To keep it simple, any event can be mapped to any programmable counters in
31 * QEMU. The generic cycle & instruction count events can also be monitored
32 * using programmable counters. In that case, mcycle & minstret must continue
33 * to provide the correct value as well. Heterogeneous PMU per hart is not
34 * supported yet. Thus, number of counters are same across all harts.
35 */
riscv_pmu_generate_fdt_node(void * fdt,uint32_t cmask,char * pmu_name)36 void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name)
37 {
38 uint32_t fdt_event_ctr_map[15] = {};
39
40 /*
41 * The event encoding is specified in the SBI specification
42 * Event idx is a 20bits wide number encoded as follows:
43 * event_idx[19:16] = type
44 * event_idx[15:0] = code
45 * The code field in cache events are encoded as follows:
46 * event_idx.code[15:3] = cache_id
47 * event_idx.code[2:1] = op_id
48 * event_idx.code[0:0] = result_id
49 */
50
51 /* SBI_PMU_HW_CPU_CYCLES: 0x01 : type(0x00) */
52 fdt_event_ctr_map[0] = cpu_to_be32(0x00000001);
53 fdt_event_ctr_map[1] = cpu_to_be32(0x00000001);
54 fdt_event_ctr_map[2] = cpu_to_be32(cmask | 1 << 0);
55
56 /* SBI_PMU_HW_INSTRUCTIONS: 0x02 : type(0x00) */
57 fdt_event_ctr_map[3] = cpu_to_be32(0x00000002);
58 fdt_event_ctr_map[4] = cpu_to_be32(0x00000002);
59 fdt_event_ctr_map[5] = cpu_to_be32(cmask | 1 << 2);
60
61 /* SBI_PMU_HW_CACHE_DTLB : 0x03 READ : 0x00 MISS : 0x00 type(0x01) */
62 fdt_event_ctr_map[6] = cpu_to_be32(0x00010019);
63 fdt_event_ctr_map[7] = cpu_to_be32(0x00010019);
64 fdt_event_ctr_map[8] = cpu_to_be32(cmask);
65
66 /* SBI_PMU_HW_CACHE_DTLB : 0x03 WRITE : 0x01 MISS : 0x00 type(0x01) */
67 fdt_event_ctr_map[9] = cpu_to_be32(0x0001001B);
68 fdt_event_ctr_map[10] = cpu_to_be32(0x0001001B);
69 fdt_event_ctr_map[11] = cpu_to_be32(cmask);
70
71 /* SBI_PMU_HW_CACHE_ITLB : 0x04 READ : 0x00 MISS : 0x00 type(0x01) */
72 fdt_event_ctr_map[12] = cpu_to_be32(0x00010021);
73 fdt_event_ctr_map[13] = cpu_to_be32(0x00010021);
74 fdt_event_ctr_map[14] = cpu_to_be32(cmask);
75
76 /* This a OpenSBI specific DT property documented in OpenSBI docs */
77 qemu_fdt_setprop(fdt, pmu_name, "riscv,event-to-mhpmcounters",
78 fdt_event_ctr_map, sizeof(fdt_event_ctr_map));
79 }
80
riscv_pmu_counter_valid(RISCVCPU * cpu,uint32_t ctr_idx)81 static bool riscv_pmu_counter_valid(RISCVCPU *cpu, uint32_t ctr_idx)
82 {
83 if (ctr_idx < 3 || ctr_idx >= RV_MAX_MHPMCOUNTERS ||
84 !(cpu->pmu_avail_ctrs & BIT(ctr_idx))) {
85 return false;
86 } else {
87 return true;
88 }
89 }
90
riscv_pmu_counter_enabled(RISCVCPU * cpu,uint32_t ctr_idx)91 static bool riscv_pmu_counter_enabled(RISCVCPU *cpu, uint32_t ctr_idx)
92 {
93 CPURISCVState *env = &cpu->env;
94
95 if (riscv_pmu_counter_valid(cpu, ctr_idx) &&
96 !get_field(env->mcountinhibit, BIT(ctr_idx))) {
97 return true;
98 } else {
99 return false;
100 }
101 }
102
riscv_pmu_incr_ctr_rv32(RISCVCPU * cpu,uint32_t ctr_idx)103 static int riscv_pmu_incr_ctr_rv32(RISCVCPU *cpu, uint32_t ctr_idx)
104 {
105 CPURISCVState *env = &cpu->env;
106 target_ulong max_val = UINT32_MAX;
107 PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
108 bool virt_on = env->virt_enabled;
109
110 /* Privilege mode filtering */
111 if ((env->priv == PRV_M &&
112 (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_MINH)) ||
113 (env->priv == PRV_S && virt_on &&
114 (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_VSINH)) ||
115 (env->priv == PRV_U && virt_on &&
116 (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_VUINH)) ||
117 (env->priv == PRV_S && !virt_on &&
118 (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_SINH)) ||
119 (env->priv == PRV_U && !virt_on &&
120 (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_UINH))) {
121 return 0;
122 }
123
124 /* Handle the overflow scenario */
125 if (counter->mhpmcounter_val == max_val) {
126 if (counter->mhpmcounterh_val == max_val) {
127 counter->mhpmcounter_val = 0;
128 counter->mhpmcounterh_val = 0;
129 /* Generate interrupt only if OF bit is clear */
130 if (!(env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_OF)) {
131 env->mhpmeventh_val[ctr_idx] |= MHPMEVENTH_BIT_OF;
132 riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1));
133 }
134 } else {
135 counter->mhpmcounterh_val++;
136 }
137 } else {
138 counter->mhpmcounter_val++;
139 }
140
141 return 0;
142 }
143
riscv_pmu_incr_ctr_rv64(RISCVCPU * cpu,uint32_t ctr_idx)144 static int riscv_pmu_incr_ctr_rv64(RISCVCPU *cpu, uint32_t ctr_idx)
145 {
146 CPURISCVState *env = &cpu->env;
147 PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
148 uint64_t max_val = UINT64_MAX;
149 bool virt_on = env->virt_enabled;
150
151 /* Privilege mode filtering */
152 if ((env->priv == PRV_M &&
153 (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_MINH)) ||
154 (env->priv == PRV_S && virt_on &&
155 (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_VSINH)) ||
156 (env->priv == PRV_U && virt_on &&
157 (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_VUINH)) ||
158 (env->priv == PRV_S && !virt_on &&
159 (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_SINH)) ||
160 (env->priv == PRV_U && !virt_on &&
161 (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_UINH))) {
162 return 0;
163 }
164
165 /* Handle the overflow scenario */
166 if (counter->mhpmcounter_val == max_val) {
167 counter->mhpmcounter_val = 0;
168 /* Generate interrupt only if OF bit is clear */
169 if (!(env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_OF)) {
170 env->mhpmevent_val[ctr_idx] |= MHPMEVENT_BIT_OF;
171 riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1));
172 }
173 } else {
174 counter->mhpmcounter_val++;
175 }
176 return 0;
177 }
178
riscv_pmu_incr_ctr(RISCVCPU * cpu,enum riscv_pmu_event_idx event_idx)179 int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx)
180 {
181 uint32_t ctr_idx;
182 int ret;
183 CPURISCVState *env = &cpu->env;
184 gpointer value;
185
186 if (!cpu->cfg.pmu_mask) {
187 return 0;
188 }
189 value = g_hash_table_lookup(cpu->pmu_event_ctr_map,
190 GUINT_TO_POINTER(event_idx));
191 if (!value) {
192 return -1;
193 }
194
195 ctr_idx = GPOINTER_TO_UINT(value);
196 if (!riscv_pmu_counter_enabled(cpu, ctr_idx) ||
197 get_field(env->mcountinhibit, BIT(ctr_idx))) {
198 return -1;
199 }
200
201 if (riscv_cpu_mxl(env) == MXL_RV32) {
202 ret = riscv_pmu_incr_ctr_rv32(cpu, ctr_idx);
203 } else {
204 ret = riscv_pmu_incr_ctr_rv64(cpu, ctr_idx);
205 }
206
207 return ret;
208 }
209
riscv_pmu_ctr_monitor_instructions(CPURISCVState * env,uint32_t target_ctr)210 bool riscv_pmu_ctr_monitor_instructions(CPURISCVState *env,
211 uint32_t target_ctr)
212 {
213 RISCVCPU *cpu;
214 uint32_t event_idx;
215 uint32_t ctr_idx;
216
217 /* Fixed instret counter */
218 if (target_ctr == 2) {
219 return true;
220 }
221
222 cpu = env_archcpu(env);
223 if (!cpu->pmu_event_ctr_map) {
224 return false;
225 }
226
227 event_idx = RISCV_PMU_EVENT_HW_INSTRUCTIONS;
228 ctr_idx = GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_map,
229 GUINT_TO_POINTER(event_idx)));
230 if (!ctr_idx) {
231 return false;
232 }
233
234 return target_ctr == ctr_idx ? true : false;
235 }
236
riscv_pmu_ctr_monitor_cycles(CPURISCVState * env,uint32_t target_ctr)237 bool riscv_pmu_ctr_monitor_cycles(CPURISCVState *env, uint32_t target_ctr)
238 {
239 RISCVCPU *cpu;
240 uint32_t event_idx;
241 uint32_t ctr_idx;
242
243 /* Fixed mcycle counter */
244 if (target_ctr == 0) {
245 return true;
246 }
247
248 cpu = env_archcpu(env);
249 if (!cpu->pmu_event_ctr_map) {
250 return false;
251 }
252
253 event_idx = RISCV_PMU_EVENT_HW_CPU_CYCLES;
254 ctr_idx = GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_map,
255 GUINT_TO_POINTER(event_idx)));
256
257 /* Counter zero is not used for event_ctr_map */
258 if (!ctr_idx) {
259 return false;
260 }
261
262 return (target_ctr == ctr_idx) ? true : false;
263 }
264
pmu_remove_event_map(gpointer key,gpointer value,gpointer udata)265 static gboolean pmu_remove_event_map(gpointer key, gpointer value,
266 gpointer udata)
267 {
268 return (GPOINTER_TO_UINT(value) == GPOINTER_TO_UINT(udata)) ? true : false;
269 }
270
pmu_icount_ticks_to_ns(int64_t value)271 static int64_t pmu_icount_ticks_to_ns(int64_t value)
272 {
273 int64_t ret = 0;
274
275 if (icount_enabled()) {
276 ret = icount_to_ns(value);
277 } else {
278 ret = (NANOSECONDS_PER_SECOND / RISCV_TIMEBASE_FREQ) * value;
279 }
280
281 return ret;
282 }
283
riscv_pmu_update_event_map(CPURISCVState * env,uint64_t value,uint32_t ctr_idx)284 int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value,
285 uint32_t ctr_idx)
286 {
287 uint32_t event_idx;
288 RISCVCPU *cpu = env_archcpu(env);
289
290 if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->pmu_event_ctr_map) {
291 return -1;
292 }
293
294 /*
295 * Expected mhpmevent value is zero for reset case. Remove the current
296 * mapping.
297 */
298 if (!value) {
299 g_hash_table_foreach_remove(cpu->pmu_event_ctr_map,
300 pmu_remove_event_map,
301 GUINT_TO_POINTER(ctr_idx));
302 return 0;
303 }
304
305 event_idx = value & MHPMEVENT_IDX_MASK;
306 if (g_hash_table_lookup(cpu->pmu_event_ctr_map,
307 GUINT_TO_POINTER(event_idx))) {
308 return 0;
309 }
310
311 switch (event_idx) {
312 case RISCV_PMU_EVENT_HW_CPU_CYCLES:
313 case RISCV_PMU_EVENT_HW_INSTRUCTIONS:
314 case RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS:
315 case RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS:
316 case RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS:
317 break;
318 default:
319 /* We don't support any raw events right now */
320 return -1;
321 }
322 g_hash_table_insert(cpu->pmu_event_ctr_map, GUINT_TO_POINTER(event_idx),
323 GUINT_TO_POINTER(ctr_idx));
324
325 return 0;
326 }
327
pmu_timer_trigger_irq(RISCVCPU * cpu,enum riscv_pmu_event_idx evt_idx)328 static void pmu_timer_trigger_irq(RISCVCPU *cpu,
329 enum riscv_pmu_event_idx evt_idx)
330 {
331 uint32_t ctr_idx;
332 CPURISCVState *env = &cpu->env;
333 PMUCTRState *counter;
334 target_ulong *mhpmevent_val;
335 uint64_t of_bit_mask;
336 int64_t irq_trigger_at;
337
338 if (evt_idx != RISCV_PMU_EVENT_HW_CPU_CYCLES &&
339 evt_idx != RISCV_PMU_EVENT_HW_INSTRUCTIONS) {
340 return;
341 }
342
343 ctr_idx = GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_map,
344 GUINT_TO_POINTER(evt_idx)));
345 if (!riscv_pmu_counter_enabled(cpu, ctr_idx)) {
346 return;
347 }
348
349 if (riscv_cpu_mxl(env) == MXL_RV32) {
350 mhpmevent_val = &env->mhpmeventh_val[ctr_idx];
351 of_bit_mask = MHPMEVENTH_BIT_OF;
352 } else {
353 mhpmevent_val = &env->mhpmevent_val[ctr_idx];
354 of_bit_mask = MHPMEVENT_BIT_OF;
355 }
356
357 counter = &env->pmu_ctrs[ctr_idx];
358 if (counter->irq_overflow_left > 0) {
359 irq_trigger_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
360 counter->irq_overflow_left;
361 timer_mod_anticipate_ns(cpu->pmu_timer, irq_trigger_at);
362 counter->irq_overflow_left = 0;
363 return;
364 }
365
366 if (cpu->pmu_avail_ctrs & BIT(ctr_idx)) {
367 /* Generate interrupt only if OF bit is clear */
368 if (!(*mhpmevent_val & of_bit_mask)) {
369 *mhpmevent_val |= of_bit_mask;
370 riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1));
371 }
372 }
373 }
374
375 /* Timer callback for instret and cycle counter overflow */
riscv_pmu_timer_cb(void * priv)376 void riscv_pmu_timer_cb(void *priv)
377 {
378 RISCVCPU *cpu = priv;
379
380 /* Timer event was triggered only for these events */
381 pmu_timer_trigger_irq(cpu, RISCV_PMU_EVENT_HW_CPU_CYCLES);
382 pmu_timer_trigger_irq(cpu, RISCV_PMU_EVENT_HW_INSTRUCTIONS);
383 }
384
riscv_pmu_setup_timer(CPURISCVState * env,uint64_t value,uint32_t ctr_idx)385 int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx)
386 {
387 uint64_t overflow_delta, overflow_at;
388 int64_t overflow_ns, overflow_left = 0;
389 RISCVCPU *cpu = env_archcpu(env);
390 PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
391
392 if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf) {
393 return -1;
394 }
395
396 if (value) {
397 overflow_delta = UINT64_MAX - value + 1;
398 } else {
399 overflow_delta = UINT64_MAX;
400 }
401
402 /*
403 * QEMU supports only int64_t timers while RISC-V counters are uint64_t.
404 * Compute the leftover and save it so that it can be reprogrammed again
405 * when timer expires.
406 */
407 if (overflow_delta > INT64_MAX) {
408 overflow_left = overflow_delta - INT64_MAX;
409 }
410
411 if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
412 riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
413 overflow_ns = pmu_icount_ticks_to_ns((int64_t)overflow_delta);
414 overflow_left = pmu_icount_ticks_to_ns(overflow_left) ;
415 } else {
416 return -1;
417 }
418 overflow_at = (uint64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
419 overflow_ns;
420
421 if (overflow_at > INT64_MAX) {
422 overflow_left += overflow_at - INT64_MAX;
423 counter->irq_overflow_left = overflow_left;
424 overflow_at = INT64_MAX;
425 }
426 timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
427
428 return 0;
429 }
430
431
riscv_pmu_init(RISCVCPU * cpu,Error ** errp)432 void riscv_pmu_init(RISCVCPU *cpu, Error **errp)
433 {
434 if (cpu->cfg.pmu_mask & (COUNTEREN_CY | COUNTEREN_TM | COUNTEREN_IR)) {
435 error_setg(errp, "\"pmu-mask\" contains invalid bits (0-2) set");
436 return;
437 }
438
439 if (ctpop32(cpu->cfg.pmu_mask) > (RV_MAX_MHPMCOUNTERS - 3)) {
440 error_setg(errp, "Number of counters exceeds maximum available");
441 return;
442 }
443
444 cpu->pmu_event_ctr_map = g_hash_table_new(g_direct_hash, g_direct_equal);
445 if (!cpu->pmu_event_ctr_map) {
446 error_setg(errp, "Unable to allocate PMU event hash table");
447 return;
448 }
449
450 cpu->pmu_avail_ctrs = cpu->cfg.pmu_mask;
451 }
452