xref: /openbmc/qemu/target/arm/cpregs-pmu.c (revision a666a84b32690fa414325ab23e50616f91ef00b1)
1ae208642SRichard Henderson /*
2ae208642SRichard Henderson  * QEMU ARM CP Register PMU insns
3ae208642SRichard Henderson  * SPDX-License-Identifier: GPL-2.0-or-later
4ae208642SRichard Henderson  */
5ae208642SRichard Henderson 
6ae208642SRichard Henderson #include "qemu/osdep.h"
7ae208642SRichard Henderson #include "qemu/timer.h"
8ae208642SRichard Henderson #include "exec/icount.h"
9ae208642SRichard Henderson #include "hw/irq.h"
10ae208642SRichard Henderson #include "cpu.h"
11ae208642SRichard Henderson #include "cpu-features.h"
12ae208642SRichard Henderson #include "cpregs.h"
13ae208642SRichard Henderson #include "internals.h"
14ae208642SRichard Henderson 
15ae208642SRichard Henderson 
16ae208642SRichard Henderson #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
17ae208642SRichard Henderson 
18ae208642SRichard Henderson /*
19ae208642SRichard Henderson  * Check for traps to performance monitor registers, which are controlled
20ae208642SRichard Henderson  * by MDCR_EL2.TPM for EL2 and MDCR_EL3.TPM for EL3.
21ae208642SRichard Henderson  */
access_tpm(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)22ae208642SRichard Henderson static CPAccessResult access_tpm(CPUARMState *env, const ARMCPRegInfo *ri,
23ae208642SRichard Henderson                                  bool isread)
24ae208642SRichard Henderson {
25ae208642SRichard Henderson     int el = arm_current_el(env);
26ae208642SRichard Henderson     uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
27ae208642SRichard Henderson 
28ae208642SRichard Henderson     if (el < 2 && (mdcr_el2 & MDCR_TPM)) {
29ae208642SRichard Henderson         return CP_ACCESS_TRAP_EL2;
30ae208642SRichard Henderson     }
31ae208642SRichard Henderson     if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) {
32ae208642SRichard Henderson         return CP_ACCESS_TRAP_EL3;
33ae208642SRichard Henderson     }
34ae208642SRichard Henderson     return CP_ACCESS_OK;
35ae208642SRichard Henderson }
36ae208642SRichard Henderson 
37ae208642SRichard Henderson typedef struct pm_event {
38ae208642SRichard Henderson     uint16_t number; /* PMEVTYPER.evtCount is 16 bits wide */
39ae208642SRichard Henderson     /* If the event is supported on this CPU (used to generate PMCEID[01]) */
40ae208642SRichard Henderson     bool (*supported)(CPUARMState *);
41ae208642SRichard Henderson     /*
42ae208642SRichard Henderson      * Retrieve the current count of the underlying event. The programmed
43ae208642SRichard Henderson      * counters hold a difference from the return value from this function
44ae208642SRichard Henderson      */
45ae208642SRichard Henderson     uint64_t (*get_count)(CPUARMState *);
46ae208642SRichard Henderson     /*
47ae208642SRichard Henderson      * Return how many nanoseconds it will take (at a minimum) for count events
48ae208642SRichard Henderson      * to occur. A negative value indicates the counter will never overflow, or
49ae208642SRichard Henderson      * that the counter has otherwise arranged for the overflow bit to be set
50ae208642SRichard Henderson      * and the PMU interrupt to be raised on overflow.
51ae208642SRichard Henderson      */
52ae208642SRichard Henderson     int64_t (*ns_per_count)(uint64_t);
53ae208642SRichard Henderson } pm_event;
54ae208642SRichard Henderson 
event_always_supported(CPUARMState * env)55ae208642SRichard Henderson static bool event_always_supported(CPUARMState *env)
56ae208642SRichard Henderson {
57ae208642SRichard Henderson     return true;
58ae208642SRichard Henderson }
59ae208642SRichard Henderson 
swinc_get_count(CPUARMState * env)60ae208642SRichard Henderson static uint64_t swinc_get_count(CPUARMState *env)
61ae208642SRichard Henderson {
62ae208642SRichard Henderson     /*
63ae208642SRichard Henderson      * SW_INCR events are written directly to the pmevcntr's by writes to
64ae208642SRichard Henderson      * PMSWINC, so there is no underlying count maintained by the PMU itself
65ae208642SRichard Henderson      */
66ae208642SRichard Henderson     return 0;
67ae208642SRichard Henderson }
68ae208642SRichard Henderson 
swinc_ns_per(uint64_t ignored)69ae208642SRichard Henderson static int64_t swinc_ns_per(uint64_t ignored)
70ae208642SRichard Henderson {
71ae208642SRichard Henderson     return -1;
72ae208642SRichard Henderson }
73ae208642SRichard Henderson 
74ae208642SRichard Henderson /*
75ae208642SRichard Henderson  * Return the underlying cycle count for the PMU cycle counters. If we're in
76ae208642SRichard Henderson  * usermode, simply return 0.
77ae208642SRichard Henderson  */
cycles_get_count(CPUARMState * env)78ae208642SRichard Henderson static uint64_t cycles_get_count(CPUARMState *env)
79ae208642SRichard Henderson {
80ae208642SRichard Henderson #ifndef CONFIG_USER_ONLY
81ae208642SRichard Henderson     return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
82ae208642SRichard Henderson                    ARM_CPU_FREQ, NANOSECONDS_PER_SECOND);
83ae208642SRichard Henderson #else
84ae208642SRichard Henderson     return cpu_get_host_ticks();
85ae208642SRichard Henderson #endif
86ae208642SRichard Henderson }
87ae208642SRichard Henderson 
88ae208642SRichard Henderson #ifndef CONFIG_USER_ONLY
cycles_ns_per(uint64_t cycles)89ae208642SRichard Henderson static int64_t cycles_ns_per(uint64_t cycles)
90ae208642SRichard Henderson {
91ae208642SRichard Henderson     return (ARM_CPU_FREQ / NANOSECONDS_PER_SECOND) * cycles;
92ae208642SRichard Henderson }
93ae208642SRichard Henderson 
instructions_supported(CPUARMState * env)94ae208642SRichard Henderson static bool instructions_supported(CPUARMState *env)
95ae208642SRichard Henderson {
96ae208642SRichard Henderson     /* Precise instruction counting */
97ae208642SRichard Henderson     return icount_enabled() == ICOUNT_PRECISE;
98ae208642SRichard Henderson }
99ae208642SRichard Henderson 
instructions_get_count(CPUARMState * env)100ae208642SRichard Henderson static uint64_t instructions_get_count(CPUARMState *env)
101ae208642SRichard Henderson {
102ae208642SRichard Henderson     assert(icount_enabled() == ICOUNT_PRECISE);
103ae208642SRichard Henderson     return (uint64_t)icount_get_raw();
104ae208642SRichard Henderson }
105ae208642SRichard Henderson 
instructions_ns_per(uint64_t icount)106ae208642SRichard Henderson static int64_t instructions_ns_per(uint64_t icount)
107ae208642SRichard Henderson {
108ae208642SRichard Henderson     assert(icount_enabled() == ICOUNT_PRECISE);
109ae208642SRichard Henderson     return icount_to_ns((int64_t)icount);
110ae208642SRichard Henderson }
111ae208642SRichard Henderson #endif
112ae208642SRichard Henderson 
pmuv3p1_events_supported(CPUARMState * env)113ae208642SRichard Henderson static bool pmuv3p1_events_supported(CPUARMState *env)
114ae208642SRichard Henderson {
115ae208642SRichard Henderson     /* For events which are supported in any v8.1 PMU */
116ae208642SRichard Henderson     return cpu_isar_feature(any_pmuv3p1, env_archcpu(env));
117ae208642SRichard Henderson }
118ae208642SRichard Henderson 
pmuv3p4_events_supported(CPUARMState * env)119ae208642SRichard Henderson static bool pmuv3p4_events_supported(CPUARMState *env)
120ae208642SRichard Henderson {
121ae208642SRichard Henderson     /* For events which are supported in any v8.1 PMU */
122ae208642SRichard Henderson     return cpu_isar_feature(any_pmuv3p4, env_archcpu(env));
123ae208642SRichard Henderson }
124ae208642SRichard Henderson 
zero_event_get_count(CPUARMState * env)125ae208642SRichard Henderson static uint64_t zero_event_get_count(CPUARMState *env)
126ae208642SRichard Henderson {
127ae208642SRichard Henderson     /* For events which on QEMU never fire, so their count is always zero */
128ae208642SRichard Henderson     return 0;
129ae208642SRichard Henderson }
130ae208642SRichard Henderson 
zero_event_ns_per(uint64_t cycles)131ae208642SRichard Henderson static int64_t zero_event_ns_per(uint64_t cycles)
132ae208642SRichard Henderson {
133ae208642SRichard Henderson     /* An event which never fires can never overflow */
134ae208642SRichard Henderson     return -1;
135ae208642SRichard Henderson }
136ae208642SRichard Henderson 
137ae208642SRichard Henderson static const pm_event pm_events[] = {
138ae208642SRichard Henderson     { .number = 0x000, /* SW_INCR */
139ae208642SRichard Henderson       .supported = event_always_supported,
140ae208642SRichard Henderson       .get_count = swinc_get_count,
141ae208642SRichard Henderson       .ns_per_count = swinc_ns_per,
142ae208642SRichard Henderson     },
143ae208642SRichard Henderson #ifndef CONFIG_USER_ONLY
144ae208642SRichard Henderson     { .number = 0x008, /* INST_RETIRED, Instruction architecturally executed */
145ae208642SRichard Henderson       .supported = instructions_supported,
146ae208642SRichard Henderson       .get_count = instructions_get_count,
147ae208642SRichard Henderson       .ns_per_count = instructions_ns_per,
148ae208642SRichard Henderson     },
149ae208642SRichard Henderson     { .number = 0x011, /* CPU_CYCLES, Cycle */
150ae208642SRichard Henderson       .supported = event_always_supported,
151ae208642SRichard Henderson       .get_count = cycles_get_count,
152ae208642SRichard Henderson       .ns_per_count = cycles_ns_per,
153ae208642SRichard Henderson     },
154ae208642SRichard Henderson #endif
155ae208642SRichard Henderson     { .number = 0x023, /* STALL_FRONTEND */
156ae208642SRichard Henderson       .supported = pmuv3p1_events_supported,
157ae208642SRichard Henderson       .get_count = zero_event_get_count,
158ae208642SRichard Henderson       .ns_per_count = zero_event_ns_per,
159ae208642SRichard Henderson     },
160ae208642SRichard Henderson     { .number = 0x024, /* STALL_BACKEND */
161ae208642SRichard Henderson       .supported = pmuv3p1_events_supported,
162ae208642SRichard Henderson       .get_count = zero_event_get_count,
163ae208642SRichard Henderson       .ns_per_count = zero_event_ns_per,
164ae208642SRichard Henderson     },
165ae208642SRichard Henderson     { .number = 0x03c, /* STALL */
166ae208642SRichard Henderson       .supported = pmuv3p4_events_supported,
167ae208642SRichard Henderson       .get_count = zero_event_get_count,
168ae208642SRichard Henderson       .ns_per_count = zero_event_ns_per,
169ae208642SRichard Henderson     },
170ae208642SRichard Henderson };
171ae208642SRichard Henderson 
172ae208642SRichard Henderson /*
173ae208642SRichard Henderson  * Note: Before increasing MAX_EVENT_ID beyond 0x3f into the 0x40xx range of
174ae208642SRichard Henderson  * events (i.e. the statistical profiling extension), this implementation
175ae208642SRichard Henderson  * should first be updated to something sparse instead of the current
176ae208642SRichard Henderson  * supported_event_map[] array.
177ae208642SRichard Henderson  */
178ae208642SRichard Henderson #define MAX_EVENT_ID 0x3c
179ae208642SRichard Henderson #define UNSUPPORTED_EVENT UINT16_MAX
180ae208642SRichard Henderson static uint16_t supported_event_map[MAX_EVENT_ID + 1];
181ae208642SRichard Henderson 
182ae208642SRichard Henderson /*
183ae208642SRichard Henderson  * Called upon CPU initialization to initialize PMCEID[01]_EL0 and build a map
184ae208642SRichard Henderson  * of ARM event numbers to indices in our pm_events array.
185ae208642SRichard Henderson  *
186ae208642SRichard Henderson  * Note: Events in the 0x40XX range are not currently supported.
187ae208642SRichard Henderson  */
pmu_init(ARMCPU * cpu)188ae208642SRichard Henderson void pmu_init(ARMCPU *cpu)
189ae208642SRichard Henderson {
190ae208642SRichard Henderson     unsigned int i;
191ae208642SRichard Henderson 
192ae208642SRichard Henderson     /*
193ae208642SRichard Henderson      * Empty supported_event_map and cpu->pmceid[01] before adding supported
194ae208642SRichard Henderson      * events to them
195ae208642SRichard Henderson      */
196ae208642SRichard Henderson     for (i = 0; i < ARRAY_SIZE(supported_event_map); i++) {
197ae208642SRichard Henderson         supported_event_map[i] = UNSUPPORTED_EVENT;
198ae208642SRichard Henderson     }
199ae208642SRichard Henderson     cpu->pmceid0 = 0;
200ae208642SRichard Henderson     cpu->pmceid1 = 0;
201ae208642SRichard Henderson 
202ae208642SRichard Henderson     for (i = 0; i < ARRAY_SIZE(pm_events); i++) {
203ae208642SRichard Henderson         const pm_event *cnt = &pm_events[i];
204ae208642SRichard Henderson         assert(cnt->number <= MAX_EVENT_ID);
205ae208642SRichard Henderson         /* We do not currently support events in the 0x40xx range */
206ae208642SRichard Henderson         assert(cnt->number <= 0x3f);
207ae208642SRichard Henderson 
208ae208642SRichard Henderson         if (cnt->supported(&cpu->env)) {
209ae208642SRichard Henderson             supported_event_map[cnt->number] = i;
210ae208642SRichard Henderson             uint64_t event_mask = 1ULL << (cnt->number & 0x1f);
211ae208642SRichard Henderson             if (cnt->number & 0x20) {
212ae208642SRichard Henderson                 cpu->pmceid1 |= event_mask;
213ae208642SRichard Henderson             } else {
214ae208642SRichard Henderson                 cpu->pmceid0 |= event_mask;
215ae208642SRichard Henderson             }
216ae208642SRichard Henderson         }
217ae208642SRichard Henderson     }
218ae208642SRichard Henderson }
219ae208642SRichard Henderson 
220ae208642SRichard Henderson /*
221ae208642SRichard Henderson  * Check at runtime whether a PMU event is supported for the current machine
222ae208642SRichard Henderson  */
event_supported(uint16_t number)223ae208642SRichard Henderson static bool event_supported(uint16_t number)
224ae208642SRichard Henderson {
225ae208642SRichard Henderson     if (number > MAX_EVENT_ID) {
226ae208642SRichard Henderson         return false;
227ae208642SRichard Henderson     }
228ae208642SRichard Henderson     return supported_event_map[number] != UNSUPPORTED_EVENT;
229ae208642SRichard Henderson }
230ae208642SRichard Henderson 
pmreg_access(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)231ae208642SRichard Henderson static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri,
232ae208642SRichard Henderson                                    bool isread)
233ae208642SRichard Henderson {
234ae208642SRichard Henderson     /*
235ae208642SRichard Henderson      * Performance monitor registers user accessibility is controlled
236ae208642SRichard Henderson      * by PMUSERENR. MDCR_EL2.TPM and MDCR_EL3.TPM allow configurable
237ae208642SRichard Henderson      * trapping to EL2 or EL3 for other accesses.
238ae208642SRichard Henderson      */
239ae208642SRichard Henderson     int el = arm_current_el(env);
240ae208642SRichard Henderson     uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
241ae208642SRichard Henderson 
242ae208642SRichard Henderson     if (el == 0 && !(env->cp15.c9_pmuserenr & 1)) {
243ae208642SRichard Henderson         return CP_ACCESS_TRAP_EL1;
244ae208642SRichard Henderson     }
245ae208642SRichard Henderson     if (el < 2 && (mdcr_el2 & MDCR_TPM)) {
246ae208642SRichard Henderson         return CP_ACCESS_TRAP_EL2;
247ae208642SRichard Henderson     }
248ae208642SRichard Henderson     if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) {
249ae208642SRichard Henderson         return CP_ACCESS_TRAP_EL3;
250ae208642SRichard Henderson     }
251ae208642SRichard Henderson 
252ae208642SRichard Henderson     return CP_ACCESS_OK;
253ae208642SRichard Henderson }
254ae208642SRichard Henderson 
pmreg_access_xevcntr(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)255ae208642SRichard Henderson static CPAccessResult pmreg_access_xevcntr(CPUARMState *env,
256ae208642SRichard Henderson                                            const ARMCPRegInfo *ri,
257ae208642SRichard Henderson                                            bool isread)
258ae208642SRichard Henderson {
259ae208642SRichard Henderson     /* ER: event counter read trap control */
260ae208642SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V8)
261ae208642SRichard Henderson         && arm_current_el(env) == 0
262ae208642SRichard Henderson         && (env->cp15.c9_pmuserenr & (1 << 3)) != 0
263ae208642SRichard Henderson         && isread) {
264ae208642SRichard Henderson         return CP_ACCESS_OK;
265ae208642SRichard Henderson     }
266ae208642SRichard Henderson 
267ae208642SRichard Henderson     return pmreg_access(env, ri, isread);
268ae208642SRichard Henderson }
269ae208642SRichard Henderson 
pmreg_access_swinc(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)270ae208642SRichard Henderson static CPAccessResult pmreg_access_swinc(CPUARMState *env,
271ae208642SRichard Henderson                                          const ARMCPRegInfo *ri,
272ae208642SRichard Henderson                                          bool isread)
273ae208642SRichard Henderson {
274ae208642SRichard Henderson     /* SW: software increment write trap control */
275ae208642SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V8)
276ae208642SRichard Henderson         && arm_current_el(env) == 0
277ae208642SRichard Henderson         && (env->cp15.c9_pmuserenr & (1 << 1)) != 0
278ae208642SRichard Henderson         && !isread) {
279ae208642SRichard Henderson         return CP_ACCESS_OK;
280ae208642SRichard Henderson     }
281ae208642SRichard Henderson 
282ae208642SRichard Henderson     return pmreg_access(env, ri, isread);
283ae208642SRichard Henderson }
284ae208642SRichard Henderson 
pmreg_access_selr(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)285ae208642SRichard Henderson static CPAccessResult pmreg_access_selr(CPUARMState *env,
286ae208642SRichard Henderson                                         const ARMCPRegInfo *ri,
287ae208642SRichard Henderson                                         bool isread)
288ae208642SRichard Henderson {
289ae208642SRichard Henderson     /* ER: event counter read trap control */
290ae208642SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V8)
291ae208642SRichard Henderson         && arm_current_el(env) == 0
292ae208642SRichard Henderson         && (env->cp15.c9_pmuserenr & (1 << 3)) != 0) {
293ae208642SRichard Henderson         return CP_ACCESS_OK;
294ae208642SRichard Henderson     }
295ae208642SRichard Henderson 
296ae208642SRichard Henderson     return pmreg_access(env, ri, isread);
297ae208642SRichard Henderson }
298ae208642SRichard Henderson 
pmreg_access_ccntr(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)299ae208642SRichard Henderson static CPAccessResult pmreg_access_ccntr(CPUARMState *env,
300ae208642SRichard Henderson                                          const ARMCPRegInfo *ri,
301ae208642SRichard Henderson                                          bool isread)
302ae208642SRichard Henderson {
303ae208642SRichard Henderson     /* CR: cycle counter read trap control */
304ae208642SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V8)
305ae208642SRichard Henderson         && arm_current_el(env) == 0
306ae208642SRichard Henderson         && (env->cp15.c9_pmuserenr & (1 << 2)) != 0
307ae208642SRichard Henderson         && isread) {
308ae208642SRichard Henderson         return CP_ACCESS_OK;
309ae208642SRichard Henderson     }
310ae208642SRichard Henderson 
311ae208642SRichard Henderson     return pmreg_access(env, ri, isread);
312ae208642SRichard Henderson }
313ae208642SRichard Henderson 
314ae208642SRichard Henderson /*
315ae208642SRichard Henderson  * Returns true if the counter (pass 31 for PMCCNTR) should count events using
316ae208642SRichard Henderson  * the current EL, security state, and register configuration.
317ae208642SRichard Henderson  */
pmu_counter_enabled(CPUARMState * env,uint8_t counter)318ae208642SRichard Henderson static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
319ae208642SRichard Henderson {
320ae208642SRichard Henderson     uint64_t filter;
321ae208642SRichard Henderson     bool e, p, u, nsk, nsu, nsh, m;
322ae208642SRichard Henderson     bool enabled, prohibited = false, filtered;
323ae208642SRichard Henderson     bool secure = arm_is_secure(env);
324ae208642SRichard Henderson     int el = arm_current_el(env);
325ae208642SRichard Henderson     uint64_t mdcr_el2;
326ae208642SRichard Henderson     uint8_t hpmn;
327ae208642SRichard Henderson 
328ae208642SRichard Henderson     /*
329ae208642SRichard Henderson      * We might be called for M-profile cores where MDCR_EL2 doesn't
330ae208642SRichard Henderson      * exist and arm_mdcr_el2_eff() will assert, so this early-exit check
331ae208642SRichard Henderson      * must be before we read that value.
332ae208642SRichard Henderson      */
333ae208642SRichard Henderson     if (!arm_feature(env, ARM_FEATURE_PMU)) {
334ae208642SRichard Henderson         return false;
335ae208642SRichard Henderson     }
336ae208642SRichard Henderson 
337ae208642SRichard Henderson     mdcr_el2 = arm_mdcr_el2_eff(env);
338ae208642SRichard Henderson     hpmn = mdcr_el2 & MDCR_HPMN;
339ae208642SRichard Henderson 
340ae208642SRichard Henderson     if (!arm_feature(env, ARM_FEATURE_EL2) ||
341ae208642SRichard Henderson             (counter < hpmn || counter == 31)) {
342ae208642SRichard Henderson         e = env->cp15.c9_pmcr & PMCRE;
343ae208642SRichard Henderson     } else {
344ae208642SRichard Henderson         e = mdcr_el2 & MDCR_HPME;
345ae208642SRichard Henderson     }
346ae208642SRichard Henderson     enabled = e && (env->cp15.c9_pmcnten & (1 << counter));
347ae208642SRichard Henderson 
348ae208642SRichard Henderson     /* Is event counting prohibited? */
349ae208642SRichard Henderson     if (el == 2 && (counter < hpmn || counter == 31)) {
350ae208642SRichard Henderson         prohibited = mdcr_el2 & MDCR_HPMD;
351ae208642SRichard Henderson     }
352ae208642SRichard Henderson     if (secure) {
353ae208642SRichard Henderson         prohibited = prohibited || !(env->cp15.mdcr_el3 & MDCR_SPME);
354ae208642SRichard Henderson     }
355ae208642SRichard Henderson 
356ae208642SRichard Henderson     if (counter == 31) {
357ae208642SRichard Henderson         /*
358ae208642SRichard Henderson          * The cycle counter defaults to running. PMCR.DP says "disable
359ae208642SRichard Henderson          * the cycle counter when event counting is prohibited".
360ae208642SRichard Henderson          * Some MDCR bits disable the cycle counter specifically.
361ae208642SRichard Henderson          */
362ae208642SRichard Henderson         prohibited = prohibited && env->cp15.c9_pmcr & PMCRDP;
363ae208642SRichard Henderson         if (cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) {
364ae208642SRichard Henderson             if (secure) {
365ae208642SRichard Henderson                 prohibited = prohibited || (env->cp15.mdcr_el3 & MDCR_SCCD);
366ae208642SRichard Henderson             }
367ae208642SRichard Henderson             if (el == 2) {
368ae208642SRichard Henderson                 prohibited = prohibited || (mdcr_el2 & MDCR_HCCD);
369ae208642SRichard Henderson             }
370ae208642SRichard Henderson         }
371ae208642SRichard Henderson     }
372ae208642SRichard Henderson 
373ae208642SRichard Henderson     if (counter == 31) {
374ae208642SRichard Henderson         filter = env->cp15.pmccfiltr_el0;
375ae208642SRichard Henderson     } else {
376ae208642SRichard Henderson         filter = env->cp15.c14_pmevtyper[counter];
377ae208642SRichard Henderson     }
378ae208642SRichard Henderson 
379ae208642SRichard Henderson     p   = filter & PMXEVTYPER_P;
380ae208642SRichard Henderson     u   = filter & PMXEVTYPER_U;
381ae208642SRichard Henderson     nsk = arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_NSK);
382ae208642SRichard Henderson     nsu = arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_NSU);
383ae208642SRichard Henderson     nsh = arm_feature(env, ARM_FEATURE_EL2) && (filter & PMXEVTYPER_NSH);
384ae208642SRichard Henderson     m   = arm_el_is_aa64(env, 1) &&
385ae208642SRichard Henderson               arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_M);
386ae208642SRichard Henderson 
387ae208642SRichard Henderson     if (el == 0) {
388ae208642SRichard Henderson         filtered = secure ? u : u != nsu;
389ae208642SRichard Henderson     } else if (el == 1) {
390ae208642SRichard Henderson         filtered = secure ? p : p != nsk;
391ae208642SRichard Henderson     } else if (el == 2) {
392ae208642SRichard Henderson         filtered = !nsh;
393ae208642SRichard Henderson     } else { /* EL3 */
394ae208642SRichard Henderson         filtered = m != p;
395ae208642SRichard Henderson     }
396ae208642SRichard Henderson 
397ae208642SRichard Henderson     if (counter != 31) {
398ae208642SRichard Henderson         /*
399ae208642SRichard Henderson          * If not checking PMCCNTR, ensure the counter is setup to an event we
400ae208642SRichard Henderson          * support
401ae208642SRichard Henderson          */
402ae208642SRichard Henderson         uint16_t event = filter & PMXEVTYPER_EVTCOUNT;
403ae208642SRichard Henderson         if (!event_supported(event)) {
404ae208642SRichard Henderson             return false;
405ae208642SRichard Henderson         }
406ae208642SRichard Henderson     }
407ae208642SRichard Henderson 
408ae208642SRichard Henderson     return enabled && !prohibited && !filtered;
409ae208642SRichard Henderson }
410ae208642SRichard Henderson 
pmu_update_irq(CPUARMState * env)411ae208642SRichard Henderson static void pmu_update_irq(CPUARMState *env)
412ae208642SRichard Henderson {
413ae208642SRichard Henderson     ARMCPU *cpu = env_archcpu(env);
414ae208642SRichard Henderson     qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) &&
415ae208642SRichard Henderson             (env->cp15.c9_pminten & env->cp15.c9_pmovsr));
416ae208642SRichard Henderson }
417ae208642SRichard Henderson 
pmccntr_clockdiv_enabled(CPUARMState * env)418ae208642SRichard Henderson static bool pmccntr_clockdiv_enabled(CPUARMState *env)
419ae208642SRichard Henderson {
420ae208642SRichard Henderson     /*
421ae208642SRichard Henderson      * Return true if the clock divider is enabled and the cycle counter
422ae208642SRichard Henderson      * is supposed to tick only once every 64 clock cycles. This is
423ae208642SRichard Henderson      * controlled by PMCR.D, but if PMCR.LC is set to enable the long
424ae208642SRichard Henderson      * (64-bit) cycle counter PMCR.D has no effect.
425ae208642SRichard Henderson      */
426ae208642SRichard Henderson     return (env->cp15.c9_pmcr & (PMCRD | PMCRLC)) == PMCRD;
427ae208642SRichard Henderson }
428ae208642SRichard Henderson 
pmevcntr_is_64_bit(CPUARMState * env,int counter)429ae208642SRichard Henderson static bool pmevcntr_is_64_bit(CPUARMState *env, int counter)
430ae208642SRichard Henderson {
431ae208642SRichard Henderson     /* Return true if the specified event counter is configured to be 64 bit */
432ae208642SRichard Henderson 
433ae208642SRichard Henderson     /* This isn't intended to be used with the cycle counter */
434ae208642SRichard Henderson     assert(counter < 31);
435ae208642SRichard Henderson 
436ae208642SRichard Henderson     if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) {
437ae208642SRichard Henderson         return false;
438ae208642SRichard Henderson     }
439ae208642SRichard Henderson 
440ae208642SRichard Henderson     if (arm_feature(env, ARM_FEATURE_EL2)) {
441ae208642SRichard Henderson         /*
442ae208642SRichard Henderson          * MDCR_EL2.HLP still applies even when EL2 is disabled in the
443ae208642SRichard Henderson          * current security state, so we don't use arm_mdcr_el2_eff() here.
444ae208642SRichard Henderson          */
445ae208642SRichard Henderson         bool hlp = env->cp15.mdcr_el2 & MDCR_HLP;
446ae208642SRichard Henderson         int hpmn = env->cp15.mdcr_el2 & MDCR_HPMN;
447ae208642SRichard Henderson 
448ae208642SRichard Henderson         if (counter >= hpmn) {
449ae208642SRichard Henderson             return hlp;
450ae208642SRichard Henderson         }
451ae208642SRichard Henderson     }
452ae208642SRichard Henderson     return env->cp15.c9_pmcr & PMCRLP;
453ae208642SRichard Henderson }
454ae208642SRichard Henderson 
455ae208642SRichard Henderson /*
456ae208642SRichard Henderson  * Ensure c15_ccnt is the guest-visible count so that operations such as
457ae208642SRichard Henderson  * enabling/disabling the counter or filtering, modifying the count itself,
458ae208642SRichard Henderson  * etc. can be done logically. This is essentially a no-op if the counter is
459ae208642SRichard Henderson  * not enabled at the time of the call.
460ae208642SRichard Henderson  */
pmccntr_op_start(CPUARMState * env)461ae208642SRichard Henderson static void pmccntr_op_start(CPUARMState *env)
462ae208642SRichard Henderson {
463ae208642SRichard Henderson     uint64_t cycles = cycles_get_count(env);
464ae208642SRichard Henderson 
465ae208642SRichard Henderson     if (pmu_counter_enabled(env, 31)) {
466ae208642SRichard Henderson         uint64_t eff_cycles = cycles;
467ae208642SRichard Henderson         if (pmccntr_clockdiv_enabled(env)) {
468ae208642SRichard Henderson             eff_cycles /= 64;
469ae208642SRichard Henderson         }
470ae208642SRichard Henderson 
471ae208642SRichard Henderson         uint64_t new_pmccntr = eff_cycles - env->cp15.c15_ccnt_delta;
472ae208642SRichard Henderson 
473ae208642SRichard Henderson         uint64_t overflow_mask = env->cp15.c9_pmcr & PMCRLC ? \
474ae208642SRichard Henderson                                  1ull << 63 : 1ull << 31;
475ae208642SRichard Henderson         if (env->cp15.c15_ccnt & ~new_pmccntr & overflow_mask) {
476ae208642SRichard Henderson             env->cp15.c9_pmovsr |= (1ULL << 31);
477ae208642SRichard Henderson             pmu_update_irq(env);
478ae208642SRichard Henderson         }
479ae208642SRichard Henderson 
480ae208642SRichard Henderson         env->cp15.c15_ccnt = new_pmccntr;
481ae208642SRichard Henderson     }
482ae208642SRichard Henderson     env->cp15.c15_ccnt_delta = cycles;
483ae208642SRichard Henderson }
484ae208642SRichard Henderson 
485ae208642SRichard Henderson /*
486ae208642SRichard Henderson  * If PMCCNTR is enabled, recalculate the delta between the clock and the
487ae208642SRichard Henderson  * guest-visible count. A call to pmccntr_op_finish should follow every call to
488ae208642SRichard Henderson  * pmccntr_op_start.
489ae208642SRichard Henderson  */
pmccntr_op_finish(CPUARMState * env)490ae208642SRichard Henderson static void pmccntr_op_finish(CPUARMState *env)
491ae208642SRichard Henderson {
492ae208642SRichard Henderson     if (pmu_counter_enabled(env, 31)) {
493ae208642SRichard Henderson #ifndef CONFIG_USER_ONLY
494ae208642SRichard Henderson         /* Calculate when the counter will next overflow */
495ae208642SRichard Henderson         uint64_t remaining_cycles = -env->cp15.c15_ccnt;
496ae208642SRichard Henderson         if (!(env->cp15.c9_pmcr & PMCRLC)) {
497ae208642SRichard Henderson             remaining_cycles = (uint32_t)remaining_cycles;
498ae208642SRichard Henderson         }
499ae208642SRichard Henderson         int64_t overflow_in = cycles_ns_per(remaining_cycles);
500ae208642SRichard Henderson 
501ae208642SRichard Henderson         if (overflow_in > 0) {
502ae208642SRichard Henderson             int64_t overflow_at;
503ae208642SRichard Henderson 
504ae208642SRichard Henderson             if (!sadd64_overflow(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
505ae208642SRichard Henderson                                  overflow_in, &overflow_at)) {
506ae208642SRichard Henderson                 ARMCPU *cpu = env_archcpu(env);
507ae208642SRichard Henderson                 timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
508ae208642SRichard Henderson             }
509ae208642SRichard Henderson         }
510ae208642SRichard Henderson #endif
511ae208642SRichard Henderson 
512ae208642SRichard Henderson         uint64_t prev_cycles = env->cp15.c15_ccnt_delta;
513ae208642SRichard Henderson         if (pmccntr_clockdiv_enabled(env)) {
514ae208642SRichard Henderson             prev_cycles /= 64;
515ae208642SRichard Henderson         }
516ae208642SRichard Henderson         env->cp15.c15_ccnt_delta = prev_cycles - env->cp15.c15_ccnt;
517ae208642SRichard Henderson     }
518ae208642SRichard Henderson }
519ae208642SRichard Henderson 
pmevcntr_op_start(CPUARMState * env,uint8_t counter)520ae208642SRichard Henderson static void pmevcntr_op_start(CPUARMState *env, uint8_t counter)
521ae208642SRichard Henderson {
522ae208642SRichard Henderson 
523ae208642SRichard Henderson     uint16_t event = env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCOUNT;
524ae208642SRichard Henderson     uint64_t count = 0;
525ae208642SRichard Henderson     if (event_supported(event)) {
526ae208642SRichard Henderson         uint16_t event_idx = supported_event_map[event];
527ae208642SRichard Henderson         count = pm_events[event_idx].get_count(env);
528ae208642SRichard Henderson     }
529ae208642SRichard Henderson 
530ae208642SRichard Henderson     if (pmu_counter_enabled(env, counter)) {
531ae208642SRichard Henderson         uint64_t new_pmevcntr = count - env->cp15.c14_pmevcntr_delta[counter];
532ae208642SRichard Henderson         uint64_t overflow_mask = pmevcntr_is_64_bit(env, counter) ?
533ae208642SRichard Henderson             1ULL << 63 : 1ULL << 31;
534ae208642SRichard Henderson 
535ae208642SRichard Henderson         if (env->cp15.c14_pmevcntr[counter] & ~new_pmevcntr & overflow_mask) {
536ae208642SRichard Henderson             env->cp15.c9_pmovsr |= (1 << counter);
537ae208642SRichard Henderson             pmu_update_irq(env);
538ae208642SRichard Henderson         }
539ae208642SRichard Henderson         env->cp15.c14_pmevcntr[counter] = new_pmevcntr;
540ae208642SRichard Henderson     }
541ae208642SRichard Henderson     env->cp15.c14_pmevcntr_delta[counter] = count;
542ae208642SRichard Henderson }
543ae208642SRichard Henderson 
pmevcntr_op_finish(CPUARMState * env,uint8_t counter)544ae208642SRichard Henderson static void pmevcntr_op_finish(CPUARMState *env, uint8_t counter)
545ae208642SRichard Henderson {
546ae208642SRichard Henderson     if (pmu_counter_enabled(env, counter)) {
547ae208642SRichard Henderson #ifndef CONFIG_USER_ONLY
548ae208642SRichard Henderson         uint16_t event = env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCOUNT;
549ae208642SRichard Henderson         uint16_t event_idx = supported_event_map[event];
550ae208642SRichard Henderson         uint64_t delta = -(env->cp15.c14_pmevcntr[counter] + 1);
551ae208642SRichard Henderson         int64_t overflow_in;
552ae208642SRichard Henderson 
553ae208642SRichard Henderson         if (!pmevcntr_is_64_bit(env, counter)) {
554ae208642SRichard Henderson             delta = (uint32_t)delta;
555ae208642SRichard Henderson         }
556ae208642SRichard Henderson         overflow_in = pm_events[event_idx].ns_per_count(delta);
557ae208642SRichard Henderson 
558ae208642SRichard Henderson         if (overflow_in > 0) {
559ae208642SRichard Henderson             int64_t overflow_at;
560ae208642SRichard Henderson 
561ae208642SRichard Henderson             if (!sadd64_overflow(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
562ae208642SRichard Henderson                                  overflow_in, &overflow_at)) {
563ae208642SRichard Henderson                 ARMCPU *cpu = env_archcpu(env);
564ae208642SRichard Henderson                 timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
565ae208642SRichard Henderson             }
566ae208642SRichard Henderson         }
567ae208642SRichard Henderson #endif
568ae208642SRichard Henderson 
569ae208642SRichard Henderson         env->cp15.c14_pmevcntr_delta[counter] -=
570ae208642SRichard Henderson             env->cp15.c14_pmevcntr[counter];
571ae208642SRichard Henderson     }
572ae208642SRichard Henderson }
573ae208642SRichard Henderson 
pmu_op_start(CPUARMState * env)574ae208642SRichard Henderson void pmu_op_start(CPUARMState *env)
575ae208642SRichard Henderson {
576ae208642SRichard Henderson     unsigned int i;
577ae208642SRichard Henderson     pmccntr_op_start(env);
578ae208642SRichard Henderson     for (i = 0; i < pmu_num_counters(env); i++) {
579ae208642SRichard Henderson         pmevcntr_op_start(env, i);
580ae208642SRichard Henderson     }
581ae208642SRichard Henderson }
582ae208642SRichard Henderson 
pmu_op_finish(CPUARMState * env)583ae208642SRichard Henderson void pmu_op_finish(CPUARMState *env)
584ae208642SRichard Henderson {
585ae208642SRichard Henderson     unsigned int i;
586ae208642SRichard Henderson     pmccntr_op_finish(env);
587ae208642SRichard Henderson     for (i = 0; i < pmu_num_counters(env); i++) {
588ae208642SRichard Henderson         pmevcntr_op_finish(env, i);
589ae208642SRichard Henderson     }
590ae208642SRichard Henderson }
591ae208642SRichard Henderson 
pmu_pre_el_change(ARMCPU * cpu,void * ignored)592ae208642SRichard Henderson void pmu_pre_el_change(ARMCPU *cpu, void *ignored)
593ae208642SRichard Henderson {
594ae208642SRichard Henderson     pmu_op_start(&cpu->env);
595ae208642SRichard Henderson }
596ae208642SRichard Henderson 
pmu_post_el_change(ARMCPU * cpu,void * ignored)597ae208642SRichard Henderson void pmu_post_el_change(ARMCPU *cpu, void *ignored)
598ae208642SRichard Henderson {
599ae208642SRichard Henderson     pmu_op_finish(&cpu->env);
600ae208642SRichard Henderson }
601ae208642SRichard Henderson 
arm_pmu_timer_cb(void * opaque)602ae208642SRichard Henderson void arm_pmu_timer_cb(void *opaque)
603ae208642SRichard Henderson {
604ae208642SRichard Henderson     ARMCPU *cpu = opaque;
605ae208642SRichard Henderson 
606ae208642SRichard Henderson     /*
607ae208642SRichard Henderson      * Update all the counter values based on the current underlying counts,
608ae208642SRichard Henderson      * triggering interrupts to be raised, if necessary. pmu_op_finish() also
609ae208642SRichard Henderson      * has the effect of setting the cpu->pmu_timer to the next earliest time a
610ae208642SRichard Henderson      * counter may expire.
611ae208642SRichard Henderson      */
612ae208642SRichard Henderson     pmu_op_start(&cpu->env);
613ae208642SRichard Henderson     pmu_op_finish(&cpu->env);
614ae208642SRichard Henderson }
615ae208642SRichard Henderson 
pmcr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)616ae208642SRichard Henderson static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
617ae208642SRichard Henderson                        uint64_t value)
618ae208642SRichard Henderson {
619ae208642SRichard Henderson     pmu_op_start(env);
620ae208642SRichard Henderson 
621ae208642SRichard Henderson     if (value & PMCRC) {
622ae208642SRichard Henderson         /* The counter has been reset */
623ae208642SRichard Henderson         env->cp15.c15_ccnt = 0;
624ae208642SRichard Henderson     }
625ae208642SRichard Henderson 
626ae208642SRichard Henderson     if (value & PMCRP) {
627ae208642SRichard Henderson         unsigned int i;
628ae208642SRichard Henderson         for (i = 0; i < pmu_num_counters(env); i++) {
629ae208642SRichard Henderson             env->cp15.c14_pmevcntr[i] = 0;
630ae208642SRichard Henderson         }
631ae208642SRichard Henderson     }
632ae208642SRichard Henderson 
633ae208642SRichard Henderson     env->cp15.c9_pmcr &= ~PMCR_WRITABLE_MASK;
634ae208642SRichard Henderson     env->cp15.c9_pmcr |= (value & PMCR_WRITABLE_MASK);
635ae208642SRichard Henderson 
636ae208642SRichard Henderson     pmu_op_finish(env);
637ae208642SRichard Henderson }
638ae208642SRichard Henderson 
pmcr_read(CPUARMState * env,const ARMCPRegInfo * ri)639ae208642SRichard Henderson static uint64_t pmcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
640ae208642SRichard Henderson {
641ae208642SRichard Henderson     uint64_t pmcr = env->cp15.c9_pmcr;
642ae208642SRichard Henderson 
643ae208642SRichard Henderson     /*
644ae208642SRichard Henderson      * If EL2 is implemented and enabled for the current security state, reads
645ae208642SRichard Henderson      * of PMCR.N from EL1 or EL0 return the value of MDCR_EL2.HPMN or HDCR.HPMN.
646ae208642SRichard Henderson      */
647ae208642SRichard Henderson     if (arm_current_el(env) <= 1 && arm_is_el2_enabled(env)) {
648ae208642SRichard Henderson         pmcr &= ~PMCRN_MASK;
649ae208642SRichard Henderson         pmcr |= (env->cp15.mdcr_el2 & MDCR_HPMN) << PMCRN_SHIFT;
650ae208642SRichard Henderson     }
651ae208642SRichard Henderson 
652ae208642SRichard Henderson     return pmcr;
653ae208642SRichard Henderson }
654ae208642SRichard Henderson 
pmswinc_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)655ae208642SRichard Henderson static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri,
656ae208642SRichard Henderson                           uint64_t value)
657ae208642SRichard Henderson {
658ae208642SRichard Henderson     unsigned int i;
659ae208642SRichard Henderson     uint64_t overflow_mask, new_pmswinc;
660ae208642SRichard Henderson 
661ae208642SRichard Henderson     for (i = 0; i < pmu_num_counters(env); i++) {
662ae208642SRichard Henderson         /* Increment a counter's count iff: */
663ae208642SRichard Henderson         if ((value & (1 << i)) && /* counter's bit is set */
664ae208642SRichard Henderson                 /* counter is enabled and not filtered */
665ae208642SRichard Henderson                 pmu_counter_enabled(env, i) &&
666ae208642SRichard Henderson                 /* counter is SW_INCR */
667ae208642SRichard Henderson                 (env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) == 0x0) {
668ae208642SRichard Henderson             pmevcntr_op_start(env, i);
669ae208642SRichard Henderson 
670ae208642SRichard Henderson             /*
671ae208642SRichard Henderson              * Detect if this write causes an overflow since we can't predict
672ae208642SRichard Henderson              * PMSWINC overflows like we can for other events
673ae208642SRichard Henderson              */
674ae208642SRichard Henderson             new_pmswinc = env->cp15.c14_pmevcntr[i] + 1;
675ae208642SRichard Henderson 
676ae208642SRichard Henderson             overflow_mask = pmevcntr_is_64_bit(env, i) ?
677ae208642SRichard Henderson                 1ULL << 63 : 1ULL << 31;
678ae208642SRichard Henderson 
679ae208642SRichard Henderson             if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & overflow_mask) {
680ae208642SRichard Henderson                 env->cp15.c9_pmovsr |= (1 << i);
681ae208642SRichard Henderson                 pmu_update_irq(env);
682ae208642SRichard Henderson             }
683ae208642SRichard Henderson 
684ae208642SRichard Henderson             env->cp15.c14_pmevcntr[i] = new_pmswinc;
685ae208642SRichard Henderson 
686ae208642SRichard Henderson             pmevcntr_op_finish(env, i);
687ae208642SRichard Henderson         }
688ae208642SRichard Henderson     }
689ae208642SRichard Henderson }
690ae208642SRichard Henderson 
pmccntr_read(CPUARMState * env,const ARMCPRegInfo * ri)691ae208642SRichard Henderson static uint64_t pmccntr_read(CPUARMState *env, const ARMCPRegInfo *ri)
692ae208642SRichard Henderson {
693ae208642SRichard Henderson     uint64_t ret;
694ae208642SRichard Henderson     pmccntr_op_start(env);
695ae208642SRichard Henderson     ret = env->cp15.c15_ccnt;
696ae208642SRichard Henderson     pmccntr_op_finish(env);
697ae208642SRichard Henderson     return ret;
698ae208642SRichard Henderson }
699ae208642SRichard Henderson 
pmselr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)700ae208642SRichard Henderson static void pmselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
701ae208642SRichard Henderson                          uint64_t value)
702ae208642SRichard Henderson {
703ae208642SRichard Henderson     /*
704ae208642SRichard Henderson      * The value of PMSELR.SEL affects the behavior of PMXEVTYPER and
705ae208642SRichard Henderson      * PMXEVCNTR. We allow [0..31] to be written to PMSELR here; in the
706ae208642SRichard Henderson      * meanwhile, we check PMSELR.SEL when PMXEVTYPER and PMXEVCNTR are
707ae208642SRichard Henderson      * accessed.
708ae208642SRichard Henderson      */
709ae208642SRichard Henderson     env->cp15.c9_pmselr = value & 0x1f;
710ae208642SRichard Henderson }
711ae208642SRichard Henderson 
pmccntr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)712ae208642SRichard Henderson static void pmccntr_write(CPUARMState *env, const ARMCPRegInfo *ri,
713ae208642SRichard Henderson                         uint64_t value)
714ae208642SRichard Henderson {
715ae208642SRichard Henderson     pmccntr_op_start(env);
716ae208642SRichard Henderson     env->cp15.c15_ccnt = value;
717ae208642SRichard Henderson     pmccntr_op_finish(env);
718ae208642SRichard Henderson }
719ae208642SRichard Henderson 
pmccntr_write32(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)720ae208642SRichard Henderson static void pmccntr_write32(CPUARMState *env, const ARMCPRegInfo *ri,
721ae208642SRichard Henderson                             uint64_t value)
722ae208642SRichard Henderson {
723ae208642SRichard Henderson     uint64_t cur_val = pmccntr_read(env, NULL);
724ae208642SRichard Henderson 
725ae208642SRichard Henderson     pmccntr_write(env, ri, deposit64(cur_val, 0, 32, value));
726ae208642SRichard Henderson }
727ae208642SRichard Henderson 
pmccfiltr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)728ae208642SRichard Henderson static void pmccfiltr_write(CPUARMState *env, const ARMCPRegInfo *ri,
729ae208642SRichard Henderson                             uint64_t value)
730ae208642SRichard Henderson {
731ae208642SRichard Henderson     pmccntr_op_start(env);
732ae208642SRichard Henderson     env->cp15.pmccfiltr_el0 = value & PMCCFILTR_EL0;
733ae208642SRichard Henderson     pmccntr_op_finish(env);
734ae208642SRichard Henderson }
735ae208642SRichard Henderson 
pmccfiltr_write_a32(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)736ae208642SRichard Henderson static void pmccfiltr_write_a32(CPUARMState *env, const ARMCPRegInfo *ri,
737ae208642SRichard Henderson                             uint64_t value)
738ae208642SRichard Henderson {
739ae208642SRichard Henderson     pmccntr_op_start(env);
740ae208642SRichard Henderson     /* M is not accessible from AArch32 */
741ae208642SRichard Henderson     env->cp15.pmccfiltr_el0 = (env->cp15.pmccfiltr_el0 & PMCCFILTR_M) |
742ae208642SRichard Henderson         (value & PMCCFILTR);
743ae208642SRichard Henderson     pmccntr_op_finish(env);
744ae208642SRichard Henderson }
745ae208642SRichard Henderson 
pmccfiltr_read_a32(CPUARMState * env,const ARMCPRegInfo * ri)746ae208642SRichard Henderson static uint64_t pmccfiltr_read_a32(CPUARMState *env, const ARMCPRegInfo *ri)
747ae208642SRichard Henderson {
748ae208642SRichard Henderson     /* M is not visible in AArch32 */
749ae208642SRichard Henderson     return env->cp15.pmccfiltr_el0 & PMCCFILTR;
750ae208642SRichard Henderson }
751ae208642SRichard Henderson 
pmcntenset_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)752ae208642SRichard Henderson static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
753ae208642SRichard Henderson                             uint64_t value)
754ae208642SRichard Henderson {
755ae208642SRichard Henderson     pmu_op_start(env);
756ae208642SRichard Henderson     value &= pmu_counter_mask(env);
757ae208642SRichard Henderson     env->cp15.c9_pmcnten |= value;
758ae208642SRichard Henderson     pmu_op_finish(env);
759ae208642SRichard Henderson }
760ae208642SRichard Henderson 
pmcntenclr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)761ae208642SRichard Henderson static void pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
762ae208642SRichard Henderson                              uint64_t value)
763ae208642SRichard Henderson {
764ae208642SRichard Henderson     pmu_op_start(env);
765ae208642SRichard Henderson     value &= pmu_counter_mask(env);
766ae208642SRichard Henderson     env->cp15.c9_pmcnten &= ~value;
767ae208642SRichard Henderson     pmu_op_finish(env);
768ae208642SRichard Henderson }
769ae208642SRichard Henderson 
pmovsr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)770ae208642SRichard Henderson static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
771ae208642SRichard Henderson                          uint64_t value)
772ae208642SRichard Henderson {
773ae208642SRichard Henderson     value &= pmu_counter_mask(env);
774ae208642SRichard Henderson     env->cp15.c9_pmovsr &= ~value;
775ae208642SRichard Henderson     pmu_update_irq(env);
776ae208642SRichard Henderson }
777ae208642SRichard Henderson 
pmovsset_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)778ae208642SRichard Henderson static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri,
779ae208642SRichard Henderson                          uint64_t value)
780ae208642SRichard Henderson {
781ae208642SRichard Henderson     value &= pmu_counter_mask(env);
782ae208642SRichard Henderson     env->cp15.c9_pmovsr |= value;
783ae208642SRichard Henderson     pmu_update_irq(env);
784ae208642SRichard Henderson }
785ae208642SRichard Henderson 
pmevtyper_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value,const uint8_t counter)786ae208642SRichard Henderson static void pmevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri,
787ae208642SRichard Henderson                              uint64_t value, const uint8_t counter)
788ae208642SRichard Henderson {
789ae208642SRichard Henderson     if (counter == 31) {
790ae208642SRichard Henderson         pmccfiltr_write(env, ri, value);
791ae208642SRichard Henderson     } else if (counter < pmu_num_counters(env)) {
792ae208642SRichard Henderson         pmevcntr_op_start(env, counter);
793ae208642SRichard Henderson 
794ae208642SRichard Henderson         /*
795ae208642SRichard Henderson          * If this counter's event type is changing, store the current
796ae208642SRichard Henderson          * underlying count for the new type in c14_pmevcntr_delta[counter] so
797ae208642SRichard Henderson          * pmevcntr_op_finish has the correct baseline when it converts back to
798ae208642SRichard Henderson          * a delta.
799ae208642SRichard Henderson          */
800ae208642SRichard Henderson         uint16_t old_event = env->cp15.c14_pmevtyper[counter] &
801ae208642SRichard Henderson             PMXEVTYPER_EVTCOUNT;
802ae208642SRichard Henderson         uint16_t new_event = value & PMXEVTYPER_EVTCOUNT;
803ae208642SRichard Henderson         if (old_event != new_event) {
804ae208642SRichard Henderson             uint64_t count = 0;
805ae208642SRichard Henderson             if (event_supported(new_event)) {
806ae208642SRichard Henderson                 uint16_t event_idx = supported_event_map[new_event];
807ae208642SRichard Henderson                 count = pm_events[event_idx].get_count(env);
808ae208642SRichard Henderson             }
809ae208642SRichard Henderson             env->cp15.c14_pmevcntr_delta[counter] = count;
810ae208642SRichard Henderson         }
811ae208642SRichard Henderson 
812ae208642SRichard Henderson         env->cp15.c14_pmevtyper[counter] = value & PMXEVTYPER_MASK;
813ae208642SRichard Henderson         pmevcntr_op_finish(env, counter);
814ae208642SRichard Henderson     }
815ae208642SRichard Henderson     /*
816ae208642SRichard Henderson      * Attempts to access PMXEVTYPER are CONSTRAINED UNPREDICTABLE when
817ae208642SRichard Henderson      * PMSELR value is equal to or greater than the number of implemented
818ae208642SRichard Henderson      * counters, but not equal to 0x1f. We opt to behave as a RAZ/WI.
819ae208642SRichard Henderson      */
820ae208642SRichard Henderson }
821ae208642SRichard Henderson 
pmevtyper_read(CPUARMState * env,const ARMCPRegInfo * ri,const uint8_t counter)822ae208642SRichard Henderson static uint64_t pmevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri,
823ae208642SRichard Henderson                                const uint8_t counter)
824ae208642SRichard Henderson {
825ae208642SRichard Henderson     if (counter == 31) {
826ae208642SRichard Henderson         return env->cp15.pmccfiltr_el0;
827ae208642SRichard Henderson     } else if (counter < pmu_num_counters(env)) {
828ae208642SRichard Henderson         return env->cp15.c14_pmevtyper[counter];
829ae208642SRichard Henderson     } else {
830ae208642SRichard Henderson       /*
831ae208642SRichard Henderson        * We opt to behave as a RAZ/WI when attempts to access PMXEVTYPER
832ae208642SRichard Henderson        * are CONSTRAINED UNPREDICTABLE. See comments in pmevtyper_write().
833ae208642SRichard Henderson        */
834ae208642SRichard Henderson         return 0;
835ae208642SRichard Henderson     }
836ae208642SRichard Henderson }
837ae208642SRichard Henderson 
pmevtyper_writefn(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)838ae208642SRichard Henderson static void pmevtyper_writefn(CPUARMState *env, const ARMCPRegInfo *ri,
839ae208642SRichard Henderson                               uint64_t value)
840ae208642SRichard Henderson {
841ae208642SRichard Henderson     uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
842ae208642SRichard Henderson     pmevtyper_write(env, ri, value, counter);
843ae208642SRichard Henderson }
844ae208642SRichard Henderson 
pmevtyper_rawwrite(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)845ae208642SRichard Henderson static void pmevtyper_rawwrite(CPUARMState *env, const ARMCPRegInfo *ri,
846ae208642SRichard Henderson                                uint64_t value)
847ae208642SRichard Henderson {
848ae208642SRichard Henderson     uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
849ae208642SRichard Henderson     env->cp15.c14_pmevtyper[counter] = value;
850ae208642SRichard Henderson 
851ae208642SRichard Henderson     /*
852ae208642SRichard Henderson      * pmevtyper_rawwrite is called between a pair of pmu_op_start and
853ae208642SRichard Henderson      * pmu_op_finish calls when loading saved state for a migration. Because
854ae208642SRichard Henderson      * we're potentially updating the type of event here, the value written to
855ae208642SRichard Henderson      * c14_pmevcntr_delta by the preceding pmu_op_start call may be for a
856ae208642SRichard Henderson      * different counter type. Therefore, we need to set this value to the
857ae208642SRichard Henderson      * current count for the counter type we're writing so that pmu_op_finish
858ae208642SRichard Henderson      * has the correct count for its calculation.
859ae208642SRichard Henderson      */
860ae208642SRichard Henderson     uint16_t event = value & PMXEVTYPER_EVTCOUNT;
861ae208642SRichard Henderson     if (event_supported(event)) {
862ae208642SRichard Henderson         uint16_t event_idx = supported_event_map[event];
863ae208642SRichard Henderson         env->cp15.c14_pmevcntr_delta[counter] =
864ae208642SRichard Henderson             pm_events[event_idx].get_count(env);
865ae208642SRichard Henderson     }
866ae208642SRichard Henderson }
867ae208642SRichard Henderson 
pmevtyper_readfn(CPUARMState * env,const ARMCPRegInfo * ri)868ae208642SRichard Henderson static uint64_t pmevtyper_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
869ae208642SRichard Henderson {
870ae208642SRichard Henderson     uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
871ae208642SRichard Henderson     return pmevtyper_read(env, ri, counter);
872ae208642SRichard Henderson }
873ae208642SRichard Henderson 
pmxevtyper_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)874ae208642SRichard Henderson static void pmxevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri,
875ae208642SRichard Henderson                              uint64_t value)
876ae208642SRichard Henderson {
877ae208642SRichard Henderson     pmevtyper_write(env, ri, value, env->cp15.c9_pmselr & 31);
878ae208642SRichard Henderson }
879ae208642SRichard Henderson 
pmxevtyper_read(CPUARMState * env,const ARMCPRegInfo * ri)880ae208642SRichard Henderson static uint64_t pmxevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri)
881ae208642SRichard Henderson {
882ae208642SRichard Henderson     return pmevtyper_read(env, ri, env->cp15.c9_pmselr & 31);
883ae208642SRichard Henderson }
884ae208642SRichard Henderson 
pmevcntr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value,uint8_t counter)885ae208642SRichard Henderson static void pmevcntr_write(CPUARMState *env, const ARMCPRegInfo *ri,
886ae208642SRichard Henderson                              uint64_t value, uint8_t counter)
887ae208642SRichard Henderson {
888ae208642SRichard Henderson     if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) {
889ae208642SRichard Henderson         /* Before FEAT_PMUv3p5, top 32 bits of event counters are RES0 */
890ae208642SRichard Henderson         value &= MAKE_64BIT_MASK(0, 32);
891ae208642SRichard Henderson     }
892ae208642SRichard Henderson     if (counter < pmu_num_counters(env)) {
893ae208642SRichard Henderson         pmevcntr_op_start(env, counter);
894ae208642SRichard Henderson         env->cp15.c14_pmevcntr[counter] = value;
895ae208642SRichard Henderson         pmevcntr_op_finish(env, counter);
896ae208642SRichard Henderson     }
897ae208642SRichard Henderson     /*
898ae208642SRichard Henderson      * We opt to behave as a RAZ/WI when attempts to access PM[X]EVCNTR
899ae208642SRichard Henderson      * are CONSTRAINED UNPREDICTABLE.
900ae208642SRichard Henderson      */
901ae208642SRichard Henderson }
902ae208642SRichard Henderson 
pmevcntr_read(CPUARMState * env,const ARMCPRegInfo * ri,uint8_t counter)903ae208642SRichard Henderson static uint64_t pmevcntr_read(CPUARMState *env, const ARMCPRegInfo *ri,
904ae208642SRichard Henderson                               uint8_t counter)
905ae208642SRichard Henderson {
906ae208642SRichard Henderson     if (counter < pmu_num_counters(env)) {
907ae208642SRichard Henderson         uint64_t ret;
908ae208642SRichard Henderson         pmevcntr_op_start(env, counter);
909ae208642SRichard Henderson         ret = env->cp15.c14_pmevcntr[counter];
910ae208642SRichard Henderson         pmevcntr_op_finish(env, counter);
911ae208642SRichard Henderson         if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) {
912ae208642SRichard Henderson             /* Before FEAT_PMUv3p5, top 32 bits of event counters are RES0 */
913ae208642SRichard Henderson             ret &= MAKE_64BIT_MASK(0, 32);
914ae208642SRichard Henderson         }
915ae208642SRichard Henderson         return ret;
916ae208642SRichard Henderson     } else {
917ae208642SRichard Henderson       /*
918ae208642SRichard Henderson        * We opt to behave as a RAZ/WI when attempts to access PM[X]EVCNTR
919ae208642SRichard Henderson        * are CONSTRAINED UNPREDICTABLE.
920ae208642SRichard Henderson        */
921ae208642SRichard Henderson         return 0;
922ae208642SRichard Henderson     }
923ae208642SRichard Henderson }
924ae208642SRichard Henderson 
pmevcntr_writefn(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)925ae208642SRichard Henderson static void pmevcntr_writefn(CPUARMState *env, const ARMCPRegInfo *ri,
926ae208642SRichard Henderson                              uint64_t value)
927ae208642SRichard Henderson {
928ae208642SRichard Henderson     uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
929ae208642SRichard Henderson     pmevcntr_write(env, ri, value, counter);
930ae208642SRichard Henderson }
931ae208642SRichard Henderson 
pmevcntr_readfn(CPUARMState * env,const ARMCPRegInfo * ri)932ae208642SRichard Henderson static uint64_t pmevcntr_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
933ae208642SRichard Henderson {
934ae208642SRichard Henderson     uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
935ae208642SRichard Henderson     return pmevcntr_read(env, ri, counter);
936ae208642SRichard Henderson }
937ae208642SRichard Henderson 
pmevcntr_rawwrite(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)938ae208642SRichard Henderson static void pmevcntr_rawwrite(CPUARMState *env, const ARMCPRegInfo *ri,
939ae208642SRichard Henderson                              uint64_t value)
940ae208642SRichard Henderson {
941ae208642SRichard Henderson     uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
942ae208642SRichard Henderson     assert(counter < pmu_num_counters(env));
943ae208642SRichard Henderson     env->cp15.c14_pmevcntr[counter] = value;
944ae208642SRichard Henderson     pmevcntr_write(env, ri, value, counter);
945ae208642SRichard Henderson }
946ae208642SRichard Henderson 
pmevcntr_rawread(CPUARMState * env,const ARMCPRegInfo * ri)947ae208642SRichard Henderson static uint64_t pmevcntr_rawread(CPUARMState *env, const ARMCPRegInfo *ri)
948ae208642SRichard Henderson {
949ae208642SRichard Henderson     uint8_t counter = ((ri->crm & 3) << 3) | (ri->opc2 & 7);
950ae208642SRichard Henderson     assert(counter < pmu_num_counters(env));
951ae208642SRichard Henderson     return env->cp15.c14_pmevcntr[counter];
952ae208642SRichard Henderson }
953ae208642SRichard Henderson 
pmxevcntr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)954ae208642SRichard Henderson static void pmxevcntr_write(CPUARMState *env, const ARMCPRegInfo *ri,
955ae208642SRichard Henderson                              uint64_t value)
956ae208642SRichard Henderson {
957ae208642SRichard Henderson     pmevcntr_write(env, ri, value, env->cp15.c9_pmselr & 31);
958ae208642SRichard Henderson }
959ae208642SRichard Henderson 
pmxevcntr_read(CPUARMState * env,const ARMCPRegInfo * ri)960ae208642SRichard Henderson static uint64_t pmxevcntr_read(CPUARMState *env, const ARMCPRegInfo *ri)
961ae208642SRichard Henderson {
962ae208642SRichard Henderson     return pmevcntr_read(env, ri, env->cp15.c9_pmselr & 31);
963ae208642SRichard Henderson }
964ae208642SRichard Henderson 
pmuserenr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)965ae208642SRichard Henderson static void pmuserenr_write(CPUARMState *env, const ARMCPRegInfo *ri,
966ae208642SRichard Henderson                             uint64_t value)
967ae208642SRichard Henderson {
968ae208642SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V8)) {
969ae208642SRichard Henderson         env->cp15.c9_pmuserenr = value & 0xf;
970ae208642SRichard Henderson     } else {
971ae208642SRichard Henderson         env->cp15.c9_pmuserenr = value & 1;
972ae208642SRichard Henderson     }
973ae208642SRichard Henderson }
974ae208642SRichard Henderson 
pmintenset_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)975ae208642SRichard Henderson static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
976ae208642SRichard Henderson                              uint64_t value)
977ae208642SRichard Henderson {
978ae208642SRichard Henderson     /* We have no event counters so only the C bit can be changed */
979ae208642SRichard Henderson     value &= pmu_counter_mask(env);
980ae208642SRichard Henderson     env->cp15.c9_pminten |= value;
981ae208642SRichard Henderson     pmu_update_irq(env);
982ae208642SRichard Henderson }
983ae208642SRichard Henderson 
pmintenclr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)984ae208642SRichard Henderson static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
985ae208642SRichard Henderson                              uint64_t value)
986ae208642SRichard Henderson {
987ae208642SRichard Henderson     value &= pmu_counter_mask(env);
988ae208642SRichard Henderson     env->cp15.c9_pminten &= ~value;
989ae208642SRichard Henderson     pmu_update_irq(env);
990ae208642SRichard Henderson }
991ae208642SRichard Henderson 
992ae208642SRichard Henderson static const ARMCPRegInfo v7_pm_reginfo[] = {
993ae208642SRichard Henderson     /*
994ae208642SRichard Henderson      * Performance monitors are implementation defined in v7,
995ae208642SRichard Henderson      * but with an ARM recommended set of registers, which we
996ae208642SRichard Henderson      * follow.
997ae208642SRichard Henderson      *
998ae208642SRichard Henderson      * Performance registers fall into three categories:
999ae208642SRichard Henderson      *  (a) always UNDEF in PL0, RW in PL1 (PMINTENSET, PMINTENCLR)
1000ae208642SRichard Henderson      *  (b) RO in PL0 (ie UNDEF on write), RW in PL1 (PMUSERENR)
1001ae208642SRichard Henderson      *  (c) UNDEF in PL0 if PMUSERENR.EN==0, otherwise accessible (all others)
1002ae208642SRichard Henderson      * For the cases controlled by PMUSERENR we must set .access to PL0_RW
1003ae208642SRichard Henderson      * or PL0_RO as appropriate and then check PMUSERENR in the helper fn.
1004ae208642SRichard Henderson      */
1005ae208642SRichard Henderson     { .name = "PMCNTENSET", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 1,
1006ae208642SRichard Henderson       .access = PL0_RW, .type = ARM_CP_ALIAS | ARM_CP_IO,
1007ae208642SRichard Henderson       .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcnten),
1008ae208642SRichard Henderson       .writefn = pmcntenset_write,
1009ae208642SRichard Henderson       .accessfn = pmreg_access,
1010ae208642SRichard Henderson       .fgt = FGT_PMCNTEN,
1011ae208642SRichard Henderson       .raw_writefn = raw_write },
1012ae208642SRichard Henderson     { .name = "PMCNTENSET_EL0", .state = ARM_CP_STATE_AA64, .type = ARM_CP_IO,
1013ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 1,
1014ae208642SRichard Henderson       .access = PL0_RW, .accessfn = pmreg_access,
1015ae208642SRichard Henderson       .fgt = FGT_PMCNTEN,
1016ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten), .resetvalue = 0,
1017ae208642SRichard Henderson       .writefn = pmcntenset_write, .raw_writefn = raw_write },
1018ae208642SRichard Henderson     { .name = "PMCNTENCLR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 2,
1019ae208642SRichard Henderson       .access = PL0_RW,
1020ae208642SRichard Henderson       .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcnten),
1021ae208642SRichard Henderson       .accessfn = pmreg_access,
1022ae208642SRichard Henderson       .fgt = FGT_PMCNTEN,
1023ae208642SRichard Henderson       .writefn = pmcntenclr_write, .raw_writefn = raw_write,
1024ae208642SRichard Henderson       .type = ARM_CP_ALIAS | ARM_CP_IO },
1025ae208642SRichard Henderson     { .name = "PMCNTENCLR_EL0", .state = ARM_CP_STATE_AA64,
1026ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 2,
1027ae208642SRichard Henderson       .access = PL0_RW, .accessfn = pmreg_access,
1028ae208642SRichard Henderson       .fgt = FGT_PMCNTEN,
1029ae208642SRichard Henderson       .type = ARM_CP_ALIAS | ARM_CP_IO,
1030ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten),
1031ae208642SRichard Henderson       .writefn = pmcntenclr_write, .raw_writefn = raw_write },
1032ae208642SRichard Henderson     { .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3,
1033ae208642SRichard Henderson       .access = PL0_RW, .type = ARM_CP_IO,
1034ae208642SRichard Henderson       .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr),
1035ae208642SRichard Henderson       .accessfn = pmreg_access,
1036ae208642SRichard Henderson       .fgt = FGT_PMOVS,
1037ae208642SRichard Henderson       .writefn = pmovsr_write,
1038ae208642SRichard Henderson       .raw_writefn = raw_write },
1039ae208642SRichard Henderson     { .name = "PMOVSCLR_EL0", .state = ARM_CP_STATE_AA64,
1040ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 3,
1041ae208642SRichard Henderson       .access = PL0_RW, .accessfn = pmreg_access,
1042ae208642SRichard Henderson       .fgt = FGT_PMOVS,
1043ae208642SRichard Henderson       .type = ARM_CP_ALIAS | ARM_CP_IO,
1044ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
1045ae208642SRichard Henderson       .writefn = pmovsr_write,
1046ae208642SRichard Henderson       .raw_writefn = raw_write },
1047ae208642SRichard Henderson     { .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4,
1048ae208642SRichard Henderson       .access = PL0_W, .accessfn = pmreg_access_swinc,
1049ae208642SRichard Henderson       .fgt = FGT_PMSWINC_EL0,
1050ae208642SRichard Henderson       .type = ARM_CP_NO_RAW | ARM_CP_IO,
1051ae208642SRichard Henderson       .writefn = pmswinc_write },
1052ae208642SRichard Henderson     { .name = "PMSWINC_EL0", .state = ARM_CP_STATE_AA64,
1053ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 4,
1054ae208642SRichard Henderson       .access = PL0_W, .accessfn = pmreg_access_swinc,
1055ae208642SRichard Henderson       .fgt = FGT_PMSWINC_EL0,
1056ae208642SRichard Henderson       .type = ARM_CP_NO_RAW | ARM_CP_IO,
1057ae208642SRichard Henderson       .writefn = pmswinc_write },
1058ae208642SRichard Henderson     { .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
1059ae208642SRichard Henderson       .access = PL0_RW, .type = ARM_CP_ALIAS,
1060ae208642SRichard Henderson       .fgt = FGT_PMSELR_EL0,
1061ae208642SRichard Henderson       .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmselr),
1062ae208642SRichard Henderson       .accessfn = pmreg_access_selr, .writefn = pmselr_write,
1063ae208642SRichard Henderson       .raw_writefn = raw_write},
1064ae208642SRichard Henderson     { .name = "PMSELR_EL0", .state = ARM_CP_STATE_AA64,
1065ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 5,
1066ae208642SRichard Henderson       .access = PL0_RW, .accessfn = pmreg_access_selr,
1067ae208642SRichard Henderson       .fgt = FGT_PMSELR_EL0,
1068ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.c9_pmselr),
1069ae208642SRichard Henderson       .writefn = pmselr_write, .raw_writefn = raw_write, },
1070ae208642SRichard Henderson     { .name = "PMCCNTR_EL0", .state = ARM_CP_STATE_AA64,
1071ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 0,
1072ae208642SRichard Henderson       .access = PL0_RW, .accessfn = pmreg_access_ccntr,
1073ae208642SRichard Henderson       .fgt = FGT_PMCCNTR_EL0,
1074ae208642SRichard Henderson       .type = ARM_CP_IO,
1075ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.c15_ccnt),
1076ae208642SRichard Henderson       .readfn = pmccntr_read, .writefn = pmccntr_write,
1077ae208642SRichard Henderson       .raw_readfn = raw_read, .raw_writefn = raw_write, },
1078ae208642SRichard Henderson     { .name = "PMCCFILTR", .cp = 15, .opc1 = 0, .crn = 14, .crm = 15, .opc2 = 7,
1079ae208642SRichard Henderson       .writefn = pmccfiltr_write_a32, .readfn = pmccfiltr_read_a32,
1080ae208642SRichard Henderson       .access = PL0_RW, .accessfn = pmreg_access,
1081ae208642SRichard Henderson       .fgt = FGT_PMCCFILTR_EL0,
1082ae208642SRichard Henderson       .type = ARM_CP_ALIAS | ARM_CP_IO,
1083ae208642SRichard Henderson       .resetvalue = 0, },
1084ae208642SRichard Henderson     { .name = "PMCCFILTR_EL0", .state = ARM_CP_STATE_AA64,
1085ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 15, .opc2 = 7,
1086ae208642SRichard Henderson       .writefn = pmccfiltr_write, .raw_writefn = raw_write,
1087ae208642SRichard Henderson       .access = PL0_RW, .accessfn = pmreg_access,
1088ae208642SRichard Henderson       .fgt = FGT_PMCCFILTR_EL0,
1089ae208642SRichard Henderson       .type = ARM_CP_IO,
1090ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.pmccfiltr_el0),
1091ae208642SRichard Henderson       .resetvalue = 0, },
1092ae208642SRichard Henderson     { .name = "PMXEVTYPER", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 1,
1093ae208642SRichard Henderson       .access = PL0_RW, .type = ARM_CP_NO_RAW | ARM_CP_IO,
1094ae208642SRichard Henderson       .accessfn = pmreg_access,
1095ae208642SRichard Henderson       .fgt = FGT_PMEVTYPERN_EL0,
1096ae208642SRichard Henderson       .writefn = pmxevtyper_write, .readfn = pmxevtyper_read },
1097ae208642SRichard Henderson     { .name = "PMXEVTYPER_EL0", .state = ARM_CP_STATE_AA64,
1098ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 1,
1099ae208642SRichard Henderson       .access = PL0_RW, .type = ARM_CP_NO_RAW | ARM_CP_IO,
1100ae208642SRichard Henderson       .accessfn = pmreg_access,
1101ae208642SRichard Henderson       .fgt = FGT_PMEVTYPERN_EL0,
1102ae208642SRichard Henderson       .writefn = pmxevtyper_write, .readfn = pmxevtyper_read },
1103ae208642SRichard Henderson     { .name = "PMXEVCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 2,
1104ae208642SRichard Henderson       .access = PL0_RW, .type = ARM_CP_NO_RAW | ARM_CP_IO,
1105ae208642SRichard Henderson       .accessfn = pmreg_access_xevcntr,
1106ae208642SRichard Henderson       .fgt = FGT_PMEVCNTRN_EL0,
1107ae208642SRichard Henderson       .writefn = pmxevcntr_write, .readfn = pmxevcntr_read },
1108ae208642SRichard Henderson     { .name = "PMXEVCNTR_EL0", .state = ARM_CP_STATE_AA64,
1109ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 2,
1110ae208642SRichard Henderson       .access = PL0_RW, .type = ARM_CP_NO_RAW | ARM_CP_IO,
1111ae208642SRichard Henderson       .accessfn = pmreg_access_xevcntr,
1112ae208642SRichard Henderson       .fgt = FGT_PMEVCNTRN_EL0,
1113ae208642SRichard Henderson       .writefn = pmxevcntr_write, .readfn = pmxevcntr_read },
1114ae208642SRichard Henderson     { .name = "PMUSERENR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 0,
1115ae208642SRichard Henderson       .access = PL0_R | PL1_RW, .accessfn = access_tpm,
1116ae208642SRichard Henderson       .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmuserenr),
1117ae208642SRichard Henderson       .resetvalue = 0,
1118ae208642SRichard Henderson       .writefn = pmuserenr_write, .raw_writefn = raw_write },
1119ae208642SRichard Henderson     { .name = "PMUSERENR_EL0", .state = ARM_CP_STATE_AA64,
1120ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 14, .opc2 = 0,
1121ae208642SRichard Henderson       .access = PL0_R | PL1_RW, .accessfn = access_tpm, .type = ARM_CP_ALIAS,
1122ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr),
1123ae208642SRichard Henderson       .resetvalue = 0,
1124ae208642SRichard Henderson       .writefn = pmuserenr_write, .raw_writefn = raw_write },
1125ae208642SRichard Henderson     { .name = "PMINTENSET", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 1,
1126ae208642SRichard Henderson       .access = PL1_RW, .accessfn = access_tpm,
1127ae208642SRichard Henderson       .fgt = FGT_PMINTEN,
1128ae208642SRichard Henderson       .type = ARM_CP_ALIAS | ARM_CP_IO,
1129ae208642SRichard Henderson       .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pminten),
1130ae208642SRichard Henderson       .resetvalue = 0,
1131ae208642SRichard Henderson       .writefn = pmintenset_write, .raw_writefn = raw_write },
1132ae208642SRichard Henderson     { .name = "PMINTENSET_EL1", .state = ARM_CP_STATE_AA64,
1133ae208642SRichard Henderson       .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 1,
1134ae208642SRichard Henderson       .access = PL1_RW, .accessfn = access_tpm,
1135ae208642SRichard Henderson       .fgt = FGT_PMINTEN,
1136ae208642SRichard Henderson       .type = ARM_CP_IO,
1137ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
1138ae208642SRichard Henderson       .writefn = pmintenset_write, .raw_writefn = raw_write,
1139ae208642SRichard Henderson       .resetvalue = 0x0 },
1140ae208642SRichard Henderson     { .name = "PMINTENCLR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 2,
1141ae208642SRichard Henderson       .access = PL1_RW, .accessfn = access_tpm,
1142ae208642SRichard Henderson       .fgt = FGT_PMINTEN,
1143ae208642SRichard Henderson       .type = ARM_CP_ALIAS | ARM_CP_IO,
1144ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
1145ae208642SRichard Henderson       .writefn = pmintenclr_write, .raw_writefn = raw_write },
1146ae208642SRichard Henderson     { .name = "PMINTENCLR_EL1", .state = ARM_CP_STATE_AA64,
1147ae208642SRichard Henderson       .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 2,
1148ae208642SRichard Henderson       .access = PL1_RW, .accessfn = access_tpm,
1149ae208642SRichard Henderson       .fgt = FGT_PMINTEN,
1150ae208642SRichard Henderson       .type = ARM_CP_ALIAS | ARM_CP_IO,
1151ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
1152ae208642SRichard Henderson       .writefn = pmintenclr_write, .raw_writefn = raw_write },
1153ae208642SRichard Henderson };
1154ae208642SRichard Henderson 
1155ae208642SRichard Henderson static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
1156ae208642SRichard Henderson     /* PMOVSSET is not implemented in v7 before v7ve */
1157ae208642SRichard Henderson     { .name = "PMOVSSET", .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 3,
1158ae208642SRichard Henderson       .access = PL0_RW, .accessfn = pmreg_access,
1159ae208642SRichard Henderson       .fgt = FGT_PMOVS,
1160ae208642SRichard Henderson       .type = ARM_CP_ALIAS | ARM_CP_IO,
1161ae208642SRichard Henderson       .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr),
1162ae208642SRichard Henderson       .writefn = pmovsset_write,
1163ae208642SRichard Henderson       .raw_writefn = raw_write },
1164ae208642SRichard Henderson     { .name = "PMOVSSET_EL0", .state = ARM_CP_STATE_AA64,
1165ae208642SRichard Henderson       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 14, .opc2 = 3,
1166ae208642SRichard Henderson       .access = PL0_RW, .accessfn = pmreg_access,
1167ae208642SRichard Henderson       .fgt = FGT_PMOVS,
1168ae208642SRichard Henderson       .type = ARM_CP_ALIAS | ARM_CP_IO,
1169ae208642SRichard Henderson       .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
1170ae208642SRichard Henderson       .writefn = pmovsset_write,
1171ae208642SRichard Henderson       .raw_writefn = raw_write },
1172ae208642SRichard Henderson };
1173ae208642SRichard Henderson 
define_pm_cpregs(ARMCPU * cpu)1174ae208642SRichard Henderson void define_pm_cpregs(ARMCPU *cpu)
1175ae208642SRichard Henderson {
1176ae208642SRichard Henderson     CPUARMState *env = &cpu->env;
1177ae208642SRichard Henderson 
1178ae208642SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V7)) {
1179ae208642SRichard Henderson         /*
1180ae208642SRichard Henderson          * v7 performance monitor control register: same implementor
1181ae208642SRichard Henderson          * field as main ID register, and we implement four counters in
1182ae208642SRichard Henderson          * addition to the cycle count register.
1183ae208642SRichard Henderson          */
1184ae208642SRichard Henderson         static const ARMCPRegInfo pmcr = {
1185ae208642SRichard Henderson             .name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0,
1186ae208642SRichard Henderson             .access = PL0_RW,
1187ae208642SRichard Henderson             .fgt = FGT_PMCR_EL0,
1188ae208642SRichard Henderson             .type = ARM_CP_IO | ARM_CP_ALIAS,
1189ae208642SRichard Henderson             .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
1190ae208642SRichard Henderson             .accessfn = pmreg_access,
1191ae208642SRichard Henderson             .readfn = pmcr_read, .raw_readfn = raw_read,
1192ae208642SRichard Henderson             .writefn = pmcr_write, .raw_writefn = raw_write,
1193ae208642SRichard Henderson         };
1194ae208642SRichard Henderson         const ARMCPRegInfo pmcr64 = {
1195ae208642SRichard Henderson             .name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
1196ae208642SRichard Henderson             .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 0,
1197ae208642SRichard Henderson             .access = PL0_RW, .accessfn = pmreg_access,
1198ae208642SRichard Henderson             .fgt = FGT_PMCR_EL0,
1199ae208642SRichard Henderson             .type = ARM_CP_IO,
1200ae208642SRichard Henderson             .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
1201ae208642SRichard Henderson             .resetvalue = cpu->isar.reset_pmcr_el0,
1202ae208642SRichard Henderson             .readfn = pmcr_read, .raw_readfn = raw_read,
1203ae208642SRichard Henderson             .writefn = pmcr_write, .raw_writefn = raw_write,
1204ae208642SRichard Henderson         };
1205ae208642SRichard Henderson 
1206ae208642SRichard Henderson         define_one_arm_cp_reg(cpu, &pmcr);
1207ae208642SRichard Henderson         define_one_arm_cp_reg(cpu, &pmcr64);
1208ae208642SRichard Henderson         define_arm_cp_regs(cpu, v7_pm_reginfo);
1209*cd9f752fSAlex Richardson         /*
1210*cd9f752fSAlex Richardson          * 32-bit AArch32 PMCCNTR. We don't expose this to GDB if the
1211*cd9f752fSAlex Richardson          * new-in-v8 PMUv3 64-bit AArch32 PMCCNTR register is implemented
1212*cd9f752fSAlex Richardson          * (as that will provide the GDB user's view of "PMCCNTR").
1213*cd9f752fSAlex Richardson          */
1214*cd9f752fSAlex Richardson         ARMCPRegInfo pmccntr = {
1215*cd9f752fSAlex Richardson             .name = "PMCCNTR",
1216*cd9f752fSAlex Richardson             .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0,
1217*cd9f752fSAlex Richardson             .access = PL0_RW, .accessfn = pmreg_access_ccntr,
1218*cd9f752fSAlex Richardson             .resetvalue = 0, .type = ARM_CP_ALIAS | ARM_CP_IO,
1219*cd9f752fSAlex Richardson             .fgt = FGT_PMCCNTR_EL0,
1220*cd9f752fSAlex Richardson             .readfn = pmccntr_read, .writefn = pmccntr_write32,
1221*cd9f752fSAlex Richardson         };
1222*cd9f752fSAlex Richardson         if (arm_feature(env, ARM_FEATURE_V8)) {
1223*cd9f752fSAlex Richardson             pmccntr.type |= ARM_CP_NO_GDB;
1224*cd9f752fSAlex Richardson         }
1225*cd9f752fSAlex Richardson         define_one_arm_cp_reg(cpu, &pmccntr);
1226ae208642SRichard Henderson 
1227ae208642SRichard Henderson         for (unsigned i = 0, pmcrn = pmu_num_counters(env); i < pmcrn; i++) {
1228ae208642SRichard Henderson             g_autofree char *pmevcntr_name = g_strdup_printf("PMEVCNTR%d", i);
1229ae208642SRichard Henderson             g_autofree char *pmevcntr_el0_name = g_strdup_printf("PMEVCNTR%d_EL0", i);
1230ae208642SRichard Henderson             g_autofree char *pmevtyper_name = g_strdup_printf("PMEVTYPER%d", i);
1231ae208642SRichard Henderson             g_autofree char *pmevtyper_el0_name = g_strdup_printf("PMEVTYPER%d_EL0", i);
1232ae208642SRichard Henderson 
1233ae208642SRichard Henderson             ARMCPRegInfo pmev_regs[] = {
1234ae208642SRichard Henderson                 { .name = pmevcntr_name, .cp = 15, .crn = 14,
1235ae208642SRichard Henderson                   .crm = 8 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
1236ae208642SRichard Henderson                   .access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
1237ae208642SRichard Henderson                   .fgt = FGT_PMEVCNTRN_EL0,
1238ae208642SRichard Henderson                   .readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
1239ae208642SRichard Henderson                   .accessfn = pmreg_access_xevcntr },
1240ae208642SRichard Henderson                 { .name = pmevcntr_el0_name, .state = ARM_CP_STATE_AA64,
1241ae208642SRichard Henderson                   .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 8 | (3 & (i >> 3)),
1242ae208642SRichard Henderson                   .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access_xevcntr,
1243ae208642SRichard Henderson                   .type = ARM_CP_IO,
1244ae208642SRichard Henderson                   .fgt = FGT_PMEVCNTRN_EL0,
1245ae208642SRichard Henderson                   .readfn = pmevcntr_readfn, .writefn = pmevcntr_writefn,
1246ae208642SRichard Henderson                   .raw_readfn = pmevcntr_rawread,
1247ae208642SRichard Henderson                   .raw_writefn = pmevcntr_rawwrite },
1248ae208642SRichard Henderson                 { .name = pmevtyper_name, .cp = 15, .crn = 14,
1249ae208642SRichard Henderson                   .crm = 12 | (3 & (i >> 3)), .opc1 = 0, .opc2 = i & 7,
1250ae208642SRichard Henderson                   .access = PL0_RW, .type = ARM_CP_IO | ARM_CP_ALIAS,
1251ae208642SRichard Henderson                   .fgt = FGT_PMEVTYPERN_EL0,
1252ae208642SRichard Henderson                   .readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
1253ae208642SRichard Henderson                   .accessfn = pmreg_access },
1254ae208642SRichard Henderson                 { .name = pmevtyper_el0_name, .state = ARM_CP_STATE_AA64,
1255ae208642SRichard Henderson                   .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 12 | (3 & (i >> 3)),
1256ae208642SRichard Henderson                   .opc2 = i & 7, .access = PL0_RW, .accessfn = pmreg_access,
1257ae208642SRichard Henderson                   .fgt = FGT_PMEVTYPERN_EL0,
1258ae208642SRichard Henderson                   .type = ARM_CP_IO,
1259ae208642SRichard Henderson                   .readfn = pmevtyper_readfn, .writefn = pmevtyper_writefn,
1260ae208642SRichard Henderson                   .raw_writefn = pmevtyper_rawwrite },
1261ae208642SRichard Henderson             };
1262ae208642SRichard Henderson             define_arm_cp_regs(cpu, pmev_regs);
1263ae208642SRichard Henderson         }
1264ae208642SRichard Henderson     }
1265ae208642SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V7VE)) {
1266ae208642SRichard Henderson         define_arm_cp_regs(cpu, pmovsset_cp_reginfo);
1267ae208642SRichard Henderson     }
1268ae208642SRichard Henderson 
1269ae208642SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V8)) {
1270ae208642SRichard Henderson         const ARMCPRegInfo v8_pm_reginfo[] = {
1271ae208642SRichard Henderson             { .name = "PMCEID0", .state = ARM_CP_STATE_AA32,
1272ae208642SRichard Henderson               .cp = 15, .opc1 = 0, .crn = 9, .crm = 12, .opc2 = 6,
1273ae208642SRichard Henderson               .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
1274ae208642SRichard Henderson               .fgt = FGT_PMCEIDN_EL0,
1275ae208642SRichard Henderson               .resetvalue = extract64(cpu->pmceid0, 0, 32) },
1276ae208642SRichard Henderson             { .name = "PMCEID0_EL0", .state = ARM_CP_STATE_AA64,
1277ae208642SRichard Henderson               .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 6,
1278ae208642SRichard Henderson               .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
1279ae208642SRichard Henderson               .fgt = FGT_PMCEIDN_EL0,
1280ae208642SRichard Henderson               .resetvalue = cpu->pmceid0 },
1281ae208642SRichard Henderson             { .name = "PMCEID1", .state = ARM_CP_STATE_AA32,
1282ae208642SRichard Henderson               .cp = 15, .opc1 = 0, .crn = 9, .crm = 12, .opc2 = 7,
1283ae208642SRichard Henderson               .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
1284ae208642SRichard Henderson               .fgt = FGT_PMCEIDN_EL0,
1285ae208642SRichard Henderson               .resetvalue = extract64(cpu->pmceid1, 0, 32) },
1286ae208642SRichard Henderson             { .name = "PMCEID1_EL0", .state = ARM_CP_STATE_AA64,
1287ae208642SRichard Henderson               .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 7,
1288ae208642SRichard Henderson               .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
1289ae208642SRichard Henderson               .fgt = FGT_PMCEIDN_EL0,
1290ae208642SRichard Henderson               .resetvalue = cpu->pmceid1 },
1291*cd9f752fSAlex Richardson             /* AArch32 64-bit PMCCNTR view: added in PMUv3 with Armv8 */
1292*cd9f752fSAlex Richardson             { .name = "PMCCNTR", .state = ARM_CP_STATE_AA32,
1293*cd9f752fSAlex Richardson               .cp = 15, .crm = 9, .opc1 = 0,
1294*cd9f752fSAlex Richardson               .access = PL0_RW, .accessfn = pmreg_access_ccntr, .resetvalue = 0,
1295*cd9f752fSAlex Richardson               .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_64BIT,
1296*cd9f752fSAlex Richardson               .fgt = FGT_PMCCNTR_EL0, .readfn = pmccntr_read,
1297*cd9f752fSAlex Richardson               .writefn = pmccntr_write,  },
1298ae208642SRichard Henderson         };
1299ae208642SRichard Henderson         define_arm_cp_regs(cpu, v8_pm_reginfo);
1300ae208642SRichard Henderson     }
1301ae208642SRichard Henderson 
1302ae208642SRichard Henderson     if (cpu_isar_feature(aa32_pmuv3p1, cpu)) {
1303ae208642SRichard Henderson         ARMCPRegInfo v81_pmu_regs[] = {
1304ae208642SRichard Henderson             { .name = "PMCEID2", .state = ARM_CP_STATE_AA32,
1305ae208642SRichard Henderson               .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 4,
1306ae208642SRichard Henderson               .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
1307ae208642SRichard Henderson               .fgt = FGT_PMCEIDN_EL0,
1308ae208642SRichard Henderson               .resetvalue = extract64(cpu->pmceid0, 32, 32) },
1309ae208642SRichard Henderson             { .name = "PMCEID3", .state = ARM_CP_STATE_AA32,
1310ae208642SRichard Henderson               .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 5,
1311ae208642SRichard Henderson               .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
1312ae208642SRichard Henderson               .fgt = FGT_PMCEIDN_EL0,
1313ae208642SRichard Henderson               .resetvalue = extract64(cpu->pmceid1, 32, 32) },
1314ae208642SRichard Henderson         };
1315ae208642SRichard Henderson         define_arm_cp_regs(cpu, v81_pmu_regs);
1316ae208642SRichard Henderson     }
1317ae208642SRichard Henderson 
1318ae208642SRichard Henderson     if (cpu_isar_feature(any_pmuv3p4, cpu)) {
1319ae208642SRichard Henderson         static const ARMCPRegInfo v84_pmmir = {
1320ae208642SRichard Henderson             .name = "PMMIR_EL1", .state = ARM_CP_STATE_BOTH,
1321ae208642SRichard Henderson             .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 6,
1322ae208642SRichard Henderson             .access = PL1_R, .accessfn = pmreg_access, .type = ARM_CP_CONST,
1323ae208642SRichard Henderson             .fgt = FGT_PMMIR_EL1,
1324ae208642SRichard Henderson             .resetvalue = 0
1325ae208642SRichard Henderson         };
1326ae208642SRichard Henderson         define_one_arm_cp_reg(cpu, &v84_pmmir);
1327ae208642SRichard Henderson     }
1328ae208642SRichard Henderson }
1329