aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-01-26 18:16:34 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-01-26 18:16:35 +0000
commit7a1dc45af581d2b643cdbf33c01fd96271616fbd (patch)
tree161b70bf428bde22f9def021d04a65365d86149e /target
parentb9c4a2018aa9c89233b8fc68ce26faf8e4ce1c78 (diff)
parent5e6be95ed1578c7cfac2082b39384d99fd912508 (diff)
Merge tag 'pull-target-arm-20240126' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue: * Fix VNCR fault detection logic * Fix A64 scalar SQSHRN and SQRSHRN * Fix incorrect aa64_tidcp1 feature check * hw/arm/virt.c: Remove newline from error_report() string * hw/arm/musicpal: Convert to qemu_add_kbd_event_handler() * hw/arm/allwinner-a10: Unconditionally map the USB Host controllers * hw/arm/nseries: Unconditionally map the TUSB6010 USB Host controller * hw/arm: Add EHCI/OHCI controllers to Allwinner R40 and Bananapi board * hw/arm: Add AHCI/SATA controller to Allwinner R40 and Bananapi board * hw/arm: Add watchdog timer to Allwinner H40 and Bananapi board * arm: various include header cleanups * cleanups to allow some files to be built only once * fsl-imx6ul: Add various missing unimplemented devices * docs/system/arm/virt.rst: Add note on CPU features off by default * hw/char/imx_serial: Implement receive FIFO and ageing timer * target/xtensa: fix OOB TLB entry access * bswap.h: Fix const_le64() macro * hw/arm: add PCIe to Freescale i.MX6 # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmWzwpsZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3oTVD/4jM7ttKlXxtWsJ/cKDL5Im # uMmDECPrdK2qaNpONfV/YC3WadM6bSgB8OQd2YlI67DLgl3Hfaa+GnQsZhEgZ3lC # VECOTg5OKwwJY+Ac86t1GJa483wDEQ6NL08oLN94n9Ub/9G0S3oWpmE4bgof7PzW # rbLDDpKP+W5NfkqMfA5piV7N6mFHvg9wqFX//quqySIiu8NesKV9LmlP/FyNDU/s # 8ZeSqo/tq/IHr9IeYUtOoxVwYUOPuNKwD+vwy1taiXgjvVtq2URrCrlc4+KCWJsj # VUBSXdY2boqK31KFZ9NP9kJhIS5gmzgnK8YrHX6sgSbh+IybZUv+y/4eSO/LDYIi # r2VQF6oTtkmcIxUqAI6ZAehzZUIrB22QItUN8rg0slKBM8e/xHYaEBY8APKCLcvE # h59DLq1rPZG3Aie/h3/RjTfT2kI83PiE1mDGbhKf9G8UfXHEH8Eabd0g66UWfzlK # 67o7bwwzwXgoGk2hgMY/yobB3pF5YCly/a3aN/aLEj387y8sNaT1ASR9LETj7TC3 # xOhn5f8G6OFKMVI3K8Sco8ILP15LELprAW2keL4jn+4y3Hfq5yC984yOSnlM0wug # wWRvEr7U1ZiEbDaOvoa0beuYpeq1sm4OZ5yGJxGy3IuQ8pZpkHVTrBxw/NCNQnos # fK5czVTGqvvmPXgPsQQm1A== # =vYTy # -----END PGP SIGNATURE----- # gpg: Signature made Fri 26 Jan 2024 14:32:59 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-20240126' of https://git.linaro.org/people/pmaydell/qemu-arm: (36 commits) hw/arm: add PCIe to Freescale i.MX6 target/arm: Fix incorrect aa64_tidcp1 feature check bswap.h: Fix const_le64() macro target/arm: Fix A64 scalar SQSHRN and SQRSHRN hw/char/imx_serial: Implement receive FIFO and ageing timer docs/system/arm/virt.rst: Add note on CPU features off by default fsl-imx6ul: Add various missing unimplemented devices hw/arm: Build various units only once target/arm: Move GTimer definitions to new 'gtimer.h' header target/arm: Move e2h_access() helper around target/arm: Move ARM_CPU_IRQ/FIQ definitions to 'cpu-qom.h' header hw/arm/armv7m: Make 'hw/intc/armv7m_nvic.h' a target agnostic header target/arm: Expose M-profile register bank index definitions hw/misc/xlnx-versal-crl: Build it only once hw/misc/xlnx-versal-crl: Include generic 'cpu-qom.h' instead of 'cpu.h' hw/cpu/a9mpcore: Build it only once target/arm: Declare ARM_CPU_TYPE_NAME/SUFFIX in 'cpu-qom.h' target/arm: Expose arm_cpu_mp_affinity() in 'multiprocessing.h' header target/arm: Create arm_cpu_mp_affinity target/arm: Rename arm_cpu_mp_affinity ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/arm/arm-powerctl.c3
-rw-r--r--target/arm/cpregs.h3
-rw-r--r--target/arm/cpu-features.h4
-rw-r--r--target/arm/cpu-qom.h24
-rw-r--r--target/arm/cpu.c13
-rw-r--r--target/arm/cpu.h34
-rw-r--r--target/arm/gtimer.h21
-rw-r--r--target/arm/helper.c30
-rw-r--r--target/arm/hvf/hvf.c6
-rw-r--r--target/arm/kvm.c1
-rw-r--r--target/arm/machine.c1
-rw-r--r--target/arm/multiprocessing.h16
-rw-r--r--target/arm/tcg/psci.c3
-rw-r--r--target/arm/tcg/tlb_helper.c2
-rw-r--r--target/arm/tcg/translate-a64.c2
-rw-r--r--target/xtensa/mmu_helper.c47
16 files changed, 143 insertions, 67 deletions
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
index 8850381565..2b2055c6ac 100644
--- a/target/arm/arm-powerctl.c
+++ b/target/arm/arm-powerctl.c
@@ -16,6 +16,7 @@
#include "qemu/log.h"
#include "qemu/main-loop.h"
#include "sysemu/tcg.h"
+#include "target/arm/multiprocessing.h"
#ifndef DEBUG_ARM_POWERCTL
#define DEBUG_ARM_POWERCTL 0
@@ -37,7 +38,7 @@ CPUState *arm_get_cpu_by_id(uint64_t id)
CPU_FOREACH(cpu) {
ARMCPU *armcpu = ARM_CPU(cpu);
- if (armcpu->mp_affinity == id) {
+ if (arm_cpu_mp_affinity(armcpu) == id) {
return cpu;
}
}
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index b6fdd0f3eb..cc7c54378f 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -21,6 +21,9 @@
#ifndef TARGET_ARM_CPREGS_H
#define TARGET_ARM_CPREGS_H
+#include "hw/registerfields.h"
+#include "target/arm/kvm-consts.h"
+
/*
* ARMCPRegInfo type field bits:
*/
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 7a590c824c..7567854db6 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -20,6 +20,8 @@
#ifndef TARGET_ARM_FEATURES_H
#define TARGET_ARM_FEATURES_H
+#include "hw/registerfields.h"
+
/*
* Naming convention for isar_feature functions:
* Functions which test 32-bit ID registers should have _aa32_ in
@@ -771,7 +773,7 @@ static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
{
- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR1, TIDCP1) != 0;
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, TIDCP1) != 0;
}
static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id)
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
index 02b914c876..8e032691db 100644
--- a/target/arm/cpu-qom.h
+++ b/target/arm/cpu-qom.h
@@ -33,4 +33,28 @@ typedef struct AArch64CPUClass AArch64CPUClass;
DECLARE_CLASS_CHECKERS(AArch64CPUClass, AARCH64_CPU,
TYPE_AARCH64_CPU)
+#define ARM_CPU_TYPE_SUFFIX "-" TYPE_ARM_CPU
+#define ARM_CPU_TYPE_NAME(name) (name ARM_CPU_TYPE_SUFFIX)
+
+/* Meanings of the ARMCPU object's four inbound GPIO lines */
+#define ARM_CPU_IRQ 0
+#define ARM_CPU_FIQ 1
+#define ARM_CPU_VIRQ 2
+#define ARM_CPU_VFIQ 3
+
+/* For M profile, some registers are banked secure vs non-secure;
+ * these are represented as a 2-element array where the first element
+ * is the non-secure copy and the second is the secure copy.
+ * When the CPU does not have implement the security extension then
+ * only the first element is used.
+ * This means that the copy for the current security state can be
+ * accessed via env->registerfield[env->v7m.secure] (whether the security
+ * extension is implemented or not).
+ */
+enum {
+ M_REG_NS = 0,
+ M_REG_S = 1,
+ M_REG_NUM_BANKS = 2,
+};
+
#endif
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 593695b424..b60e103046 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -48,6 +48,8 @@
#include "disas/capstone.h"
#include "fpu/softfloat.h"
#include "cpregs.h"
+#include "target/arm/cpu-qom.h"
+#include "target/arm/gtimer.h"
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
{
@@ -1307,13 +1309,18 @@ static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
}
}
-uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz)
+uint64_t arm_build_mp_affinity(int idx, uint8_t clustersz)
{
uint32_t Aff1 = idx / clustersz;
uint32_t Aff0 = idx % clustersz;
return (Aff1 << ARM_AFF1_SHIFT) | Aff0;
}
+uint64_t arm_cpu_mp_affinity(ARMCPU *cpu)
+{
+ return cpu->mp_affinity;
+}
+
static void arm_cpu_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
@@ -2113,8 +2120,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
* so these bits always RAZ.
*/
if (cpu->mp_affinity == ARM64_AFFINITY_INVALID) {
- cpu->mp_affinity = arm_cpu_mp_affinity(cs->cpu_index,
- ARM_DEFAULT_CPUS_PER_CLUSTER);
+ cpu->mp_affinity = arm_build_mp_affinity(cs->cpu_index,
+ ARM_DEFAULT_CPUS_PER_CLUSTER);
}
if (cpu->reset_hivecs) {
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index ec276fcd57..d3477b1601 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -26,6 +26,8 @@
#include "cpu-qom.h"
#include "exec/cpu-defs.h"
#include "qapi/qapi-types-common.h"
+#include "target/arm/multiprocessing.h"
+#include "target/arm/gtimer.h"
/* ARM processors have a weak memory model */
#define TCG_GUEST_DEFAULT_MO (0)
@@ -72,21 +74,6 @@
#define ARMV7M_EXCP_PENDSV 14
#define ARMV7M_EXCP_SYSTICK 15
-/* For M profile, some registers are banked secure vs non-secure;
- * these are represented as a 2-element array where the first element
- * is the non-secure copy and the second is the secure copy.
- * When the CPU does not have implement the security extension then
- * only the first element is used.
- * This means that the copy for the current security state can be
- * accessed via env->registerfield[env->v7m.secure] (whether the security
- * extension is implemented or not).
- */
-enum {
- M_REG_NS = 0,
- M_REG_S = 1,
- M_REG_NUM_BANKS = 2,
-};
-
/* ARM-specific interrupt pending bits. */
#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_EXT_2
@@ -107,12 +94,6 @@ enum {
#define offsetofhigh32(S, M) (offsetof(S, M) + sizeof(uint32_t))
#endif
-/* Meanings of the ARMCPU object's four inbound GPIO lines */
-#define ARM_CPU_IRQ 0
-#define ARM_CPU_FIQ 1
-#define ARM_CPU_VIRQ 2
-#define ARM_CPU_VFIQ 3
-
/* ARM-specific extra insn start words:
* 1: Conditional execution bits
* 2: Partial exception syndrome for data aborts
@@ -160,13 +141,6 @@ typedef struct ARMGenericTimer {
uint64_t ctl; /* Timer Control register */
} ARMGenericTimer;
-#define GTIMER_PHYS 0
-#define GTIMER_VIRT 1
-#define GTIMER_HYP 2
-#define GTIMER_SEC 3
-#define GTIMER_HYPVIRT 4
-#define NUM_GTIMERS 5
-
#define VTCR_NSW (1u << 29)
#define VTCR_NSA (1u << 30)
#define VSTCR_SW VTCR_NSW
@@ -1171,7 +1145,7 @@ void arm_cpu_post_init(Object *obj);
(ARM_AFF0_MASK | ARM_AFF1_MASK | ARM_AFF2_MASK | ARM_AFF3_MASK)
#define ARM64_AFFINITY_INVALID (~ARM64_AFFINITY_MASK)
-uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz);
+uint64_t arm_build_mp_affinity(int idx, uint8_t clustersz);
#ifndef CONFIG_USER_ONLY
extern const VMStateDescription vmstate_arm_cpu;
@@ -2836,8 +2810,6 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
#define ARM_CPUID_TI915T 0x54029152
#define ARM_CPUID_TI925T 0x54029252
-#define ARM_CPU_TYPE_SUFFIX "-" TYPE_ARM_CPU
-#define ARM_CPU_TYPE_NAME(name) (name ARM_CPU_TYPE_SUFFIX)
#define CPU_RESOLVING_TYPE TYPE_ARM_CPU
#define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
new file mode 100644
index 0000000000..b992941bef
--- /dev/null
+++ b/target/arm/gtimer.h
@@ -0,0 +1,21 @@
+/*
+ * ARM generic timer definitions for Arm A-class CPU
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef TARGET_ARM_GTIMER_H
+#define TARGET_ARM_GTIMER_H
+
+enum {
+ GTIMER_PHYS = 0,
+ GTIMER_VIRT = 1,
+ GTIMER_HYP = 2,
+ GTIMER_SEC = 3,
+ GTIMER_HYPVIRT = 4,
+#define NUM_GTIMERS 5
+};
+
+#endif
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e068d35383..945d8571a6 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -30,6 +30,7 @@
#include "semihosting/common-semi.h"
#endif
#include "cpregs.h"
+#include "target/arm/gtimer.h"
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
@@ -3345,20 +3346,6 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
},
};
-static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
- bool isread)
-{
- if (arm_current_el(env) == 1) {
- /* This must be a FEAT_NV access */
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
- return CP_ACCESS_OK;
- }
- if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
- return CP_ACCESS_TRAP;
- }
- return CP_ACCESS_OK;
-}
-
#else
/*
@@ -6546,6 +6533,21 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
};
#ifndef CONFIG_USER_ONLY
+
+static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_current_el(env) == 1) {
+ /* This must be a FEAT_NV access */
+ /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
+ return CP_ACCESS_OK;
+ }
+ if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
+ return CP_ACCESS_TRAP;
+ }
+ return CP_ACCESS_OK;
+}
+
/* Test if system register redirection is to occur in the current state. */
static bool redirect_for_e2h(CPUARMState *env)
{
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index a537a5bc94..e5f0f60093 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -28,6 +28,8 @@
#include "arm-powerctl.h"
#include "target/arm/cpu.h"
#include "target/arm/internals.h"
+#include "target/arm/multiprocessing.h"
+#include "target/arm/gtimer.h"
#include "trace/trace-target_arm_hvf.h"
#include "migration/vmstate.h"
@@ -1016,7 +1018,7 @@ static void hvf_raise_exception(CPUState *cpu, uint32_t excp,
static void hvf_psci_cpu_off(ARMCPU *arm_cpu)
{
- int32_t ret = arm_set_cpu_off(arm_cpu->mp_affinity);
+ int32_t ret = arm_set_cpu_off(arm_cpu_mp_affinity(arm_cpu));
assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS);
}
@@ -1045,7 +1047,7 @@ static bool hvf_handle_psci_call(CPUState *cpu)
int32_t ret = 0;
trace_hvf_psci_call(param[0], param[1], param[2], param[3],
- arm_cpu->mp_affinity);
+ arm_cpu_mp_affinity(arm_cpu));
switch (param[0]) {
case QEMU_PSCI_0_2_FN_PSCI_VERSION:
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 8f52b211f9..81813030a5 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -38,6 +38,7 @@
#include "qemu/log.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/ghes.h"
+#include "target/arm/gtimer.h"
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_LAST_INFO
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 542be14bec..9d7dbaea54 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -7,6 +7,7 @@
#include "internals.h"
#include "cpu-features.h"
#include "migration/cpu.h"
+#include "target/arm/gtimer.h"
static bool vfp_needed(void *opaque)
{
diff --git a/target/arm/multiprocessing.h b/target/arm/multiprocessing.h
new file mode 100644
index 0000000000..81715d345c
--- /dev/null
+++ b/target/arm/multiprocessing.h
@@ -0,0 +1,16 @@
+/*
+ * ARM multiprocessor CPU helpers
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef TARGET_ARM_MULTIPROCESSING_H
+#define TARGET_ARM_MULTIPROCESSING_H
+
+#include "target/arm/cpu-qom.h"
+
+uint64_t arm_cpu_mp_affinity(ARMCPU *cpu);
+
+#endif
diff --git a/target/arm/tcg/psci.c b/target/arm/tcg/psci.c
index 9080a91d9c..51d2ca3d30 100644
--- a/target/arm/tcg/psci.c
+++ b/target/arm/tcg/psci.c
@@ -24,6 +24,7 @@
#include "sysemu/runstate.h"
#include "internals.h"
#include "arm-powerctl.h"
+#include "target/arm/multiprocessing.h"
bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
{
@@ -215,7 +216,7 @@ err:
return;
cpu_off:
- ret = arm_set_cpu_off(cpu->mp_affinity);
+ ret = arm_set_cpu_off(arm_cpu_mp_affinity(cpu));
/* notreached */
/* sanity check in case something failed */
assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS);
diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c
index dd5de74ffb..5477c7fb7d 100644
--- a/target/arm/tcg/tlb_helper.c
+++ b/target/arm/tcg/tlb_helper.c
@@ -184,7 +184,7 @@ void arm_deliver_fault(ARMCPU *cpu, vaddr addr,
* (and indeed syndrome does not have the EC field in it,
* because we masked that out in disas_set_insn_syndrome())
*/
- bool is_vncr = (mmu_idx != MMU_INST_FETCH) &&
+ bool is_vncr = (access_type != MMU_INST_FETCH) &&
(env->exception.syndrome & ARM_EL_VNCR);
if (is_vncr) {
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 27335e8540..340265beb0 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -8343,7 +8343,7 @@ static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
narrowfn(tcg_rd_narrowed, tcg_env, tcg_rd);
tcg_gen_extu_i32_i64(tcg_rd, tcg_rd_narrowed);
if (i == 0) {
- tcg_gen_mov_i64(tcg_final, tcg_rd);
+ tcg_gen_extract_i64(tcg_final, tcg_rd, 0, esize);
} else {
tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
}
diff --git a/target/xtensa/mmu_helper.c b/target/xtensa/mmu_helper.c
index 12552a3347..2fda4e887c 100644
--- a/target/xtensa/mmu_helper.c
+++ b/target/xtensa/mmu_helper.c
@@ -224,22 +224,31 @@ static void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v,
* Split TLB address into TLB way, entry index and VPN (with index).
* See ISA, 4.6.5.5 - 4.6.5.8 for the TLB addressing format
*/
-static void split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb,
- uint32_t *vpn, uint32_t *wi, uint32_t *ei)
+static bool split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb,
+ uint32_t *vpn, uint32_t *wi, uint32_t *ei)
{
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
*wi = v & (dtlb ? 0xf : 0x7);
- split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei);
+ if (*wi < (dtlb ? env->config->dtlb.nways : env->config->itlb.nways)) {
+ split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei);
+ return true;
+ } else {
+ return false;
+ }
} else {
*vpn = v & REGION_PAGE_MASK;
*wi = 0;
*ei = (v >> 29) & 0x7;
+ return true;
}
}
static xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env, bool dtlb,
unsigned wi, unsigned ei)
{
+ const xtensa_tlb *tlb = dtlb ? &env->config->dtlb : &env->config->itlb;
+
+ assert(wi < tlb->nways && ei < tlb->way_size[wi]);
return dtlb ?
env->dtlb[wi] + ei :
env->itlb[wi] + ei;
@@ -252,11 +261,14 @@ static xtensa_tlb_entry *get_tlb_entry(CPUXtensaState *env,
uint32_t wi;
uint32_t ei;
- split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
- if (pwi) {
- *pwi = wi;
+ if (split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei)) {
+ if (pwi) {
+ *pwi = wi;
+ }
+ return xtensa_tlb_get_entry(env, dtlb, wi, ei);
+ } else {
+ return NULL;
}
- return xtensa_tlb_get_entry(env, dtlb, wi, ei);
}
static void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
@@ -482,7 +494,12 @@ uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
uint32_t wi;
const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
- return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
+
+ if (entry) {
+ return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid;
+ } else {
+ return 0;
+ }
} else {
return v & REGION_PAGE_MASK;
}
@@ -491,7 +508,12 @@ uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
uint32_t HELPER(rtlb1)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
{
const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, NULL);
- return entry->paddr | entry->attr;
+
+ if (entry) {
+ return entry->paddr | entry->attr;
+ } else {
+ return 0;
+ }
}
void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
@@ -499,7 +521,7 @@ void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb)
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
uint32_t wi;
xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi);
- if (entry->variable && entry->asid) {
+ if (entry && entry->variable && entry->asid) {
tlb_flush_page(env_cpu(env), entry->vaddr);
entry->asid = 0;
}
@@ -537,8 +559,9 @@ void HELPER(wtlb)(CPUXtensaState *env, uint32_t p, uint32_t v, uint32_t dtlb)
uint32_t vpn;
uint32_t wi;
uint32_t ei;
- split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei);
- xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
+ if (split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei)) {
+ xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
+ }
}
/*!