1671efad1SFabiano Rosas /*
2671efad1SFabiano Rosas * ARM hflags
3671efad1SFabiano Rosas *
4671efad1SFabiano Rosas * This code is licensed under the GNU GPL v2 or later.
5671efad1SFabiano Rosas *
6671efad1SFabiano Rosas * SPDX-License-Identifier: GPL-2.0-or-later
7671efad1SFabiano Rosas */
8671efad1SFabiano Rosas #include "qemu/osdep.h"
9671efad1SFabiano Rosas #include "cpu.h"
10671efad1SFabiano Rosas #include "internals.h"
115a534314SPeter Maydell #include "cpu-features.h"
124759aae4SRichard Henderson #include "exec/translation-block.h"
13b6aeb8d2SRichard Henderson #include "accel/tcg/cpu-ops.h"
14671efad1SFabiano Rosas #include "cpregs.h"
15671efad1SFabiano Rosas
16*12ae629dSPierrick Bouvier #define HELPER_H "tcg/helper.h"
17*12ae629dSPierrick Bouvier #include "exec/helper-proto.h.inc"
18*12ae629dSPierrick Bouvier
fgt_svc(CPUARMState * env,int el)19671efad1SFabiano Rosas static inline bool fgt_svc(CPUARMState *env, int el)
20671efad1SFabiano Rosas {
21671efad1SFabiano Rosas /*
22671efad1SFabiano Rosas * Assuming fine-grained-traps are active, return true if we
23671efad1SFabiano Rosas * should be trapping on SVC instructions. Only AArch64 can
24671efad1SFabiano Rosas * trap on an SVC at EL1, but we don't need to special-case this
25671efad1SFabiano Rosas * because if this is AArch32 EL1 then arm_fgt_active() is false.
26671efad1SFabiano Rosas * We also know el is 0 or 1.
27671efad1SFabiano Rosas */
28671efad1SFabiano Rosas return el == 0 ?
29671efad1SFabiano Rosas FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL0) :
30671efad1SFabiano Rosas FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL1);
31671efad1SFabiano Rosas }
32671efad1SFabiano Rosas
3359754f85SRichard Henderson /* Return true if memory alignment should be enforced. */
aprofile_require_alignment(CPUARMState * env,int el,uint64_t sctlr)3459754f85SRichard Henderson static bool aprofile_require_alignment(CPUARMState *env, int el, uint64_t sctlr)
3559754f85SRichard Henderson {
3659754f85SRichard Henderson #ifdef CONFIG_USER_ONLY
3759754f85SRichard Henderson return false;
3859754f85SRichard Henderson #else
3959754f85SRichard Henderson /* Check the alignment enable bit. */
4059754f85SRichard Henderson if (sctlr & SCTLR_A) {
4159754f85SRichard Henderson return true;
4259754f85SRichard Henderson }
4359754f85SRichard Henderson
4459754f85SRichard Henderson /*
457b19a355SRichard Henderson * With PMSA, when the MPU is disabled, all memory types in the
467b19a355SRichard Henderson * default map are Normal, so don't need aligment enforcing.
477b19a355SRichard Henderson */
487b19a355SRichard Henderson if (arm_feature(env, ARM_FEATURE_PMSA)) {
497b19a355SRichard Henderson return false;
507b19a355SRichard Henderson }
517b19a355SRichard Henderson
527b19a355SRichard Henderson /*
537b19a355SRichard Henderson * With VMSA, if translation is disabled, then the default memory type
547b19a355SRichard Henderson * is Device(-nGnRnE) instead of Normal, which requires that alignment
5559754f85SRichard Henderson * be enforced. Since this affects all ram, it is most efficient
5659754f85SRichard Henderson * to handle this during translation.
5759754f85SRichard Henderson */
5859754f85SRichard Henderson if (sctlr & SCTLR_M) {
5959754f85SRichard Henderson /* Translation enabled: memory type in PTE via MAIR_ELx. */
6059754f85SRichard Henderson return false;
6159754f85SRichard Henderson }
6259754f85SRichard Henderson if (el < 2 && (arm_hcr_el2_eff(env) & (HCR_DC | HCR_VM))) {
6359754f85SRichard Henderson /* Stage 2 translation enabled: memory type in PTE. */
6459754f85SRichard Henderson return false;
6559754f85SRichard Henderson }
6659754f85SRichard Henderson return true;
6759754f85SRichard Henderson #endif
6859754f85SRichard Henderson }
6959754f85SRichard Henderson
access_secure_reg(CPUARMState * env)7023560adaSPeter Maydell bool access_secure_reg(CPUARMState *env)
7123560adaSPeter Maydell {
7223560adaSPeter Maydell bool ret = (arm_feature(env, ARM_FEATURE_EL3) &&
7323560adaSPeter Maydell !arm_el_is_aa64(env, 3) &&
7423560adaSPeter Maydell !(env->cp15.scr_el3 & SCR_NS));
7523560adaSPeter Maydell
7623560adaSPeter Maydell return ret;
7723560adaSPeter Maydell }
7823560adaSPeter Maydell
rebuild_hflags_common(CPUARMState * env,int fp_el,ARMMMUIdx mmu_idx,CPUARMTBFlags flags)79671efad1SFabiano Rosas static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el,
80671efad1SFabiano Rosas ARMMMUIdx mmu_idx,
81671efad1SFabiano Rosas CPUARMTBFlags flags)
82671efad1SFabiano Rosas {
83671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, FPEXC_EL, fp_el);
84671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
85671efad1SFabiano Rosas
86671efad1SFabiano Rosas if (arm_singlestep_active(env)) {
87671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, SS_ACTIVE, 1);
88671efad1SFabiano Rosas }
89671efad1SFabiano Rosas
90671efad1SFabiano Rosas return flags;
91671efad1SFabiano Rosas }
92671efad1SFabiano Rosas
rebuild_hflags_common_32(CPUARMState * env,int fp_el,ARMMMUIdx mmu_idx,CPUARMTBFlags flags)93671efad1SFabiano Rosas static CPUARMTBFlags rebuild_hflags_common_32(CPUARMState *env, int fp_el,
94671efad1SFabiano Rosas ARMMMUIdx mmu_idx,
95671efad1SFabiano Rosas CPUARMTBFlags flags)
96671efad1SFabiano Rosas {
97671efad1SFabiano Rosas bool sctlr_b = arm_sctlr_b(env);
98671efad1SFabiano Rosas
99671efad1SFabiano Rosas if (sctlr_b) {
100671efad1SFabiano Rosas DP_TBFLAG_A32(flags, SCTLR__B, 1);
101671efad1SFabiano Rosas }
102671efad1SFabiano Rosas if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) {
103671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, BE_DATA, 1);
104671efad1SFabiano Rosas }
105671efad1SFabiano Rosas DP_TBFLAG_A32(flags, NS, !access_secure_reg(env));
106671efad1SFabiano Rosas
107671efad1SFabiano Rosas return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
108671efad1SFabiano Rosas }
109671efad1SFabiano Rosas
rebuild_hflags_m32(CPUARMState * env,int fp_el,ARMMMUIdx mmu_idx)110671efad1SFabiano Rosas static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el,
111671efad1SFabiano Rosas ARMMMUIdx mmu_idx)
112671efad1SFabiano Rosas {
113671efad1SFabiano Rosas CPUARMTBFlags flags = {};
114671efad1SFabiano Rosas uint32_t ccr = env->v7m.ccr[env->v7m.secure];
115671efad1SFabiano Rosas
116671efad1SFabiano Rosas /* Without HaveMainExt, CCR.UNALIGN_TRP is RES1. */
117671efad1SFabiano Rosas if (ccr & R_V7M_CCR_UNALIGN_TRP_MASK) {
118671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
119671efad1SFabiano Rosas }
120671efad1SFabiano Rosas
121671efad1SFabiano Rosas if (arm_v7m_is_handler_mode(env)) {
122671efad1SFabiano Rosas DP_TBFLAG_M32(flags, HANDLER, 1);
123671efad1SFabiano Rosas }
124671efad1SFabiano Rosas
125671efad1SFabiano Rosas /*
126671efad1SFabiano Rosas * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN
127671efad1SFabiano Rosas * is suppressing them because the requested execution priority
128671efad1SFabiano Rosas * is less than 0.
129671efad1SFabiano Rosas */
130671efad1SFabiano Rosas if (arm_feature(env, ARM_FEATURE_V8) &&
131671efad1SFabiano Rosas !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
132671efad1SFabiano Rosas (ccr & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
133671efad1SFabiano Rosas DP_TBFLAG_M32(flags, STACKCHECK, 1);
134671efad1SFabiano Rosas }
135671efad1SFabiano Rosas
136671efad1SFabiano Rosas if (arm_feature(env, ARM_FEATURE_M_SECURITY) && env->v7m.secure) {
137671efad1SFabiano Rosas DP_TBFLAG_M32(flags, SECURE, 1);
138671efad1SFabiano Rosas }
139671efad1SFabiano Rosas
140671efad1SFabiano Rosas return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
141671efad1SFabiano Rosas }
142671efad1SFabiano Rosas
143671efad1SFabiano Rosas /* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */
sme_fa64(CPUARMState * env,int el)144671efad1SFabiano Rosas static bool sme_fa64(CPUARMState *env, int el)
145671efad1SFabiano Rosas {
146671efad1SFabiano Rosas if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) {
147671efad1SFabiano Rosas return false;
148671efad1SFabiano Rosas }
149671efad1SFabiano Rosas
150671efad1SFabiano Rosas if (el <= 1 && !el_is_in_host(env, el)) {
151671efad1SFabiano Rosas if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) {
152671efad1SFabiano Rosas return false;
153671efad1SFabiano Rosas }
154671efad1SFabiano Rosas }
155671efad1SFabiano Rosas if (el <= 2 && arm_is_el2_enabled(env)) {
156671efad1SFabiano Rosas if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) {
157671efad1SFabiano Rosas return false;
158671efad1SFabiano Rosas }
159671efad1SFabiano Rosas }
160671efad1SFabiano Rosas if (arm_feature(env, ARM_FEATURE_EL3)) {
161671efad1SFabiano Rosas if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) {
162671efad1SFabiano Rosas return false;
163671efad1SFabiano Rosas }
164671efad1SFabiano Rosas }
165671efad1SFabiano Rosas
166671efad1SFabiano Rosas return true;
167671efad1SFabiano Rosas }
168671efad1SFabiano Rosas
rebuild_hflags_a32(CPUARMState * env,int fp_el,ARMMMUIdx mmu_idx)169671efad1SFabiano Rosas static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
170671efad1SFabiano Rosas ARMMMUIdx mmu_idx)
171671efad1SFabiano Rosas {
172671efad1SFabiano Rosas CPUARMTBFlags flags = {};
173671efad1SFabiano Rosas int el = arm_current_el(env);
17459754f85SRichard Henderson uint64_t sctlr = arm_sctlr(env, el);
175671efad1SFabiano Rosas
17659754f85SRichard Henderson if (aprofile_require_alignment(env, el, sctlr)) {
177671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
178671efad1SFabiano Rosas }
179671efad1SFabiano Rosas
180671efad1SFabiano Rosas if (arm_el_is_aa64(env, 1)) {
181671efad1SFabiano Rosas DP_TBFLAG_A32(flags, VFPEN, 1);
182671efad1SFabiano Rosas }
183671efad1SFabiano Rosas
184671efad1SFabiano Rosas if (el < 2 && env->cp15.hstr_el2 && arm_is_el2_enabled(env) &&
185671efad1SFabiano Rosas (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
186671efad1SFabiano Rosas DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1);
187671efad1SFabiano Rosas }
188671efad1SFabiano Rosas
189671efad1SFabiano Rosas if (arm_fgt_active(env, el)) {
190671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1);
191671efad1SFabiano Rosas if (fgt_svc(env, el)) {
192671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, FGT_SVC, 1);
193671efad1SFabiano Rosas }
194671efad1SFabiano Rosas }
195671efad1SFabiano Rosas
196671efad1SFabiano Rosas if (env->uncached_cpsr & CPSR_IL) {
197671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
198671efad1SFabiano Rosas }
199671efad1SFabiano Rosas
200671efad1SFabiano Rosas /*
201671efad1SFabiano Rosas * The SME exception we are testing for is raised via
202671efad1SFabiano Rosas * AArch64.CheckFPAdvSIMDEnabled(), as called from
203671efad1SFabiano Rosas * AArch32.CheckAdvSIMDOrFPEnabled().
204671efad1SFabiano Rosas */
205671efad1SFabiano Rosas if (el == 0
206671efad1SFabiano Rosas && FIELD_EX64(env->svcr, SVCR, SM)
207671efad1SFabiano Rosas && (!arm_is_el2_enabled(env)
208671efad1SFabiano Rosas || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE)))
209671efad1SFabiano Rosas && arm_el_is_aa64(env, 1)
210671efad1SFabiano Rosas && !sme_fa64(env, el)) {
211671efad1SFabiano Rosas DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1);
212671efad1SFabiano Rosas }
213671efad1SFabiano Rosas
214671efad1SFabiano Rosas return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
215671efad1SFabiano Rosas }
216671efad1SFabiano Rosas
rebuild_hflags_a64(CPUARMState * env,int el,int fp_el,ARMMMUIdx mmu_idx)217671efad1SFabiano Rosas static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
218671efad1SFabiano Rosas ARMMMUIdx mmu_idx)
219671efad1SFabiano Rosas {
220671efad1SFabiano Rosas CPUARMTBFlags flags = {};
221671efad1SFabiano Rosas ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
222671efad1SFabiano Rosas uint64_t tcr = regime_tcr(env, mmu_idx);
223e37e98b7SPeter Maydell uint64_t hcr = arm_hcr_el2_eff(env);
224671efad1SFabiano Rosas uint64_t sctlr;
225671efad1SFabiano Rosas int tbii, tbid;
226671efad1SFabiano Rosas
227671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, AARCH64_STATE, 1);
228671efad1SFabiano Rosas
229671efad1SFabiano Rosas /* Get control bits for tagged addresses. */
230671efad1SFabiano Rosas tbid = aa64_va_parameter_tbi(tcr, mmu_idx);
231671efad1SFabiano Rosas tbii = tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx);
232671efad1SFabiano Rosas
233671efad1SFabiano Rosas DP_TBFLAG_A64(flags, TBII, tbii);
234671efad1SFabiano Rosas DP_TBFLAG_A64(flags, TBID, tbid);
235671efad1SFabiano Rosas
236671efad1SFabiano Rosas if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
237671efad1SFabiano Rosas int sve_el = sve_exception_el(env, el);
238671efad1SFabiano Rosas
239671efad1SFabiano Rosas /*
240671efad1SFabiano Rosas * If either FP or SVE are disabled, translator does not need len.
241671efad1SFabiano Rosas * If SVE EL > FP EL, FP exception has precedence, and translator
242671efad1SFabiano Rosas * does not need SVE EL. Save potential re-translations by forcing
243671efad1SFabiano Rosas * the unneeded data to zero.
244671efad1SFabiano Rosas */
245671efad1SFabiano Rosas if (fp_el != 0) {
246671efad1SFabiano Rosas if (sve_el > fp_el) {
247671efad1SFabiano Rosas sve_el = 0;
248671efad1SFabiano Rosas }
249671efad1SFabiano Rosas } else if (sve_el == 0) {
250671efad1SFabiano Rosas DP_TBFLAG_A64(flags, VL, sve_vqm1_for_el(env, el));
251671efad1SFabiano Rosas }
252671efad1SFabiano Rosas DP_TBFLAG_A64(flags, SVEEXC_EL, sve_el);
253671efad1SFabiano Rosas }
254671efad1SFabiano Rosas if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
255671efad1SFabiano Rosas int sme_el = sme_exception_el(env, el);
256671efad1SFabiano Rosas bool sm = FIELD_EX64(env->svcr, SVCR, SM);
257671efad1SFabiano Rosas
258671efad1SFabiano Rosas DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el);
259671efad1SFabiano Rosas if (sme_el == 0) {
260671efad1SFabiano Rosas /* Similarly, do not compute SVL if SME is disabled. */
261671efad1SFabiano Rosas int svl = sve_vqm1_for_el_sm(env, el, true);
262671efad1SFabiano Rosas DP_TBFLAG_A64(flags, SVL, svl);
263671efad1SFabiano Rosas if (sm) {
264671efad1SFabiano Rosas /* If SVE is disabled, we will not have set VL above. */
265671efad1SFabiano Rosas DP_TBFLAG_A64(flags, VL, svl);
266671efad1SFabiano Rosas }
267671efad1SFabiano Rosas }
268671efad1SFabiano Rosas if (sm) {
269671efad1SFabiano Rosas DP_TBFLAG_A64(flags, PSTATE_SM, 1);
270671efad1SFabiano Rosas DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el));
271671efad1SFabiano Rosas }
272671efad1SFabiano Rosas DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA));
273671efad1SFabiano Rosas }
274671efad1SFabiano Rosas
275671efad1SFabiano Rosas sctlr = regime_sctlr(env, stage1);
276671efad1SFabiano Rosas
27759754f85SRichard Henderson if (aprofile_require_alignment(env, el, sctlr)) {
278671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
279671efad1SFabiano Rosas }
280671efad1SFabiano Rosas
281671efad1SFabiano Rosas if (arm_cpu_data_is_big_endian_a64(el, sctlr)) {
282671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, BE_DATA, 1);
283671efad1SFabiano Rosas }
284671efad1SFabiano Rosas
285671efad1SFabiano Rosas if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) {
286671efad1SFabiano Rosas /*
287671efad1SFabiano Rosas * In order to save space in flags, we record only whether
288671efad1SFabiano Rosas * pauth is "inactive", meaning all insns are implemented as
289671efad1SFabiano Rosas * a nop, or "active" when some action must be performed.
290671efad1SFabiano Rosas * The decision of which action to take is left to a helper.
291671efad1SFabiano Rosas */
292671efad1SFabiano Rosas if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) {
293671efad1SFabiano Rosas DP_TBFLAG_A64(flags, PAUTH_ACTIVE, 1);
294671efad1SFabiano Rosas }
295671efad1SFabiano Rosas }
296671efad1SFabiano Rosas
297671efad1SFabiano Rosas if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
298671efad1SFabiano Rosas /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
299671efad1SFabiano Rosas if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
300671efad1SFabiano Rosas DP_TBFLAG_A64(flags, BT, 1);
301671efad1SFabiano Rosas }
302671efad1SFabiano Rosas }
303671efad1SFabiano Rosas
30483f624d9SRichard Henderson if (cpu_isar_feature(aa64_lse2, env_archcpu(env))) {
30583f624d9SRichard Henderson if (sctlr & SCTLR_nAA) {
30683f624d9SRichard Henderson DP_TBFLAG_A64(flags, NAA, 1);
30783f624d9SRichard Henderson }
30883f624d9SRichard Henderson }
30983f624d9SRichard Henderson
310671efad1SFabiano Rosas /* Compute the condition for using AccType_UNPRIV for LDTR et al. */
311671efad1SFabiano Rosas if (!(env->pstate & PSTATE_UAO)) {
312671efad1SFabiano Rosas switch (mmu_idx) {
313671efad1SFabiano Rosas case ARMMMUIdx_E10_1:
314671efad1SFabiano Rosas case ARMMMUIdx_E10_1_PAN:
3152e9b1e50SPeter Maydell /* FEAT_NV: NV,NV1 == 1,1 means we don't do UNPRIV accesses */
3162e9b1e50SPeter Maydell if ((hcr & (HCR_NV | HCR_NV1)) != (HCR_NV | HCR_NV1)) {
317671efad1SFabiano Rosas DP_TBFLAG_A64(flags, UNPRIV, 1);
3182e9b1e50SPeter Maydell }
319671efad1SFabiano Rosas break;
320671efad1SFabiano Rosas case ARMMMUIdx_E20_2:
321671efad1SFabiano Rosas case ARMMMUIdx_E20_2_PAN:
322671efad1SFabiano Rosas /*
323671efad1SFabiano Rosas * Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is
324671efad1SFabiano Rosas * gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.
325671efad1SFabiano Rosas */
326671efad1SFabiano Rosas if (env->cp15.hcr_el2 & HCR_TGE) {
327671efad1SFabiano Rosas DP_TBFLAG_A64(flags, UNPRIV, 1);
328671efad1SFabiano Rosas }
329671efad1SFabiano Rosas break;
330671efad1SFabiano Rosas default:
331671efad1SFabiano Rosas break;
332671efad1SFabiano Rosas }
333671efad1SFabiano Rosas }
334671efad1SFabiano Rosas
335671efad1SFabiano Rosas if (env->pstate & PSTATE_IL) {
336671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
337671efad1SFabiano Rosas }
338671efad1SFabiano Rosas
339671efad1SFabiano Rosas if (arm_fgt_active(env, el)) {
340671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1);
341671efad1SFabiano Rosas if (FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, ERET)) {
342e37e98b7SPeter Maydell DP_TBFLAG_A64(flags, TRAP_ERET, 1);
343671efad1SFabiano Rosas }
344671efad1SFabiano Rosas if (fgt_svc(env, el)) {
345671efad1SFabiano Rosas DP_TBFLAG_ANY(flags, FGT_SVC, 1);
346671efad1SFabiano Rosas }
347671efad1SFabiano Rosas }
348671efad1SFabiano Rosas
349e37e98b7SPeter Maydell /*
350e37e98b7SPeter Maydell * ERET can also be trapped for FEAT_NV. arm_hcr_el2_eff() takes care
351e37e98b7SPeter Maydell * of "is EL2 enabled" and the NV bit can only be set if FEAT_NV is present.
352e37e98b7SPeter Maydell */
353e37e98b7SPeter Maydell if (el == 1 && (hcr & HCR_NV)) {
354e37e98b7SPeter Maydell DP_TBFLAG_A64(flags, TRAP_ERET, 1);
35567d10fc4SPeter Maydell DP_TBFLAG_A64(flags, NV, 1);
356c35da11dSPeter Maydell if (hcr & HCR_NV1) {
357c35da11dSPeter Maydell DP_TBFLAG_A64(flags, NV1, 1);
358c35da11dSPeter Maydell }
359c35da11dSPeter Maydell if (hcr & HCR_NV2) {
360c35da11dSPeter Maydell DP_TBFLAG_A64(flags, NV2, 1);
361daf9b4a0SPeter Maydell if (hcr & HCR_E2H) {
362daf9b4a0SPeter Maydell DP_TBFLAG_A64(flags, NV2_MEM_E20, 1);
363daf9b4a0SPeter Maydell }
364daf9b4a0SPeter Maydell if (env->cp15.sctlr_el[2] & SCTLR_EE) {
365daf9b4a0SPeter Maydell DP_TBFLAG_A64(flags, NV2_MEM_BE, 1);
366daf9b4a0SPeter Maydell }
367c35da11dSPeter Maydell }
368e37e98b7SPeter Maydell }
369e37e98b7SPeter Maydell
370671efad1SFabiano Rosas if (cpu_isar_feature(aa64_mte, env_archcpu(env))) {
371671efad1SFabiano Rosas /*
372671efad1SFabiano Rosas * Set MTE_ACTIVE if any access may be Checked, and leave clear
373671efad1SFabiano Rosas * if all accesses must be Unchecked:
374671efad1SFabiano Rosas * 1) If no TBI, then there are no tags in the address to check,
375671efad1SFabiano Rosas * 2) If Tag Check Override, then all accesses are Unchecked,
376671efad1SFabiano Rosas * 3) If Tag Check Fail == 0, then Checked access have no effect,
377671efad1SFabiano Rosas * 4) If no Allocation Tag Access, then all accesses are Unchecked.
378671efad1SFabiano Rosas */
379671efad1SFabiano Rosas if (allocation_tag_access_enabled(env, el, sctlr)) {
380671efad1SFabiano Rosas DP_TBFLAG_A64(flags, ATA, 1);
381671efad1SFabiano Rosas if (tbid
382671efad1SFabiano Rosas && !(env->pstate & PSTATE_TCO)
383671efad1SFabiano Rosas && (sctlr & (el == 0 ? SCTLR_TCF0 : SCTLR_TCF))) {
384671efad1SFabiano Rosas DP_TBFLAG_A64(flags, MTE_ACTIVE, 1);
385903dbefcSPeter Maydell if (!EX_TBFLAG_A64(flags, UNPRIV)) {
386903dbefcSPeter Maydell /*
387903dbefcSPeter Maydell * In non-unpriv contexts (eg EL0), unpriv load/stores
388903dbefcSPeter Maydell * act like normal ones; duplicate the MTE info to
389903dbefcSPeter Maydell * avoid translate-a64.c having to check UNPRIV to see
390903dbefcSPeter Maydell * whether it is OK to index into MTE_ACTIVE[].
391903dbefcSPeter Maydell */
392903dbefcSPeter Maydell DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1);
393903dbefcSPeter Maydell }
394671efad1SFabiano Rosas }
395671efad1SFabiano Rosas }
396671efad1SFabiano Rosas /* And again for unprivileged accesses, if required. */
397671efad1SFabiano Rosas if (EX_TBFLAG_A64(flags, UNPRIV)
398671efad1SFabiano Rosas && tbid
399671efad1SFabiano Rosas && !(env->pstate & PSTATE_TCO)
400671efad1SFabiano Rosas && (sctlr & SCTLR_TCF0)
401671efad1SFabiano Rosas && allocation_tag_access_enabled(env, 0, sctlr)) {
402671efad1SFabiano Rosas DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1);
403671efad1SFabiano Rosas }
404179e9a3bSPeter Maydell /*
40551464c56SMichael Tokarev * For unpriv tag-setting accesses we also need ATA0. Again, in
406179e9a3bSPeter Maydell * contexts where unpriv and normal insns are the same we
407179e9a3bSPeter Maydell * duplicate the ATA bit to save effort for translate-a64.c.
408179e9a3bSPeter Maydell */
409179e9a3bSPeter Maydell if (EX_TBFLAG_A64(flags, UNPRIV)) {
410179e9a3bSPeter Maydell if (allocation_tag_access_enabled(env, 0, sctlr)) {
411179e9a3bSPeter Maydell DP_TBFLAG_A64(flags, ATA0, 1);
412179e9a3bSPeter Maydell }
413179e9a3bSPeter Maydell } else {
414179e9a3bSPeter Maydell DP_TBFLAG_A64(flags, ATA0, EX_TBFLAG_A64(flags, ATA));
415179e9a3bSPeter Maydell }
416671efad1SFabiano Rosas /* Cache TCMA as well as TBI. */
417671efad1SFabiano Rosas DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx));
418671efad1SFabiano Rosas }
419671efad1SFabiano Rosas
420731528d3SPeter Maydell if (env->vfp.fpcr & FPCR_AH) {
421731528d3SPeter Maydell DP_TBFLAG_A64(flags, AH, 1);
422731528d3SPeter Maydell }
4237025fa99SPeter Maydell if (env->vfp.fpcr & FPCR_NEP) {
4247025fa99SPeter Maydell /*
4257025fa99SPeter Maydell * In streaming-SVE without FA64, NEP behaves as if zero;
4267025fa99SPeter Maydell * compare pseudocode IsMerging()
4277025fa99SPeter Maydell */
4287025fa99SPeter Maydell if (!(EX_TBFLAG_A64(flags, PSTATE_SM) && !sme_fa64(env, el))) {
4297025fa99SPeter Maydell DP_TBFLAG_A64(flags, NEP, 1);
4307025fa99SPeter Maydell }
4317025fa99SPeter Maydell }
432731528d3SPeter Maydell
433671efad1SFabiano Rosas return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
434671efad1SFabiano Rosas }
435671efad1SFabiano Rosas
rebuild_hflags_internal(CPUARMState * env)436671efad1SFabiano Rosas static CPUARMTBFlags rebuild_hflags_internal(CPUARMState *env)
437671efad1SFabiano Rosas {
438671efad1SFabiano Rosas int el = arm_current_el(env);
439671efad1SFabiano Rosas int fp_el = fp_exception_el(env, el);
440671efad1SFabiano Rosas ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
441671efad1SFabiano Rosas
442671efad1SFabiano Rosas if (is_a64(env)) {
443671efad1SFabiano Rosas return rebuild_hflags_a64(env, el, fp_el, mmu_idx);
444671efad1SFabiano Rosas } else if (arm_feature(env, ARM_FEATURE_M)) {
445671efad1SFabiano Rosas return rebuild_hflags_m32(env, fp_el, mmu_idx);
446671efad1SFabiano Rosas } else {
447671efad1SFabiano Rosas return rebuild_hflags_a32(env, fp_el, mmu_idx);
448671efad1SFabiano Rosas }
449671efad1SFabiano Rosas }
450671efad1SFabiano Rosas
arm_rebuild_hflags(CPUARMState * env)451671efad1SFabiano Rosas void arm_rebuild_hflags(CPUARMState *env)
452671efad1SFabiano Rosas {
453671efad1SFabiano Rosas env->hflags = rebuild_hflags_internal(env);
454671efad1SFabiano Rosas }
455671efad1SFabiano Rosas
456671efad1SFabiano Rosas /*
457671efad1SFabiano Rosas * If we have triggered a EL state change we can't rely on the
458671efad1SFabiano Rosas * translator having passed it to us, we need to recompute.
459671efad1SFabiano Rosas */
HELPER(rebuild_hflags_m32_newel)460671efad1SFabiano Rosas void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env)
461671efad1SFabiano Rosas {
462671efad1SFabiano Rosas int el = arm_current_el(env);
463671efad1SFabiano Rosas int fp_el = fp_exception_el(env, el);
464671efad1SFabiano Rosas ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
465671efad1SFabiano Rosas
466671efad1SFabiano Rosas env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
467671efad1SFabiano Rosas }
468671efad1SFabiano Rosas
HELPER(rebuild_hflags_m32)469671efad1SFabiano Rosas void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
470671efad1SFabiano Rosas {
471671efad1SFabiano Rosas int fp_el = fp_exception_el(env, el);
472671efad1SFabiano Rosas ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
473671efad1SFabiano Rosas
474671efad1SFabiano Rosas env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
475671efad1SFabiano Rosas }
476671efad1SFabiano Rosas
477671efad1SFabiano Rosas /*
478671efad1SFabiano Rosas * If we have triggered a EL state change we can't rely on the
479671efad1SFabiano Rosas * translator having passed it to us, we need to recompute.
480671efad1SFabiano Rosas */
HELPER(rebuild_hflags_a32_newel)481671efad1SFabiano Rosas void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env)
482671efad1SFabiano Rosas {
483671efad1SFabiano Rosas int el = arm_current_el(env);
484671efad1SFabiano Rosas int fp_el = fp_exception_el(env, el);
485671efad1SFabiano Rosas ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
486671efad1SFabiano Rosas env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx);
487671efad1SFabiano Rosas }
488671efad1SFabiano Rosas
HELPER(rebuild_hflags_a32)489671efad1SFabiano Rosas void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el)
490671efad1SFabiano Rosas {
491671efad1SFabiano Rosas int fp_el = fp_exception_el(env, el);
492671efad1SFabiano Rosas ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
493671efad1SFabiano Rosas
494671efad1SFabiano Rosas env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx);
495671efad1SFabiano Rosas }
496671efad1SFabiano Rosas
HELPER(rebuild_hflags_a64)497671efad1SFabiano Rosas void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el)
498671efad1SFabiano Rosas {
499671efad1SFabiano Rosas int fp_el = fp_exception_el(env, el);
500671efad1SFabiano Rosas ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
501671efad1SFabiano Rosas
502671efad1SFabiano Rosas env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx);
503671efad1SFabiano Rosas }
504671efad1SFabiano Rosas
assert_hflags_rebuild_correctly(CPUARMState * env)5059da84372SRichard Henderson static void assert_hflags_rebuild_correctly(CPUARMState *env)
506671efad1SFabiano Rosas {
507671efad1SFabiano Rosas #ifdef CONFIG_DEBUG_TCG
508671efad1SFabiano Rosas CPUARMTBFlags c = env->hflags;
509671efad1SFabiano Rosas CPUARMTBFlags r = rebuild_hflags_internal(env);
510671efad1SFabiano Rosas
511671efad1SFabiano Rosas if (unlikely(c.flags != r.flags || c.flags2 != r.flags2)) {
512671efad1SFabiano Rosas fprintf(stderr, "TCG hflags mismatch "
5139fac3975SPierrick Bouvier "(current:(0x%08x,0x%016" PRIx64 ")"
5149fac3975SPierrick Bouvier " rebuilt:(0x%08x,0x%016" PRIx64 ")\n",
515671efad1SFabiano Rosas c.flags, c.flags2, r.flags, r.flags2);
516671efad1SFabiano Rosas abort();
517671efad1SFabiano Rosas }
518671efad1SFabiano Rosas #endif
519671efad1SFabiano Rosas }
520b6aeb8d2SRichard Henderson
mve_no_pred(CPUARMState * env)521b6aeb8d2SRichard Henderson static bool mve_no_pred(CPUARMState *env)
522b6aeb8d2SRichard Henderson {
523b6aeb8d2SRichard Henderson /*
524b6aeb8d2SRichard Henderson * Return true if there is definitely no predication of MVE
525b6aeb8d2SRichard Henderson * instructions by VPR or LTPSIZE. (Returning false even if there
526b6aeb8d2SRichard Henderson * isn't any predication is OK; generated code will just be
527b6aeb8d2SRichard Henderson * a little worse.)
528b6aeb8d2SRichard Henderson * If the CPU does not implement MVE then this TB flag is always 0.
529b6aeb8d2SRichard Henderson *
530b6aeb8d2SRichard Henderson * NOTE: if you change this logic, the "recalculate s->mve_no_pred"
531b6aeb8d2SRichard Henderson * logic in gen_update_fp_context() needs to be updated to match.
532b6aeb8d2SRichard Henderson *
533b6aeb8d2SRichard Henderson * We do not include the effect of the ECI bits here -- they are
534b6aeb8d2SRichard Henderson * tracked in other TB flags. This simplifies the logic for
535b6aeb8d2SRichard Henderson * "when did we emit code that changes the MVE_NO_PRED TB flag
536b6aeb8d2SRichard Henderson * and thus need to end the TB?".
537b6aeb8d2SRichard Henderson */
538b6aeb8d2SRichard Henderson if (cpu_isar_feature(aa32_mve, env_archcpu(env))) {
539b6aeb8d2SRichard Henderson return false;
540b6aeb8d2SRichard Henderson }
541b6aeb8d2SRichard Henderson if (env->v7m.vpr) {
542b6aeb8d2SRichard Henderson return false;
543b6aeb8d2SRichard Henderson }
544b6aeb8d2SRichard Henderson if (env->v7m.ltpsize < 4) {
545b6aeb8d2SRichard Henderson return false;
546b6aeb8d2SRichard Henderson }
547b6aeb8d2SRichard Henderson return true;
548b6aeb8d2SRichard Henderson }
549b6aeb8d2SRichard Henderson
arm_get_tb_cpu_state(CPUState * cs)550c37f8978SRichard Henderson TCGTBCPUState arm_get_tb_cpu_state(CPUState *cs)
551b6aeb8d2SRichard Henderson {
5524759aae4SRichard Henderson CPUARMState *env = cpu_env(cs);
553b6aeb8d2SRichard Henderson CPUARMTBFlags flags;
5544759aae4SRichard Henderson vaddr pc;
555b6aeb8d2SRichard Henderson
556b6aeb8d2SRichard Henderson assert_hflags_rebuild_correctly(env);
557b6aeb8d2SRichard Henderson flags = env->hflags;
558b6aeb8d2SRichard Henderson
559b6aeb8d2SRichard Henderson if (EX_TBFLAG_ANY(flags, AARCH64_STATE)) {
5604759aae4SRichard Henderson pc = env->pc;
561b6aeb8d2SRichard Henderson if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
562b6aeb8d2SRichard Henderson DP_TBFLAG_A64(flags, BTYPE, env->btype);
563b6aeb8d2SRichard Henderson }
564b6aeb8d2SRichard Henderson } else {
5654759aae4SRichard Henderson pc = env->regs[15];
566b6aeb8d2SRichard Henderson
567b6aeb8d2SRichard Henderson if (arm_feature(env, ARM_FEATURE_M)) {
568b6aeb8d2SRichard Henderson if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
569b6aeb8d2SRichard Henderson FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S)
570b6aeb8d2SRichard Henderson != env->v7m.secure) {
571b6aeb8d2SRichard Henderson DP_TBFLAG_M32(flags, FPCCR_S_WRONG, 1);
572b6aeb8d2SRichard Henderson }
573b6aeb8d2SRichard Henderson
574b6aeb8d2SRichard Henderson if ((env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
575b6aeb8d2SRichard Henderson (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
576b6aeb8d2SRichard Henderson (env->v7m.secure &&
577b6aeb8d2SRichard Henderson !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
578b6aeb8d2SRichard Henderson /*
579b6aeb8d2SRichard Henderson * ASPEN is set, but FPCA/SFPA indicate that there is no
580b6aeb8d2SRichard Henderson * active FP context; we must create a new FP context before
581b6aeb8d2SRichard Henderson * executing any FP insn.
582b6aeb8d2SRichard Henderson */
583b6aeb8d2SRichard Henderson DP_TBFLAG_M32(flags, NEW_FP_CTXT_NEEDED, 1);
584b6aeb8d2SRichard Henderson }
585b6aeb8d2SRichard Henderson
586b6aeb8d2SRichard Henderson bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
587b6aeb8d2SRichard Henderson if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
588b6aeb8d2SRichard Henderson DP_TBFLAG_M32(flags, LSPACT, 1);
589b6aeb8d2SRichard Henderson }
590b6aeb8d2SRichard Henderson
591b6aeb8d2SRichard Henderson if (mve_no_pred(env)) {
592b6aeb8d2SRichard Henderson DP_TBFLAG_M32(flags, MVE_NO_PRED, 1);
593b6aeb8d2SRichard Henderson }
594b6aeb8d2SRichard Henderson } else {
595b6aeb8d2SRichard Henderson /*
596b6aeb8d2SRichard Henderson * Note that XSCALE_CPAR shares bits with VECSTRIDE.
597b6aeb8d2SRichard Henderson * Note that VECLEN+VECSTRIDE are RES0 for M-profile.
598b6aeb8d2SRichard Henderson */
599b6aeb8d2SRichard Henderson if (arm_feature(env, ARM_FEATURE_XSCALE)) {
600b6aeb8d2SRichard Henderson DP_TBFLAG_A32(flags, XSCALE_CPAR, env->cp15.c15_cpar);
601b6aeb8d2SRichard Henderson } else {
602b6aeb8d2SRichard Henderson DP_TBFLAG_A32(flags, VECLEN, env->vfp.vec_len);
603b6aeb8d2SRichard Henderson DP_TBFLAG_A32(flags, VECSTRIDE, env->vfp.vec_stride);
604b6aeb8d2SRichard Henderson }
605b6aeb8d2SRichard Henderson if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
606b6aeb8d2SRichard Henderson DP_TBFLAG_A32(flags, VFPEN, 1);
607b6aeb8d2SRichard Henderson }
608b6aeb8d2SRichard Henderson }
609b6aeb8d2SRichard Henderson
610b6aeb8d2SRichard Henderson DP_TBFLAG_AM32(flags, THUMB, env->thumb);
611b6aeb8d2SRichard Henderson DP_TBFLAG_AM32(flags, CONDEXEC, env->condexec_bits);
612b6aeb8d2SRichard Henderson }
613b6aeb8d2SRichard Henderson
614b6aeb8d2SRichard Henderson /*
615b6aeb8d2SRichard Henderson * The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
616b6aeb8d2SRichard Henderson * states defined in the ARM ARM for software singlestep:
617b6aeb8d2SRichard Henderson * SS_ACTIVE PSTATE.SS State
618b6aeb8d2SRichard Henderson * 0 x Inactive (the TB flag for SS is always 0)
619b6aeb8d2SRichard Henderson * 1 0 Active-pending
620b6aeb8d2SRichard Henderson * 1 1 Active-not-pending
621b6aeb8d2SRichard Henderson * SS_ACTIVE is set in hflags; PSTATE__SS is computed every TB.
622b6aeb8d2SRichard Henderson */
623b6aeb8d2SRichard Henderson if (EX_TBFLAG_ANY(flags, SS_ACTIVE) && (env->pstate & PSTATE_SS)) {
624b6aeb8d2SRichard Henderson DP_TBFLAG_ANY(flags, PSTATE__SS, 1);
625b6aeb8d2SRichard Henderson }
626b6aeb8d2SRichard Henderson
6274759aae4SRichard Henderson return (TCGTBCPUState){
6284759aae4SRichard Henderson .pc = pc,
6294759aae4SRichard Henderson .flags = flags.flags,
6304759aae4SRichard Henderson .cs_base = flags.flags2,
6314759aae4SRichard Henderson };
632b6aeb8d2SRichard Henderson }
633