aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2023-02-27 14:46:00 +0000
committerPeter Maydell <peter.maydell@linaro.org>2023-02-27 14:46:00 +0000
commite1f9f73ba15e0356ce1aa3317d7bd294f587ab58 (patch)
treed12f488cfe0f67ba5f073f005e851dd4c480ceae /target
parent3db629f03e8caf39526cd0415dac16a6a6484107 (diff)
parente844f0c5d0bd2c4d8d3c1622eb2a88586c9c4677 (diff)
Merge tag 'pull-target-arm-20230227' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue: * Various code cleanups * More refactoring working towards allowing a build without CONFIG_TCG # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmP8ty0ZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3na0EACToAEGC4/iFigdKD7ZwG3F # FvoDcMRRSdElcSo7BTDrFBBOH5/BYhorUq+mVpPvEYADXNaPOCmXWieSJpu68sJC # VpVLPMhGS8lTsT16C2vB/4Lh4t8pJgs7aej90nqKk2rGgKw4ZNwMS+7Eg6n2lKf/ # V27+O+drJxgYzO6feveuKtIQXsHkx4//DNOCDPLLvrrOk+1NWnyPyT/UDxV/emyr # KLBbeXqcNhPkn7xZtvM7WARSHZcqhEPBkIAJG2H9HE4imxNm8d8ADZjEMbfE9ZNE # MDanpM6BYYDWw4y2A8J5QmbiLu3znH8RWmWHww1v6UQ7qyBCLx+HyEGKipGd3Eoe # 48hi/ktsAJUb1lRrk9gOJ+NsokGINzI5urFOReUh1q6+5us0Q0VpwjyVvhi8REy3 # 5gOMDC7O2zH+bLN08kseDXfc7vR9wLrIHqMloMgJzpjG5KcL67nVCPHcOwxe0sfn # 0SYWUY0UFNSYgEGBG6JfM6LiM1lRREzlw6YnnaJ+GUf/jdIUbMV6PKpL34TGLeQ3 # xEWrKV0+PMoWHwN0Pdo1tMXm7mc/9H27Mf7hB5k0Hp3dfQ7nIdkfnFA2YEUSxIQt # OXYsKLTJmO/4XIAYCHhIOncPTmM6KWNQajDJMIuEdYYV67Xb88EIv5Hg8q6tS/mN # uuQfun3Z2UbAtGvzN5Yx1w== # =K0Vo # -----END PGP SIGNATURE----- # gpg: Signature made Mon 27 Feb 2023 13:59:09 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20230227' of https://git.linaro.org/people/pmaydell/qemu-arm: (25 commits) hw: Replace qemu_or_irq typedef by OrIRQState hw/or-irq: Declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE() hw/irq: Declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE() iothread: Remove unused IOThreadClass / IOTHREAD_CLASS hw/arm/musicpal: Remove unused dummy MemoryRegion hw/intc/armv7m_nvic: Use QOM cast CPU() macro hw/timer/cmsdk-apb-timer: Remove unused 'qdev-properties.h' header hw/char/cmsdk-apb-uart: Open-code cmsdk_apb_uart_create() hw/char/xilinx_uartlite: Open-code xilinx_uartlite_create() hw/char/xilinx_uartlite: Expose XILINX_UARTLITE QOM type hw/char/pl011: Open-code pl011_luminary_create() hw/char/pl011: Un-inline pl011_create() hw/gpio/max7310: Simplify max7310_realize() tests/avocado: add machine:none tag to version.py cpu-defs.h: Expose CPUTLBEntryFull to non-TCG code target/arm: Don't access TCG code when debugging with KVM target/arm: Move regime_using_lpae_format into internal.h target/arm: Move hflags code into the tcg directory target/arm: Wrap arm_rebuild_hflags calls with tcg_enabled target/arm: Move psci.c into the tcg directory ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/arm/arm-powerctl.c7
-rw-r--r--target/arm/cpu.c9
-rw-r--r--target/arm/debug_helper.c490
-rw-r--r--target/arm/helper.c411
-rw-r--r--target/arm/internals.h23
-rw-r--r--target/arm/machine.c12
-rw-r--r--target/arm/meson.build46
-rw-r--r--target/arm/ptw.c4
-rw-r--r--target/arm/tcg-stubs.c27
-rw-r--r--target/arm/tcg/a32-uncond.decode (renamed from target/arm/a32-uncond.decode)0
-rw-r--r--target/arm/tcg/a32.decode (renamed from target/arm/a32.decode)0
-rw-r--r--target/arm/tcg/crypto_helper.c (renamed from target/arm/crypto_helper.c)0
-rw-r--r--target/arm/tcg/helper-a64.c (renamed from target/arm/helper-a64.c)0
-rw-r--r--target/arm/tcg/hflags.c403
-rw-r--r--target/arm/tcg/iwmmxt_helper.c (renamed from target/arm/iwmmxt_helper.c)0
-rw-r--r--target/arm/tcg/m-nocp.decode (renamed from target/arm/m-nocp.decode)0
-rw-r--r--target/arm/tcg/m_helper.c (renamed from target/arm/m_helper.c)0
-rw-r--r--target/arm/tcg/meson.build50
-rw-r--r--target/arm/tcg/mte_helper.c (renamed from target/arm/mte_helper.c)0
-rw-r--r--target/arm/tcg/mve.decode (renamed from target/arm/mve.decode)0
-rw-r--r--target/arm/tcg/mve_helper.c (renamed from target/arm/mve_helper.c)0
-rw-r--r--target/arm/tcg/neon-dp.decode (renamed from target/arm/neon-dp.decode)0
-rw-r--r--target/arm/tcg/neon-ls.decode (renamed from target/arm/neon-ls.decode)0
-rw-r--r--target/arm/tcg/neon-shared.decode (renamed from target/arm/neon-shared.decode)0
-rw-r--r--target/arm/tcg/neon_helper.c (renamed from target/arm/neon_helper.c)0
-rw-r--r--target/arm/tcg/op_helper.c (renamed from target/arm/op_helper.c)0
-rw-r--r--target/arm/tcg/pauth_helper.c (renamed from target/arm/pauth_helper.c)0
-rw-r--r--target/arm/tcg/psci.c (renamed from target/arm/psci.c)0
-rw-r--r--target/arm/tcg/sme-fa64.decode (renamed from target/arm/sme-fa64.decode)0
-rw-r--r--target/arm/tcg/sme.decode (renamed from target/arm/sme.decode)0
-rw-r--r--target/arm/tcg/sme_helper.c (renamed from target/arm/sme_helper.c)0
-rw-r--r--target/arm/tcg/sve.decode (renamed from target/arm/sve.decode)0
-rw-r--r--target/arm/tcg/sve_helper.c (renamed from target/arm/sve_helper.c)0
-rw-r--r--target/arm/tcg/t16.decode (renamed from target/arm/t16.decode)0
-rw-r--r--target/arm/tcg/t32.decode (renamed from target/arm/t32.decode)0
-rw-r--r--target/arm/tcg/tlb_helper.c (renamed from target/arm/tlb_helper.c)18
-rw-r--r--target/arm/tcg/translate-a64.c (renamed from target/arm/translate-a64.c)0
-rw-r--r--target/arm/tcg/translate-a64.h (renamed from target/arm/translate-a64.h)0
-rw-r--r--target/arm/tcg/translate-m-nocp.c (renamed from target/arm/translate-m-nocp.c)0
-rw-r--r--target/arm/tcg/translate-mve.c (renamed from target/arm/translate-mve.c)0
-rw-r--r--target/arm/tcg/translate-neon.c (renamed from target/arm/translate-neon.c)0
-rw-r--r--target/arm/tcg/translate-sme.c (renamed from target/arm/translate-sme.c)0
-rw-r--r--target/arm/tcg/translate-sve.c (renamed from target/arm/translate-sve.c)0
-rw-r--r--target/arm/tcg/translate-vfp.c (renamed from target/arm/translate-vfp.c)0
-rw-r--r--target/arm/tcg/translate.c (renamed from target/arm/translate.c)0
-rw-r--r--target/arm/tcg/translate.h (renamed from target/arm/translate.h)0
-rw-r--r--target/arm/tcg/vec_helper.c (renamed from target/arm/vec_helper.c)0
-rw-r--r--target/arm/tcg/vec_internal.h (renamed from target/arm/vec_internal.h)0
-rw-r--r--target/arm/tcg/vfp-uncond.decode (renamed from target/arm/vfp-uncond.decode)0
-rw-r--r--target/arm/tcg/vfp.decode (renamed from target/arm/vfp.decode)0
50 files changed, 794 insertions, 706 deletions
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
index b75f813b40..326a03153d 100644
--- a/target/arm/arm-powerctl.c
+++ b/target/arm/arm-powerctl.c
@@ -15,6 +15,7 @@
#include "arm-powerctl.h"
#include "qemu/log.h"
#include "qemu/main-loop.h"
+#include "sysemu/tcg.h"
#ifndef DEBUG_ARM_POWERCTL
#define DEBUG_ARM_POWERCTL 0
@@ -127,8 +128,10 @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state,
target_cpu->env.regs[0] = info->context_id;
}
- /* CP15 update requires rebuilding hflags */
- arm_rebuild_hflags(&target_cpu->env);
+ if (tcg_enabled()) {
+ /* CP15 update requires rebuilding hflags */
+ arm_rebuild_hflags(&target_cpu->env);
+ }
/* Start the new CPU at the requested address */
cpu_set_pc(target_cpu_state, info->entry);
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 876ab8f3bf..0b333a749f 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -539,9 +539,12 @@ static void arm_cpu_reset_hold(Object *obj)
}
#endif
- hw_breakpoint_update_all(cpu);
- hw_watchpoint_update_all(cpu);
- arm_rebuild_hflags(env);
+ if (tcg_enabled()) {
+ hw_breakpoint_update_all(cpu);
+ hw_watchpoint_update_all(cpu);
+
+ arm_rebuild_hflags(env);
+ }
}
#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index 3c671c88c1..dfc8b2a1a5 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -12,8 +12,9 @@
#include "cpregs.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
+#include "sysemu/tcg.h"
-
+#ifdef CONFIG_TCG
/* Return the Exception Level targeted by debug exceptions. */
static int arm_debug_target_el(CPUARMState *env)
{
@@ -536,6 +537,243 @@ void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)
raise_exception_debug(env, EXCP_UDEF, syndrome);
}
+void hw_watchpoint_update(ARMCPU *cpu, int n)
+{
+ CPUARMState *env = &cpu->env;
+ vaddr len = 0;
+ vaddr wvr = env->cp15.dbgwvr[n];
+ uint64_t wcr = env->cp15.dbgwcr[n];
+ int mask;
+ int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
+
+ if (env->cpu_watchpoint[n]) {
+ cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]);
+ env->cpu_watchpoint[n] = NULL;
+ }
+
+ if (!FIELD_EX64(wcr, DBGWCR, E)) {
+ /* E bit clear : watchpoint disabled */
+ return;
+ }
+
+ switch (FIELD_EX64(wcr, DBGWCR, LSC)) {
+ case 0:
+ /* LSC 00 is reserved and must behave as if the wp is disabled */
+ return;
+ case 1:
+ flags |= BP_MEM_READ;
+ break;
+ case 2:
+ flags |= BP_MEM_WRITE;
+ break;
+ case 3:
+ flags |= BP_MEM_ACCESS;
+ break;
+ }
+
+ /*
+ * Attempts to use both MASK and BAS fields simultaneously are
+ * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case,
+ * thus generating a watchpoint for every byte in the masked region.
+ */
+ mask = FIELD_EX64(wcr, DBGWCR, MASK);
+ if (mask == 1 || mask == 2) {
+ /*
+ * Reserved values of MASK; we must act as if the mask value was
+ * some non-reserved value, or as if the watchpoint were disabled.
+ * We choose the latter.
+ */
+ return;
+ } else if (mask) {
+ /* Watchpoint covers an aligned area up to 2GB in size */
+ len = 1ULL << mask;
+ /*
+ * If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE
+ * whether the watchpoint fires when the unmasked bits match; we opt
+ * to generate the exceptions.
+ */
+ wvr &= ~(len - 1);
+ } else {
+ /* Watchpoint covers bytes defined by the byte address select bits */
+ int bas = FIELD_EX64(wcr, DBGWCR, BAS);
+ int basstart;
+
+ if (extract64(wvr, 2, 1)) {
+ /*
+ * Deprecated case of an only 4-aligned address. BAS[7:4] are
+ * ignored, and BAS[3:0] define which bytes to watch.
+ */
+ bas &= 0xf;
+ }
+
+ if (bas == 0) {
+ /* This must act as if the watchpoint is disabled */
+ return;
+ }
+
+ /*
+ * The BAS bits are supposed to be programmed to indicate a contiguous
+ * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether
+ * we fire for each byte in the word/doubleword addressed by the WVR.
+ * We choose to ignore any non-zero bits after the first range of 1s.
+ */
+ basstart = ctz32(bas);
+ len = cto32(bas >> basstart);
+ wvr += basstart;
+ }
+
+ cpu_watchpoint_insert(CPU(cpu), wvr, len, flags,
+ &env->cpu_watchpoint[n]);
+}
+
+void hw_watchpoint_update_all(ARMCPU *cpu)
+{
+ int i;
+ CPUARMState *env = &cpu->env;
+
+ /*
+ * Completely clear out existing QEMU watchpoints and our array, to
+ * avoid possible stale entries following migration load.
+ */
+ cpu_watchpoint_remove_all(CPU(cpu), BP_CPU);
+ memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint));
+
+ for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) {
+ hw_watchpoint_update(cpu, i);
+ }
+}
+
+void hw_breakpoint_update(ARMCPU *cpu, int n)
+{
+ CPUARMState *env = &cpu->env;
+ uint64_t bvr = env->cp15.dbgbvr[n];
+ uint64_t bcr = env->cp15.dbgbcr[n];
+ vaddr addr;
+ int bt;
+ int flags = BP_CPU;
+
+ if (env->cpu_breakpoint[n]) {
+ cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]);
+ env->cpu_breakpoint[n] = NULL;
+ }
+
+ if (!extract64(bcr, 0, 1)) {
+ /* E bit clear : watchpoint disabled */
+ return;
+ }
+
+ bt = extract64(bcr, 20, 4);
+
+ switch (bt) {
+ case 4: /* unlinked address mismatch (reserved if AArch64) */
+ case 5: /* linked address mismatch (reserved if AArch64) */
+ qemu_log_mask(LOG_UNIMP,
+ "arm: address mismatch breakpoint types not implemented\n");
+ return;
+ case 0: /* unlinked address match */
+ case 1: /* linked address match */
+ {
+ /*
+ * Bits [1:0] are RES0.
+ *
+ * It is IMPLEMENTATION DEFINED whether bits [63:49]
+ * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit
+ * of the VA field ([48] or [52] for FEAT_LVA), or whether the
+ * value is read as written. It is CONSTRAINED UNPREDICTABLE
+ * whether the RESS bits are ignored when comparing an address.
+ * Therefore we are allowed to compare the entire register, which
+ * lets us avoid considering whether FEAT_LVA is actually enabled.
+ *
+ * The BAS field is used to allow setting breakpoints on 16-bit
+ * wide instructions; it is CONSTRAINED UNPREDICTABLE whether
+ * a bp will fire if the addresses covered by the bp and the addresses
+ * covered by the insn overlap but the insn doesn't start at the
+ * start of the bp address range. We choose to require the insn and
+ * the bp to have the same address. The constraints on writing to
+ * BAS enforced in dbgbcr_write mean we have only four cases:
+ * 0b0000 => no breakpoint
+ * 0b0011 => breakpoint on addr
+ * 0b1100 => breakpoint on addr + 2
+ * 0b1111 => breakpoint on addr
+ * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c).
+ */
+ int bas = extract64(bcr, 5, 4);
+ addr = bvr & ~3ULL;
+ if (bas == 0) {
+ return;
+ }
+ if (bas == 0xc) {
+ addr += 2;
+ }
+ break;
+ }
+ case 2: /* unlinked context ID match */
+ case 8: /* unlinked VMID match (reserved if no EL2) */
+ case 10: /* unlinked context ID and VMID match (reserved if no EL2) */
+ qemu_log_mask(LOG_UNIMP,
+ "arm: unlinked context breakpoint types not implemented\n");
+ return;
+ case 9: /* linked VMID match (reserved if no EL2) */
+ case 11: /* linked context ID and VMID match (reserved if no EL2) */
+ case 3: /* linked context ID match */
+ default:
+ /*
+ * We must generate no events for Linked context matches (unless
+ * they are linked to by some other bp/wp, which is handled in
+ * updates for the linking bp/wp). We choose to also generate no events
+ * for reserved values.
+ */
+ return;
+ }
+
+ cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]);
+}
+
+void hw_breakpoint_update_all(ARMCPU *cpu)
+{
+ int i;
+ CPUARMState *env = &cpu->env;
+
+ /*
+ * Completely clear out existing QEMU breakpoints and our array, to
+ * avoid possible stale entries following migration load.
+ */
+ cpu_breakpoint_remove_all(CPU(cpu), BP_CPU);
+ memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint));
+
+ for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) {
+ hw_breakpoint_update(cpu, i);
+ }
+}
+
+#if !defined(CONFIG_USER_ONLY)
+
+vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+
+ /*
+ * In BE32 system mode, target memory is stored byteswapped (on a
+ * little-endian host system), and by the time we reach here (via an
+ * opcode helper) the addresses of subword accesses have been adjusted
+ * to account for that, which means that watchpoints will not match.
+ * Undo the adjustment here.
+ */
+ if (arm_sctlr_b(env)) {
+ if (len == 1) {
+ addr ^= 3;
+ } else if (len == 2) {
+ addr ^= 2;
+ }
+ }
+
+ return addr;
+}
+
+#endif /* !CONFIG_USER_ONLY */
+#endif /* CONFIG_TCG */
+
/*
* Check for traps to "powerdown debug" registers, which are controlled
* by MDCR.TDOSA
@@ -813,112 +1051,6 @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
.access = PL0_R, .type = ARM_CP_CONST | ARM_CP_64BIT, .resetvalue = 0 },
};
-void hw_watchpoint_update(ARMCPU *cpu, int n)
-{
- CPUARMState *env = &cpu->env;
- vaddr len = 0;
- vaddr wvr = env->cp15.dbgwvr[n];
- uint64_t wcr = env->cp15.dbgwcr[n];
- int mask;
- int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
-
- if (env->cpu_watchpoint[n]) {
- cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]);
- env->cpu_watchpoint[n] = NULL;
- }
-
- if (!FIELD_EX64(wcr, DBGWCR, E)) {
- /* E bit clear : watchpoint disabled */
- return;
- }
-
- switch (FIELD_EX64(wcr, DBGWCR, LSC)) {
- case 0:
- /* LSC 00 is reserved and must behave as if the wp is disabled */
- return;
- case 1:
- flags |= BP_MEM_READ;
- break;
- case 2:
- flags |= BP_MEM_WRITE;
- break;
- case 3:
- flags |= BP_MEM_ACCESS;
- break;
- }
-
- /*
- * Attempts to use both MASK and BAS fields simultaneously are
- * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case,
- * thus generating a watchpoint for every byte in the masked region.
- */
- mask = FIELD_EX64(wcr, DBGWCR, MASK);
- if (mask == 1 || mask == 2) {
- /*
- * Reserved values of MASK; we must act as if the mask value was
- * some non-reserved value, or as if the watchpoint were disabled.
- * We choose the latter.
- */
- return;
- } else if (mask) {
- /* Watchpoint covers an aligned area up to 2GB in size */
- len = 1ULL << mask;
- /*
- * If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE
- * whether the watchpoint fires when the unmasked bits match; we opt
- * to generate the exceptions.
- */
- wvr &= ~(len - 1);
- } else {
- /* Watchpoint covers bytes defined by the byte address select bits */
- int bas = FIELD_EX64(wcr, DBGWCR, BAS);
- int basstart;
-
- if (extract64(wvr, 2, 1)) {
- /*
- * Deprecated case of an only 4-aligned address. BAS[7:4] are
- * ignored, and BAS[3:0] define which bytes to watch.
- */
- bas &= 0xf;
- }
-
- if (bas == 0) {
- /* This must act as if the watchpoint is disabled */
- return;
- }
-
- /*
- * The BAS bits are supposed to be programmed to indicate a contiguous
- * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether
- * we fire for each byte in the word/doubleword addressed by the WVR.
- * We choose to ignore any non-zero bits after the first range of 1s.
- */
- basstart = ctz32(bas);
- len = cto32(bas >> basstart);
- wvr += basstart;
- }
-
- cpu_watchpoint_insert(CPU(cpu), wvr, len, flags,
- &env->cpu_watchpoint[n]);
-}
-
-void hw_watchpoint_update_all(ARMCPU *cpu)
-{
- int i;
- CPUARMState *env = &cpu->env;
-
- /*
- * Completely clear out existing QEMU watchpoints and our array, to
- * avoid possible stale entries following migration load.
- */
- cpu_watchpoint_remove_all(CPU(cpu), BP_CPU);
- memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint));
-
- for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) {
- hw_watchpoint_update(cpu, i);
- }
-}
-
static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
@@ -939,7 +1071,9 @@ static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri,
value &= ~3ULL;
raw_write(env, ri, value);
- hw_watchpoint_update(cpu, i);
+ if (tcg_enabled()) {
+ hw_watchpoint_update(cpu, i);
+ }
}
static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -949,109 +1083,8 @@ static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
int i = ri->crm;
raw_write(env, ri, value);
- hw_watchpoint_update(cpu, i);
-}
-
-void hw_breakpoint_update(ARMCPU *cpu, int n)
-{
- CPUARMState *env = &cpu->env;
- uint64_t bvr = env->cp15.dbgbvr[n];
- uint64_t bcr = env->cp15.dbgbcr[n];
- vaddr addr;
- int bt;
- int flags = BP_CPU;
-
- if (env->cpu_breakpoint[n]) {
- cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]);
- env->cpu_breakpoint[n] = NULL;
- }
-
- if (!extract64(bcr, 0, 1)) {
- /* E bit clear : watchpoint disabled */
- return;
- }
-
- bt = extract64(bcr, 20, 4);
-
- switch (bt) {
- case 4: /* unlinked address mismatch (reserved if AArch64) */
- case 5: /* linked address mismatch (reserved if AArch64) */
- qemu_log_mask(LOG_UNIMP,
- "arm: address mismatch breakpoint types not implemented\n");
- return;
- case 0: /* unlinked address match */
- case 1: /* linked address match */
- {
- /*
- * Bits [1:0] are RES0.
- *
- * It is IMPLEMENTATION DEFINED whether bits [63:49]
- * ([63:53] for FEAT_LVA) are hardwired to a copy of the sign bit
- * of the VA field ([48] or [52] for FEAT_LVA), or whether the
- * value is read as written. It is CONSTRAINED UNPREDICTABLE
- * whether the RESS bits are ignored when comparing an address.
- * Therefore we are allowed to compare the entire register, which
- * lets us avoid considering whether FEAT_LVA is actually enabled.
- *
- * The BAS field is used to allow setting breakpoints on 16-bit
- * wide instructions; it is CONSTRAINED UNPREDICTABLE whether
- * a bp will fire if the addresses covered by the bp and the addresses
- * covered by the insn overlap but the insn doesn't start at the
- * start of the bp address range. We choose to require the insn and
- * the bp to have the same address. The constraints on writing to
- * BAS enforced in dbgbcr_write mean we have only four cases:
- * 0b0000 => no breakpoint
- * 0b0011 => breakpoint on addr
- * 0b1100 => breakpoint on addr + 2
- * 0b1111 => breakpoint on addr
- * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c).
- */
- int bas = extract64(bcr, 5, 4);
- addr = bvr & ~3ULL;
- if (bas == 0) {
- return;
- }
- if (bas == 0xc) {
- addr += 2;
- }
- break;
- }
- case 2: /* unlinked context ID match */
- case 8: /* unlinked VMID match (reserved if no EL2) */
- case 10: /* unlinked context ID and VMID match (reserved if no EL2) */
- qemu_log_mask(LOG_UNIMP,
- "arm: unlinked context breakpoint types not implemented\n");
- return;
- case 9: /* linked VMID match (reserved if no EL2) */
- case 11: /* linked context ID and VMID match (reserved if no EL2) */
- case 3: /* linked context ID match */
- default:
- /*
- * We must generate no events for Linked context matches (unless
- * they are linked to by some other bp/wp, which is handled in
- * updates for the linking bp/wp). We choose to also generate no events
- * for reserved values.
- */
- return;
- }
-
- cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]);
-}
-
-void hw_breakpoint_update_all(ARMCPU *cpu)
-{
- int i;
- CPUARMState *env = &cpu->env;
-
- /*
- * Completely clear out existing QEMU breakpoints and our array, to
- * avoid possible stale entries following migration load.
- */
- cpu_breakpoint_remove_all(CPU(cpu), BP_CPU);
- memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint));
-
- for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) {
- hw_breakpoint_update(cpu, i);
+ if (tcg_enabled()) {
+ hw_watchpoint_update(cpu, i);
}
}
@@ -1062,7 +1095,9 @@ static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri,
int i = ri->crm;
raw_write(env, ri, value);
- hw_breakpoint_update(cpu, i);
+ if (tcg_enabled()) {
+ hw_breakpoint_update(cpu, i);
+ }
}
static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -1079,7 +1114,9 @@ static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
value = deposit64(value, 8, 1, extract64(value, 7, 1));
raw_write(env, ri, value);
- hw_breakpoint_update(cpu, i);
+ if (tcg_enabled()) {
+ hw_breakpoint_update(cpu, i);
+ }
}
void define_debug_regs(ARMCPU *cpu)
@@ -1202,30 +1239,3 @@ void define_debug_regs(ARMCPU *cpu)
g_free(dbgwcr_el1_name);
}
}
-
-#if !defined(CONFIG_USER_ONLY)
-
-vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)
-{
- ARMCPU *cpu = ARM_CPU(cs);
- CPUARMState *env = &cpu->env;
-
- /*
- * In BE32 system mode, target memory is stored byteswapped (on a
- * little-endian host system), and by the time we reach here (via an
- * opcode helper) the addresses of subword accesses have been adjusted
- * to account for that, which means that watchpoints will not match.
- * Undo the adjustment here.
- */
- if (arm_sctlr_b(env)) {
- if (len == 1) {
- addr ^= 3;
- } else if (len == 2) {
- addr ^= 2;
- }
- }
-
- return addr;
-}
-
-#endif
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 07d4100365..14af7ba095 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5173,7 +5173,7 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
/* This may enable/disable the MMU, so do a TLB flush. */
tlb_flush(CPU(cpu));
- if (ri->type & ARM_CP_SUPPRESS_TB_END) {
+ if (tcg_enabled() && ri->type & ARM_CP_SUPPRESS_TB_END) {
/*
* Normally we would always end the TB on an SCTLR write; see the
* comment in ARMCPRegInfo sctlr initialization below for why Xscale
@@ -6669,32 +6669,6 @@ int sme_exception_el(CPUARMState *env, int el)
return 0;
}
-/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */
-static bool sme_fa64(CPUARMState *env, int el)
-{
- if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) {
- return false;
- }
-
- if (el <= 1 && !el_is_in_host(env, el)) {
- if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) {
- return false;
- }
- }
- if (el <= 2 && arm_is_el2_enabled(env)) {
- if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) {
- return false;
- }
- }
- if (arm_feature(env, ARM_FEATURE_EL3)) {
- if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) {
- return false;
- }
- }
-
- return true;
-}
-
/*
* Given that SVE is enabled, return the vector length for EL.
*/
@@ -6841,7 +6815,9 @@ void aarch64_set_svcr(CPUARMState *env, uint64_t new, uint64_t mask)
memset(env->zarray, 0, sizeof(env->zarray));
}
- arm_rebuild_hflags(env);
+ if (tcg_enabled()) {
+ arm_rebuild_hflags(env);
+ }
}
static void svcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -9886,7 +9862,7 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
}
mask &= ~CACHED_CPSR_BITS;
env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
- if (rebuild_hflags) {
+ if (tcg_enabled() && rebuild_hflags) {
arm_rebuild_hflags(env);
}
}
@@ -10445,7 +10421,10 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
env->regs[14] = env->regs[15] + offset;
}
env->regs[15] = newpc;
- arm_rebuild_hflags(env);
+
+ if (tcg_enabled()) {
+ arm_rebuild_hflags(env);
+ }
}
static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs)
@@ -11001,7 +10980,10 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
pstate_write(env, PSTATE_DAIF | new_mode);
env->aarch64 = true;
aarch64_restore_sp(env, new_el);
- helper_rebuild_hflags_a64(env, new_el);
+
+ if (tcg_enabled()) {
+ helper_rebuild_hflags_a64(env, new_el);
+ }
env->pc = addr;
@@ -11142,7 +11124,7 @@ int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx)
}
}
-static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
+int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
{
if (regime_has_2_ranges(mmu_idx)) {
return extract64(tcr, 57, 2);
@@ -11853,371 +11835,6 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env)
return arm_mmu_idx_el(env, arm_current_el(env));
}
-static inline bool fgt_svc(CPUARMState *env, int el)
-{
- /*
- * Assuming fine-grained-traps are active, return true if we
- * should be trapping on SVC instructions. Only AArch64 can
- * trap on an SVC at EL1, but we don't need to special-case this
- * because if this is AArch32 EL1 then arm_fgt_active() is false.
- * We also know el is 0 or 1.
- */
- return el == 0 ?
- FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL0) :
- FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL1);
-}
-
-static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el,
- ARMMMUIdx mmu_idx,
- CPUARMTBFlags flags)
-{
- DP_TBFLAG_ANY(flags, FPEXC_EL, fp_el);
- DP_TBFLAG_ANY(flags, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
-
- if (arm_singlestep_active(env)) {
- DP_TBFLAG_ANY(flags, SS_ACTIVE, 1);
- }
-
- return flags;
-}
-
-static CPUARMTBFlags rebuild_hflags_common_32(CPUARMState *env, int fp_el,
- ARMMMUIdx mmu_idx,
- CPUARMTBFlags flags)
-{
- bool sctlr_b = arm_sctlr_b(env);
-
- if (sctlr_b) {
- DP_TBFLAG_A32(flags, SCTLR__B, 1);
- }
- if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) {
- DP_TBFLAG_ANY(flags, BE_DATA, 1);
- }
- DP_TBFLAG_A32(flags, NS, !access_secure_reg(env));
-
- return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
-}
-
-static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el,
- ARMMMUIdx mmu_idx)
-{
- CPUARMTBFlags flags = {};
- uint32_t ccr = env->v7m.ccr[env->v7m.secure];
-
- /* Without HaveMainExt, CCR.UNALIGN_TRP is RES1. */
- if (ccr & R_V7M_CCR_UNALIGN_TRP_MASK) {
- DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
- }
-
- if (arm_v7m_is_handler_mode(env)) {
- DP_TBFLAG_M32(flags, HANDLER, 1);
- }
-
- /*
- * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN
- * is suppressing them because the requested execution priority
- * is less than 0.
- */
- if (arm_feature(env, ARM_FEATURE_V8) &&
- !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
- (ccr & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
- DP_TBFLAG_M32(flags, STACKCHECK, 1);
- }
-
- if (arm_feature(env, ARM_FEATURE_M_SECURITY) && env->v7m.secure) {
- DP_TBFLAG_M32(flags, SECURE, 1);
- }
-
- return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
-}
-
-static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
- ARMMMUIdx mmu_idx)
-{
- CPUARMTBFlags flags = {};
- int el = arm_current_el(env);
-
- if (arm_sctlr(env, el) & SCTLR_A) {
- DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
- }
-
- if (arm_el_is_aa64(env, 1)) {
- DP_TBFLAG_A32(flags, VFPEN, 1);
- }
-
- if (el < 2 && env->cp15.hstr_el2 && arm_is_el2_enabled(env) &&
- (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
- DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1);
- }
-
- if (arm_fgt_active(env, el)) {
- DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1);
- if (fgt_svc(env, el)) {
- DP_TBFLAG_ANY(flags, FGT_SVC, 1);
- }
- }
-
- if (env->uncached_cpsr & CPSR_IL) {
- DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
- }
-
- /*
- * The SME exception we are testing for is raised via
- * AArch64.CheckFPAdvSIMDEnabled(), as called from
- * AArch32.CheckAdvSIMDOrFPEnabled().
- */
- if (el == 0
- && FIELD_EX64(env->svcr, SVCR, SM)
- && (!arm_is_el2_enabled(env)
- || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE)))
- && arm_el_is_aa64(env, 1)
- && !sme_fa64(env, el)) {
- DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1);
- }
-
- return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
-}
-
-static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
- ARMMMUIdx mmu_idx)
-{
- CPUARMTBFlags flags = {};
- ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
- uint64_t tcr = regime_tcr(env, mmu_idx);
- uint64_t sctlr;
- int tbii, tbid;
-
- DP_TBFLAG_ANY(flags, AARCH64_STATE, 1);
-
- /* Get control bits for tagged addresses. */
- tbid = aa64_va_parameter_tbi(tcr, mmu_idx);
- tbii = tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx);
-
- DP_TBFLAG_A64(flags, TBII, tbii);
- DP_TBFLAG_A64(flags, TBID, tbid);
-
- if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
- int sve_el = sve_exception_el(env, el);
-
- /*
- * If either FP or SVE are disabled, translator does not need len.
- * If SVE EL > FP EL, FP exception has precedence, and translator
- * does not need SVE EL. Save potential re-translations by forcing
- * the unneeded data to zero.
- */
- if (fp_el != 0) {
- if (sve_el > fp_el) {
- sve_el = 0;
- }
- } else if (sve_el == 0) {
- DP_TBFLAG_A64(flags, VL, sve_vqm1_for_el(env, el));
- }
- DP_TBFLAG_A64(flags, SVEEXC_EL, sve_el);
- }
- if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
- int sme_el = sme_exception_el(env, el);
- bool sm = FIELD_EX64(env->svcr, SVCR, SM);
-
- DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el);
- if (sme_el == 0) {
- /* Similarly, do not compute SVL if SME is disabled. */
- int svl = sve_vqm1_for_el_sm(env, el, true);
- DP_TBFLAG_A64(flags, SVL, svl);
- if (sm) {
- /* If SVE is disabled, we will not have set VL above. */
- DP_TBFLAG_A64(flags, VL, svl);
- }
- }
- if (sm) {
- DP_TBFLAG_A64(flags, PSTATE_SM, 1);
- DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el));
- }
- DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA));
- }
-
- sctlr = regime_sctlr(env, stage1);
-
- if (sctlr & SCTLR_A) {
- DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
- }
-
- if (arm_cpu_data_is_big_endian_a64(el, sctlr)) {
- DP_TBFLAG_ANY(flags, BE_DATA, 1);
- }
-
- if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) {
- /*
- * In order to save space in flags, we record only whether
- * pauth is "inactive", meaning all insns are implemented as
- * a nop, or "active" when some action must be performed.
- * The decision of which action to take is left to a helper.
- */
- if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) {
- DP_TBFLAG_A64(flags, PAUTH_ACTIVE, 1);
- }
- }
-
- if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
- /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
- if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
- DP_TBFLAG_A64(flags, BT, 1);
- }
- }
-
- /* Compute the condition for using AccType_UNPRIV for LDTR et al. */
- if (!(env->pstate & PSTATE_UAO)) {
- switch (mmu_idx) {
- case ARMMMUIdx_E10_1:
- case ARMMMUIdx_E10_1_PAN:
- /* TODO: ARMv8.3-NV */
- DP_TBFLAG_A64(flags, UNPRIV, 1);
- break;
- case ARMMMUIdx_E20_2:
- case ARMMMUIdx_E20_2_PAN:
- /*
- * Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is
- * gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.
- */
- if (env->cp15.hcr_el2 & HCR_TGE) {
- DP_TBFLAG_A64(flags, UNPRIV, 1);
- }
- break;
- default:
- break;
- }
- }
-
- if (env->pstate & PSTATE_IL) {
- DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
- }
-
- if (arm_fgt_active(env, el)) {
- DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1);
- if (FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, ERET)) {
- DP_TBFLAG_A64(flags, FGT_ERET, 1);
- }
- if (fgt_svc(env, el)) {
- DP_TBFLAG_ANY(flags, FGT_SVC, 1);
- }
- }
-
- if (cpu_isar_feature(aa64_mte, env_archcpu(env))) {
- /*
- * Set MTE_ACTIVE if any access may be Checked, and leave clear
- * if all accesses must be Unchecked:
- * 1) If no TBI, then there are no tags in the address to check,
- * 2) If Tag Check Override, then all accesses are Unchecked,
- * 3) If Tag Check Fail == 0, then Checked access have no effect,
- * 4) If no Allocation Tag Access, then all accesses are Unchecked.
- */
- if (allocation_tag_access_enabled(env, el, sctlr)) {
- DP_TBFLAG_A64(flags, ATA, 1);
- if (tbid
- && !(env->pstate & PSTATE_TCO)
- && (sctlr & (el == 0 ? SCTLR_TCF0 : SCTLR_TCF))) {
- DP_TBFLAG_A64(flags, MTE_ACTIVE, 1);
- }
- }
- /* And again for unprivileged accesses, if required. */
- if (EX_TBFLAG_A64(flags, UNPRIV)
- && tbid
- && !(env->pstate & PSTATE_TCO)
- && (sctlr & SCTLR_TCF0)
- && allocation_tag_access_enabled(env, 0, sctlr)) {
- DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1);
- }
- /* Cache TCMA as well as TBI. */
- DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx));
- }
-
- return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
-}
-
-static CPUARMTBFlags rebuild_hflags_internal(CPUARMState *env)
-{
- int el = arm_current_el(env);
- int fp_el = fp_exception_el(env, el);
- ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
-
- if (is_a64(env)) {
- return rebuild_hflags_a64(env, el, fp_el, mmu_idx);
- } else if (arm_feature(env, ARM_FEATURE_M)) {
- return rebuild_hflags_m32(env, fp_el, mmu_idx);
- } else {
- return rebuild_hflags_a32(env, fp_el, mmu_idx);
- }
-}
-
-void arm_rebuild_hflags(CPUARMState *env)
-{
- env->hflags = rebuild_hflags_internal(env);
-}
-
-/*
- * If we have triggered a EL state change we can't rely on the
- * translator having passed it to us, we need to recompute.
- */
-void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env)
-{
- int el = arm_current_el(env);
- int fp_el = fp_exception_el(env, el);
- ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
-
- env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
-}
-
-void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
-{
- int fp_el = fp_exception_el(env, el);
- ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
-
- env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
-}
-
-/*
- * If we have triggered a EL state change we can't rely on the
- * translator having passed it to us, we need to recompute.
- */
-void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env)
-{
- int el = arm_current_el(env);
- int fp_el = fp_exception_el(env, el);
- ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
- env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx);
-}
-
-void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el)
-{
- int fp_el = fp_exception_el(env, el);
- ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
-
- env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx);
-}
-
-void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el)
-{
- int fp_el = fp_exception_el(env, el);
- ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
-
- env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx);
-}
-
-static inline void assert_hflags_rebuild_correctly(CPUARMState *env)
-{
-#ifdef CONFIG_DEBUG_TCG
- CPUARMTBFlags c = env->hflags;
- CPUARMTBFlags r = rebuild_hflags_internal(env);
-
- if (unlikely(c.flags != r.flags || c.flags2 != r.flags2)) {
- fprintf(stderr, "TCG hflags mismatch "
- "(current:(0x%08x,0x" TARGET_FMT_lx ")"
- " rebuilt:(0x%08x,0x" TARGET_FMT_lx ")\n",
- c.flags, c.flags2, r.flags, r.flags2);
- abort();
- }
-#endif
-}
-
static bool mve_no_pred(CPUARMState *env)
{
/*
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 759b70c646..680c574717 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -600,9 +600,6 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx);
/* Return the MMU index for a v7M CPU in the specified security state */
ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
-/* Return true if the translation regime is using LPAE format page tables */
-bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx);
-
/*
* Return true if the stage 1 translation regime is using LPAE
* format page tables
@@ -767,6 +764,24 @@ static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
return env->cp15.tcr_el[regime_el(env, mmu_idx)];
}
+/* Return true if the translation regime is using LPAE format page tables */
+static inline bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
+{
+ int el = regime_el(env, mmu_idx);
+ if (el == 2 || arm_el_is_aa64(env, el)) {
+ return true;
+ }
+ if (arm_feature(env, ARM_FEATURE_PMSA) &&
+ arm_feature(env, ARM_FEATURE_V8)) {
+ return true;
+ }
+ if (arm_feature(env, ARM_FEATURE_LPAE)
+ && (regime_tcr(env, mmu_idx) & TTBCR_EAE)) {
+ return true;
+ }
+ return false;
+}
+
/**
* arm_num_brps: Return number of implemented breakpoints.
* Note that the ID register BRPS field is "number of bps - 1",
@@ -1073,6 +1088,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx);
+int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx);
/* Determine if allocation tags are available. */
static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
@@ -1383,4 +1399,5 @@ static inline bool arm_fgt_active(CPUARMState *env, int el)
(!arm_feature(env, ARM_FEATURE_EL3) || (env->cp15.scr_el3 & SCR_FGTEN));
}
+void assert_hflags_rebuild_correctly(CPUARMState *env);
#endif
diff --git a/target/arm/machine.c b/target/arm/machine.c
index b4c3850570..fc4a4a4064 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -2,6 +2,7 @@
#include "cpu.h"
#include "qemu/error-report.h"
#include "sysemu/kvm.h"
+#include "sysemu/tcg.h"
#include "kvm_arm.h"
#include "internals.h"
#include "migration/cpu.h"
@@ -848,8 +849,10 @@ static int cpu_post_load(void *opaque, int version_id)
return -1;
}
- hw_breakpoint_update_all(cpu);
- hw_watchpoint_update_all(cpu);
+ if (tcg_enabled()) {
+ hw_breakpoint_update_all(cpu);
+ hw_watchpoint_update_all(cpu);
+ }
/*
* TCG gen_update_fp_context() relies on the invariant that
@@ -868,7 +871,10 @@ static int cpu_post_load(void *opaque, int version_id)
if (!kvm_enabled()) {
pmu_op_finish(&cpu->env);
}
- arm_rebuild_hflags(&cpu->env);
+
+ if (tcg_enabled()) {
+ arm_rebuild_hflags(&cpu->env);
+ }
return 0;
}
diff --git a/target/arm/meson.build b/target/arm/meson.build
index 87e911b27f..a5191b57e1 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -1,40 +1,9 @@
-gen = [
- decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
- decodetree.process('sme.decode', extra_args: '--decode=disas_sme'),
- decodetree.process('sme-fa64.decode', extra_args: '--static-decode=disas_sme_fa64'),
- decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
- decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
- decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
- decodetree.process('vfp.decode', extra_args: '--decode=disas_vfp'),
- decodetree.process('vfp-uncond.decode', extra_args: '--decode=disas_vfp_uncond'),
- decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'),
- decodetree.process('mve.decode', extra_args: '--decode=disas_mve'),
- decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'),
- decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'),
- decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'),
- decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-decode=disas_t16']),
-]
-
arm_ss = ss.source_set()
-arm_ss.add(gen)
arm_ss.add(files(
'cpu.c',
- 'crypto_helper.c',
'debug_helper.c',
'gdbstub.c',
'helper.c',
- 'iwmmxt_helper.c',
- 'm_helper.c',
- 'mve_helper.c',
- 'neon_helper.c',
- 'op_helper.c',
- 'tlb_helper.c',
- 'translate.c',
- 'translate-m-nocp.c',
- 'translate-mve.c',
- 'translate-neon.c',
- 'translate-vfp.c',
- 'vec_helper.c',
'vfp_helper.c',
'cpu_tcg.c',
))
@@ -45,14 +14,6 @@ arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: fil
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
'cpu64.c',
'gdbstub64.c',
- 'helper-a64.c',
- 'mte_helper.c',
- 'pauth_helper.c',
- 'sve_helper.c',
- 'sme_helper.c',
- 'translate-a64.c',
- 'translate-sve.c',
- 'translate-sme.c',
))
arm_softmmu_ss = ss.source_set()
@@ -61,11 +22,16 @@ arm_softmmu_ss.add(files(
'arm-powerctl.c',
'machine.c',
'monitor.c',
- 'psci.c',
'ptw.c',
))
subdir('hvf')
+if 'CONFIG_TCG' in config_all
+ subdir('tcg')
+else
+ arm_ss.add(files('tcg-stubs.c'))
+endif
+
target_arch += {'arm': arm_ss}
target_softmmu_arch += {'arm': arm_softmmu_ss}
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 2b125fff44..be0cc6bc15 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -254,6 +254,7 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
ptw->out_host = NULL;
ptw->out_rw = false;
} else {
+#ifdef CONFIG_TCG
CPUTLBEntryFull *full;
int flags;
@@ -270,6 +271,9 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
ptw->out_rw = full->prot & PAGE_WRITE;
pte_attrs = full->pte_attrs;
pte_secure = full->attrs.secure;
+#else
+ g_assert_not_reached();
+#endif
}
if (regime_is_stage2(s2_mmu_idx)) {
diff --git a/target/arm/tcg-stubs.c b/target/arm/tcg-stubs.c
new file mode 100644
index 0000000000..152b172e24
--- /dev/null
+++ b/target/arm/tcg-stubs.c
@@ -0,0 +1,27 @@
+/*
+ * QEMU ARM stubs for some TCG helper functions
+ *
+ * Copyright 2021 SUSE LLC
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "internals.h"
+
+void write_v7m_exception(CPUARMState *env, uint32_t new_exc)
+{
+ g_assert_not_reached();
+}
+
+void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome,
+ uint32_t target_el, uintptr_t ra)
+{
+ g_assert_not_reached();
+}
+/* Temporarily while cpu_get_tb_cpu_state() is still in common code */
+void assert_hflags_rebuild_correctly(CPUARMState *env)
+{
+}
diff --git a/target/arm/a32-uncond.decode b/target/arm/tcg/a32-uncond.decode
index 2339de2e94..2339de2e94 100644
--- a/target/arm/a32-uncond.decode
+++ b/target/arm/tcg/a32-uncond.decode
diff --git a/target/arm/a32.decode b/target/arm/tcg/a32.decode
index f2ca480949..f2ca480949 100644
--- a/target/arm/a32.decode
+++ b/target/arm/tcg/a32.decode
diff --git a/target/arm/crypto_helper.c b/target/arm/tcg/crypto_helper.c
index d28690321f..d28690321f 100644
--- a/target/arm/crypto_helper.c
+++ b/target/arm/tcg/crypto_helper.c
diff --git a/target/arm/helper-a64.c b/target/arm/tcg/helper-a64.c
index 0972a4bdd0..0972a4bdd0 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/tcg/helper-a64.c
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
new file mode 100644
index 0000000000..b2ccd77cff
--- /dev/null
+++ b/target/arm/tcg/hflags.c
@@ -0,0 +1,403 @@
+/*
+ * ARM hflags
+ *
+ * This code is licensed under the GNU GPL v2 or later.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "internals.h"
+#include "exec/helper-proto.h"
+#include "cpregs.h"
+
+static inline bool fgt_svc(CPUARMState *env, int el)
+{
+ /*
+ * Assuming fine-grained-traps are active, return true if we
+ * should be trapping on SVC instructions. Only AArch64 can
+ * trap on an SVC at EL1, but we don't need to special-case this
+ * because if this is AArch32 EL1 then arm_fgt_active() is false.
+ * We also know el is 0 or 1.
+ */
+ return el == 0 ?
+ FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL0) :
+ FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL1);
+}
+
+static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el,
+ ARMMMUIdx mmu_idx,
+ CPUARMTBFlags flags)
+{
+ DP_TBFLAG_ANY(flags, FPEXC_EL, fp_el);
+ DP_TBFLAG_ANY(flags, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
+
+ if (arm_singlestep_active(env)) {
+ DP_TBFLAG_ANY(flags, SS_ACTIVE, 1);
+ }
+
+ return flags;
+}
+
+static CPUARMTBFlags rebuild_hflags_common_32(CPUARMState *env, int fp_el,
+ ARMMMUIdx mmu_idx,
+ CPUARMTBFlags flags)
+{
+ bool sctlr_b = arm_sctlr_b(env);
+
+ if (sctlr_b) {
+ DP_TBFLAG_A32(flags, SCTLR__B, 1);
+ }
+ if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) {
+ DP_TBFLAG_ANY(flags, BE_DATA, 1);
+ }
+ DP_TBFLAG_A32(flags, NS, !access_secure_reg(env));
+
+ return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
+}
+
+static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el,
+ ARMMMUIdx mmu_idx)
+{
+ CPUARMTBFlags flags = {};
+ uint32_t ccr = env->v7m.ccr[env->v7m.secure];
+
+ /* Without HaveMainExt, CCR.UNALIGN_TRP is RES1. */
+ if (ccr & R_V7M_CCR_UNALIGN_TRP_MASK) {
+ DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
+ }
+
+ if (arm_v7m_is_handler_mode(env)) {
+ DP_TBFLAG_M32(flags, HANDLER, 1);
+ }
+
+ /*
+ * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN
+ * is suppressing them because the requested execution priority
+ * is less than 0.
+ */
+ if (arm_feature(env, ARM_FEATURE_V8) &&
+ !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
+ (ccr & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
+ DP_TBFLAG_M32(flags, STACKCHECK, 1);
+ }
+
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) && env->v7m.secure) {
+ DP_TBFLAG_M32(flags, SECURE, 1);
+ }
+
+ return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
+}
+
+/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */
+static bool sme_fa64(CPUARMState *env, int el)
+{
+ if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) {
+ return false;
+ }
+
+ if (el <= 1 && !el_is_in_host(env, el)) {
+ if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) {
+ return false;
+ }
+ }
+ if (el <= 2 && arm_is_el2_enabled(env)) {
+ if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) {
+ return false;
+ }
+ }
+ if (arm_feature(env, ARM_FEATURE_EL3)) {
+ if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
+ ARMMMUIdx mmu_idx)
+{
+ CPUARMTBFlags flags = {};
+ int el = arm_current_el(env);
+
+ if (arm_sctlr(env, el) & SCTLR_A) {
+ DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
+ }
+
+ if (arm_el_is_aa64(env, 1)) {
+ DP_TBFLAG_A32(flags, VFPEN, 1);
+ }
+
+ if (el < 2 && env->cp15.hstr_el2 && arm_is_el2_enabled(env) &&
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
+ DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1);
+ }
+
+ if (arm_fgt_active(env, el)) {
+ DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1);
+ if (fgt_svc(env, el)) {
+ DP_TBFLAG_ANY(flags, FGT_SVC, 1);
+ }
+ }
+
+ if (env->uncached_cpsr & CPSR_IL) {
+ DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
+ }
+
+ /*
+ * The SME exception we are testing for is raised via
+ * AArch64.CheckFPAdvSIMDEnabled(), as called from
+ * AArch32.CheckAdvSIMDOrFPEnabled().
+ */
+ if (el == 0
+ && FIELD_EX64(env->svcr, SVCR, SM)
+ && (!arm_is_el2_enabled(env)
+ || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE)))
+ && arm_el_is_aa64(env, 1)
+ && !sme_fa64(env, el)) {
+ DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1);
+ }
+
+ return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
+}
+
+static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
+ ARMMMUIdx mmu_idx)
+{
+ CPUARMTBFlags flags = {};
+ ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
+ uint64_t tcr = regime_tcr(env, mmu_idx);
+ uint64_t sctlr;
+ int tbii, tbid;
+
+ DP_TBFLAG_ANY(flags, AARCH64_STATE, 1);
+
+ /* Get control bits for tagged addresses. */
+ tbid = aa64_va_parameter_tbi(tcr, mmu_idx);
+ tbii = tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx);
+
+ DP_TBFLAG_A64(flags, TBII, tbii);
+ DP_TBFLAG_A64(flags, TBID, tbid);
+
+ if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
+ int sve_el = sve_exception_el(env, el);
+
+ /*
+ * If either FP or SVE are disabled, translator does not need len.
+ * If SVE EL > FP EL, FP exception has precedence, and translator
+ * does not need SVE EL. Save potential re-translations by forcing
+ * the unneeded data to zero.
+ */
+ if (fp_el != 0) {
+ if (sve_el > fp_el) {
+ sve_el = 0;
+ }
+ } else if (sve_el == 0) {
+ DP_TBFLAG_A64(flags, VL, sve_vqm1_for_el(env, el));
+ }
+ DP_TBFLAG_A64(flags, SVEEXC_EL, sve_el);
+ }
+ if (cpu_isar_feature(aa64_sme, env_archcpu(env))) {
+ int sme_el = sme_exception_el(env, el);
+ bool sm = FIELD_EX64(env->svcr, SVCR, SM);
+
+ DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el);
+ if (sme_el == 0) {
+ /* Similarly, do not compute SVL if SME is disabled. */
+ int svl = sve_vqm1_for_el_sm(env, el, true);
+ DP_TBFLAG_A64(flags, SVL, svl);
+ if (sm) {
+ /* If SVE is disabled, we will not have set VL above. */
+ DP_TBFLAG_A64(flags, VL, svl);
+ }
+ }
+ if (sm) {
+ DP_TBFLAG_A64(flags, PSTATE_SM, 1);
+ DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el));
+ }
+ DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA));
+ }
+
+ sctlr = regime_sctlr(env, stage1);
+
+ if (sctlr & SCTLR_A) {
+ DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
+ }
+
+ if (arm_cpu_data_is_big_endian_a64(el, sctlr)) {
+ DP_TBFLAG_ANY(flags, BE_DATA, 1);
+ }
+
+ if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) {
+ /*
+ * In order to save space in flags, we record only whether
+ * pauth is "inactive", meaning all insns are implemented as
+ * a nop, or "active" when some action must be performed.
+ * The decision of which action to take is left to a helper.
+ */
+ if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) {
+ DP_TBFLAG_A64(flags, PAUTH_ACTIVE, 1);
+ }
+ }
+
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
+ /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
+ if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
+ DP_TBFLAG_A64(flags, BT, 1);
+ }
+ }
+
+ /* Compute the condition for using AccType_UNPRIV for LDTR et al. */
+ if (!(env->pstate & PSTATE_UAO)) {
+ switch (mmu_idx) {
+ case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
+ /* TODO: ARMv8.3-NV */
+ DP_TBFLAG_A64(flags, UNPRIV, 1);
+ break;
+ case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
+ /*
+ * Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is
+ * gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.
+ */
+ if (env->cp15.hcr_el2 & HCR_TGE) {
+ DP_TBFLAG_A64(flags, UNPRIV, 1);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (env->pstate & PSTATE_IL) {
+ DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
+ }
+
+ if (arm_fgt_active(env, el)) {
+ DP_TBFLAG_ANY(flags, FGT_ACTIVE, 1);
+ if (FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, ERET)) {
+ DP_TBFLAG_A64(flags, FGT_ERET, 1);
+ }
+ if (fgt_svc(env, el)) {
+ DP_TBFLAG_ANY(flags, FGT_SVC, 1);
+ }
+ }
+
+ if (cpu_isar_feature(aa64_mte, env_archcpu(env))) {
+ /*
+ * Set MTE_ACTIVE if any access may be Checked, and leave clear
+ * if all accesses must be Unchecked:
+ * 1) If no TBI, then there are no tags in the address to check,
+ * 2) If Tag Check Override, then all accesses are Unchecked,
+ * 3) If Tag Check Fail == 0, then Checked access have no effect,
+ * 4) If no Allocation Tag Access, then all accesses are Unchecked.
+ */
+ if (allocation_tag_access_enabled(env, el, sctlr)) {
+ DP_TBFLAG_A64(flags, ATA, 1);
+ if (tbid
+ && !(env->pstate & PSTATE_TCO)
+ && (sctlr & (el == 0 ? SCTLR_TCF0 : SCTLR_TCF))) {
+ DP_TBFLAG_A64(flags, MTE_ACTIVE, 1);
+ }
+ }
+ /* And again for unprivileged accesses, if required. */
+ if (EX_TBFLAG_A64(flags, UNPRIV)
+ && tbid
+ && !(env->pstate & PSTATE_TCO)
+ && (sctlr & SCTLR_TCF0)
+ && allocation_tag_access_enabled(env, 0, sctlr)) {
+ DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1);
+ }
+ /* Cache TCMA as well as TBI. */
+ DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx));
+ }
+
+ return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
+}
+
+static CPUARMTBFlags rebuild_hflags_internal(CPUARMState *env)
+{
+ int el = arm_current_el(env);
+ int fp_el = fp_exception_el(env, el);
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
+
+ if (is_a64(env)) {
+ return rebuild_hflags_a64(env, el, fp_el, mmu_idx);
+ } else if (arm_feature(env, ARM_FEATURE_M)) {
+ return rebuild_hflags_m32(env, fp_el, mmu_idx);
+ } else {
+ return rebuild_hflags_a32(env, fp_el, mmu_idx);
+ }
+}
+
+void arm_rebuild_hflags(CPUARMState *env)
+{
+ env->hflags = rebuild_hflags_internal(env);
+}
+
+/*
+ * If we have triggered a EL state change we can't rely on the
+ * translator having passed it to us, we need to recompute.
+ */
+void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env)
+{
+ int el = arm_current_el(env);
+ int fp_el = fp_exception_el(env, el);
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
+
+ env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
+}
+
+void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
+{
+ int fp_el = fp_exception_el(env, el);
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
+
+ env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
+}
+
+/*
+ * If we have triggered a EL state change we can't rely on the
+ * translator having passed it to us, we need to recompute.
+ */
+void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env)
+{
+ int el = arm_current_el(env);
+ int fp_el = fp_exception_el(env, el);
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
+ env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx);
+}
+
+void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el)
+{
+ int fp_el = fp_exception_el(env, el);
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
+
+ env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx);
+}
+
+void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el)
+{
+ int fp_el = fp_exception_el(env, el);
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
+
+ env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx);
+}
+
+void assert_hflags_rebuild_correctly(CPUARMState *env)
+{
+#ifdef CONFIG_DEBUG_TCG
+ CPUARMTBFlags c = env->hflags;
+ CPUARMTBFlags r = rebuild_hflags_internal(env);
+
+ if (unlikely(c.flags != r.flags || c.flags2 != r.flags2)) {
+ fprintf(stderr, "TCG hflags mismatch "
+ "(current:(0x%08x,0x" TARGET_FMT_lx ")"
+ " rebuilt:(0x%08x,0x" TARGET_FMT_lx ")\n",
+ c.flags, c.flags2, r.flags, r.flags2);
+ abort();
+ }
+#endif
+}
diff --git a/target/arm/iwmmxt_helper.c b/target/arm/tcg/iwmmxt_helper.c
index 610b1b2103..610b1b2103 100644
--- a/target/arm/iwmmxt_helper.c
+++ b/target/arm/tcg/iwmmxt_helper.c
diff --git a/target/arm/m-nocp.decode b/target/arm/tcg/m-nocp.decode
index b65c801c97..b65c801c97 100644
--- a/target/arm/m-nocp.decode
+++ b/target/arm/tcg/m-nocp.decode
diff --git a/target/arm/m_helper.c b/target/arm/tcg/m_helper.c
index f94e87e728..f94e87e728 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/tcg/m_helper.c
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
new file mode 100644
index 0000000000..d27e76af6c
--- /dev/null
+++ b/target/arm/tcg/meson.build
@@ -0,0 +1,50 @@
+gen = [
+ decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
+ decodetree.process('sme.decode', extra_args: '--decode=disas_sme'),
+ decodetree.process('sme-fa64.decode', extra_args: '--static-decode=disas_sme_fa64'),
+ decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
+ decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
+ decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
+ decodetree.process('vfp.decode', extra_args: '--decode=disas_vfp'),
+ decodetree.process('vfp-uncond.decode', extra_args: '--decode=disas_vfp_uncond'),
+ decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'),
+ decodetree.process('mve.decode', extra_args: '--decode=disas_mve'),
+ decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'),
+ decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'),
+ decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'),
+ decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-decode=disas_t16']),
+]
+
+arm_ss.add(gen)
+
+arm_ss.add(files(
+ 'translate.c',
+ 'translate-m-nocp.c',
+ 'translate-mve.c',
+ 'translate-neon.c',
+ 'translate-vfp.c',
+ 'crypto_helper.c',
+ 'hflags.c',
+ 'iwmmxt_helper.c',
+ 'm_helper.c',
+ 'mve_helper.c',
+ 'neon_helper.c',
+ 'op_helper.c',
+ 'tlb_helper.c',
+ 'vec_helper.c',
+))
+
+arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
+ 'translate-a64.c',
+ 'translate-sve.c',
+ 'translate-sme.c',
+ 'helper-a64.c',
+ 'mte_helper.c',
+ 'pauth_helper.c',
+ 'sme_helper.c',
+ 'sve_helper.c',
+))
+
+arm_softmmu_ss.add(files(
+ 'psci.c',
+))
diff --git a/target/arm/mte_helper.c b/target/arm/tcg/mte_helper.c
index 98bcf59c22..98bcf59c22 100644
--- a/target/arm/mte_helper.c
+++ b/target/arm/tcg/mte_helper.c
diff --git a/target/arm/mve.decode b/target/arm/tcg/mve.decode
index 14a4f39802..14a4f39802 100644
--- a/target/arm/mve.decode
+++ b/target/arm/tcg/mve.decode
diff --git a/target/arm/mve_helper.c b/target/arm/tcg/mve_helper.c
index 403b345ea3..403b345ea3 100644
--- a/target/arm/mve_helper.c
+++ b/target/arm/tcg/mve_helper.c
diff --git a/target/arm/neon-dp.decode b/target/arm/tcg/neon-dp.decode
index fd3a01bfa0..fd3a01bfa0 100644
--- a/target/arm/neon-dp.decode
+++ b/target/arm/tcg/neon-dp.decode
diff --git a/target/arm/neon-ls.decode b/target/arm/tcg/neon-ls.decode
index c5f364cbc0..c5f364cbc0 100644
--- a/target/arm/neon-ls.decode
+++ b/target/arm/tcg/neon-ls.decode
diff --git a/target/arm/neon-shared.decode b/target/arm/tcg/neon-shared.decode
index 8e6bd0b61f..8e6bd0b61f 100644
--- a/target/arm/neon-shared.decode
+++ b/target/arm/tcg/neon-shared.decode
diff --git a/target/arm/neon_helper.c b/target/arm/tcg/neon_helper.c
index bc6c4a54e9..bc6c4a54e9 100644
--- a/target/arm/neon_helper.c
+++ b/target/arm/tcg/neon_helper.c
diff --git a/target/arm/op_helper.c b/target/arm/tcg/op_helper.c
index 3baf8004f6..3baf8004f6 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/tcg/op_helper.c
diff --git a/target/arm/pauth_helper.c b/target/arm/tcg/pauth_helper.c
index d0483bf051..d0483bf051 100644
--- a/target/arm/pauth_helper.c
+++ b/target/arm/tcg/pauth_helper.c
diff --git a/target/arm/psci.c b/target/arm/tcg/psci.c
index 6c1239bb96..6c1239bb96 100644
--- a/target/arm/psci.c
+++ b/target/arm/tcg/psci.c
diff --git a/target/arm/sme-fa64.decode b/target/arm/tcg/sme-fa64.decode
index 47708ccc8d..47708ccc8d 100644
--- a/target/arm/sme-fa64.decode
+++ b/target/arm/tcg/sme-fa64.decode
diff --git a/target/arm/sme.decode b/target/arm/tcg/sme.decode
index 628804e37a..628804e37a 100644
--- a/target/arm/sme.decode
+++ b/target/arm/tcg/sme.decode
diff --git a/target/arm/sme_helper.c b/target/arm/tcg/sme_helper.c
index 1e67fcac30..1e67fcac30 100644
--- a/target/arm/sme_helper.c
+++ b/target/arm/tcg/sme_helper.c
diff --git a/target/arm/sve.decode b/target/arm/tcg/sve.decode
index 14b3a69c36..14b3a69c36 100644
--- a/target/arm/sve.decode
+++ b/target/arm/tcg/sve.decode
diff --git a/target/arm/sve_helper.c b/target/arm/tcg/sve_helper.c
index 521fc9b969..521fc9b969 100644
--- a/target/arm/sve_helper.c
+++ b/target/arm/tcg/sve_helper.c
diff --git a/target/arm/t16.decode b/target/arm/tcg/t16.decode
index 646c74929d..646c74929d 100644
--- a/target/arm/t16.decode
+++ b/target/arm/tcg/t16.decode
diff --git a/target/arm/t32.decode b/target/arm/tcg/t32.decode
index f21ad0167a..f21ad0167a 100644
--- a/target/arm/t32.decode
+++ b/target/arm/tcg/t32.decode
diff --git a/target/arm/tlb_helper.c b/target/arm/tcg/tlb_helper.c
index 60abcbebe6..31eb77f7df 100644
--- a/target/arm/tlb_helper.c
+++ b/target/arm/tcg/tlb_helper.c
@@ -12,24 +12,6 @@
#include "exec/helper-proto.h"
-/* Return true if the translation regime is using LPAE format page tables */
-bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
-{
- int el = regime_el(env, mmu_idx);
- if (el == 2 || arm_el_is_aa64(env, el)) {
- return true;
- }
- if (arm_feature(env, ARM_FEATURE_PMSA) &&
- arm_feature(env, ARM_FEATURE_V8)) {
- return true;
- }
- if (arm_feature(env, ARM_FEATURE_LPAE)
- && (regime_tcr(env, mmu_idx) & TTBCR_EAE)) {
- return true;
- }
- return false;
-}
-
/*
* Returns true if the stage 1 translation regime is using LPAE format page
* tables. Used when raising alignment exceptions, whose FSR changes depending
diff --git a/target/arm/translate-a64.c b/target/arm/tcg/translate-a64.c
index da9f877476..da9f877476 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
diff --git a/target/arm/translate-a64.h b/target/arm/tcg/translate-a64.h
index ad3762d1ac..ad3762d1ac 100644
--- a/target/arm/translate-a64.h
+++ b/target/arm/tcg/translate-a64.h
diff --git a/target/arm/translate-m-nocp.c b/target/arm/tcg/translate-m-nocp.c
index 5df7d46120..5df7d46120 100644
--- a/target/arm/translate-m-nocp.c
+++ b/target/arm/tcg/translate-m-nocp.c
diff --git a/target/arm/translate-mve.c b/target/arm/tcg/translate-mve.c
index db7ea3f603..db7ea3f603 100644
--- a/target/arm/translate-mve.c
+++ b/target/arm/tcg/translate-mve.c
diff --git a/target/arm/translate-neon.c b/target/arm/tcg/translate-neon.c
index 4016339d46..4016339d46 100644
--- a/target/arm/translate-neon.c
+++ b/target/arm/tcg/translate-neon.c
diff --git a/target/arm/translate-sme.c b/target/arm/tcg/translate-sme.c
index 7b87a9df63..7b87a9df63 100644
--- a/target/arm/translate-sme.c
+++ b/target/arm/tcg/translate-sme.c
diff --git a/target/arm/translate-sve.c b/target/arm/tcg/translate-sve.c
index 621a2abb22..621a2abb22 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/tcg/translate-sve.c
diff --git a/target/arm/translate-vfp.c b/target/arm/tcg/translate-vfp.c
index 5c5d58d2c6..5c5d58d2c6 100644
--- a/target/arm/translate-vfp.c
+++ b/target/arm/tcg/translate-vfp.c
diff --git a/target/arm/translate.c b/target/arm/tcg/translate.c
index c23a3462bf..c23a3462bf 100644
--- a/target/arm/translate.c
+++ b/target/arm/tcg/translate.c
diff --git a/target/arm/translate.h b/target/arm/tcg/translate.h
index 3717824b75..3717824b75 100644
--- a/target/arm/translate.h
+++ b/target/arm/tcg/translate.h
diff --git a/target/arm/vec_helper.c b/target/arm/tcg/vec_helper.c
index f59d3b26ea..f59d3b26ea 100644
--- a/target/arm/vec_helper.c
+++ b/target/arm/tcg/vec_helper.c
diff --git a/target/arm/vec_internal.h b/target/arm/tcg/vec_internal.h
index 1f4ed80ff7..1f4ed80ff7 100644
--- a/target/arm/vec_internal.h
+++ b/target/arm/tcg/vec_internal.h
diff --git a/target/arm/vfp-uncond.decode b/target/arm/tcg/vfp-uncond.decode
index 5c50447a66..5c50447a66 100644
--- a/target/arm/vfp-uncond.decode
+++ b/target/arm/tcg/vfp-uncond.decode
diff --git a/target/arm/vfp.decode b/target/arm/tcg/vfp.decode
index 5405e80197..5405e80197 100644
--- a/target/arm/vfp.decode
+++ b/target/arm/tcg/vfp.decode