target/riscv: vector_helper: Fixup local variables shadowing
[qemu/kevin.git] / target / riscv / pmu.c
blob36f6307d286b5b7272428cfbb75367e1b6fa6e3d
1 /*
2 * RISC-V PMU file.
4 * Copyright (c) 2021 Western Digital Corporation or its affiliates.
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.
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.
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/>.
19 #include "qemu/osdep.h"
20 #include "qemu/log.h"
21 #include "cpu.h"
22 #include "pmu.h"
23 #include "sysemu/cpu-timers.h"
24 #include "sysemu/device_tree.h"
26 #define RISCV_TIMEBASE_FREQ 1000000000 /* 1Ghz */
27 #define MAKE_32BIT_MASK(shift, length) \
28 (((uint32_t)(~0UL) >> (32 - (length))) << (shift))
31 * To keep it simple, any event can be mapped to any programmable counters in
32 * QEMU. The generic cycle & instruction count events can also be monitored
33 * using programmable counters. In that case, mcycle & minstret must continue
34 * to provide the correct value as well. Heterogeneous PMU per hart is not
35 * supported yet. Thus, number of counters are same across all harts.
37 void riscv_pmu_generate_fdt_node(void *fdt, int num_ctrs, char *pmu_name)
39 uint32_t fdt_event_ctr_map[15] = {};
40 uint32_t cmask;
42 /* All the programmable counters can map to any event */
43 cmask = MAKE_32BIT_MASK(3, num_ctrs);
46 * The event encoding is specified in the SBI specification
47 * Event idx is a 20bits wide number encoded as follows:
48 * event_idx[19:16] = type
49 * event_idx[15:0] = code
50 * The code field in cache events are encoded as follows:
51 * event_idx.code[15:3] = cache_id
52 * event_idx.code[2:1] = op_id
53 * event_idx.code[0:0] = result_id
56 /* SBI_PMU_HW_CPU_CYCLES: 0x01 : type(0x00) */
57 fdt_event_ctr_map[0] = cpu_to_be32(0x00000001);
58 fdt_event_ctr_map[1] = cpu_to_be32(0x00000001);
59 fdt_event_ctr_map[2] = cpu_to_be32(cmask | 1 << 0);
61 /* SBI_PMU_HW_INSTRUCTIONS: 0x02 : type(0x00) */
62 fdt_event_ctr_map[3] = cpu_to_be32(0x00000002);
63 fdt_event_ctr_map[4] = cpu_to_be32(0x00000002);
64 fdt_event_ctr_map[5] = cpu_to_be32(cmask | 1 << 2);
66 /* SBI_PMU_HW_CACHE_DTLB : 0x03 READ : 0x00 MISS : 0x00 type(0x01) */
67 fdt_event_ctr_map[6] = cpu_to_be32(0x00010019);
68 fdt_event_ctr_map[7] = cpu_to_be32(0x00010019);
69 fdt_event_ctr_map[8] = cpu_to_be32(cmask);
71 /* SBI_PMU_HW_CACHE_DTLB : 0x03 WRITE : 0x01 MISS : 0x00 type(0x01) */
72 fdt_event_ctr_map[9] = cpu_to_be32(0x0001001B);
73 fdt_event_ctr_map[10] = cpu_to_be32(0x0001001B);
74 fdt_event_ctr_map[11] = cpu_to_be32(cmask);
76 /* SBI_PMU_HW_CACHE_ITLB : 0x04 READ : 0x00 MISS : 0x00 type(0x01) */
77 fdt_event_ctr_map[12] = cpu_to_be32(0x00010021);
78 fdt_event_ctr_map[13] = cpu_to_be32(0x00010021);
79 fdt_event_ctr_map[14] = cpu_to_be32(cmask);
81 /* This a OpenSBI specific DT property documented in OpenSBI docs */
82 qemu_fdt_setprop(fdt, pmu_name, "riscv,event-to-mhpmcounters",
83 fdt_event_ctr_map, sizeof(fdt_event_ctr_map));
86 static bool riscv_pmu_counter_valid(RISCVCPU *cpu, uint32_t ctr_idx)
88 if (ctr_idx < 3 || ctr_idx >= RV_MAX_MHPMCOUNTERS ||
89 !(cpu->pmu_avail_ctrs & BIT(ctr_idx))) {
90 return false;
91 } else {
92 return true;
96 static bool riscv_pmu_counter_enabled(RISCVCPU *cpu, uint32_t ctr_idx)
98 CPURISCVState *env = &cpu->env;
100 if (riscv_pmu_counter_valid(cpu, ctr_idx) &&
101 !get_field(env->mcountinhibit, BIT(ctr_idx))) {
102 return true;
103 } else {
104 return false;
108 static int riscv_pmu_incr_ctr_rv32(RISCVCPU *cpu, uint32_t ctr_idx)
110 CPURISCVState *env = &cpu->env;
111 target_ulong max_val = UINT32_MAX;
112 PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
113 bool virt_on = env->virt_enabled;
115 /* Privilege mode filtering */
116 if ((env->priv == PRV_M &&
117 (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_MINH)) ||
118 (env->priv == PRV_S && virt_on &&
119 (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_VSINH)) ||
120 (env->priv == PRV_U && virt_on &&
121 (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_VUINH)) ||
122 (env->priv == PRV_S && !virt_on &&
123 (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_SINH)) ||
124 (env->priv == PRV_U && !virt_on &&
125 (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_UINH))) {
126 return 0;
129 /* Handle the overflow scenario */
130 if (counter->mhpmcounter_val == max_val) {
131 if (counter->mhpmcounterh_val == max_val) {
132 counter->mhpmcounter_val = 0;
133 counter->mhpmcounterh_val = 0;
134 /* Generate interrupt only if OF bit is clear */
135 if (!(env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_OF)) {
136 env->mhpmeventh_val[ctr_idx] |= MHPMEVENTH_BIT_OF;
137 riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1));
139 } else {
140 counter->mhpmcounterh_val++;
142 } else {
143 counter->mhpmcounter_val++;
146 return 0;
149 static int riscv_pmu_incr_ctr_rv64(RISCVCPU *cpu, uint32_t ctr_idx)
151 CPURISCVState *env = &cpu->env;
152 PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
153 uint64_t max_val = UINT64_MAX;
154 bool virt_on = env->virt_enabled;
156 /* Privilege mode filtering */
157 if ((env->priv == PRV_M &&
158 (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_MINH)) ||
159 (env->priv == PRV_S && virt_on &&
160 (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_VSINH)) ||
161 (env->priv == PRV_U && virt_on &&
162 (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_VUINH)) ||
163 (env->priv == PRV_S && !virt_on &&
164 (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_SINH)) ||
165 (env->priv == PRV_U && !virt_on &&
166 (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_UINH))) {
167 return 0;
170 /* Handle the overflow scenario */
171 if (counter->mhpmcounter_val == max_val) {
172 counter->mhpmcounter_val = 0;
173 /* Generate interrupt only if OF bit is clear */
174 if (!(env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_OF)) {
175 env->mhpmevent_val[ctr_idx] |= MHPMEVENT_BIT_OF;
176 riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1));
178 } else {
179 counter->mhpmcounter_val++;
181 return 0;
184 int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx)
186 uint32_t ctr_idx;
187 int ret;
188 CPURISCVState *env = &cpu->env;
189 gpointer value;
191 if (!cpu->cfg.pmu_num) {
192 return 0;
194 value = g_hash_table_lookup(cpu->pmu_event_ctr_map,
195 GUINT_TO_POINTER(event_idx));
196 if (!value) {
197 return -1;
200 ctr_idx = GPOINTER_TO_UINT(value);
201 if (!riscv_pmu_counter_enabled(cpu, ctr_idx) ||
202 get_field(env->mcountinhibit, BIT(ctr_idx))) {
203 return -1;
206 if (riscv_cpu_mxl(env) == MXL_RV32) {
207 ret = riscv_pmu_incr_ctr_rv32(cpu, ctr_idx);
208 } else {
209 ret = riscv_pmu_incr_ctr_rv64(cpu, ctr_idx);
212 return ret;
215 bool riscv_pmu_ctr_monitor_instructions(CPURISCVState *env,
216 uint32_t target_ctr)
218 RISCVCPU *cpu;
219 uint32_t event_idx;
220 uint32_t ctr_idx;
222 /* Fixed instret counter */
223 if (target_ctr == 2) {
224 return true;
227 cpu = env_archcpu(env);
228 if (!cpu->pmu_event_ctr_map) {
229 return false;
232 event_idx = RISCV_PMU_EVENT_HW_INSTRUCTIONS;
233 ctr_idx = GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_map,
234 GUINT_TO_POINTER(event_idx)));
235 if (!ctr_idx) {
236 return false;
239 return target_ctr == ctr_idx ? true : false;
242 bool riscv_pmu_ctr_monitor_cycles(CPURISCVState *env, uint32_t target_ctr)
244 RISCVCPU *cpu;
245 uint32_t event_idx;
246 uint32_t ctr_idx;
248 /* Fixed mcycle counter */
249 if (target_ctr == 0) {
250 return true;
253 cpu = env_archcpu(env);
254 if (!cpu->pmu_event_ctr_map) {
255 return false;
258 event_idx = RISCV_PMU_EVENT_HW_CPU_CYCLES;
259 ctr_idx = GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_map,
260 GUINT_TO_POINTER(event_idx)));
262 /* Counter zero is not used for event_ctr_map */
263 if (!ctr_idx) {
264 return false;
267 return (target_ctr == ctr_idx) ? true : false;
270 static gboolean pmu_remove_event_map(gpointer key, gpointer value,
271 gpointer udata)
273 return (GPOINTER_TO_UINT(value) == GPOINTER_TO_UINT(udata)) ? true : false;
276 static int64_t pmu_icount_ticks_to_ns(int64_t value)
278 int64_t ret = 0;
280 if (icount_enabled()) {
281 ret = icount_to_ns(value);
282 } else {
283 ret = (NANOSECONDS_PER_SECOND / RISCV_TIMEBASE_FREQ) * value;
286 return ret;
289 int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value,
290 uint32_t ctr_idx)
292 uint32_t event_idx;
293 RISCVCPU *cpu = env_archcpu(env);
295 if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->pmu_event_ctr_map) {
296 return -1;
300 * Expected mhpmevent value is zero for reset case. Remove the current
301 * mapping.
303 if (!value) {
304 g_hash_table_foreach_remove(cpu->pmu_event_ctr_map,
305 pmu_remove_event_map,
306 GUINT_TO_POINTER(ctr_idx));
307 return 0;
310 event_idx = value & MHPMEVENT_IDX_MASK;
311 if (g_hash_table_lookup(cpu->pmu_event_ctr_map,
312 GUINT_TO_POINTER(event_idx))) {
313 return 0;
316 switch (event_idx) {
317 case RISCV_PMU_EVENT_HW_CPU_CYCLES:
318 case RISCV_PMU_EVENT_HW_INSTRUCTIONS:
319 case RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS:
320 case RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS:
321 case RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS:
322 break;
323 default:
324 /* We don't support any raw events right now */
325 return -1;
327 g_hash_table_insert(cpu->pmu_event_ctr_map, GUINT_TO_POINTER(event_idx),
328 GUINT_TO_POINTER(ctr_idx));
330 return 0;
333 static void pmu_timer_trigger_irq(RISCVCPU *cpu,
334 enum riscv_pmu_event_idx evt_idx)
336 uint32_t ctr_idx;
337 CPURISCVState *env = &cpu->env;
338 PMUCTRState *counter;
339 target_ulong *mhpmevent_val;
340 uint64_t of_bit_mask;
341 int64_t irq_trigger_at;
343 if (evt_idx != RISCV_PMU_EVENT_HW_CPU_CYCLES &&
344 evt_idx != RISCV_PMU_EVENT_HW_INSTRUCTIONS) {
345 return;
348 ctr_idx = GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_map,
349 GUINT_TO_POINTER(evt_idx)));
350 if (!riscv_pmu_counter_enabled(cpu, ctr_idx)) {
351 return;
354 if (riscv_cpu_mxl(env) == MXL_RV32) {
355 mhpmevent_val = &env->mhpmeventh_val[ctr_idx];
356 of_bit_mask = MHPMEVENTH_BIT_OF;
357 } else {
358 mhpmevent_val = &env->mhpmevent_val[ctr_idx];
359 of_bit_mask = MHPMEVENT_BIT_OF;
362 counter = &env->pmu_ctrs[ctr_idx];
363 if (counter->irq_overflow_left > 0) {
364 irq_trigger_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
365 counter->irq_overflow_left;
366 timer_mod_anticipate_ns(cpu->pmu_timer, irq_trigger_at);
367 counter->irq_overflow_left = 0;
368 return;
371 if (cpu->pmu_avail_ctrs & BIT(ctr_idx)) {
372 /* Generate interrupt only if OF bit is clear */
373 if (!(*mhpmevent_val & of_bit_mask)) {
374 *mhpmevent_val |= of_bit_mask;
375 riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1));
380 /* Timer callback for instret and cycle counter overflow */
381 void riscv_pmu_timer_cb(void *priv)
383 RISCVCPU *cpu = priv;
385 /* Timer event was triggered only for these events */
386 pmu_timer_trigger_irq(cpu, RISCV_PMU_EVENT_HW_CPU_CYCLES);
387 pmu_timer_trigger_irq(cpu, RISCV_PMU_EVENT_HW_INSTRUCTIONS);
390 int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx)
392 uint64_t overflow_delta, overflow_at;
393 int64_t overflow_ns, overflow_left = 0;
394 RISCVCPU *cpu = env_archcpu(env);
395 PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
397 if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf) {
398 return -1;
401 if (value) {
402 overflow_delta = UINT64_MAX - value + 1;
403 } else {
404 overflow_delta = UINT64_MAX;
408 * QEMU supports only int64_t timers while RISC-V counters are uint64_t.
409 * Compute the leftover and save it so that it can be reprogrammed again
410 * when timer expires.
412 if (overflow_delta > INT64_MAX) {
413 overflow_left = overflow_delta - INT64_MAX;
416 if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
417 riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
418 overflow_ns = pmu_icount_ticks_to_ns((int64_t)overflow_delta);
419 overflow_left = pmu_icount_ticks_to_ns(overflow_left) ;
420 } else {
421 return -1;
423 overflow_at = (uint64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
424 overflow_ns;
426 if (overflow_at > INT64_MAX) {
427 overflow_left += overflow_at - INT64_MAX;
428 counter->irq_overflow_left = overflow_left;
429 overflow_at = INT64_MAX;
431 timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
433 return 0;
437 int riscv_pmu_init(RISCVCPU *cpu, int num_counters)
439 if (num_counters > (RV_MAX_MHPMCOUNTERS - 3)) {
440 return -1;
443 cpu->pmu_event_ctr_map = g_hash_table_new(g_direct_hash, g_direct_equal);
444 if (!cpu->pmu_event_ctr_map) {
445 /* PMU support can not be enabled */
446 qemu_log_mask(LOG_UNIMP, "PMU events can't be supported\n");
447 cpu->cfg.pmu_num = 0;
448 return -1;
451 /* Create a bitmask of available programmable counters */
452 cpu->pmu_avail_ctrs = MAKE_32BIT_MASK(3, num_counters);
454 return 0;