xref: /openbmc/qemu/target/arm/debug_helper.c (revision 37600704ddfeca7b98342dc3c298ce014af6b73a)
19dd5cca4SPhilippe Mathieu-Daudé /*
29dd5cca4SPhilippe Mathieu-Daudé  * ARM debug helpers.
39dd5cca4SPhilippe Mathieu-Daudé  *
49dd5cca4SPhilippe Mathieu-Daudé  * This code is licensed under the GNU GPL v2 or later.
59dd5cca4SPhilippe Mathieu-Daudé  *
69dd5cca4SPhilippe Mathieu-Daudé  * SPDX-License-Identifier: GPL-2.0-or-later
79dd5cca4SPhilippe Mathieu-Daudé  */
89dd5cca4SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
9f43ee493SPeter Maydell #include "qemu/log.h"
109dd5cca4SPhilippe Mathieu-Daudé #include "cpu.h"
119dd5cca4SPhilippe Mathieu-Daudé #include "internals.h"
125a534314SPeter Maydell #include "cpu-features.h"
13f43ee493SPeter Maydell #include "cpregs.h"
149dd5cca4SPhilippe Mathieu-Daudé #include "exec/exec-all.h"
159dd5cca4SPhilippe Mathieu-Daudé #include "exec/helper-proto.h"
162059ec75SFabiano Rosas #include "sysemu/tcg.h"
179dd5cca4SPhilippe Mathieu-Daudé 
182059ec75SFabiano Rosas #ifdef CONFIG_TCG
1938e8a13cSRichard Henderson /* Return the Exception Level targeted by debug exceptions. */
arm_debug_target_el(CPUARMState * env)2038e8a13cSRichard Henderson static int arm_debug_target_el(CPUARMState *env)
2138e8a13cSRichard Henderson {
2238e8a13cSRichard Henderson     bool secure = arm_is_secure(env);
2338e8a13cSRichard Henderson     bool route_to_el2 = false;
2438e8a13cSRichard Henderson 
255d78893fSPeter Maydell     if (arm_feature(env, ARM_FEATURE_M)) {
265d78893fSPeter Maydell         return 1;
275d78893fSPeter Maydell     }
285d78893fSPeter Maydell 
2938e8a13cSRichard Henderson     if (arm_is_el2_enabled(env)) {
3038e8a13cSRichard Henderson         route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
3138e8a13cSRichard Henderson                        env->cp15.mdcr_el2 & MDCR_TDE;
3238e8a13cSRichard Henderson     }
3338e8a13cSRichard Henderson 
3438e8a13cSRichard Henderson     if (route_to_el2) {
3538e8a13cSRichard Henderson         return 2;
3638e8a13cSRichard Henderson     } else if (arm_feature(env, ARM_FEATURE_EL3) &&
3738e8a13cSRichard Henderson                !arm_el_is_aa64(env, 3) && secure) {
3838e8a13cSRichard Henderson         return 3;
3938e8a13cSRichard Henderson     } else {
4038e8a13cSRichard Henderson         return 1;
4138e8a13cSRichard Henderson     }
4238e8a13cSRichard Henderson }
4338e8a13cSRichard Henderson 
4404eacf6eSRichard Henderson /*
4504eacf6eSRichard Henderson  * Raise an exception to the debug target el.
4604eacf6eSRichard Henderson  * Modify syndrome to indicate when origin and target EL are the same.
4704eacf6eSRichard Henderson  */
4804eacf6eSRichard Henderson G_NORETURN static void
raise_exception_debug(CPUARMState * env,uint32_t excp,uint32_t syndrome)4904eacf6eSRichard Henderson raise_exception_debug(CPUARMState *env, uint32_t excp, uint32_t syndrome)
5004eacf6eSRichard Henderson {
5104eacf6eSRichard Henderson     int debug_el = arm_debug_target_el(env);
5204eacf6eSRichard Henderson     int cur_el = arm_current_el(env);
5304eacf6eSRichard Henderson 
5404eacf6eSRichard Henderson     /*
5504eacf6eSRichard Henderson      * If singlestep is targeting a lower EL than the current one, then
5604eacf6eSRichard Henderson      * DisasContext.ss_active must be false and we can never get here.
5704eacf6eSRichard Henderson      * Similarly for watchpoint and breakpoint matches.
5804eacf6eSRichard Henderson      */
5904eacf6eSRichard Henderson     assert(debug_el >= cur_el);
6004eacf6eSRichard Henderson     syndrome |= (debug_el == cur_el) << ARM_EL_EC_SHIFT;
6104eacf6eSRichard Henderson     raise_exception(env, excp, syndrome, debug_el);
6204eacf6eSRichard Henderson }
6304eacf6eSRichard Henderson 
6431c8df53SRichard Henderson /* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
aa64_generate_debug_exceptions(CPUARMState * env)6531c8df53SRichard Henderson static bool aa64_generate_debug_exceptions(CPUARMState *env)
6631c8df53SRichard Henderson {
6731c8df53SRichard Henderson     int cur_el = arm_current_el(env);
6831c8df53SRichard Henderson     int debug_el;
6931c8df53SRichard Henderson 
7031c8df53SRichard Henderson     if (cur_el == 3) {
7131c8df53SRichard Henderson         return false;
7231c8df53SRichard Henderson     }
7331c8df53SRichard Henderson 
7431c8df53SRichard Henderson     /* MDCR_EL3.SDD disables debug events from Secure state */
7531c8df53SRichard Henderson     if (arm_is_secure_below_el3(env)
7631c8df53SRichard Henderson         && extract32(env->cp15.mdcr_el3, 16, 1)) {
7731c8df53SRichard Henderson         return false;
7831c8df53SRichard Henderson     }
7931c8df53SRichard Henderson 
8031c8df53SRichard Henderson     /*
8131c8df53SRichard Henderson      * Same EL to same EL debug exceptions need MDSCR_KDE enabled
8231c8df53SRichard Henderson      * while not masking the (D)ebug bit in DAIF.
8331c8df53SRichard Henderson      */
8431c8df53SRichard Henderson     debug_el = arm_debug_target_el(env);
8531c8df53SRichard Henderson 
8631c8df53SRichard Henderson     if (cur_el == debug_el) {
8731c8df53SRichard Henderson         return extract32(env->cp15.mdscr_el1, 13, 1)
8831c8df53SRichard Henderson             && !(env->daif & PSTATE_D);
8931c8df53SRichard Henderson     }
9031c8df53SRichard Henderson 
9131c8df53SRichard Henderson     /* Otherwise the debug target needs to be a higher EL */
9231c8df53SRichard Henderson     return debug_el > cur_el;
9331c8df53SRichard Henderson }
9431c8df53SRichard Henderson 
aa32_generate_debug_exceptions(CPUARMState * env)9531c8df53SRichard Henderson static bool aa32_generate_debug_exceptions(CPUARMState *env)
9631c8df53SRichard Henderson {
9731c8df53SRichard Henderson     int el = arm_current_el(env);
9831c8df53SRichard Henderson 
9931c8df53SRichard Henderson     if (el == 0 && arm_el_is_aa64(env, 1)) {
10031c8df53SRichard Henderson         return aa64_generate_debug_exceptions(env);
10131c8df53SRichard Henderson     }
10231c8df53SRichard Henderson 
10331c8df53SRichard Henderson     if (arm_is_secure(env)) {
10431c8df53SRichard Henderson         int spd;
10531c8df53SRichard Henderson 
10631c8df53SRichard Henderson         if (el == 0 && (env->cp15.sder & 1)) {
10731c8df53SRichard Henderson             /*
10831c8df53SRichard Henderson              * SDER.SUIDEN means debug exceptions from Secure EL0
10931c8df53SRichard Henderson              * are always enabled. Otherwise they are controlled by
11031c8df53SRichard Henderson              * SDCR.SPD like those from other Secure ELs.
11131c8df53SRichard Henderson              */
11231c8df53SRichard Henderson             return true;
11331c8df53SRichard Henderson         }
11431c8df53SRichard Henderson 
11531c8df53SRichard Henderson         spd = extract32(env->cp15.mdcr_el3, 14, 2);
11631c8df53SRichard Henderson         switch (spd) {
11731c8df53SRichard Henderson         case 1:
11831c8df53SRichard Henderson             /* SPD == 0b01 is reserved, but behaves as 0b00. */
11931c8df53SRichard Henderson         case 0:
12031c8df53SRichard Henderson             /*
12131c8df53SRichard Henderson              * For 0b00 we return true if external secure invasive debug
12231c8df53SRichard Henderson              * is enabled. On real hardware this is controlled by external
12331c8df53SRichard Henderson              * signals to the core. QEMU always permits debug, and behaves
12431c8df53SRichard Henderson              * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high.
12531c8df53SRichard Henderson              */
12631c8df53SRichard Henderson             return true;
12731c8df53SRichard Henderson         case 2:
12831c8df53SRichard Henderson             return false;
12931c8df53SRichard Henderson         case 3:
13031c8df53SRichard Henderson             return true;
13131c8df53SRichard Henderson         }
13231c8df53SRichard Henderson     }
13331c8df53SRichard Henderson 
13431c8df53SRichard Henderson     return el != 2;
13531c8df53SRichard Henderson }
13631c8df53SRichard Henderson 
13731c8df53SRichard Henderson /*
13831c8df53SRichard Henderson  * Return true if debugging exceptions are currently enabled.
13931c8df53SRichard Henderson  * This corresponds to what in ARM ARM pseudocode would be
14031c8df53SRichard Henderson  *    if UsingAArch32() then
14131c8df53SRichard Henderson  *        return AArch32.GenerateDebugExceptions()
14231c8df53SRichard Henderson  *    else
14331c8df53SRichard Henderson  *        return AArch64.GenerateDebugExceptions()
14431c8df53SRichard Henderson  * We choose to push the if() down into this function for clarity,
14531c8df53SRichard Henderson  * since the pseudocode has it at all callsites except for the one in
14631c8df53SRichard Henderson  * CheckSoftwareStep(), where it is elided because both branches would
14731c8df53SRichard Henderson  * always return the same value.
14831c8df53SRichard Henderson  */
arm_generate_debug_exceptions(CPUARMState * env)14931c8df53SRichard Henderson bool arm_generate_debug_exceptions(CPUARMState *env)
15031c8df53SRichard Henderson {
151f94a6df5SPeter Maydell     if ((env->cp15.oslsr_el1 & 1) || (env->cp15.osdlr_el1 & 1)) {
15240b20027SPeter Maydell         return false;
15340b20027SPeter Maydell     }
154831c1b10SRichard Henderson     if (is_a64(env)) {
15531c8df53SRichard Henderson         return aa64_generate_debug_exceptions(env);
15631c8df53SRichard Henderson     } else {
15731c8df53SRichard Henderson         return aa32_generate_debug_exceptions(env);
15831c8df53SRichard Henderson     }
15931c8df53SRichard Henderson }
16031c8df53SRichard Henderson 
16155ba15b7SRichard Henderson /*
16255ba15b7SRichard Henderson  * Is single-stepping active? (Note that the "is EL_D AArch64?" check
16355ba15b7SRichard Henderson  * implicitly means this always returns false in pre-v8 CPUs.)
16455ba15b7SRichard Henderson  */
arm_singlestep_active(CPUARMState * env)16555ba15b7SRichard Henderson bool arm_singlestep_active(CPUARMState *env)
16655ba15b7SRichard Henderson {
16755ba15b7SRichard Henderson     return extract32(env->cp15.mdscr_el1, 0, 1)
16855ba15b7SRichard Henderson         && arm_el_is_aa64(env, arm_debug_target_el(env))
16955ba15b7SRichard Henderson         && arm_generate_debug_exceptions(env);
17055ba15b7SRichard Henderson }
17155ba15b7SRichard Henderson 
1729dd5cca4SPhilippe Mathieu-Daudé /* Return true if the linked breakpoint entry lbn passes its checks */
linked_bp_matches(ARMCPU * cpu,int lbn)1739dd5cca4SPhilippe Mathieu-Daudé static bool linked_bp_matches(ARMCPU *cpu, int lbn)
1749dd5cca4SPhilippe Mathieu-Daudé {
1759dd5cca4SPhilippe Mathieu-Daudé     CPUARMState *env = &cpu->env;
1769dd5cca4SPhilippe Mathieu-Daudé     uint64_t bcr = env->cp15.dbgbcr[lbn];
17788ce6c6eSPeter Maydell     int brps = arm_num_brps(cpu);
17888ce6c6eSPeter Maydell     int ctx_cmps = arm_num_ctx_cmps(cpu);
1799dd5cca4SPhilippe Mathieu-Daudé     int bt;
1809dd5cca4SPhilippe Mathieu-Daudé     uint32_t contextidr;
181e2a1a461SRichard Henderson     uint64_t hcr_el2;
1829dd5cca4SPhilippe Mathieu-Daudé 
1839dd5cca4SPhilippe Mathieu-Daudé     /*
1849dd5cca4SPhilippe Mathieu-Daudé      * Links to unimplemented or non-context aware breakpoints are
1859dd5cca4SPhilippe Mathieu-Daudé      * CONSTRAINED UNPREDICTABLE: either behave as if disabled, or
1869dd5cca4SPhilippe Mathieu-Daudé      * as if linked to an UNKNOWN context-aware breakpoint (in which
1879dd5cca4SPhilippe Mathieu-Daudé      * case DBGWCR<n>_EL1.LBN must indicate that breakpoint).
1889dd5cca4SPhilippe Mathieu-Daudé      * We choose the former.
1899dd5cca4SPhilippe Mathieu-Daudé      */
19088ce6c6eSPeter Maydell     if (lbn >= brps || lbn < (brps - ctx_cmps)) {
1919dd5cca4SPhilippe Mathieu-Daudé         return false;
1929dd5cca4SPhilippe Mathieu-Daudé     }
1939dd5cca4SPhilippe Mathieu-Daudé 
1949dd5cca4SPhilippe Mathieu-Daudé     bcr = env->cp15.dbgbcr[lbn];
1959dd5cca4SPhilippe Mathieu-Daudé 
1969dd5cca4SPhilippe Mathieu-Daudé     if (extract64(bcr, 0, 1) == 0) {
1979dd5cca4SPhilippe Mathieu-Daudé         /* Linked breakpoint disabled : generate no events */
1989dd5cca4SPhilippe Mathieu-Daudé         return false;
1999dd5cca4SPhilippe Mathieu-Daudé     }
2009dd5cca4SPhilippe Mathieu-Daudé 
2019dd5cca4SPhilippe Mathieu-Daudé     bt = extract64(bcr, 20, 4);
202e2a1a461SRichard Henderson     hcr_el2 = arm_hcr_el2_eff(env);
2039dd5cca4SPhilippe Mathieu-Daudé 
2049dd5cca4SPhilippe Mathieu-Daudé     switch (bt) {
2059dd5cca4SPhilippe Mathieu-Daudé     case 3: /* linked context ID match */
206e2a1a461SRichard Henderson         switch (arm_current_el(env)) {
207e2a1a461SRichard Henderson         default:
208e2a1a461SRichard Henderson             /* Context matches never fire in AArch64 EL3 */
209e2a1a461SRichard Henderson             return false;
210e2a1a461SRichard Henderson         case 2:
211e2a1a461SRichard Henderson             if (!(hcr_el2 & HCR_E2H)) {
212e2a1a461SRichard Henderson                 /* Context matches never fire in EL2 without E2H enabled. */
2139dd5cca4SPhilippe Mathieu-Daudé                 return false;
2149dd5cca4SPhilippe Mathieu-Daudé             }
215e2a1a461SRichard Henderson             contextidr = env->cp15.contextidr_el[2];
216e2a1a461SRichard Henderson             break;
217e2a1a461SRichard Henderson         case 1:
218e2a1a461SRichard Henderson             contextidr = env->cp15.contextidr_el[1];
219e2a1a461SRichard Henderson             break;
220e2a1a461SRichard Henderson         case 0:
221e2a1a461SRichard Henderson             if ((hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
222e2a1a461SRichard Henderson                 contextidr = env->cp15.contextidr_el[2];
223e2a1a461SRichard Henderson             } else {
224e2a1a461SRichard Henderson                 contextidr = env->cp15.contextidr_el[1];
225e2a1a461SRichard Henderson             }
226e2a1a461SRichard Henderson             break;
227e2a1a461SRichard Henderson         }
228e2a1a461SRichard Henderson         break;
229e2a1a461SRichard Henderson 
230e2a1a461SRichard Henderson     case 7:  /* linked contextidr_el1 match */
231e2a1a461SRichard Henderson         contextidr = env->cp15.contextidr_el[1];
232e2a1a461SRichard Henderson         break;
233e2a1a461SRichard Henderson     case 13: /* linked contextidr_el2 match */
234e2a1a461SRichard Henderson         contextidr = env->cp15.contextidr_el[2];
235e2a1a461SRichard Henderson         break;
236e2a1a461SRichard Henderson 
2379dd5cca4SPhilippe Mathieu-Daudé     case 9: /* linked VMID match (reserved if no EL2) */
2389dd5cca4SPhilippe Mathieu-Daudé     case 11: /* linked context ID and VMID match (reserved if no EL2) */
239e2a1a461SRichard Henderson     case 15: /* linked full context ID match */
2409dd5cca4SPhilippe Mathieu-Daudé     default:
2419dd5cca4SPhilippe Mathieu-Daudé         /*
2429dd5cca4SPhilippe Mathieu-Daudé          * Links to Unlinked context breakpoints must generate no
2439dd5cca4SPhilippe Mathieu-Daudé          * events; we choose to do the same for reserved values too.
2449dd5cca4SPhilippe Mathieu-Daudé          */
2459dd5cca4SPhilippe Mathieu-Daudé         return false;
2469dd5cca4SPhilippe Mathieu-Daudé     }
2479dd5cca4SPhilippe Mathieu-Daudé 
248e2a1a461SRichard Henderson     /*
249e2a1a461SRichard Henderson      * We match the whole register even if this is AArch32 using the
250e2a1a461SRichard Henderson      * short descriptor format (in which case it holds both PROCID and ASID),
251e2a1a461SRichard Henderson      * since we don't implement the optional v7 context ID masking.
252e2a1a461SRichard Henderson      */
253e2a1a461SRichard Henderson     return contextidr == (uint32_t)env->cp15.dbgbvr[lbn];
2549dd5cca4SPhilippe Mathieu-Daudé }
2559dd5cca4SPhilippe Mathieu-Daudé 
bp_wp_matches(ARMCPU * cpu,int n,bool is_wp)2569dd5cca4SPhilippe Mathieu-Daudé static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
2579dd5cca4SPhilippe Mathieu-Daudé {
2589dd5cca4SPhilippe Mathieu-Daudé     CPUARMState *env = &cpu->env;
2599dd5cca4SPhilippe Mathieu-Daudé     uint64_t cr;
2609dd5cca4SPhilippe Mathieu-Daudé     int pac, hmc, ssc, wt, lbn;
2619dd5cca4SPhilippe Mathieu-Daudé     /*
2629dd5cca4SPhilippe Mathieu-Daudé      * Note that for watchpoints the check is against the CPU security
2639dd5cca4SPhilippe Mathieu-Daudé      * state, not the S/NS attribute on the offending data access.
2649dd5cca4SPhilippe Mathieu-Daudé      */
2659dd5cca4SPhilippe Mathieu-Daudé     bool is_secure = arm_is_secure(env);
2669dd5cca4SPhilippe Mathieu-Daudé     int access_el = arm_current_el(env);
2679dd5cca4SPhilippe Mathieu-Daudé 
2689dd5cca4SPhilippe Mathieu-Daudé     if (is_wp) {
2699dd5cca4SPhilippe Mathieu-Daudé         CPUWatchpoint *wp = env->cpu_watchpoint[n];
2709dd5cca4SPhilippe Mathieu-Daudé 
2719dd5cca4SPhilippe Mathieu-Daudé         if (!wp || !(wp->flags & BP_WATCHPOINT_HIT)) {
2729dd5cca4SPhilippe Mathieu-Daudé             return false;
2739dd5cca4SPhilippe Mathieu-Daudé         }
2749dd5cca4SPhilippe Mathieu-Daudé         cr = env->cp15.dbgwcr[n];
2759dd5cca4SPhilippe Mathieu-Daudé         if (wp->hitattrs.user) {
2769dd5cca4SPhilippe Mathieu-Daudé             /*
2779dd5cca4SPhilippe Mathieu-Daudé              * The LDRT/STRT/LDT/STT "unprivileged access" instructions should
2789dd5cca4SPhilippe Mathieu-Daudé              * match watchpoints as if they were accesses done at EL0, even if
2799dd5cca4SPhilippe Mathieu-Daudé              * the CPU is at EL1 or higher.
2809dd5cca4SPhilippe Mathieu-Daudé              */
2819dd5cca4SPhilippe Mathieu-Daudé             access_el = 0;
2829dd5cca4SPhilippe Mathieu-Daudé         }
2839dd5cca4SPhilippe Mathieu-Daudé     } else {
2849dd5cca4SPhilippe Mathieu-Daudé         uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
2859dd5cca4SPhilippe Mathieu-Daudé 
2869dd5cca4SPhilippe Mathieu-Daudé         if (!env->cpu_breakpoint[n] || env->cpu_breakpoint[n]->pc != pc) {
2879dd5cca4SPhilippe Mathieu-Daudé             return false;
2889dd5cca4SPhilippe Mathieu-Daudé         }
2899dd5cca4SPhilippe Mathieu-Daudé         cr = env->cp15.dbgbcr[n];
2909dd5cca4SPhilippe Mathieu-Daudé     }
2919dd5cca4SPhilippe Mathieu-Daudé     /*
2929dd5cca4SPhilippe Mathieu-Daudé      * The WATCHPOINT_HIT flag guarantees us that the watchpoint is
2939dd5cca4SPhilippe Mathieu-Daudé      * enabled and that the address and access type match; for breakpoints
2949dd5cca4SPhilippe Mathieu-Daudé      * we know the address matched; check the remaining fields, including
2959dd5cca4SPhilippe Mathieu-Daudé      * linked breakpoints. We rely on WCR and BCR having the same layout
2969dd5cca4SPhilippe Mathieu-Daudé      * for the LBN, SSC, HMC, PAC/PMC and is-linked fields.
2979dd5cca4SPhilippe Mathieu-Daudé      * Note that some combinations of {PAC, HMC, SSC} are reserved and
2989dd5cca4SPhilippe Mathieu-Daudé      * must act either like some valid combination or as if the watchpoint
2999dd5cca4SPhilippe Mathieu-Daudé      * were disabled. We choose the former, and use this together with
3009dd5cca4SPhilippe Mathieu-Daudé      * the fact that EL3 must always be Secure and EL2 must always be
3019dd5cca4SPhilippe Mathieu-Daudé      * Non-Secure to simplify the code slightly compared to the full
3029dd5cca4SPhilippe Mathieu-Daudé      * table in the ARM ARM.
3039dd5cca4SPhilippe Mathieu-Daudé      */
3048b7a5bbeSRichard Henderson     pac = FIELD_EX64(cr, DBGWCR, PAC);
3058b7a5bbeSRichard Henderson     hmc = FIELD_EX64(cr, DBGWCR, HMC);
3068b7a5bbeSRichard Henderson     ssc = FIELD_EX64(cr, DBGWCR, SSC);
3079dd5cca4SPhilippe Mathieu-Daudé 
3089dd5cca4SPhilippe Mathieu-Daudé     switch (ssc) {
3099dd5cca4SPhilippe Mathieu-Daudé     case 0:
3109dd5cca4SPhilippe Mathieu-Daudé         break;
3119dd5cca4SPhilippe Mathieu-Daudé     case 1:
3129dd5cca4SPhilippe Mathieu-Daudé     case 3:
3139dd5cca4SPhilippe Mathieu-Daudé         if (is_secure) {
3149dd5cca4SPhilippe Mathieu-Daudé             return false;
3159dd5cca4SPhilippe Mathieu-Daudé         }
3169dd5cca4SPhilippe Mathieu-Daudé         break;
3179dd5cca4SPhilippe Mathieu-Daudé     case 2:
3189dd5cca4SPhilippe Mathieu-Daudé         if (!is_secure) {
3199dd5cca4SPhilippe Mathieu-Daudé             return false;
3209dd5cca4SPhilippe Mathieu-Daudé         }
3219dd5cca4SPhilippe Mathieu-Daudé         break;
3229dd5cca4SPhilippe Mathieu-Daudé     }
3239dd5cca4SPhilippe Mathieu-Daudé 
3249dd5cca4SPhilippe Mathieu-Daudé     switch (access_el) {
3259dd5cca4SPhilippe Mathieu-Daudé     case 3:
3269dd5cca4SPhilippe Mathieu-Daudé     case 2:
3279dd5cca4SPhilippe Mathieu-Daudé         if (!hmc) {
3289dd5cca4SPhilippe Mathieu-Daudé             return false;
3299dd5cca4SPhilippe Mathieu-Daudé         }
3309dd5cca4SPhilippe Mathieu-Daudé         break;
3319dd5cca4SPhilippe Mathieu-Daudé     case 1:
3329dd5cca4SPhilippe Mathieu-Daudé         if (extract32(pac, 0, 1) == 0) {
3339dd5cca4SPhilippe Mathieu-Daudé             return false;
3349dd5cca4SPhilippe Mathieu-Daudé         }
3359dd5cca4SPhilippe Mathieu-Daudé         break;
3369dd5cca4SPhilippe Mathieu-Daudé     case 0:
3379dd5cca4SPhilippe Mathieu-Daudé         if (extract32(pac, 1, 1) == 0) {
3389dd5cca4SPhilippe Mathieu-Daudé             return false;
3399dd5cca4SPhilippe Mathieu-Daudé         }
3409dd5cca4SPhilippe Mathieu-Daudé         break;
3419dd5cca4SPhilippe Mathieu-Daudé     default:
3429dd5cca4SPhilippe Mathieu-Daudé         g_assert_not_reached();
3439dd5cca4SPhilippe Mathieu-Daudé     }
3449dd5cca4SPhilippe Mathieu-Daudé 
3458b7a5bbeSRichard Henderson     wt = FIELD_EX64(cr, DBGWCR, WT);
3468b7a5bbeSRichard Henderson     lbn = FIELD_EX64(cr, DBGWCR, LBN);
3479dd5cca4SPhilippe Mathieu-Daudé 
3489dd5cca4SPhilippe Mathieu-Daudé     if (wt && !linked_bp_matches(cpu, lbn)) {
3499dd5cca4SPhilippe Mathieu-Daudé         return false;
3509dd5cca4SPhilippe Mathieu-Daudé     }
3519dd5cca4SPhilippe Mathieu-Daudé 
3529dd5cca4SPhilippe Mathieu-Daudé     return true;
3539dd5cca4SPhilippe Mathieu-Daudé }
3549dd5cca4SPhilippe Mathieu-Daudé 
check_watchpoints(ARMCPU * cpu)3559dd5cca4SPhilippe Mathieu-Daudé static bool check_watchpoints(ARMCPU *cpu)
3569dd5cca4SPhilippe Mathieu-Daudé {
3579dd5cca4SPhilippe Mathieu-Daudé     CPUARMState *env = &cpu->env;
3589dd5cca4SPhilippe Mathieu-Daudé     int n;
3599dd5cca4SPhilippe Mathieu-Daudé 
3609dd5cca4SPhilippe Mathieu-Daudé     /*
3619dd5cca4SPhilippe Mathieu-Daudé      * If watchpoints are disabled globally or we can't take debug
3629dd5cca4SPhilippe Mathieu-Daudé      * exceptions here then watchpoint firings are ignored.
3639dd5cca4SPhilippe Mathieu-Daudé      */
3649dd5cca4SPhilippe Mathieu-Daudé     if (extract32(env->cp15.mdscr_el1, 15, 1) == 0
3659dd5cca4SPhilippe Mathieu-Daudé         || !arm_generate_debug_exceptions(env)) {
3669dd5cca4SPhilippe Mathieu-Daudé         return false;
3679dd5cca4SPhilippe Mathieu-Daudé     }
3689dd5cca4SPhilippe Mathieu-Daudé 
3699dd5cca4SPhilippe Mathieu-Daudé     for (n = 0; n < ARRAY_SIZE(env->cpu_watchpoint); n++) {
3709dd5cca4SPhilippe Mathieu-Daudé         if (bp_wp_matches(cpu, n, true)) {
3719dd5cca4SPhilippe Mathieu-Daudé             return true;
3729dd5cca4SPhilippe Mathieu-Daudé         }
3739dd5cca4SPhilippe Mathieu-Daudé     }
3749dd5cca4SPhilippe Mathieu-Daudé     return false;
3759dd5cca4SPhilippe Mathieu-Daudé }
3769dd5cca4SPhilippe Mathieu-Daudé 
arm_debug_check_breakpoint(CPUState * cs)377b00d86bcSRichard Henderson bool arm_debug_check_breakpoint(CPUState *cs)
3789dd5cca4SPhilippe Mathieu-Daudé {
379b00d86bcSRichard Henderson     ARMCPU *cpu = ARM_CPU(cs);
3809dd5cca4SPhilippe Mathieu-Daudé     CPUARMState *env = &cpu->env;
3818dc89f1fSRichard Henderson     target_ulong pc;
3829dd5cca4SPhilippe Mathieu-Daudé     int n;
3839dd5cca4SPhilippe Mathieu-Daudé 
3849dd5cca4SPhilippe Mathieu-Daudé     /*
3859dd5cca4SPhilippe Mathieu-Daudé      * If breakpoints are disabled globally or we can't take debug
3869dd5cca4SPhilippe Mathieu-Daudé      * exceptions here then breakpoint firings are ignored.
3879dd5cca4SPhilippe Mathieu-Daudé      */
3889dd5cca4SPhilippe Mathieu-Daudé     if (extract32(env->cp15.mdscr_el1, 15, 1) == 0
3899dd5cca4SPhilippe Mathieu-Daudé         || !arm_generate_debug_exceptions(env)) {
3909dd5cca4SPhilippe Mathieu-Daudé         return false;
3919dd5cca4SPhilippe Mathieu-Daudé     }
3929dd5cca4SPhilippe Mathieu-Daudé 
3938dc89f1fSRichard Henderson     /*
3948dc89f1fSRichard Henderson      * Single-step exceptions have priority over breakpoint exceptions.
3958dc89f1fSRichard Henderson      * If single-step state is active-pending, suppress the bp.
3968dc89f1fSRichard Henderson      */
3978dc89f1fSRichard Henderson     if (arm_singlestep_active(env) && !(env->pstate & PSTATE_SS)) {
3988dc89f1fSRichard Henderson         return false;
3998dc89f1fSRichard Henderson     }
4008dc89f1fSRichard Henderson 
4018dc89f1fSRichard Henderson     /*
4028dc89f1fSRichard Henderson      * PC alignment faults have priority over breakpoint exceptions.
4038dc89f1fSRichard Henderson      */
4048dc89f1fSRichard Henderson     pc = is_a64(env) ? env->pc : env->regs[15];
4058dc89f1fSRichard Henderson     if ((is_a64(env) || !env->thumb) && (pc & 3) != 0) {
4068dc89f1fSRichard Henderson         return false;
4078dc89f1fSRichard Henderson     }
4088dc89f1fSRichard Henderson 
4098dc89f1fSRichard Henderson     /*
4108dc89f1fSRichard Henderson      * Instruction aborts have priority over breakpoint exceptions.
4118dc89f1fSRichard Henderson      * TODO: We would need to look up the page for PC and verify that
4128dc89f1fSRichard Henderson      * it is present and executable.
4138dc89f1fSRichard Henderson      */
4148dc89f1fSRichard Henderson 
4159dd5cca4SPhilippe Mathieu-Daudé     for (n = 0; n < ARRAY_SIZE(env->cpu_breakpoint); n++) {
4169dd5cca4SPhilippe Mathieu-Daudé         if (bp_wp_matches(cpu, n, false)) {
4179dd5cca4SPhilippe Mathieu-Daudé             return true;
4189dd5cca4SPhilippe Mathieu-Daudé         }
4199dd5cca4SPhilippe Mathieu-Daudé     }
4209dd5cca4SPhilippe Mathieu-Daudé     return false;
4219dd5cca4SPhilippe Mathieu-Daudé }
4229dd5cca4SPhilippe Mathieu-Daudé 
arm_debug_check_watchpoint(CPUState * cs,CPUWatchpoint * wp)4239dd5cca4SPhilippe Mathieu-Daudé bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
4249dd5cca4SPhilippe Mathieu-Daudé {
4259dd5cca4SPhilippe Mathieu-Daudé     /*
4269dd5cca4SPhilippe Mathieu-Daudé      * Called by core code when a CPU watchpoint fires; need to check if this
4279dd5cca4SPhilippe Mathieu-Daudé      * is also an architectural watchpoint match.
4289dd5cca4SPhilippe Mathieu-Daudé      */
4299dd5cca4SPhilippe Mathieu-Daudé     ARMCPU *cpu = ARM_CPU(cs);
4309dd5cca4SPhilippe Mathieu-Daudé 
4319dd5cca4SPhilippe Mathieu-Daudé     return check_watchpoints(cpu);
4329dd5cca4SPhilippe Mathieu-Daudé }
4339dd5cca4SPhilippe Mathieu-Daudé 
434a853e3aeSRichard Henderson /*
435a853e3aeSRichard Henderson  * Return the FSR value for a debug exception (watchpoint, hardware
436a853e3aeSRichard Henderson  * breakpoint or BKPT insn) targeting the specified exception level.
437a853e3aeSRichard Henderson  */
arm_debug_exception_fsr(CPUARMState * env)438a853e3aeSRichard Henderson static uint32_t arm_debug_exception_fsr(CPUARMState *env)
439a853e3aeSRichard Henderson {
440a853e3aeSRichard Henderson     ARMMMUFaultInfo fi = { .type = ARMFault_Debug };
441a853e3aeSRichard Henderson     int target_el = arm_debug_target_el(env);
4425d78893fSPeter Maydell     bool using_lpae;
443a853e3aeSRichard Henderson 
4445d78893fSPeter Maydell     if (arm_feature(env, ARM_FEATURE_M)) {
4455d78893fSPeter Maydell         using_lpae = false;
4465d78893fSPeter Maydell     } else if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
447a853e3aeSRichard Henderson         using_lpae = true;
448452c67a4STobias Röhmel     } else if (arm_feature(env, ARM_FEATURE_PMSA) &&
449452c67a4STobias Röhmel                arm_feature(env, ARM_FEATURE_V8)) {
450452c67a4STobias Röhmel         using_lpae = true;
4515d78893fSPeter Maydell     } else if (arm_feature(env, ARM_FEATURE_LPAE) &&
452cb4a0a34SPeter Maydell                (env->cp15.tcr_el[target_el] & TTBCR_EAE)) {
453a853e3aeSRichard Henderson         using_lpae = true;
4545d78893fSPeter Maydell     } else {
4555d78893fSPeter Maydell         using_lpae = false;
456a853e3aeSRichard Henderson     }
457a853e3aeSRichard Henderson 
458a853e3aeSRichard Henderson     if (using_lpae) {
459a853e3aeSRichard Henderson         return arm_fi_to_lfsc(&fi);
460a853e3aeSRichard Henderson     } else {
461a853e3aeSRichard Henderson         return arm_fi_to_sfsc(&fi);
462a853e3aeSRichard Henderson     }
463a853e3aeSRichard Henderson }
464a853e3aeSRichard Henderson 
arm_debug_excp_handler(CPUState * cs)4659dd5cca4SPhilippe Mathieu-Daudé void arm_debug_excp_handler(CPUState *cs)
4669dd5cca4SPhilippe Mathieu-Daudé {
4679dd5cca4SPhilippe Mathieu-Daudé     /*
4689dd5cca4SPhilippe Mathieu-Daudé      * Called by core code when a watchpoint or breakpoint fires;
4699dd5cca4SPhilippe Mathieu-Daudé      * need to check which one and raise the appropriate exception.
4709dd5cca4SPhilippe Mathieu-Daudé      */
4719dd5cca4SPhilippe Mathieu-Daudé     ARMCPU *cpu = ARM_CPU(cs);
4729dd5cca4SPhilippe Mathieu-Daudé     CPUARMState *env = &cpu->env;
4739dd5cca4SPhilippe Mathieu-Daudé     CPUWatchpoint *wp_hit = cs->watchpoint_hit;
4749dd5cca4SPhilippe Mathieu-Daudé 
4759dd5cca4SPhilippe Mathieu-Daudé     if (wp_hit) {
4769dd5cca4SPhilippe Mathieu-Daudé         if (wp_hit->flags & BP_CPU) {
4779dd5cca4SPhilippe Mathieu-Daudé             bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
4789dd5cca4SPhilippe Mathieu-Daudé 
4799dd5cca4SPhilippe Mathieu-Daudé             cs->watchpoint_hit = NULL;
4809dd5cca4SPhilippe Mathieu-Daudé 
4819dd5cca4SPhilippe Mathieu-Daudé             env->exception.fsr = arm_debug_exception_fsr(env);
4829dd5cca4SPhilippe Mathieu-Daudé             env->exception.vaddress = wp_hit->hitaddr;
48304eacf6eSRichard Henderson             raise_exception_debug(env, EXCP_DATA_ABORT,
48404eacf6eSRichard Henderson                                   syn_watchpoint(0, 0, wnr));
4859dd5cca4SPhilippe Mathieu-Daudé         }
4869dd5cca4SPhilippe Mathieu-Daudé     } else {
4879dd5cca4SPhilippe Mathieu-Daudé         uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
4889dd5cca4SPhilippe Mathieu-Daudé 
4899dd5cca4SPhilippe Mathieu-Daudé         /*
4909dd5cca4SPhilippe Mathieu-Daudé          * (1) GDB breakpoints should be handled first.
4919dd5cca4SPhilippe Mathieu-Daudé          * (2) Do not raise a CPU exception if no CPU breakpoint has fired,
4929dd5cca4SPhilippe Mathieu-Daudé          * since singlestep is also done by generating a debug internal
4939dd5cca4SPhilippe Mathieu-Daudé          * exception.
4949dd5cca4SPhilippe Mathieu-Daudé          */
4959dd5cca4SPhilippe Mathieu-Daudé         if (cpu_breakpoint_test(cs, pc, BP_GDB)
4969dd5cca4SPhilippe Mathieu-Daudé             || !cpu_breakpoint_test(cs, pc, BP_CPU)) {
4979dd5cca4SPhilippe Mathieu-Daudé             return;
4989dd5cca4SPhilippe Mathieu-Daudé         }
4999dd5cca4SPhilippe Mathieu-Daudé 
5009dd5cca4SPhilippe Mathieu-Daudé         env->exception.fsr = arm_debug_exception_fsr(env);
5019dd5cca4SPhilippe Mathieu-Daudé         /*
5029dd5cca4SPhilippe Mathieu-Daudé          * FAR is UNKNOWN: clear vaddress to avoid potentially exposing
5039dd5cca4SPhilippe Mathieu-Daudé          * values to the guest that it shouldn't be able to see at its
5049dd5cca4SPhilippe Mathieu-Daudé          * exception/security level.
5059dd5cca4SPhilippe Mathieu-Daudé          */
5069dd5cca4SPhilippe Mathieu-Daudé         env->exception.vaddress = 0;
50704eacf6eSRichard Henderson         raise_exception_debug(env, EXCP_PREFETCH_ABORT, syn_breakpoint(0));
5089dd5cca4SPhilippe Mathieu-Daudé     }
5099dd5cca4SPhilippe Mathieu-Daudé }
5109dd5cca4SPhilippe Mathieu-Daudé 
51116f9d5f6SRichard Henderson /*
51216f9d5f6SRichard Henderson  * Raise an EXCP_BKPT with the specified syndrome register value,
51316f9d5f6SRichard Henderson  * targeting the correct exception level for debug exceptions.
51416f9d5f6SRichard Henderson  */
HELPER(exception_bkpt_insn)51516f9d5f6SRichard Henderson void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
51616f9d5f6SRichard Henderson {
51716f9d5f6SRichard Henderson     int debug_el = arm_debug_target_el(env);
51816f9d5f6SRichard Henderson     int cur_el = arm_current_el(env);
51916f9d5f6SRichard Henderson 
52016f9d5f6SRichard Henderson     /* FSR will only be used if the debug target EL is AArch32. */
52116f9d5f6SRichard Henderson     env->exception.fsr = arm_debug_exception_fsr(env);
52216f9d5f6SRichard Henderson     /*
52316f9d5f6SRichard Henderson      * FAR is UNKNOWN: clear vaddress to avoid potentially exposing
52416f9d5f6SRichard Henderson      * values to the guest that it shouldn't be able to see at its
52516f9d5f6SRichard Henderson      * exception/security level.
52616f9d5f6SRichard Henderson      */
52716f9d5f6SRichard Henderson     env->exception.vaddress = 0;
52816f9d5f6SRichard Henderson     /*
52916f9d5f6SRichard Henderson      * Other kinds of architectural debug exception are ignored if
53016f9d5f6SRichard Henderson      * they target an exception level below the current one (in QEMU
53116f9d5f6SRichard Henderson      * this is checked by arm_generate_debug_exceptions()). Breakpoint
53216f9d5f6SRichard Henderson      * instructions are special because they always generate an exception
53316f9d5f6SRichard Henderson      * to somewhere: if they can't go to the configured debug exception
53416f9d5f6SRichard Henderson      * level they are taken to the current exception level.
53516f9d5f6SRichard Henderson      */
53616f9d5f6SRichard Henderson     if (debug_el < cur_el) {
53716f9d5f6SRichard Henderson         debug_el = cur_el;
53816f9d5f6SRichard Henderson     }
53916f9d5f6SRichard Henderson     raise_exception(env, EXCP_BKPT, syndrome, debug_el);
54016f9d5f6SRichard Henderson }
54116f9d5f6SRichard Henderson 
HELPER(exception_swstep)542f0d7c205SRichard Henderson void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)
543f0d7c205SRichard Henderson {
54404eacf6eSRichard Henderson     raise_exception_debug(env, EXCP_UDEF, syndrome);
545f0d7c205SRichard Henderson }
546f0d7c205SRichard Henderson 
hw_watchpoint_update(ARMCPU * cpu,int n)5472059ec75SFabiano Rosas void hw_watchpoint_update(ARMCPU *cpu, int n)
5482059ec75SFabiano Rosas {
5492059ec75SFabiano Rosas     CPUARMState *env = &cpu->env;
5502059ec75SFabiano Rosas     vaddr len = 0;
5512059ec75SFabiano Rosas     vaddr wvr = env->cp15.dbgwvr[n];
5522059ec75SFabiano Rosas     uint64_t wcr = env->cp15.dbgwcr[n];
5532059ec75SFabiano Rosas     int mask;
5542059ec75SFabiano Rosas     int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
5552059ec75SFabiano Rosas 
5562059ec75SFabiano Rosas     if (env->cpu_watchpoint[n]) {
5572059ec75SFabiano Rosas         cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]);
5582059ec75SFabiano Rosas         env->cpu_watchpoint[n] = NULL;
5592059ec75SFabiano Rosas     }
5602059ec75SFabiano Rosas 
5612059ec75SFabiano Rosas     if (!FIELD_EX64(wcr, DBGWCR, E)) {
5622059ec75SFabiano Rosas         /* E bit clear : watchpoint disabled */
5632059ec75SFabiano Rosas         return;
5642059ec75SFabiano Rosas     }
5652059ec75SFabiano Rosas 
5662059ec75SFabiano Rosas     switch (FIELD_EX64(wcr, DBGWCR, LSC)) {
5672059ec75SFabiano Rosas     case 0:
5682059ec75SFabiano Rosas         /* LSC 00 is reserved and must behave as if the wp is disabled */
5692059ec75SFabiano Rosas         return;
5702059ec75SFabiano Rosas     case 1:
5712059ec75SFabiano Rosas         flags |= BP_MEM_READ;
5722059ec75SFabiano Rosas         break;
5732059ec75SFabiano Rosas     case 2:
5742059ec75SFabiano Rosas         flags |= BP_MEM_WRITE;
5752059ec75SFabiano Rosas         break;
5762059ec75SFabiano Rosas     case 3:
5772059ec75SFabiano Rosas         flags |= BP_MEM_ACCESS;
5782059ec75SFabiano Rosas         break;
5792059ec75SFabiano Rosas     }
5802059ec75SFabiano Rosas 
5812059ec75SFabiano Rosas     /*
5822059ec75SFabiano Rosas      * Attempts to use both MASK and BAS fields simultaneously are
5832059ec75SFabiano Rosas      * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case,
5842059ec75SFabiano Rosas      * thus generating a watchpoint for every byte in the masked region.
5852059ec75SFabiano Rosas      */
5862059ec75SFabiano Rosas     mask = FIELD_EX64(wcr, DBGWCR, MASK);
5872059ec75SFabiano Rosas     if (mask == 1 || mask == 2) {
5882059ec75SFabiano Rosas         /*
5892059ec75SFabiano Rosas          * Reserved values of MASK; we must act as if the mask value was
5902059ec75SFabiano Rosas          * some non-reserved value, or as if the watchpoint were disabled.
5912059ec75SFabiano Rosas          * We choose the latter.
5922059ec75SFabiano Rosas          */
5932059ec75SFabiano Rosas         return;
5942059ec75SFabiano Rosas     } else if (mask) {
5952059ec75SFabiano Rosas         /* Watchpoint covers an aligned area up to 2GB in size */
5962059ec75SFabiano Rosas         len = 1ULL << mask;
5972059ec75SFabiano Rosas         /*
5982059ec75SFabiano Rosas          * If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE
5992059ec75SFabiano Rosas          * whether the watchpoint fires when the unmasked bits match; we opt
6002059ec75SFabiano Rosas          * to generate the exceptions.
6012059ec75SFabiano Rosas          */
6022059ec75SFabiano Rosas         wvr &= ~(len - 1);
6032059ec75SFabiano Rosas     } else {
6042059ec75SFabiano Rosas         /* Watchpoint covers bytes defined by the byte address select bits */
6052059ec75SFabiano Rosas         int bas = FIELD_EX64(wcr, DBGWCR, BAS);
6062059ec75SFabiano Rosas         int basstart;
6072059ec75SFabiano Rosas 
6082059ec75SFabiano Rosas         if (extract64(wvr, 2, 1)) {
6092059ec75SFabiano Rosas             /*
6102059ec75SFabiano Rosas              * Deprecated case of an only 4-aligned address. BAS[7:4] are
6112059ec75SFabiano Rosas              * ignored, and BAS[3:0] define which bytes to watch.
6122059ec75SFabiano Rosas              */
6132059ec75SFabiano Rosas             bas &= 0xf;
6142059ec75SFabiano Rosas         }
6152059ec75SFabiano Rosas 
6162059ec75SFabiano Rosas         if (bas == 0) {
6172059ec75SFabiano Rosas             /* This must act as if the watchpoint is disabled */
6182059ec75SFabiano Rosas             return;
6192059ec75SFabiano Rosas         }
6202059ec75SFabiano Rosas 
6212059ec75SFabiano Rosas         /*
6222059ec75SFabiano Rosas          * The BAS bits are supposed to be programmed to indicate a contiguous
6232059ec75SFabiano Rosas          * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether
6242059ec75SFabiano Rosas          * we fire for each byte in the word/doubleword addressed by the WVR.
6252059ec75SFabiano Rosas          * We choose to ignore any non-zero bits after the first range of 1s.
6262059ec75SFabiano Rosas          */
6272059ec75SFabiano Rosas         basstart = ctz32(bas);
6282059ec75SFabiano Rosas         len = cto32(bas >> basstart);
6292059ec75SFabiano Rosas         wvr += basstart;
6302059ec75SFabiano Rosas     }
6312059ec75SFabiano Rosas 
6322059ec75SFabiano Rosas     cpu_watchpoint_insert(CPU(cpu), wvr, len, flags,
6332059ec75SFabiano Rosas                           &env->cpu_watchpoint[n]);
6342059ec75SFabiano Rosas }
6352059ec75SFabiano Rosas 
hw_watchpoint_update_all(ARMCPU * cpu)6362059ec75SFabiano Rosas void hw_watchpoint_update_all(ARMCPU *cpu)
6372059ec75SFabiano Rosas {
6382059ec75SFabiano Rosas     int i;
6392059ec75SFabiano Rosas     CPUARMState *env = &cpu->env;
6402059ec75SFabiano Rosas 
6412059ec75SFabiano Rosas     /*
6422059ec75SFabiano Rosas      * Completely clear out existing QEMU watchpoints and our array, to
6432059ec75SFabiano Rosas      * avoid possible stale entries following migration load.
6442059ec75SFabiano Rosas      */
6452059ec75SFabiano Rosas     cpu_watchpoint_remove_all(CPU(cpu), BP_CPU);
6462059ec75SFabiano Rosas     memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint));
6472059ec75SFabiano Rosas 
6482059ec75SFabiano Rosas     for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) {
6492059ec75SFabiano Rosas         hw_watchpoint_update(cpu, i);
6502059ec75SFabiano Rosas     }
6512059ec75SFabiano Rosas }
6522059ec75SFabiano Rosas 
hw_breakpoint_update(ARMCPU * cpu,int n)6532059ec75SFabiano Rosas void hw_breakpoint_update(ARMCPU *cpu, int n)
6542059ec75SFabiano Rosas {
6552059ec75SFabiano Rosas     CPUARMState *env = &cpu->env;
6562059ec75SFabiano Rosas     uint64_t bvr = env->cp15.dbgbvr[n];
6572059ec75SFabiano Rosas     uint64_t bcr = env->cp15.dbgbcr[n];
6582059ec75SFabiano Rosas     vaddr addr;
6592059ec75SFabiano Rosas     int bt;
6602059ec75SFabiano Rosas     int flags = BP_CPU;
6612059ec75SFabiano Rosas 
6622059ec75SFabiano Rosas     if (env->cpu_breakpoint[n]) {
6632059ec75SFabiano Rosas         cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]);
6642059ec75SFabiano Rosas         env->cpu_breakpoint[n] = NULL;
6652059ec75SFabiano Rosas     }
6662059ec75SFabiano Rosas 
6672059ec75SFabiano Rosas     if (!extract64(bcr, 0, 1)) {
6682059ec75SFabiano Rosas         /* E bit clear : watchpoint disabled */
6692059ec75SFabiano Rosas         return;
6702059ec75SFabiano Rosas     }
6712059ec75SFabiano Rosas 
6722059ec75SFabiano Rosas     bt = extract64(bcr, 20, 4);
6732059ec75SFabiano Rosas 
6742059ec75SFabiano Rosas     switch (bt) {
6752059ec75SFabiano Rosas     case 4: /* unlinked address mismatch (reserved if AArch64) */
6762059ec75SFabiano Rosas     case 5: /* linked address mismatch (reserved if AArch64) */
6772059ec75SFabiano Rosas         qemu_log_mask(LOG_UNIMP,
6782059ec75SFabiano Rosas                       "arm: address mismatch breakpoint types not implemented\n");
6792059ec75SFabiano Rosas         return;
6802059ec75SFabiano Rosas     case 0: /* unlinked address match */
6812059ec75SFabiano Rosas     case 1: /* linked address match */
6822059ec75SFabiano Rosas     {
6832059ec75SFabiano Rosas         /*
6842059ec75SFabiano Rosas          * Bits [1:0] are RES0.
6852059ec75SFabiano Rosas          *
6862059ec75SFabiano Rosas          * It is IMPLEMENTATION DEFINED whether bits [63:49]
6872059ec75SFabiano Rosas          * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit
6882059ec75SFabiano Rosas          * of the VA field ([48] or [52] for FEAT_LVA), or whether the
6892059ec75SFabiano Rosas          * value is read as written.  It is CONSTRAINED UNPREDICTABLE
6902059ec75SFabiano Rosas          * whether the RESS bits are ignored when comparing an address.
6912059ec75SFabiano Rosas          * Therefore we are allowed to compare the entire register, which
6922059ec75SFabiano Rosas          * lets us avoid considering whether FEAT_LVA is actually enabled.
6932059ec75SFabiano Rosas          *
6942059ec75SFabiano Rosas          * The BAS field is used to allow setting breakpoints on 16-bit
6952059ec75SFabiano Rosas          * wide instructions; it is CONSTRAINED UNPREDICTABLE whether
6962059ec75SFabiano Rosas          * a bp will fire if the addresses covered by the bp and the addresses
6972059ec75SFabiano Rosas          * covered by the insn overlap but the insn doesn't start at the
6982059ec75SFabiano Rosas          * start of the bp address range. We choose to require the insn and
6992059ec75SFabiano Rosas          * the bp to have the same address. The constraints on writing to
7002059ec75SFabiano Rosas          * BAS enforced in dbgbcr_write mean we have only four cases:
7012059ec75SFabiano Rosas          *  0b0000  => no breakpoint
7022059ec75SFabiano Rosas          *  0b0011  => breakpoint on addr
7032059ec75SFabiano Rosas          *  0b1100  => breakpoint on addr + 2
7042059ec75SFabiano Rosas          *  0b1111  => breakpoint on addr
7052059ec75SFabiano Rosas          * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c).
7062059ec75SFabiano Rosas          */
7072059ec75SFabiano Rosas         int bas = extract64(bcr, 5, 4);
7082059ec75SFabiano Rosas         addr = bvr & ~3ULL;
7092059ec75SFabiano Rosas         if (bas == 0) {
7102059ec75SFabiano Rosas             return;
7112059ec75SFabiano Rosas         }
7122059ec75SFabiano Rosas         if (bas == 0xc) {
7132059ec75SFabiano Rosas             addr += 2;
7142059ec75SFabiano Rosas         }
7152059ec75SFabiano Rosas         break;
7162059ec75SFabiano Rosas     }
7172059ec75SFabiano Rosas     case 2: /* unlinked context ID match */
7182059ec75SFabiano Rosas     case 8: /* unlinked VMID match (reserved if no EL2) */
7192059ec75SFabiano Rosas     case 10: /* unlinked context ID and VMID match (reserved if no EL2) */
7202059ec75SFabiano Rosas         qemu_log_mask(LOG_UNIMP,
7212059ec75SFabiano Rosas                       "arm: unlinked context breakpoint types not implemented\n");
7222059ec75SFabiano Rosas         return;
7232059ec75SFabiano Rosas     case 9: /* linked VMID match (reserved if no EL2) */
7242059ec75SFabiano Rosas     case 11: /* linked context ID and VMID match (reserved if no EL2) */
7252059ec75SFabiano Rosas     case 3: /* linked context ID match */
7262059ec75SFabiano Rosas     default:
7272059ec75SFabiano Rosas         /*
7282059ec75SFabiano Rosas          * We must generate no events for Linked context matches (unless
7292059ec75SFabiano Rosas          * they are linked to by some other bp/wp, which is handled in
7302059ec75SFabiano Rosas          * updates for the linking bp/wp). We choose to also generate no events
7312059ec75SFabiano Rosas          * for reserved values.
7322059ec75SFabiano Rosas          */
7332059ec75SFabiano Rosas         return;
7342059ec75SFabiano Rosas     }
7352059ec75SFabiano Rosas 
7362059ec75SFabiano Rosas     cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]);
7372059ec75SFabiano Rosas }
7382059ec75SFabiano Rosas 
hw_breakpoint_update_all(ARMCPU * cpu)7392059ec75SFabiano Rosas void hw_breakpoint_update_all(ARMCPU *cpu)
7402059ec75SFabiano Rosas {
7412059ec75SFabiano Rosas     int i;
7422059ec75SFabiano Rosas     CPUARMState *env = &cpu->env;
7432059ec75SFabiano Rosas 
7442059ec75SFabiano Rosas     /*
7452059ec75SFabiano Rosas      * Completely clear out existing QEMU breakpoints and our array, to
7462059ec75SFabiano Rosas      * avoid possible stale entries following migration load.
7472059ec75SFabiano Rosas      */
7482059ec75SFabiano Rosas     cpu_breakpoint_remove_all(CPU(cpu), BP_CPU);
7492059ec75SFabiano Rosas     memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint));
7502059ec75SFabiano Rosas 
7512059ec75SFabiano Rosas     for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) {
7522059ec75SFabiano Rosas         hw_breakpoint_update(cpu, i);
7532059ec75SFabiano Rosas     }
7542059ec75SFabiano Rosas }
7552059ec75SFabiano Rosas 
7562059ec75SFabiano Rosas #if !defined(CONFIG_USER_ONLY)
7572059ec75SFabiano Rosas 
arm_adjust_watchpoint_address(CPUState * cs,vaddr addr,int len)7582059ec75SFabiano Rosas vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
7592059ec75SFabiano Rosas {
7602059ec75SFabiano Rosas     ARMCPU *cpu = ARM_CPU(cs);
7612059ec75SFabiano Rosas     CPUARMState *env = &cpu->env;
7622059ec75SFabiano Rosas 
7632059ec75SFabiano Rosas     /*
7642059ec75SFabiano Rosas      * In BE32 system mode, target memory is stored byteswapped (on a
7652059ec75SFabiano Rosas      * little-endian host system), and by the time we reach here (via an
7662059ec75SFabiano Rosas      * opcode helper) the addresses of subword accesses have been adjusted
7672059ec75SFabiano Rosas      * to account for that, which means that watchpoints will not match.
7682059ec75SFabiano Rosas      * Undo the adjustment here.
7692059ec75SFabiano Rosas      */
7702059ec75SFabiano Rosas     if (arm_sctlr_b(env)) {
7712059ec75SFabiano Rosas         if (len == 1) {
7722059ec75SFabiano Rosas             addr ^= 3;
7732059ec75SFabiano Rosas         } else if (len == 2) {
7742059ec75SFabiano Rosas             addr ^= 2;
7752059ec75SFabiano Rosas         }
7762059ec75SFabiano Rosas     }
7772059ec75SFabiano Rosas 
7782059ec75SFabiano Rosas     return addr;
7792059ec75SFabiano Rosas }
7802059ec75SFabiano Rosas 
7812059ec75SFabiano Rosas #endif /* !CONFIG_USER_ONLY */
7822059ec75SFabiano Rosas #endif /* CONFIG_TCG */
7832059ec75SFabiano Rosas 
784f43ee493SPeter Maydell /*
785f43ee493SPeter Maydell  * Check for traps to "powerdown debug" registers, which are controlled
786f43ee493SPeter Maydell  * by MDCR.TDOSA
787f43ee493SPeter Maydell  */
access_tdosa(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)788f43ee493SPeter Maydell static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri,
789f43ee493SPeter Maydell                                    bool isread)
790f43ee493SPeter Maydell {
791f43ee493SPeter Maydell     int el = arm_current_el(env);
792f43ee493SPeter Maydell     uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
793f43ee493SPeter Maydell     bool mdcr_el2_tdosa = (mdcr_el2 & MDCR_TDOSA) || (mdcr_el2 & MDCR_TDE) ||
794f43ee493SPeter Maydell         (arm_hcr_el2_eff(env) & HCR_TGE);
795f43ee493SPeter Maydell 
796f43ee493SPeter Maydell     if (el < 2 && mdcr_el2_tdosa) {
797f43ee493SPeter Maydell         return CP_ACCESS_TRAP_EL2;
798f43ee493SPeter Maydell     }
799f43ee493SPeter Maydell     if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) {
800f43ee493SPeter Maydell         return CP_ACCESS_TRAP_EL3;
801f43ee493SPeter Maydell     }
802f43ee493SPeter Maydell     return CP_ACCESS_OK;
803f43ee493SPeter Maydell }
804f43ee493SPeter Maydell 
805f43ee493SPeter Maydell /*
806f43ee493SPeter Maydell  * Check for traps to "debug ROM" registers, which are controlled
807f43ee493SPeter Maydell  * by MDCR_EL2.TDRA for EL2 but by the more general MDCR_EL3.TDA for EL3.
808f43ee493SPeter Maydell  */
access_tdra(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)809f43ee493SPeter Maydell static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri,
810f43ee493SPeter Maydell                                   bool isread)
811f43ee493SPeter Maydell {
812f43ee493SPeter Maydell     int el = arm_current_el(env);
813f43ee493SPeter Maydell     uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
814f43ee493SPeter Maydell     bool mdcr_el2_tdra = (mdcr_el2 & MDCR_TDRA) || (mdcr_el2 & MDCR_TDE) ||
815f43ee493SPeter Maydell         (arm_hcr_el2_eff(env) & HCR_TGE);
816f43ee493SPeter Maydell 
817f43ee493SPeter Maydell     if (el < 2 && mdcr_el2_tdra) {
818f43ee493SPeter Maydell         return CP_ACCESS_TRAP_EL2;
819f43ee493SPeter Maydell     }
820f43ee493SPeter Maydell     if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) {
821f43ee493SPeter Maydell         return CP_ACCESS_TRAP_EL3;
822f43ee493SPeter Maydell     }
823f43ee493SPeter Maydell     return CP_ACCESS_OK;
824f43ee493SPeter Maydell }
825f43ee493SPeter Maydell 
826f43ee493SPeter Maydell /*
827f43ee493SPeter Maydell  * Check for traps to general debug registers, which are controlled
828f43ee493SPeter Maydell  * by MDCR_EL2.TDA for EL2 and MDCR_EL3.TDA for EL3.
829f43ee493SPeter Maydell  */
access_tda(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)830f43ee493SPeter Maydell static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri,
831f43ee493SPeter Maydell                                   bool isread)
832f43ee493SPeter Maydell {
833f43ee493SPeter Maydell     int el = arm_current_el(env);
834f43ee493SPeter Maydell     uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
835f43ee493SPeter Maydell     bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) ||
836f43ee493SPeter Maydell         (arm_hcr_el2_eff(env) & HCR_TGE);
837f43ee493SPeter Maydell 
838f43ee493SPeter Maydell     if (el < 2 && mdcr_el2_tda) {
839f43ee493SPeter Maydell         return CP_ACCESS_TRAP_EL2;
840f43ee493SPeter Maydell     }
841f43ee493SPeter Maydell     if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) {
842f43ee493SPeter Maydell         return CP_ACCESS_TRAP_EL3;
843f43ee493SPeter Maydell     }
844f43ee493SPeter Maydell     return CP_ACCESS_OK;
845f43ee493SPeter Maydell }
846f43ee493SPeter Maydell 
access_dbgvcr32(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)84783aea11dSPeter Maydell static CPAccessResult access_dbgvcr32(CPUARMState *env, const ARMCPRegInfo *ri,
84883aea11dSPeter Maydell                                       bool isread)
84983aea11dSPeter Maydell {
85083aea11dSPeter Maydell     /* MCDR_EL3.TDMA doesn't apply for FEAT_NV traps */
85183aea11dSPeter Maydell     if (arm_current_el(env) == 2 && (env->cp15.mdcr_el3 & MDCR_TDA)) {
85283aea11dSPeter Maydell         return CP_ACCESS_TRAP_EL3;
85383aea11dSPeter Maydell     }
85483aea11dSPeter Maydell     return CP_ACCESS_OK;
85583aea11dSPeter Maydell }
85683aea11dSPeter Maydell 
8571748ef03SPeter Maydell /*
8581748ef03SPeter Maydell  * Check for traps to Debug Comms Channel registers. If FEAT_FGT
8591748ef03SPeter Maydell  * is implemented then these are controlled by MDCR_EL2.TDCC for
8601748ef03SPeter Maydell  * EL2 and MDCR_EL3.TDCC for EL3. They are also controlled by
8611748ef03SPeter Maydell  * the general debug access trap bits MDCR_EL2.TDA and MDCR_EL3.TDA.
862f9ac7788SZhuojia Shen  * For EL0, they are also controlled by MDSCR_EL1.TDCC.
8631748ef03SPeter Maydell  */
access_tdcc(CPUARMState * env,const ARMCPRegInfo * ri,bool isread)8641748ef03SPeter Maydell static CPAccessResult access_tdcc(CPUARMState *env, const ARMCPRegInfo *ri,
8651748ef03SPeter Maydell                                   bool isread)
8661748ef03SPeter Maydell {
8671748ef03SPeter Maydell     int el = arm_current_el(env);
8681748ef03SPeter Maydell     uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
869f9ac7788SZhuojia Shen     bool mdscr_el1_tdcc = extract32(env->cp15.mdscr_el1, 12, 1);
8701748ef03SPeter Maydell     bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) ||
8711748ef03SPeter Maydell         (arm_hcr_el2_eff(env) & HCR_TGE);
8721748ef03SPeter Maydell     bool mdcr_el2_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) &&
8731748ef03SPeter Maydell                                           (mdcr_el2 & MDCR_TDCC);
8741748ef03SPeter Maydell     bool mdcr_el3_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) &&
8751748ef03SPeter Maydell                                           (env->cp15.mdcr_el3 & MDCR_TDCC);
8761748ef03SPeter Maydell 
877f9ac7788SZhuojia Shen     if (el < 1 && mdscr_el1_tdcc) {
878f9ac7788SZhuojia Shen         return CP_ACCESS_TRAP;
879f9ac7788SZhuojia Shen     }
8801748ef03SPeter Maydell     if (el < 2 && (mdcr_el2_tda || mdcr_el2_tdcc)) {
8811748ef03SPeter Maydell         return CP_ACCESS_TRAP_EL2;
8821748ef03SPeter Maydell     }
883*37600704SPeter Maydell     if (!arm_is_el3_or_mon(env) &&
884*37600704SPeter Maydell         ((env->cp15.mdcr_el3 & MDCR_TDA) || mdcr_el3_tdcc)) {
8851748ef03SPeter Maydell         return CP_ACCESS_TRAP_EL3;
8861748ef03SPeter Maydell     }
8871748ef03SPeter Maydell     return CP_ACCESS_OK;
8881748ef03SPeter Maydell }
oslar_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)8891748ef03SPeter Maydell 
890f43ee493SPeter Maydell static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri,
891f43ee493SPeter Maydell                         uint64_t value)
892f43ee493SPeter Maydell {
893f43ee493SPeter Maydell     /*
894f43ee493SPeter Maydell      * Writes to OSLAR_EL1 may update the OS lock status, which can be
895f43ee493SPeter Maydell      * read via a bit in OSLSR_EL1.
896f43ee493SPeter Maydell      */
897f43ee493SPeter Maydell     int oslock;
898f43ee493SPeter Maydell 
899f43ee493SPeter Maydell     if (ri->state == ARM_CP_STATE_AA32) {
900f43ee493SPeter Maydell         oslock = (value == 0xC5ACCE55);
901f43ee493SPeter Maydell     } else {
902f43ee493SPeter Maydell         oslock = value & 1;
903f43ee493SPeter Maydell     }
904f43ee493SPeter Maydell 
905f43ee493SPeter Maydell     env->cp15.oslsr_el1 = deposit32(env->cp15.oslsr_el1, 1, 1, oslock);
906f43ee493SPeter Maydell }
osdlr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)907f43ee493SPeter Maydell 
908f94a6df5SPeter Maydell static void osdlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
909f94a6df5SPeter Maydell                         uint64_t value)
910f94a6df5SPeter Maydell {
911f94a6df5SPeter Maydell     ARMCPU *cpu = env_archcpu(env);
912f94a6df5SPeter Maydell     /*
913f94a6df5SPeter Maydell      * Only defined bit is bit 0 (DLK); if Feat_DoubleLock is not
914f94a6df5SPeter Maydell      * implemented this is RAZ/WI.
915f94a6df5SPeter Maydell      */
916f94a6df5SPeter Maydell     if(arm_feature(env, ARM_FEATURE_AARCH64)
917f94a6df5SPeter Maydell        ? cpu_isar_feature(aa64_doublelock, cpu)
918f94a6df5SPeter Maydell        : cpu_isar_feature(aa32_doublelock, cpu)) {
919f94a6df5SPeter Maydell         env->cp15.osdlr_el1 = value & 1;
920f94a6df5SPeter Maydell     }
921f94a6df5SPeter Maydell }
dbgclaimset_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)922f94a6df5SPeter Maydell 
9235fc83f11SEvgeny Iakovlev static void dbgclaimset_write(CPUARMState *env, const ARMCPRegInfo *ri,
9245fc83f11SEvgeny Iakovlev                               uint64_t value)
9255fc83f11SEvgeny Iakovlev {
9265fc83f11SEvgeny Iakovlev     env->cp15.dbgclaim |= (value & 0xFF);
9275fc83f11SEvgeny Iakovlev }
dbgclaimset_read(CPUARMState * env,const ARMCPRegInfo * ri)9285fc83f11SEvgeny Iakovlev 
9295fc83f11SEvgeny Iakovlev static uint64_t dbgclaimset_read(CPUARMState *env, const ARMCPRegInfo *ri)
9305fc83f11SEvgeny Iakovlev {
9315fc83f11SEvgeny Iakovlev     /* CLAIM bits are RAO */
9325fc83f11SEvgeny Iakovlev     return 0xFF;
9335fc83f11SEvgeny Iakovlev }
dbgclaimclr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)9345fc83f11SEvgeny Iakovlev 
9355fc83f11SEvgeny Iakovlev static void dbgclaimclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
9365fc83f11SEvgeny Iakovlev                               uint64_t value)
9375fc83f11SEvgeny Iakovlev {
9385fc83f11SEvgeny Iakovlev     env->cp15.dbgclaim &= ~(value & 0xFF);
9395fc83f11SEvgeny Iakovlev }
9405fc83f11SEvgeny Iakovlev 
941f43ee493SPeter Maydell static const ARMCPRegInfo debug_cp_reginfo[] = {
942f43ee493SPeter Maydell     /*
943f43ee493SPeter Maydell      * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped
944f43ee493SPeter Maydell      * debug components. The AArch64 version of DBGDRAR is named MDRAR_EL1;
945f43ee493SPeter Maydell      * unlike DBGDRAR it is never accessible from EL0.
946f43ee493SPeter Maydell      * DBGDSAR is deprecated and must RAZ from v8 anyway, so it has no AArch64
947f43ee493SPeter Maydell      * accessor.
948f43ee493SPeter Maydell      */
949f43ee493SPeter Maydell     { .name = "DBGDRAR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
950f43ee493SPeter Maydell       .access = PL0_R, .accessfn = access_tdra,
951f654387bSAlex Bennée       .type = ARM_CP_CONST | ARM_CP_NO_GDB, .resetvalue = 0 },
952f43ee493SPeter Maydell     { .name = "MDRAR_EL1", .state = ARM_CP_STATE_AA64,
953f43ee493SPeter Maydell       .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0,
954f43ee493SPeter Maydell       .access = PL1_R, .accessfn = access_tdra,
955f43ee493SPeter Maydell       .type = ARM_CP_CONST, .resetvalue = 0 },
956f43ee493SPeter Maydell     { .name = "DBGDSAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
957f43ee493SPeter Maydell       .access = PL0_R, .accessfn = access_tdra,
958f654387bSAlex Bennée       .type = ARM_CP_CONST | ARM_CP_NO_GDB, .resetvalue = 0 },
959f43ee493SPeter Maydell     /* Monitor debug system control register; the 32-bit alias is DBGDSCRext. */
960f43ee493SPeter Maydell     { .name = "MDSCR_EL1", .state = ARM_CP_STATE_BOTH,
961f43ee493SPeter Maydell       .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,
962f43ee493SPeter Maydell       .access = PL1_RW, .accessfn = access_tda,
963917b1405SPeter Maydell       .fgt = FGT_MDSCR_EL1,
964bb7b95b0SPeter Maydell       .nv2_redirect_offset = 0x158,
965f43ee493SPeter Maydell       .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1),
966f43ee493SPeter Maydell       .resetvalue = 0 },
967f43ee493SPeter Maydell     /*
968f43ee493SPeter Maydell      * MDCCSR_EL0[30:29] map to EDSCR[30:29].  Simply RAZ as the external
969f43ee493SPeter Maydell      * Debug Communication Channel is not implemented.
970f43ee493SPeter Maydell      */
971f43ee493SPeter Maydell     { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_AA64,
972f43ee493SPeter Maydell       .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 1, .opc2 = 0,
9731748ef03SPeter Maydell       .access = PL0_R, .accessfn = access_tdcc,
974f43ee493SPeter Maydell       .type = ARM_CP_CONST, .resetvalue = 0 },
975f43ee493SPeter Maydell     /*
97670a670caSAlex Bennée      * These registers belong to the Debug Communications Channel,
97770a670caSAlex Bennée      * which is not implemented. However we implement RAZ/WI behaviour
97870a670caSAlex Bennée      * with trapping to prevent spurious SIGILLs if the guest OS does
97970a670caSAlex Bennée      * access them as the support cannot be probed for.
980b3aa2f21SEvgeny Iakovlev      */
981b3aa2f21SEvgeny Iakovlev     { .name = "OSDTRRX_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14,
982b3aa2f21SEvgeny Iakovlev       .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 2,
9831748ef03SPeter Maydell       .access = PL1_RW, .accessfn = access_tdcc,
984b3aa2f21SEvgeny Iakovlev       .type = ARM_CP_CONST, .resetvalue = 0 },
985b3aa2f21SEvgeny Iakovlev     { .name = "OSDTRTX_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14,
986b3aa2f21SEvgeny Iakovlev       .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
9871748ef03SPeter Maydell       .access = PL1_RW, .accessfn = access_tdcc,
988b3aa2f21SEvgeny Iakovlev       .type = ARM_CP_CONST, .resetvalue = 0 },
98970a670caSAlex Bennée     /* DBGDTRTX_EL0/DBGDTRRX_EL0 depend on direction */
99070a670caSAlex Bennée     { .name = "DBGDTR_EL0", .state = ARM_CP_STATE_BOTH, .cp = 14,
99170a670caSAlex Bennée       .opc0 = 2, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0,
99270a670caSAlex Bennée       .access = PL0_RW, .accessfn = access_tdcc,
99370a670caSAlex Bennée       .type = ARM_CP_CONST, .resetvalue = 0 },
994b3aa2f21SEvgeny Iakovlev     /*
995b3aa2f21SEvgeny Iakovlev      * OSECCR_EL1 provides a mechanism for an operating system
996b3aa2f21SEvgeny Iakovlev      * to access the contents of EDECCR. EDECCR is not implemented though,
997b3aa2f21SEvgeny Iakovlev      * as is the rest of external device mechanism.
998b3aa2f21SEvgeny Iakovlev      */
999b3aa2f21SEvgeny Iakovlev     { .name = "OSECCR_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14,
1000b3aa2f21SEvgeny Iakovlev       .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2,
1001b3aa2f21SEvgeny Iakovlev       .access = PL1_RW, .accessfn = access_tda,
1002917b1405SPeter Maydell       .fgt = FGT_OSECCR_EL1,
1003b3aa2f21SEvgeny Iakovlev       .type = ARM_CP_CONST, .resetvalue = 0 },
1004b3aa2f21SEvgeny Iakovlev     /*
1005f43ee493SPeter Maydell      * DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2].  Map all bits as
1006f43ee493SPeter Maydell      * it is unlikely a guest will care.
1007f43ee493SPeter Maydell      * We don't implement the configurable EL0 access.
1008f43ee493SPeter Maydell      */
1009f43ee493SPeter Maydell     { .name = "DBGDSCRint", .state = ARM_CP_STATE_AA32,
1010f43ee493SPeter Maydell       .cp = 14, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0,
1011f43ee493SPeter Maydell       .type = ARM_CP_ALIAS,
1012f43ee493SPeter Maydell       .access = PL1_R, .accessfn = access_tda,
1013f43ee493SPeter Maydell       .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), },
1014f43ee493SPeter Maydell     { .name = "OSLAR_EL1", .state = ARM_CP_STATE_BOTH,
1015f43ee493SPeter Maydell       .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4,
1016f43ee493SPeter Maydell       .access = PL1_W, .type = ARM_CP_NO_RAW,
1017f43ee493SPeter Maydell       .accessfn = access_tdosa,
1018917b1405SPeter Maydell       .fgt = FGT_OSLAR_EL1,
1019f43ee493SPeter Maydell       .writefn = oslar_write },
1020f43ee493SPeter Maydell     { .name = "OSLSR_EL1", .state = ARM_CP_STATE_BOTH,
1021f43ee493SPeter Maydell       .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 4,
1022f43ee493SPeter Maydell       .access = PL1_R, .resetvalue = 10,
1023f43ee493SPeter Maydell       .accessfn = access_tdosa,
1024917b1405SPeter Maydell       .fgt = FGT_OSLSR_EL1,
1025f43ee493SPeter Maydell       .fieldoffset = offsetof(CPUARMState, cp15.oslsr_el1) },
1026f43ee493SPeter Maydell     /* Dummy OSDLR_EL1: 32-bit Linux will read this */
1027f43ee493SPeter Maydell     { .name = "OSDLR_EL1", .state = ARM_CP_STATE_BOTH,
1028f43ee493SPeter Maydell       .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 4,
1029f43ee493SPeter Maydell       .access = PL1_RW, .accessfn = access_tdosa,
1030917b1405SPeter Maydell       .fgt = FGT_OSDLR_EL1,
1031f94a6df5SPeter Maydell       .writefn = osdlr_write,
1032f94a6df5SPeter Maydell       .fieldoffset = offsetof(CPUARMState, cp15.osdlr_el1) },
1033f43ee493SPeter Maydell     /*
1034f43ee493SPeter Maydell      * Dummy DBGVCR: Linux wants to clear this on startup, but we don't
1035f43ee493SPeter Maydell      * implement vector catch debug events yet.
1036f43ee493SPeter Maydell      */
1037f43ee493SPeter Maydell     { .name = "DBGVCR",
1038f43ee493SPeter Maydell       .cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
1039f43ee493SPeter Maydell       .access = PL1_RW, .accessfn = access_tda,
1040f43ee493SPeter Maydell       .type = ARM_CP_NOP },
1041f43ee493SPeter Maydell     /*
1042f43ee493SPeter Maydell      * Dummy MDCCINT_EL1, since we don't implement the Debug Communications
1043f43ee493SPeter Maydell      * Channel but Linux may try to access this register. The 32-bit
1044f43ee493SPeter Maydell      * alias is DBGDCCINT.
1045f43ee493SPeter Maydell      */
1046f43ee493SPeter Maydell     { .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH,
1047f43ee493SPeter Maydell       .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
10481748ef03SPeter Maydell       .access = PL1_RW, .accessfn = access_tdcc,
1049f43ee493SPeter Maydell       .type = ARM_CP_NOP },
10505fc83f11SEvgeny Iakovlev     /*
10515fc83f11SEvgeny Iakovlev      * Dummy DBGCLAIM registers.
10525fc83f11SEvgeny Iakovlev      * "The architecture does not define any functionality for the CLAIM tag bits.",
10535fc83f11SEvgeny Iakovlev      * so we only keep the raw bits
10545fc83f11SEvgeny Iakovlev      */
10555fc83f11SEvgeny Iakovlev     { .name = "DBGCLAIMSET_EL1", .state = ARM_CP_STATE_BOTH,
10565fc83f11SEvgeny Iakovlev       .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 6,
10575fc83f11SEvgeny Iakovlev       .type = ARM_CP_ALIAS,
10585fc83f11SEvgeny Iakovlev       .access = PL1_RW, .accessfn = access_tda,
1059917b1405SPeter Maydell       .fgt = FGT_DBGCLAIM,
10605fc83f11SEvgeny Iakovlev       .writefn = dbgclaimset_write, .readfn = dbgclaimset_read },
10615fc83f11SEvgeny Iakovlev     { .name = "DBGCLAIMCLR_EL1", .state = ARM_CP_STATE_BOTH,
10625fc83f11SEvgeny Iakovlev       .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 6,
10635fc83f11SEvgeny Iakovlev       .access = PL1_RW, .accessfn = access_tda,
1064917b1405SPeter Maydell       .fgt = FGT_DBGCLAIM,
10655fc83f11SEvgeny Iakovlev       .writefn = dbgclaimclr_write, .raw_writefn = raw_write,
10665fc83f11SEvgeny Iakovlev       .fieldoffset = offsetof(CPUARMState, cp15.dbgclaim) },
1067f43ee493SPeter Maydell };
1068f43ee493SPeter Maydell 
1069c36a0d57SPeter Maydell /* These are present only when EL1 supports AArch32 */
1070c36a0d57SPeter Maydell static const ARMCPRegInfo debug_aa32_el1_reginfo[] = {
1071c36a0d57SPeter Maydell     /*
1072c36a0d57SPeter Maydell      * Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor
1073c36a0d57SPeter Maydell      * to save and restore a 32-bit guest's DBGVCR)
1074c36a0d57SPeter Maydell      */
1075c36a0d57SPeter Maydell     { .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64,
1076c36a0d57SPeter Maydell       .opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,
107783aea11dSPeter Maydell       .access = PL2_RW, .accessfn = access_dbgvcr32,
1078c36a0d57SPeter Maydell       .type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP },
1079c36a0d57SPeter Maydell };
1080c36a0d57SPeter Maydell 
1081f43ee493SPeter Maydell static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
1082f43ee493SPeter Maydell     /* 64 bit access versions of the (dummy) debug registers */
1083f43ee493SPeter Maydell     { .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0,
1084f654387bSAlex Bennée       .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT | ARM_CP_NO_GDB,
1085f654387bSAlex Bennée       .resetvalue = 0 },
1086f43ee493SPeter Maydell     { .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0,
1087f654387bSAlex Bennée       .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT | ARM_CP_NO_GDB,
1088f654387bSAlex Bennée       .resetvalue = 0 },
1089f43ee493SPeter Maydell };
dbgwvr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)1090f43ee493SPeter Maydell 
1091f43ee493SPeter Maydell static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1092f43ee493SPeter Maydell                          uint64_t value)
1093f43ee493SPeter Maydell {
1094f43ee493SPeter Maydell     ARMCPU *cpu = env_archcpu(env);
1095f43ee493SPeter Maydell     int i = ri->crm;
1096f43ee493SPeter Maydell 
1097f43ee493SPeter Maydell     /*
1098f43ee493SPeter Maydell      * Bits [1:0] are RES0.
1099f43ee493SPeter Maydell      *
1100f43ee493SPeter Maydell      * It is IMPLEMENTATION DEFINED whether [63:49] ([63:53] with FEAT_LVA)
1101f43ee493SPeter Maydell      * are hardwired to the value of bit [48] ([52] with FEAT_LVA), or if
1102f43ee493SPeter Maydell      * they contain the value written.  It is CONSTRAINED UNPREDICTABLE
1103f43ee493SPeter Maydell      * whether the RESS bits are ignored when comparing an address.
1104f43ee493SPeter Maydell      *
1105f43ee493SPeter Maydell      * Therefore we are allowed to compare the entire register, which lets
1106f43ee493SPeter Maydell      * us avoid considering whether or not FEAT_LVA is actually enabled.
1107f43ee493SPeter Maydell      */
1108f43ee493SPeter Maydell     value &= ~3ULL;
1109f43ee493SPeter Maydell 
1110f43ee493SPeter Maydell     raw_write(env, ri, value);
1111fa05d1abSFabiano Rosas     if (tcg_enabled()) {
1112f43ee493SPeter Maydell         hw_watchpoint_update(cpu, i);
1113f43ee493SPeter Maydell     }
1114fa05d1abSFabiano Rosas }
dbgwcr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)1115f43ee493SPeter Maydell 
1116f43ee493SPeter Maydell static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1117f43ee493SPeter Maydell                          uint64_t value)
1118f43ee493SPeter Maydell {
1119f43ee493SPeter Maydell     ARMCPU *cpu = env_archcpu(env);
1120f43ee493SPeter Maydell     int i = ri->crm;
1121f43ee493SPeter Maydell 
1122f43ee493SPeter Maydell     raw_write(env, ri, value);
1123fa05d1abSFabiano Rosas     if (tcg_enabled()) {
1124f43ee493SPeter Maydell         hw_watchpoint_update(cpu, i);
1125f43ee493SPeter Maydell     }
1126fa05d1abSFabiano Rosas }
dbgbvr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)1127f43ee493SPeter Maydell 
1128f43ee493SPeter Maydell static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1129f43ee493SPeter Maydell                          uint64_t value)
1130f43ee493SPeter Maydell {
1131f43ee493SPeter Maydell     ARMCPU *cpu = env_archcpu(env);
1132f43ee493SPeter Maydell     int i = ri->crm;
1133f43ee493SPeter Maydell 
1134f43ee493SPeter Maydell     raw_write(env, ri, value);
1135fa05d1abSFabiano Rosas     if (tcg_enabled()) {
1136f43ee493SPeter Maydell         hw_breakpoint_update(cpu, i);
1137f43ee493SPeter Maydell     }
1138fa05d1abSFabiano Rosas }
dbgbcr_write(CPUARMState * env,const ARMCPRegInfo * ri,uint64_t value)1139f43ee493SPeter Maydell 
1140f43ee493SPeter Maydell static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1141f43ee493SPeter Maydell                          uint64_t value)
1142f43ee493SPeter Maydell {
1143f43ee493SPeter Maydell     ARMCPU *cpu = env_archcpu(env);
1144f43ee493SPeter Maydell     int i = ri->crm;
1145f43ee493SPeter Maydell 
1146f43ee493SPeter Maydell     /*
1147f43ee493SPeter Maydell      * BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only
1148f43ee493SPeter Maydell      * copy of BAS[0].
1149f43ee493SPeter Maydell      */
1150f43ee493SPeter Maydell     value = deposit64(value, 6, 1, extract64(value, 5, 1));
1151f43ee493SPeter Maydell     value = deposit64(value, 8, 1, extract64(value, 7, 1));
1152f43ee493SPeter Maydell 
1153f43ee493SPeter Maydell     raw_write(env, ri, value);
1154fa05d1abSFabiano Rosas     if (tcg_enabled()) {
1155f43ee493SPeter Maydell         hw_breakpoint_update(cpu, i);
1156f43ee493SPeter Maydell     }
1157fa05d1abSFabiano Rosas }
define_debug_regs(ARMCPU * cpu)1158f43ee493SPeter Maydell 
1159f43ee493SPeter Maydell void define_debug_regs(ARMCPU *cpu)
1160f43ee493SPeter Maydell {
1161f43ee493SPeter Maydell     /*
1162f43ee493SPeter Maydell      * Define v7 and v8 architectural debug registers.
1163f43ee493SPeter Maydell      * These are just dummy implementations for now.
1164f43ee493SPeter Maydell      */
1165f43ee493SPeter Maydell     int i;
1166f43ee493SPeter Maydell     int wrps, brps, ctx_cmps;
1167f43ee493SPeter Maydell 
1168f43ee493SPeter Maydell     /*
1169f43ee493SPeter Maydell      * The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot
1170f43ee493SPeter Maydell      * use AArch32.  Given that bit 15 is RES1, if the value is 0 then
1171f43ee493SPeter Maydell      * the register must not exist for this cpu.
1172f43ee493SPeter Maydell      */
1173f43ee493SPeter Maydell     if (cpu->isar.dbgdidr != 0) {
1174f43ee493SPeter Maydell         ARMCPRegInfo dbgdidr = {
1175f43ee493SPeter Maydell             .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0,
1176f43ee493SPeter Maydell             .opc1 = 0, .opc2 = 0,
1177f43ee493SPeter Maydell             .access = PL0_R, .accessfn = access_tda,
1178f43ee493SPeter Maydell             .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
1179f43ee493SPeter Maydell         };
1180f43ee493SPeter Maydell         define_one_arm_cp_reg(cpu, &dbgdidr);
1181f43ee493SPeter Maydell     }
1182f43ee493SPeter Maydell 
118309754ca8SPeter Maydell     /*
118409754ca8SPeter Maydell      * DBGDEVID is present in the v7 debug architecture if
118509754ca8SPeter Maydell      * DBGDIDR.DEVID_imp is 1 (bit 15); from v7.1 and on it is
118609754ca8SPeter Maydell      * mandatory (and bit 15 is RES1). DBGDEVID1 and DBGDEVID2 exist
118709754ca8SPeter Maydell      * from v7.1 of the debug architecture. Because no fields have yet
118809754ca8SPeter Maydell      * been defined in DBGDEVID2 (and quite possibly none will ever
118909754ca8SPeter Maydell      * be) we don't define an ARMISARegisters field for it.
119009754ca8SPeter Maydell      * These registers exist only if EL1 can use AArch32, but that
119109754ca8SPeter Maydell      * happens naturally because they are only PL1 accessible anyway.
119209754ca8SPeter Maydell      */
119309754ca8SPeter Maydell     if (extract32(cpu->isar.dbgdidr, 15, 1)) {
119409754ca8SPeter Maydell         ARMCPRegInfo dbgdevid = {
119509754ca8SPeter Maydell             .name = "DBGDEVID",
119609754ca8SPeter Maydell             .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 2, .crn = 7,
119709754ca8SPeter Maydell             .access = PL1_R, .accessfn = access_tda,
119809754ca8SPeter Maydell             .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdevid,
119909754ca8SPeter Maydell         };
120009754ca8SPeter Maydell         define_one_arm_cp_reg(cpu, &dbgdevid);
120109754ca8SPeter Maydell     }
120209754ca8SPeter Maydell     if (cpu_isar_feature(aa32_debugv7p1, cpu)) {
120309754ca8SPeter Maydell         ARMCPRegInfo dbgdevid12[] = {
120409754ca8SPeter Maydell             {
120509754ca8SPeter Maydell                 .name = "DBGDEVID1",
120609754ca8SPeter Maydell                 .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 1, .crn = 7,
120709754ca8SPeter Maydell                 .access = PL1_R, .accessfn = access_tda,
120809754ca8SPeter Maydell                 .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdevid1,
120909754ca8SPeter Maydell             }, {
121009754ca8SPeter Maydell                 .name = "DBGDEVID2",
121109754ca8SPeter Maydell                 .cp = 14, .opc1 = 0, .crn = 7, .opc2 = 0, .crn = 7,
121209754ca8SPeter Maydell                 .access = PL1_R, .accessfn = access_tda,
121309754ca8SPeter Maydell                 .type = ARM_CP_CONST, .resetvalue = 0,
121409754ca8SPeter Maydell             },
121509754ca8SPeter Maydell         };
121609754ca8SPeter Maydell         define_arm_cp_regs(cpu, dbgdevid12);
121709754ca8SPeter Maydell     }
121809754ca8SPeter Maydell 
1219f43ee493SPeter Maydell     brps = arm_num_brps(cpu);
1220f43ee493SPeter Maydell     wrps = arm_num_wrps(cpu);
1221f43ee493SPeter Maydell     ctx_cmps = arm_num_ctx_cmps(cpu);
1222f43ee493SPeter Maydell 
1223f43ee493SPeter Maydell     assert(ctx_cmps <= brps);
1224f43ee493SPeter Maydell 
1225f43ee493SPeter Maydell     define_arm_cp_regs(cpu, debug_cp_reginfo);
1226c36a0d57SPeter Maydell     if (cpu_isar_feature(aa64_aa32_el1, cpu)) {
1227c36a0d57SPeter Maydell         define_arm_cp_regs(cpu, debug_aa32_el1_reginfo);
1228c36a0d57SPeter Maydell     }
1229f43ee493SPeter Maydell 
1230f43ee493SPeter Maydell     if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
1231f43ee493SPeter Maydell         define_arm_cp_regs(cpu, debug_lpae_cp_reginfo);
1232f43ee493SPeter Maydell     }
1233f43ee493SPeter Maydell 
1234f43ee493SPeter Maydell     for (i = 0; i < brps; i++) {
1235f43ee493SPeter Maydell         char *dbgbvr_el1_name = g_strdup_printf("DBGBVR%d_EL1", i);
1236f43ee493SPeter Maydell         char *dbgbcr_el1_name = g_strdup_printf("DBGBCR%d_EL1", i);
1237f43ee493SPeter Maydell         ARMCPRegInfo dbgregs[] = {
1238f43ee493SPeter Maydell             { .name = dbgbvr_el1_name, .state = ARM_CP_STATE_BOTH,
1239f43ee493SPeter Maydell               .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4,
1240f43ee493SPeter Maydell               .access = PL1_RW, .accessfn = access_tda,
1241917b1405SPeter Maydell               .fgt = FGT_DBGBVRN_EL1,
1242f43ee493SPeter Maydell               .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]),
1243f43ee493SPeter Maydell               .writefn = dbgbvr_write, .raw_writefn = raw_write
1244f43ee493SPeter Maydell             },
1245f43ee493SPeter Maydell             { .name = dbgbcr_el1_name, .state = ARM_CP_STATE_BOTH,
1246f43ee493SPeter Maydell               .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5,
1247f43ee493SPeter Maydell               .access = PL1_RW, .accessfn = access_tda,
1248917b1405SPeter Maydell               .fgt = FGT_DBGBCRN_EL1,
1249f43ee493SPeter Maydell               .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]),
1250f43ee493SPeter Maydell               .writefn = dbgbcr_write, .raw_writefn = raw_write
1251f43ee493SPeter Maydell             },
1252f43ee493SPeter Maydell         };
1253f43ee493SPeter Maydell         define_arm_cp_regs(cpu, dbgregs);
1254f43ee493SPeter Maydell         g_free(dbgbvr_el1_name);
1255f43ee493SPeter Maydell         g_free(dbgbcr_el1_name);
1256f43ee493SPeter Maydell     }
1257f43ee493SPeter Maydell 
1258f43ee493SPeter Maydell     for (i = 0; i < wrps; i++) {
1259f43ee493SPeter Maydell         char *dbgwvr_el1_name = g_strdup_printf("DBGWVR%d_EL1", i);
1260f43ee493SPeter Maydell         char *dbgwcr_el1_name = g_strdup_printf("DBGWCR%d_EL1", i);
1261f43ee493SPeter Maydell         ARMCPRegInfo dbgregs[] = {
1262f43ee493SPeter Maydell             { .name = dbgwvr_el1_name, .state = ARM_CP_STATE_BOTH,
1263f43ee493SPeter Maydell               .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6,
1264f43ee493SPeter Maydell               .access = PL1_RW, .accessfn = access_tda,
1265917b1405SPeter Maydell               .fgt = FGT_DBGWVRN_EL1,
1266f43ee493SPeter Maydell               .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]),
1267f43ee493SPeter Maydell               .writefn = dbgwvr_write, .raw_writefn = raw_write
1268f43ee493SPeter Maydell             },
1269f43ee493SPeter Maydell             { .name = dbgwcr_el1_name, .state = ARM_CP_STATE_BOTH,
1270f43ee493SPeter Maydell               .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 7,
1271f43ee493SPeter Maydell               .access = PL1_RW, .accessfn = access_tda,
1272917b1405SPeter Maydell               .fgt = FGT_DBGWCRN_EL1,
1273f43ee493SPeter Maydell               .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]),
1274f43ee493SPeter Maydell               .writefn = dbgwcr_write, .raw_writefn = raw_write
1275f43ee493SPeter Maydell             },
1276f43ee493SPeter Maydell         };
1277f43ee493SPeter Maydell         define_arm_cp_regs(cpu, dbgregs);
1278f43ee493SPeter Maydell         g_free(dbgwvr_el1_name);
1279f43ee493SPeter Maydell         g_free(dbgwcr_el1_name);
1280f43ee493SPeter Maydell     }
1281f43ee493SPeter Maydell }
1282