[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-arm] [Qemu-devel] [PATCH v2 08/23] target/arm: Move all v7m in
From: |
Alex Bennée |
Subject: |
Re: [Qemu-arm] [Qemu-devel] [PATCH v2 08/23] target/arm: Move all v7m insn helpers into their own file |
Date: |
Mon, 17 Jun 2019 12:42:50 +0100 |
User-agent: |
mu4e 1.3.2; emacs 26.1 |
Philippe Mathieu-Daudé <address@hidden> writes:
> From: Samuel Ortiz <address@hidden>
>
> In preparation for supporting TCG disablement on ARM, we move most
> of TCG related v7m helpers and APIs into their own file.
>
> Signed-off-by: Samuel Ortiz <address@hidden>
> [PMD: Patch rewritten]
> Signed-off-by: Philippe Mathieu-Daudé <address@hidden>
> ---
> Is there a way to not use $CONFIG_USER_ONLY?
Is this because the CONFIG_ARM_V7M symbol only appears for softmmu
targets but we still want vXm -cpu's for user mode?
>
> target/arm/Makefile.objs | 1 +
> target/arm/helper.c | 633 -------------------------------------
> target/arm/v7m_helper.c | 654 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 655 insertions(+), 633 deletions(-)
> create mode 100644 target/arm/v7m_helper.c
>
> diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
> index 72b42f825f..5f3f965cc6 100644
> --- a/target/arm/Makefile.objs
> +++ b/target/arm/Makefile.objs
> @@ -35,6 +35,7 @@ obj-y += translate.o op_helper.o
> obj-y += crypto_helper.o
> obj-y += iwmmxt_helper.o vec_helper.o
> obj-y += neon_helper.o vfp_helper.o
> +obj-$(call lor,$(CONFIG_USER_ONLY),$(CONFIG_ARM_V7M)) += v7m_helper.o
>
> obj-$(TARGET_AARCH64) += translate-a64.o helper-a64.o
> obj-$(TARGET_AARCH64) += translate-sve.o sve_helper.o
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index a1e74cc471..a829086c6d 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -20,7 +20,6 @@
> #include "qemu/crc32c.h"
> #include "qemu/qemu-print.h"
> #include "exec/exec-all.h"
> -#include "exec/cpu_ldst.h"
> #include "arm_ldst.h"
> #include <zlib.h> /* For crc32 */
> #include "hw/semihosting/semihost.h"
> @@ -7456,75 +7455,6 @@ uint32_t HELPER(rbit)(uint32_t x)
>
> #ifdef CONFIG_USER_ONLY
>
> -/* These should probably raise undefined insn exceptions. */
> -void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
> -{
> - ARMCPU *cpu = env_archcpu(env);
> -
> - cpu_abort(CPU(cpu), "v7m_msr %d\n", reg);
> -}
> -
> -uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
> -{
> - ARMCPU *cpu = env_archcpu(env);
> -
> - cpu_abort(CPU(cpu), "v7m_mrs %d\n", reg);
> - return 0;
> -}
> -
> -void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
> -{
> - /* translate.c should never generate calls here in user-only mode */
> - g_assert_not_reached();
> -}
> -
> -void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
> -{
> - /* translate.c should never generate calls here in user-only mode */
> - g_assert_not_reached();
> -}
> -
> -void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
> -{
> - /* translate.c should never generate calls here in user-only mode */
> - g_assert_not_reached();
> -}
> -
> -void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
> -{
> - /* translate.c should never generate calls here in user-only mode */
> - g_assert_not_reached();
> -}
> -
> -void HELPER(v7m_vlldm)(CPUARMState *env, uint32_t fptr)
> -{
> - /* translate.c should never generate calls here in user-only mode */
> - g_assert_not_reached();
> -}
> -
> -uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
> -{
> - /*
> - * The TT instructions can be used by unprivileged code, but in
> - * user-only emulation we don't have the MPU.
> - * Luckily since we know we are NonSecure unprivileged (and that in
> - * turn means that the A flag wasn't specified), all the bits in the
> - * register must be zero:
> - * IREGION: 0 because IRVALID is 0
> - * IRVALID: 0 because NS
> - * S: 0 because NS
> - * NSRW: 0 because NS
> - * NSR: 0 because NS
> - * RW: 0 because unpriv and A flag not set
> - * R: 0 because unpriv and A flag not set
> - * SRVALID: 0 because NS
> - * MRVALID: 0 because unpriv and A flag not set
> - * SREGION: 0 becaus SRVALID is 0
> - * MREGION: 0 because MRVALID is 0
> - */
> - return 0;
> -}
> -
> void switch_mode(CPUARMState *env, int mode)
> {
> ARMCPU *cpu = env_archcpu(env);
> @@ -8048,109 +7978,6 @@ void switch_v7m_security_state(CPUARMState *env, bool
> new_secstate)
> }
> }
>
> -void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
> -{
> - /*
> - * Handle v7M BXNS:
> - * - if the return value is a magic value, do exception return (like BX)
> - * - otherwise bit 0 of the return value is the target security state
> - */
> - uint32_t min_magic;
> -
> - if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
> - /* Covers FNC_RETURN and EXC_RETURN magic */
> - min_magic = FNC_RETURN_MIN_MAGIC;
> - } else {
> - /* EXC_RETURN magic only */
> - min_magic = EXC_RETURN_MIN_MAGIC;
> - }
> -
> - if (dest >= min_magic) {
> - /*
> - * This is an exception return magic value; put it where
> - * do_v7m_exception_exit() expects and raise EXCEPTION_EXIT.
> - * Note that if we ever add gen_ss_advance() singlestep support to
> - * M profile this should count as an "instruction execution complete"
> - * event (compare gen_bx_excret_final_code()).
> - */
> - env->regs[15] = dest & ~1;
> - env->thumb = dest & 1;
> - HELPER(exception_internal)(env, EXCP_EXCEPTION_EXIT);
> - /* notreached */
> - }
> -
> - /* translate.c should have made BXNS UNDEF unless we're secure */
> - assert(env->v7m.secure);
> -
> - if (!(dest & 1)) {
> - env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
> - }
> - switch_v7m_security_state(env, dest & 1);
> - env->thumb = 1;
> - env->regs[15] = dest & ~1;
> -}
> -
> -void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
> -{
> - /*
> - * Handle v7M BLXNS:
> - * - bit 0 of the destination address is the target security state
> - */
> -
> - /* At this point regs[15] is the address just after the BLXNS */
> - uint32_t nextinst = env->regs[15] | 1;
> - uint32_t sp = env->regs[13] - 8;
> - uint32_t saved_psr;
> -
> - /* translate.c will have made BLXNS UNDEF unless we're secure */
> - assert(env->v7m.secure);
> -
> - if (dest & 1) {
> - /*
> - * Target is Secure, so this is just a normal BLX,
> - * except that the low bit doesn't indicate Thumb/not.
> - */
> - env->regs[14] = nextinst;
> - env->thumb = 1;
> - env->regs[15] = dest & ~1;
> - return;
> - }
> -
> - /* Target is non-secure: first push a stack frame */
> - if (!QEMU_IS_ALIGNED(sp, 8)) {
> - qemu_log_mask(LOG_GUEST_ERROR,
> - "BLXNS with misaligned SP is UNPREDICTABLE\n");
> - }
> -
> - if (sp < v7m_sp_limit(env)) {
> - raise_exception(env, EXCP_STKOF, 0, 1);
> - }
> -
> - saved_psr = env->v7m.exception;
> - if (env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK) {
> - saved_psr |= XPSR_SFPA;
> - }
> -
> - /* Note that these stores can throw exceptions on MPU faults */
> - cpu_stl_data(env, sp, nextinst);
> - cpu_stl_data(env, sp + 4, saved_psr);
> -
> - env->regs[13] = sp;
> - env->regs[14] = 0xfeffffff;
> - if (arm_v7m_is_handler_mode(env)) {
> - /*
> - * Write a dummy value to IPSR, to avoid leaking the current secure
> - * exception number to non-secure code. This is guaranteed not
> - * to cause write_v7m_exception() to actually change stacks.
> - */
> - write_v7m_exception(env, 1);
> - }
> - env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
> - switch_v7m_security_state(env, 0);
> - env->thumb = 1;
> - env->regs[15] = dest;
> -}
> -
> static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool
> threadmode,
> bool spsel)
> {
> @@ -12760,466 +12587,6 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState
> *cs, vaddr addr,
> return phys_addr;
> }
>
> -uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
> -{
> - uint32_t mask;
> - unsigned el = arm_current_el(env);
> -
> - /* First handle registers which unprivileged can read */
> -
> - switch (reg) {
> - case 0 ... 7: /* xPSR sub-fields */
> - mask = 0;
> - if ((reg & 1) && el) {
> - mask |= XPSR_EXCP; /* IPSR (unpriv. reads as zero) */
> - }
> - if (!(reg & 4)) {
> - mask |= XPSR_NZCV | XPSR_Q; /* APSR */
> - if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
> - mask |= XPSR_GE;
> - }
> - }
> - /* EPSR reads as zero */
> - return xpsr_read(env) & mask;
> - break;
> - case 20: /* CONTROL */
> - {
> - uint32_t value = env->v7m.control[env->v7m.secure];
> - if (!env->v7m.secure) {
> - /* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */
> - value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK;
> - }
> - return value;
> - }
> - case 0x94: /* CONTROL_NS */
> - /*
> - * We have to handle this here because unprivileged Secure code
> - * can read the NS CONTROL register.
> - */
> - if (!env->v7m.secure) {
> - return 0;
> - }
> - return env->v7m.control[M_REG_NS] |
> - (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK);
> - }
> -
> - if (el == 0) {
> - return 0; /* unprivileged reads others as zero */
> - }
> -
> - if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
> - switch (reg) {
> - case 0x88: /* MSP_NS */
> - if (!env->v7m.secure) {
> - return 0;
> - }
> - return env->v7m.other_ss_msp;
> - case 0x89: /* PSP_NS */
> - if (!env->v7m.secure) {
> - return 0;
> - }
> - return env->v7m.other_ss_psp;
> - case 0x8a: /* MSPLIM_NS */
> - if (!env->v7m.secure) {
> - return 0;
> - }
> - return env->v7m.msplim[M_REG_NS];
> - case 0x8b: /* PSPLIM_NS */
> - if (!env->v7m.secure) {
> - return 0;
> - }
> - return env->v7m.psplim[M_REG_NS];
> - case 0x90: /* PRIMASK_NS */
> - if (!env->v7m.secure) {
> - return 0;
> - }
> - return env->v7m.primask[M_REG_NS];
> - case 0x91: /* BASEPRI_NS */
> - if (!env->v7m.secure) {
> - return 0;
> - }
> - return env->v7m.basepri[M_REG_NS];
> - case 0x93: /* FAULTMASK_NS */
> - if (!env->v7m.secure) {
> - return 0;
> - }
> - return env->v7m.faultmask[M_REG_NS];
> - case 0x98: /* SP_NS */
> - {
> - /*
> - * This gives the non-secure SP selected based on whether we're
> - * currently in handler mode or not, using the NS CONTROL.SPSEL.
> - */
> - bool spsel = env->v7m.control[M_REG_NS] &
> R_V7M_CONTROL_SPSEL_MASK;
> -
> - if (!env->v7m.secure) {
> - return 0;
> - }
> - if (!arm_v7m_is_handler_mode(env) && spsel) {
> - return env->v7m.other_ss_psp;
> - } else {
> - return env->v7m.other_ss_msp;
> - }
> - }
> - default:
> - break;
> - }
> - }
> -
> - switch (reg) {
> - case 8: /* MSP */
> - return v7m_using_psp(env) ? env->v7m.other_sp : env->regs[13];
> - case 9: /* PSP */
> - return v7m_using_psp(env) ? env->regs[13] : env->v7m.other_sp;
> - case 10: /* MSPLIM */
> - if (!arm_feature(env, ARM_FEATURE_V8)) {
> - goto bad_reg;
> - }
> - return env->v7m.msplim[env->v7m.secure];
> - case 11: /* PSPLIM */
> - if (!arm_feature(env, ARM_FEATURE_V8)) {
> - goto bad_reg;
> - }
> - return env->v7m.psplim[env->v7m.secure];
> - case 16: /* PRIMASK */
> - return env->v7m.primask[env->v7m.secure];
> - case 17: /* BASEPRI */
> - case 18: /* BASEPRI_MAX */
> - return env->v7m.basepri[env->v7m.secure];
> - case 19: /* FAULTMASK */
> - return env->v7m.faultmask[env->v7m.secure];
> - default:
> - bad_reg:
> - qemu_log_mask(LOG_GUEST_ERROR, "Attempt to read unknown special"
> - " register %d\n", reg);
> - return 0;
> - }
> -}
> -
> -void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
> -{
> - /*
> - * We're passed bits [11..0] of the instruction; extract
> - * SYSm and the mask bits.
> - * Invalid combinations of SYSm and mask are UNPREDICTABLE;
> - * we choose to treat them as if the mask bits were valid.
> - * NB that the pseudocode 'mask' variable is bits [11..10],
> - * whereas ours is [11..8].
> - */
> - uint32_t mask = extract32(maskreg, 8, 4);
> - uint32_t reg = extract32(maskreg, 0, 8);
> - int cur_el = arm_current_el(env);
> -
> - if (cur_el == 0 && reg > 7 && reg != 20) {
> - /*
> - * only xPSR sub-fields and CONTROL.SFPA may be written by
> - * unprivileged code
> - */
> - return;
> - }
> -
> - if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
> - switch (reg) {
> - case 0x88: /* MSP_NS */
> - if (!env->v7m.secure) {
> - return;
> - }
> - env->v7m.other_ss_msp = val;
> - return;
> - case 0x89: /* PSP_NS */
> - if (!env->v7m.secure) {
> - return;
> - }
> - env->v7m.other_ss_psp = val;
> - return;
> - case 0x8a: /* MSPLIM_NS */
> - if (!env->v7m.secure) {
> - return;
> - }
> - env->v7m.msplim[M_REG_NS] = val & ~7;
> - return;
> - case 0x8b: /* PSPLIM_NS */
> - if (!env->v7m.secure) {
> - return;
> - }
> - env->v7m.psplim[M_REG_NS] = val & ~7;
> - return;
> - case 0x90: /* PRIMASK_NS */
> - if (!env->v7m.secure) {
> - return;
> - }
> - env->v7m.primask[M_REG_NS] = val & 1;
> - return;
> - case 0x91: /* BASEPRI_NS */
> - if (!env->v7m.secure || !arm_feature(env, ARM_FEATURE_M_MAIN)) {
> - return;
> - }
> - env->v7m.basepri[M_REG_NS] = val & 0xff;
> - return;
> - case 0x93: /* FAULTMASK_NS */
> - if (!env->v7m.secure || !arm_feature(env, ARM_FEATURE_M_MAIN)) {
> - return;
> - }
> - env->v7m.faultmask[M_REG_NS] = val & 1;
> - return;
> - case 0x94: /* CONTROL_NS */
> - if (!env->v7m.secure) {
> - return;
> - }
> - write_v7m_control_spsel_for_secstate(env,
> - val &
> R_V7M_CONTROL_SPSEL_MASK,
> - M_REG_NS);
> - if (arm_feature(env, ARM_FEATURE_M_MAIN)) {
> - env->v7m.control[M_REG_NS] &= ~R_V7M_CONTROL_NPRIV_MASK;
> - env->v7m.control[M_REG_NS] |= val & R_V7M_CONTROL_NPRIV_MASK;
> - }
> - /*
> - * SFPA is RAZ/WI from NS. FPCA is RO if NSACR.CP10 == 0,
> - * RES0 if the FPU is not present, and is stored in the S bank
> - */
> - if (arm_feature(env, ARM_FEATURE_VFP) &&
> - extract32(env->v7m.nsacr, 10, 1)) {
> - env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
> - env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
> - }
> - return;
> - case 0x98: /* SP_NS */
> - {
> - /*
> - * This gives the non-secure SP selected based on whether we're
> - * currently in handler mode or not, using the NS CONTROL.SPSEL.
> - */
> - bool spsel = env->v7m.control[M_REG_NS] &
> R_V7M_CONTROL_SPSEL_MASK;
> - bool is_psp = !arm_v7m_is_handler_mode(env) && spsel;
> - uint32_t limit;
> -
> - if (!env->v7m.secure) {
> - return;
> - }
> -
> - limit = is_psp ? env->v7m.psplim[false] : env->v7m.msplim[false];
> -
> - if (val < limit) {
> - CPUState *cs = env_cpu(env);
> -
> - cpu_restore_state(cs, GETPC(), true);
> - raise_exception(env, EXCP_STKOF, 0, 1);
> - }
> -
> - if (is_psp) {
> - env->v7m.other_ss_psp = val;
> - } else {
> - env->v7m.other_ss_msp = val;
> - }
> - return;
> - }
> - default:
> - break;
> - }
> - }
> -
> - switch (reg) {
> - case 0 ... 7: /* xPSR sub-fields */
> - /* only APSR is actually writable */
> - if (!(reg & 4)) {
> - uint32_t apsrmask = 0;
> -
> - if (mask & 8) {
> - apsrmask |= XPSR_NZCV | XPSR_Q;
> - }
> - if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
> - apsrmask |= XPSR_GE;
> - }
> - xpsr_write(env, val, apsrmask);
> - }
> - break;
> - case 8: /* MSP */
> - if (v7m_using_psp(env)) {
> - env->v7m.other_sp = val;
> - } else {
> - env->regs[13] = val;
> - }
> - break;
> - case 9: /* PSP */
> - if (v7m_using_psp(env)) {
> - env->regs[13] = val;
> - } else {
> - env->v7m.other_sp = val;
> - }
> - break;
> - case 10: /* MSPLIM */
> - if (!arm_feature(env, ARM_FEATURE_V8)) {
> - goto bad_reg;
> - }
> - env->v7m.msplim[env->v7m.secure] = val & ~7;
> - break;
> - case 11: /* PSPLIM */
> - if (!arm_feature(env, ARM_FEATURE_V8)) {
> - goto bad_reg;
> - }
> - env->v7m.psplim[env->v7m.secure] = val & ~7;
> - break;
> - case 16: /* PRIMASK */
> - env->v7m.primask[env->v7m.secure] = val & 1;
> - break;
> - case 17: /* BASEPRI */
> - if (!arm_feature(env, ARM_FEATURE_M_MAIN)) {
> - goto bad_reg;
> - }
> - env->v7m.basepri[env->v7m.secure] = val & 0xff;
> - break;
> - case 18: /* BASEPRI_MAX */
> - if (!arm_feature(env, ARM_FEATURE_M_MAIN)) {
> - goto bad_reg;
> - }
> - val &= 0xff;
> - if (val != 0 && (val < env->v7m.basepri[env->v7m.secure]
> - || env->v7m.basepri[env->v7m.secure] == 0)) {
> - env->v7m.basepri[env->v7m.secure] = val;
> - }
> - break;
> - case 19: /* FAULTMASK */
> - if (!arm_feature(env, ARM_FEATURE_M_MAIN)) {
> - goto bad_reg;
> - }
> - env->v7m.faultmask[env->v7m.secure] = val & 1;
> - break;
> - case 20: /* CONTROL */
> - /*
> - * Writing to the SPSEL bit only has an effect if we are in
> - * thread mode; other bits can be updated by any privileged code.
> - * write_v7m_control_spsel() deals with updating the SPSEL bit in
> - * env->v7m.control, so we only need update the others.
> - * For v7M, we must just ignore explicit writes to SPSEL in handler
> - * mode; for v8M the write is permitted but will have no effect.
> - * All these bits are writes-ignored from non-privileged code,
> - * except for SFPA.
> - */
> - if (cur_el > 0 && (arm_feature(env, ARM_FEATURE_V8) ||
> - !arm_v7m_is_handler_mode(env))) {
> - write_v7m_control_spsel(env, (val & R_V7M_CONTROL_SPSEL_MASK) !=
> 0);
> - }
> - if (cur_el > 0 && arm_feature(env, ARM_FEATURE_M_MAIN)) {
> - env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
> - env->v7m.control[env->v7m.secure] |= val &
> R_V7M_CONTROL_NPRIV_MASK;
> - }
> - if (arm_feature(env, ARM_FEATURE_VFP)) {
> - /*
> - * SFPA is RAZ/WI from NS or if no FPU.
> - * FPCA is RO if NSACR.CP10 == 0, RES0 if the FPU is not present.
> - * Both are stored in the S bank.
> - */
> - if (env->v7m.secure) {
> - env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
> - env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_SFPA_MASK;
> - }
> - if (cur_el > 0 &&
> - (env->v7m.secure || !arm_feature(env,
> ARM_FEATURE_M_SECURITY) ||
> - extract32(env->v7m.nsacr, 10, 1))) {
> - env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
> - env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
> - }
> - }
> - break;
> - default:
> - bad_reg:
> - qemu_log_mask(LOG_GUEST_ERROR, "Attempt to write unknown special"
> - " register %d\n", reg);
> - return;
> - }
> -}
> -
> -uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
> -{
> - /* Implement the TT instruction. op is bits [7:6] of the insn. */
> - bool forceunpriv = op & 1;
> - bool alt = op & 2;
> - V8M_SAttributes sattrs = {};
> - uint32_t tt_resp;
> - bool r, rw, nsr, nsrw, mrvalid;
> - int prot;
> - ARMMMUFaultInfo fi = {};
> - MemTxAttrs attrs = {};
> - hwaddr phys_addr;
> - ARMMMUIdx mmu_idx;
> - uint32_t mregion;
> - bool targetpriv;
> - bool targetsec = env->v7m.secure;
> - bool is_subpage;
> -
> - /*
> - * Work out what the security state and privilege level we're
> - * interested in is...
> - */
> - if (alt) {
> - targetsec = !targetsec;
> - }
> -
> - if (forceunpriv) {
> - targetpriv = false;
> - } else {
> - targetpriv = arm_v7m_is_handler_mode(env) ||
> - !(env->v7m.control[targetsec] & R_V7M_CONTROL_NPRIV_MASK);
> - }
> -
> - /* ...and then figure out which MMU index this is */
> - mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, targetsec,
> targetpriv);
> -
> - /*
> - * We know that the MPU and SAU don't care about the access type
> - * for our purposes beyond that we don't want to claim to be
> - * an insn fetch, so we arbitrarily call this a read.
> - */
> -
> - /*
> - * MPU region info only available for privileged or if
> - * inspecting the other MPU state.
> - */
> - if (arm_current_el(env) != 0 || alt) {
> - /* We can ignore the return value as prot is always set */
> - pmsav8_mpu_lookup(env, addr, MMU_DATA_LOAD, mmu_idx,
> - &phys_addr, &attrs, &prot, &is_subpage,
> - &fi, &mregion);
> - if (mregion == -1) {
> - mrvalid = false;
> - mregion = 0;
> - } else {
> - mrvalid = true;
> - }
> - r = prot & PAGE_READ;
> - rw = prot & PAGE_WRITE;
> - } else {
> - r = false;
> - rw = false;
> - mrvalid = false;
> - mregion = 0;
> - }
> -
> - if (env->v7m.secure) {
> - v8m_security_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, &sattrs);
> - nsr = sattrs.ns && r;
> - nsrw = sattrs.ns && rw;
> - } else {
> - sattrs.ns = true;
> - nsr = false;
> - nsrw = false;
> - }
> -
> - tt_resp = (sattrs.iregion << 24) |
> - (sattrs.irvalid << 23) |
> - ((!sattrs.ns) << 22) |
> - (nsrw << 21) |
> - (nsr << 20) |
> - (rw << 19) |
> - (r << 18) |
> - (sattrs.srvalid << 17) |
> - (mrvalid << 16) |
> - (sattrs.sregion << 8) |
> - mregion;
> -
> - return tt_resp;
> -}
> -
> #endif
>
> bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
> diff --git a/target/arm/v7m_helper.c b/target/arm/v7m_helper.c
> new file mode 100644
> index 0000000000..321154966e
> --- /dev/null
> +++ b/target/arm/v7m_helper.c
> @@ -0,0 +1,654 @@
> +/*
> + * ARM v7-M helpers.
> + *
> + * This code is licensed under the GNU GPL v2 or later.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +#include "qemu/osdep.h"
> +#include "sysemu/sysemu.h"
> +#include "cpu.h"
> +#include "internals.h"
> +#include "exec/helper-proto.h"
> +#include "exec/exec-all.h"
> +#include "arm_ldst.h"
> +#include "hw/semihosting/semihost.h"
> +#include "fpu/softfloat.h"
> +
> +#if defined(CONFIG_USER_ONLY)
> +
> +/* These should probably raise undefined insn exceptions. */
> +void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
> +{
> + ARMCPU *cpu = env_archcpu(env);
> +
> + cpu_abort(CPU(cpu), "v7m_msr %d\n", reg);
> +}
> +
> +uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
> +{
> + ARMCPU *cpu = env_archcpu(env);
> +
> + cpu_abort(CPU(cpu), "v7m_mrs %d\n", reg);
> + return 0;
> +}
> +
> +void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
> +{
> + /* translate.c should never generate calls here in user-only mode */
> + g_assert_not_reached();
> +}
> +
> +void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
> +{
> + /* translate.c should never generate calls here in user-only mode */
> + g_assert_not_reached();
> +}
> +
> +void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
> +{
> + /* translate.c should never generate calls here in user-only mode */
> + g_assert_not_reached();
> +}
> +
> +void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
> +{
> + /* translate.c should never generate calls here in user-only mode */
> + g_assert_not_reached();
> +}
> +
> +void HELPER(v7m_vlldm)(CPUARMState *env, uint32_t fptr)
> +{
> + /* translate.c should never generate calls here in user-only mode */
> + g_assert_not_reached();
> +}
> +
> +uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
> +{
> + /*
> + * The TT instructions can be used by unprivileged code, but in
> + * user-only emulation we don't have the MPU.
> + * Luckily since we know we are NonSecure unprivileged (and that in
> + * turn means that the A flag wasn't specified), all the bits in the
> + * register must be zero:
> + * IREGION: 0 because IRVALID is 0
> + * IRVALID: 0 because NS
> + * S: 0 because NS
> + * NSRW: 0 because NS
> + * NSR: 0 because NS
> + * RW: 0 because unpriv and A flag not set
> + * R: 0 because unpriv and A flag not set
> + * SRVALID: 0 because NS
> + * MRVALID: 0 because unpriv and A flag not set
> + * SREGION: 0 becaus SRVALID is 0
> + * MREGION: 0 because MRVALID is 0
> + */
> + return 0;
> +}
> +
> +#else
> +
> +void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
> +{
> + /*
> + * Handle v7M BXNS:
> + * - if the return value is a magic value, do exception return (like BX)
> + * - otherwise bit 0 of the return value is the target security state
> + */
> + uint32_t min_magic;
> +
> + if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
> + /* Covers FNC_RETURN and EXC_RETURN magic */
> + min_magic = FNC_RETURN_MIN_MAGIC;
> + } else {
> + /* EXC_RETURN magic only */
> + min_magic = EXC_RETURN_MIN_MAGIC;
> + }
> +
> + if (dest >= min_magic) {
> + /*
> + * This is an exception return magic value; put it where
> + * do_v7m_exception_exit() expects and raise EXCEPTION_EXIT.
> + * Note that if we ever add gen_ss_advance() singlestep support to
> + * M profile this should count as an "instruction execution complete"
> + * event (compare gen_bx_excret_final_code()).
> + */
> + env->regs[15] = dest & ~1;
> + env->thumb = dest & 1;
> + HELPER(exception_internal)(env, EXCP_EXCEPTION_EXIT);
> + /* notreached */
> + }
> +
> + /* translate.c should have made BXNS UNDEF unless we're secure */
> + assert(env->v7m.secure);
> +
> + if (!(dest & 1)) {
> + env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
> + }
> + switch_v7m_security_state(env, dest & 1);
> + env->thumb = 1;
> + env->regs[15] = dest & ~1;
> +}
> +
> +void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
> +{
> + /*
> + * Handle v7M BLXNS:
> + * - bit 0 of the destination address is the target security state
> + */
> +
> + /* At this point regs[15] is the address just after the BLXNS */
> + uint32_t nextinst = env->regs[15] | 1;
> + uint32_t sp = env->regs[13] - 8;
> + uint32_t saved_psr;
> +
> + /* translate.c will have made BLXNS UNDEF unless we're secure */
> + assert(env->v7m.secure);
> +
> + if (dest & 1) {
> + /*
> + * Target is Secure, so this is just a normal BLX,
> + * except that the low bit doesn't indicate Thumb/not.
> + */
> + env->regs[14] = nextinst;
> + env->thumb = 1;
> + env->regs[15] = dest & ~1;
> + return;
> + }
> +
> + /* Target is non-secure: first push a stack frame */
> + if (!QEMU_IS_ALIGNED(sp, 8)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "BLXNS with misaligned SP is UNPREDICTABLE\n");
> + }
> +
> + if (sp < v7m_sp_limit(env)) {
> + raise_exception(env, EXCP_STKOF, 0, 1);
> + }
> +
> + saved_psr = env->v7m.exception;
> + if (env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK) {
> + saved_psr |= XPSR_SFPA;
> + }
> +
> + /* Note that these stores can throw exceptions on MPU faults */
> + cpu_stl_data(env, sp, nextinst);
> + cpu_stl_data(env, sp + 4, saved_psr);
> +
> + env->regs[13] = sp;
> + env->regs[14] = 0xfeffffff;
> + if (arm_v7m_is_handler_mode(env)) {
> + /*
> + * Write a dummy value to IPSR, to avoid leaking the current secure
> + * exception number to non-secure code. This is guaranteed not
> + * to cause write_v7m_exception() to actually change stacks.
> + */
> + write_v7m_exception(env, 1);
> + }
> + env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
> + switch_v7m_security_state(env, 0);
> + env->thumb = 1;
> + env->regs[15] = dest;
> +}
> +
> +uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
> +{
> + uint32_t mask;
> + unsigned el = arm_current_el(env);
> +
> + /* First handle registers which unprivileged can read */
> +
> + switch (reg) {
> + case 0 ... 7: /* xPSR sub-fields */
> + mask = 0;
> + if ((reg & 1) && el) {
> + mask |= XPSR_EXCP; /* IPSR (unpriv. reads as zero) */
> + }
> + if (!(reg & 4)) {
> + mask |= XPSR_NZCV | XPSR_Q; /* APSR */
> + if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
> + mask |= XPSR_GE;
> + }
> + }
> + /* EPSR reads as zero */
> + return xpsr_read(env) & mask;
> + break;
> + case 20: /* CONTROL */
> + {
> + uint32_t value = env->v7m.control[env->v7m.secure];
> + if (!env->v7m.secure) {
> + /* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */
> + value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK;
> + }
> + return value;
> + }
> + case 0x94: /* CONTROL_NS */
> + /*
> + * We have to handle this here because unprivileged Secure code
> + * can read the NS CONTROL register.
> + */
> + if (!env->v7m.secure) {
> + return 0;
> + }
> + return env->v7m.control[M_REG_NS] |
> + (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK);
> + }
> +
> + if (el == 0) {
> + return 0; /* unprivileged reads others as zero */
> + }
> +
> + if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
> + switch (reg) {
> + case 0x88: /* MSP_NS */
> + if (!env->v7m.secure) {
> + return 0;
> + }
> + return env->v7m.other_ss_msp;
> + case 0x89: /* PSP_NS */
> + if (!env->v7m.secure) {
> + return 0;
> + }
> + return env->v7m.other_ss_psp;
> + case 0x8a: /* MSPLIM_NS */
> + if (!env->v7m.secure) {
> + return 0;
> + }
> + return env->v7m.msplim[M_REG_NS];
> + case 0x8b: /* PSPLIM_NS */
> + if (!env->v7m.secure) {
> + return 0;
> + }
> + return env->v7m.psplim[M_REG_NS];
> + case 0x90: /* PRIMASK_NS */
> + if (!env->v7m.secure) {
> + return 0;
> + }
> + return env->v7m.primask[M_REG_NS];
> + case 0x91: /* BASEPRI_NS */
> + if (!env->v7m.secure) {
> + return 0;
> + }
> + return env->v7m.basepri[M_REG_NS];
> + case 0x93: /* FAULTMASK_NS */
> + if (!env->v7m.secure) {
> + return 0;
> + }
> + return env->v7m.faultmask[M_REG_NS];
> + case 0x98: /* SP_NS */
> + {
> + /*
> + * This gives the non-secure SP selected based on whether we're
> + * currently in handler mode or not, using the NS CONTROL.SPSEL.
> + */
> + bool spsel = env->v7m.control[M_REG_NS] &
> R_V7M_CONTROL_SPSEL_MASK;
> +
> + if (!env->v7m.secure) {
> + return 0;
> + }
> + if (!arm_v7m_is_handler_mode(env) && spsel) {
> + return env->v7m.other_ss_psp;
> + } else {
> + return env->v7m.other_ss_msp;
> + }
> + }
> + default:
> + break;
> + }
> + }
> +
> + switch (reg) {
> + case 8: /* MSP */
> + return v7m_using_psp(env) ? env->v7m.other_sp : env->regs[13];
> + case 9: /* PSP */
> + return v7m_using_psp(env) ? env->regs[13] : env->v7m.other_sp;
> + case 10: /* MSPLIM */
> + if (!arm_feature(env, ARM_FEATURE_V8)) {
> + goto bad_reg;
> + }
> + return env->v7m.msplim[env->v7m.secure];
> + case 11: /* PSPLIM */
> + if (!arm_feature(env, ARM_FEATURE_V8)) {
> + goto bad_reg;
> + }
> + return env->v7m.psplim[env->v7m.secure];
> + case 16: /* PRIMASK */
> + return env->v7m.primask[env->v7m.secure];
> + case 17: /* BASEPRI */
> + case 18: /* BASEPRI_MAX */
> + return env->v7m.basepri[env->v7m.secure];
> + case 19: /* FAULTMASK */
> + return env->v7m.faultmask[env->v7m.secure];
> + default:
> + bad_reg:
> + qemu_log_mask(LOG_GUEST_ERROR, "Attempt to read unknown special"
> + " register %d\n", reg);
> + return 0;
> + }
> +}
> +
> +void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
> +{
> + /*
> + * We're passed bits [11..0] of the instruction; extract
> + * SYSm and the mask bits.
> + * Invalid combinations of SYSm and mask are UNPREDICTABLE;
> + * we choose to treat them as if the mask bits were valid.
> + * NB that the pseudocode 'mask' variable is bits [11..10],
> + * whereas ours is [11..8].
> + */
> + uint32_t mask = extract32(maskreg, 8, 4);
> + uint32_t reg = extract32(maskreg, 0, 8);
> + int cur_el = arm_current_el(env);
> +
> + if (cur_el == 0 && reg > 7 && reg != 20) {
> + /*
> + * only xPSR sub-fields and CONTROL.SFPA may be written by
> + * unprivileged code
> + */
> + return;
> + }
> +
> + if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
> + switch (reg) {
> + case 0x88: /* MSP_NS */
> + if (!env->v7m.secure) {
> + return;
> + }
> + env->v7m.other_ss_msp = val;
> + return;
> + case 0x89: /* PSP_NS */
> + if (!env->v7m.secure) {
> + return;
> + }
> + env->v7m.other_ss_psp = val;
> + return;
> + case 0x8a: /* MSPLIM_NS */
> + if (!env->v7m.secure) {
> + return;
> + }
> + env->v7m.msplim[M_REG_NS] = val & ~7;
> + return;
> + case 0x8b: /* PSPLIM_NS */
> + if (!env->v7m.secure) {
> + return;
> + }
> + env->v7m.psplim[M_REG_NS] = val & ~7;
> + return;
> + case 0x90: /* PRIMASK_NS */
> + if (!env->v7m.secure) {
> + return;
> + }
> + env->v7m.primask[M_REG_NS] = val & 1;
> + return;
> + case 0x91: /* BASEPRI_NS */
> + if (!env->v7m.secure || !arm_feature(env, ARM_FEATURE_M_MAIN)) {
> + return;
> + }
> + env->v7m.basepri[M_REG_NS] = val & 0xff;
> + return;
> + case 0x93: /* FAULTMASK_NS */
> + if (!env->v7m.secure || !arm_feature(env, ARM_FEATURE_M_MAIN)) {
> + return;
> + }
> + env->v7m.faultmask[M_REG_NS] = val & 1;
> + return;
> + case 0x94: /* CONTROL_NS */
> + if (!env->v7m.secure) {
> + return;
> + }
> + write_v7m_control_spsel_for_secstate(env,
> + val &
> R_V7M_CONTROL_SPSEL_MASK,
> + M_REG_NS);
> + if (arm_feature(env, ARM_FEATURE_M_MAIN)) {
> + env->v7m.control[M_REG_NS] &= ~R_V7M_CONTROL_NPRIV_MASK;
> + env->v7m.control[M_REG_NS] |= val & R_V7M_CONTROL_NPRIV_MASK;
> + }
> + /*
> + * SFPA is RAZ/WI from NS. FPCA is RO if NSACR.CP10 == 0,
> + * RES0 if the FPU is not present, and is stored in the S bank
> + */
> + if (arm_feature(env, ARM_FEATURE_VFP) &&
> + extract32(env->v7m.nsacr, 10, 1)) {
> + env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
> + env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
> + }
> + return;
> + case 0x98: /* SP_NS */
> + {
> + /*
> + * This gives the non-secure SP selected based on whether we're
> + * currently in handler mode or not, using the NS CONTROL.SPSEL.
> + */
> + bool spsel = env->v7m.control[M_REG_NS] &
> R_V7M_CONTROL_SPSEL_MASK;
> + bool is_psp = !arm_v7m_is_handler_mode(env) && spsel;
> + uint32_t limit;
> +
> + if (!env->v7m.secure) {
> + return;
> + }
> +
> + limit = is_psp ? env->v7m.psplim[false] : env->v7m.msplim[false];
> +
> + if (val < limit) {
> + CPUState *cs = env_cpu(env);
> +
> + cpu_restore_state(cs, GETPC(), true);
> + raise_exception(env, EXCP_STKOF, 0, 1);
> + }
> +
> + if (is_psp) {
> + env->v7m.other_ss_psp = val;
> + } else {
> + env->v7m.other_ss_msp = val;
> + }
> + return;
> + }
> + default:
> + break;
> + }
> + }
> +
> + switch (reg) {
> + case 0 ... 7: /* xPSR sub-fields */
> + /* only APSR is actually writable */
> + if (!(reg & 4)) {
> + uint32_t apsrmask = 0;
> +
> + if (mask & 8) {
> + apsrmask |= XPSR_NZCV | XPSR_Q;
> + }
> + if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
> + apsrmask |= XPSR_GE;
> + }
> + xpsr_write(env, val, apsrmask);
> + }
> + break;
> + case 8: /* MSP */
> + if (v7m_using_psp(env)) {
> + env->v7m.other_sp = val;
> + } else {
> + env->regs[13] = val;
> + }
> + break;
> + case 9: /* PSP */
> + if (v7m_using_psp(env)) {
> + env->regs[13] = val;
> + } else {
> + env->v7m.other_sp = val;
> + }
> + break;
> + case 10: /* MSPLIM */
> + if (!arm_feature(env, ARM_FEATURE_V8)) {
> + goto bad_reg;
> + }
> + env->v7m.msplim[env->v7m.secure] = val & ~7;
> + break;
> + case 11: /* PSPLIM */
> + if (!arm_feature(env, ARM_FEATURE_V8)) {
> + goto bad_reg;
> + }
> + env->v7m.psplim[env->v7m.secure] = val & ~7;
> + break;
> + case 16: /* PRIMASK */
> + env->v7m.primask[env->v7m.secure] = val & 1;
> + break;
> + case 17: /* BASEPRI */
> + if (!arm_feature(env, ARM_FEATURE_M_MAIN)) {
> + goto bad_reg;
> + }
> + env->v7m.basepri[env->v7m.secure] = val & 0xff;
> + break;
> + case 18: /* BASEPRI_MAX */
> + if (!arm_feature(env, ARM_FEATURE_M_MAIN)) {
> + goto bad_reg;
> + }
> + val &= 0xff;
> + if (val != 0 && (val < env->v7m.basepri[env->v7m.secure]
> + || env->v7m.basepri[env->v7m.secure] == 0)) {
> + env->v7m.basepri[env->v7m.secure] = val;
> + }
> + break;
> + case 19: /* FAULTMASK */
> + if (!arm_feature(env, ARM_FEATURE_M_MAIN)) {
> + goto bad_reg;
> + }
> + env->v7m.faultmask[env->v7m.secure] = val & 1;
> + break;
> + case 20: /* CONTROL */
> + /*
> + * Writing to the SPSEL bit only has an effect if we are in
> + * thread mode; other bits can be updated by any privileged code.
> + * write_v7m_control_spsel() deals with updating the SPSEL bit in
> + * env->v7m.control, so we only need update the others.
> + * For v7M, we must just ignore explicit writes to SPSEL in handler
> + * mode; for v8M the write is permitted but will have no effect.
> + * All these bits are writes-ignored from non-privileged code,
> + * except for SFPA.
> + */
> + if (cur_el > 0 && (arm_feature(env, ARM_FEATURE_V8) ||
> + !arm_v7m_is_handler_mode(env))) {
> + write_v7m_control_spsel(env, (val & R_V7M_CONTROL_SPSEL_MASK) !=
> 0);
> + }
> + if (cur_el > 0 && arm_feature(env, ARM_FEATURE_M_MAIN)) {
> + env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
> + env->v7m.control[env->v7m.secure] |= val &
> R_V7M_CONTROL_NPRIV_MASK;
> + }
> + if (arm_feature(env, ARM_FEATURE_VFP)) {
> + /*
> + * SFPA is RAZ/WI from NS or if no FPU.
> + * FPCA is RO if NSACR.CP10 == 0, RES0 if the FPU is not present.
> + * Both are stored in the S bank.
> + */
> + if (env->v7m.secure) {
> + env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
> + env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_SFPA_MASK;
> + }
> + if (cur_el > 0 &&
> + (env->v7m.secure || !arm_feature(env,
> ARM_FEATURE_M_SECURITY) ||
> + extract32(env->v7m.nsacr, 10, 1))) {
> + env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
> + env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
> + }
> + }
> + break;
> + default:
> + bad_reg:
> + qemu_log_mask(LOG_GUEST_ERROR, "Attempt to write unknown special"
> + " register %d\n", reg);
> + return;
> + }
> +}
> +
> +uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
> +{
> + /* Implement the TT instruction. op is bits [7:6] of the insn. */
> + bool forceunpriv = op & 1;
> + bool alt = op & 2;
> + V8M_SAttributes sattrs = {};
> + uint32_t tt_resp;
> + bool r, rw, nsr, nsrw, mrvalid;
> + int prot;
> + ARMMMUFaultInfo fi = {};
> + MemTxAttrs attrs = {};
> + hwaddr phys_addr;
> + ARMMMUIdx mmu_idx;
> + uint32_t mregion;
> + bool targetpriv;
> + bool targetsec = env->v7m.secure;
> + bool is_subpage;
> +
> + /*
> + * Work out what the security state and privilege level we're
> + * interested in is...
> + */
> + if (alt) {
> + targetsec = !targetsec;
> + }
> +
> + if (forceunpriv) {
> + targetpriv = false;
> + } else {
> + targetpriv = arm_v7m_is_handler_mode(env) ||
> + !(env->v7m.control[targetsec] & R_V7M_CONTROL_NPRIV_MASK);
> + }
> +
> + /* ...and then figure out which MMU index this is */
> + mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, targetsec,
> targetpriv);
> +
> + /*
> + * We know that the MPU and SAU don't care about the access type
> + * for our purposes beyond that we don't want to claim to be
> + * an insn fetch, so we arbitrarily call this a read.
> + */
> +
> + /*
> + * MPU region info only available for privileged or if
> + * inspecting the other MPU state.
> + */
> + if (arm_current_el(env) != 0 || alt) {
> + /* We can ignore the return value as prot is always set */
> + pmsav8_mpu_lookup(env, addr, MMU_DATA_LOAD, mmu_idx,
> + &phys_addr, &attrs, &prot, &is_subpage,
> + &fi, &mregion);
> + if (mregion == -1) {
> + mrvalid = false;
> + mregion = 0;
> + } else {
> + mrvalid = true;
> + }
> + r = prot & PAGE_READ;
> + rw = prot & PAGE_WRITE;
> + } else {
> + r = false;
> + rw = false;
> + mrvalid = false;
> + mregion = 0;
> + }
> +
> + if (env->v7m.secure) {
> + v8m_security_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, &sattrs);
> + nsr = sattrs.ns && r;
> + nsrw = sattrs.ns && rw;
> + } else {
> + sattrs.ns = true;
> + nsr = false;
> + nsrw = false;
> + }
> +
> + tt_resp = (sattrs.iregion << 24) |
> + (sattrs.irvalid << 23) |
> + ((!sattrs.ns) << 22) |
> + (nsrw << 21) |
> + (nsr << 20) |
> + (rw << 19) |
> + (r << 18) |
> + (sattrs.srvalid << 17) |
> + (mrvalid << 16) |
> + (sattrs.sregion << 8) |
> + mregion;
> +
> + return tt_resp;
> +}
> +
> +#endif /* CONFIG_USER_ONLY */
--
Alex Bennée
- Re: [Qemu-arm] [PATCH v2 09/23] target/arm: Move code around, (continued)
- [Qemu-arm] [PATCH v2 06/23] target/arm: Fix multiline comment syntax, Philippe Mathieu-Daudé, 2019/06/15
- [Qemu-arm] [PATCH v2 10/23] target/arm: Move the v7-M Security State helpers to v7m_helper, Philippe Mathieu-Daudé, 2019/06/15
- [Qemu-arm] [PATCH v2 11/23] target/arm: Declare v7m_cpacr_pass() publicly, Philippe Mathieu-Daudé, 2019/06/15
- [Qemu-arm] [PATCH v2 14/23] target/arm: Move the DC ZVA helper into op_helper, Philippe Mathieu-Daudé, 2019/06/15
- [Qemu-arm] [PATCH v2 08/23] target/arm: Move all v7m insn helpers into their own file, Philippe Mathieu-Daudé, 2019/06/15
- Re: [Qemu-arm] [Qemu-devel] [PATCH v2 08/23] target/arm: Move all v7m insn helpers into their own file,
Alex Bennée <=
- [Qemu-arm] [PATCH v2 13/23] target/arm: Make the v7-M Security State routines, Philippe Mathieu-Daudé, 2019/06/15
- [Qemu-arm] [PATCH v2 15/23] target/arm: Make ARM TLB filling routine static, Philippe Mathieu-Daudé, 2019/06/15
- [Qemu-arm] [PATCH v2 16/23] target/arm: Make arm_deliver_fault() static, Philippe Mathieu-Daudé, 2019/06/15
- [Qemu-arm] [PATCH v2 17/23] target/arm: Fix coding style issues, Philippe Mathieu-Daudé, 2019/06/15
- [Qemu-arm] [PATCH v2 18/23] target/arm: Move CPU state dumping routines to helper.c, Philippe Mathieu-Daudé, 2019/06/15