mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-24 03:15:33 +00:00
target/arm: Split M profile MNegPri mmu index into user and priv
For M profile, we currently have an mmu index MNegPri for "requested execution priority negative". This fails to distinguish "requested execution priority negative, privileged" from "requested execution priority negative, usermode", but the two can return different results for MPU lookups. Fix this by splitting MNegPri into MNegPriPriv and MNegPriUser, and similarly for the Secure equivalent MSNegPri. This takes us from 6 M profile MMU modes to 8, which means we need to bump NB_MMU_MODES; this is OK since the point where we are forced to reduce TLB sizes is 9 MMU modes. (It would in theory be possible to stick with 6 MMU indexes: {mpu-disabled,user,privileged} x {secure,nonsecure} since in the MPU-disabled case the result of an MPU lookup is always the same for both user and privileged code. However we would then need to rework the TB flags handling to put user/priv into the TB flags separately from the mmuidx. Adding an extra couple of mmu indexes is simpler.) Backports commit 62593718d77c06ad2b5e942727cead40775d2395 from qemu
This commit is contained in:
parent
d877985eea
commit
89acdeb9af
|
@ -116,7 +116,7 @@ enum {
|
||||||
#define ARM_CPU_VIRQ 2
|
#define ARM_CPU_VIRQ 2
|
||||||
#define ARM_CPU_VFIQ 3
|
#define ARM_CPU_VFIQ 3
|
||||||
|
|
||||||
#define NB_MMU_MODES 7
|
#define NB_MMU_MODES 8
|
||||||
|
|
||||||
/* ARM-specific extra insn start words:
|
/* ARM-specific extra insn start words:
|
||||||
* 1: Conditional execution bits
|
* 1: Conditional execution bits
|
||||||
|
@ -2181,13 +2181,13 @@ static inline CPUARMState *cpu_init(struct uc_struct *uc, const char *cpu_model)
|
||||||
* They have the following different MMU indexes:
|
* They have the following different MMU indexes:
|
||||||
* User
|
* User
|
||||||
* Privileged
|
* Privileged
|
||||||
* Execution priority negative (this is like privileged, but the
|
* User, execution priority negative (ie the MPU HFNMIENA bit may apply)
|
||||||
* MPU HFNMIENA bit means that it may have different access permission
|
* Privileged, execution priority negative (ditto)
|
||||||
* check results to normal privileged code, so can't share a TLB).
|
|
||||||
* If the CPU supports the v8M Security Extension then there are also:
|
* If the CPU supports the v8M Security Extension then there are also:
|
||||||
* Secure User
|
* Secure User
|
||||||
* Secure Privileged
|
* Secure Privileged
|
||||||
* Secure, execution priority negative
|
* Secure User, execution priority negative
|
||||||
|
* Secure Privileged, execution priority negative
|
||||||
*
|
*
|
||||||
* The ARMMMUIdx and the mmu index value used by the core QEMU TLB code
|
* The ARMMMUIdx and the mmu index value used by the core QEMU TLB code
|
||||||
* are not quite the same -- different CPU types (most notably M profile
|
* are not quite the same -- different CPU types (most notably M profile
|
||||||
|
@ -2206,11 +2206,18 @@ static inline CPUARMState *cpu_init(struct uc_struct *uc, const char *cpu_model)
|
||||||
* The constant names here are patterned after the general style of the names
|
* The constant names here are patterned after the general style of the names
|
||||||
* of the AT/ATS operations.
|
* of the AT/ATS operations.
|
||||||
* The values used are carefully arranged to make mmu_idx => EL lookup easy.
|
* The values used are carefully arranged to make mmu_idx => EL lookup easy.
|
||||||
|
* For M profile we arrange them to have a bit for priv, a bit for negpri
|
||||||
|
* and a bit for secure.
|
||||||
*/
|
*/
|
||||||
#define ARM_MMU_IDX_A 0x10 /* A profile */
|
#define ARM_MMU_IDX_A 0x10 /* A profile */
|
||||||
#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
|
#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
|
||||||
#define ARM_MMU_IDX_M 0x40 /* M profile */
|
#define ARM_MMU_IDX_M 0x40 /* M profile */
|
||||||
|
|
||||||
|
/* meanings of the bits for M profile mmu idx values */
|
||||||
|
#define ARM_MMU_IDX_M_PRIV 0x1
|
||||||
|
#define ARM_MMU_IDX_M_NEGPRI 0x2
|
||||||
|
#define ARM_MMU_IDX_M_S 0x4
|
||||||
|
|
||||||
#define ARM_MMU_IDX_TYPE_MASK (~0x7)
|
#define ARM_MMU_IDX_TYPE_MASK (~0x7)
|
||||||
#define ARM_MMU_IDX_COREIDX_MASK 0x7
|
#define ARM_MMU_IDX_COREIDX_MASK 0x7
|
||||||
|
|
||||||
|
@ -2224,10 +2231,12 @@ typedef enum ARMMMUIdx {
|
||||||
ARMMMUIdx_S2NS = 6 | ARM_MMU_IDX_A,
|
ARMMMUIdx_S2NS = 6 | ARM_MMU_IDX_A,
|
||||||
ARMMMUIdx_MUser = 0 | ARM_MMU_IDX_M,
|
ARMMMUIdx_MUser = 0 | ARM_MMU_IDX_M,
|
||||||
ARMMMUIdx_MPriv = 1 | ARM_MMU_IDX_M,
|
ARMMMUIdx_MPriv = 1 | ARM_MMU_IDX_M,
|
||||||
ARMMMUIdx_MNegPri = 2 | ARM_MMU_IDX_M,
|
ARMMMUIdx_MUserNegPri = 2 | ARM_MMU_IDX_M,
|
||||||
ARMMMUIdx_MSUser = 3 | ARM_MMU_IDX_M,
|
ARMMMUIdx_MPrivNegPri = 3 | ARM_MMU_IDX_M,
|
||||||
ARMMMUIdx_MSPriv = 4 | ARM_MMU_IDX_M,
|
ARMMMUIdx_MSUser = 4 | ARM_MMU_IDX_M,
|
||||||
ARMMMUIdx_MSNegPri = 5 | ARM_MMU_IDX_M,
|
ARMMMUIdx_MSPriv = 5 | ARM_MMU_IDX_M,
|
||||||
|
ARMMMUIdx_MSUserNegPri = 6 | ARM_MMU_IDX_M,
|
||||||
|
ARMMMUIdx_MSPrivNegPri = 7 | ARM_MMU_IDX_M,
|
||||||
/* Indexes below here don't have TLBs and are used only for AT system
|
/* Indexes below here don't have TLBs and are used only for AT system
|
||||||
* instructions or for the first stage of an S12 page table walk.
|
* instructions or for the first stage of an S12 page table walk.
|
||||||
*/
|
*/
|
||||||
|
@ -2248,10 +2257,12 @@ typedef enum ARMMMUIdxBit {
|
||||||
ARMMMUIdxBit_S2NS = 1 << 6,
|
ARMMMUIdxBit_S2NS = 1 << 6,
|
||||||
ARMMMUIdxBit_MUser = 1 << 0,
|
ARMMMUIdxBit_MUser = 1 << 0,
|
||||||
ARMMMUIdxBit_MPriv = 1 << 1,
|
ARMMMUIdxBit_MPriv = 1 << 1,
|
||||||
ARMMMUIdxBit_MNegPri = 1 << 2,
|
ARMMMUIdxBit_MUserNegPri = 1 << 2,
|
||||||
ARMMMUIdxBit_MSUser = 1 << 3,
|
ARMMMUIdxBit_MPrivNegPri = 1 << 3,
|
||||||
ARMMMUIdxBit_MSPriv = 1 << 4,
|
ARMMMUIdxBit_MSUser = 1 << 4,
|
||||||
ARMMMUIdxBit_MSNegPri = 1 << 5,
|
ARMMMUIdxBit_MSPriv = 1 << 5,
|
||||||
|
ARMMMUIdxBit_MSUserNegPri = 1 << 6,
|
||||||
|
ARMMMUIdxBit_MSPrivNegPri = 1 << 7,
|
||||||
} ARMMMUIdxBit;
|
} ARMMMUIdxBit;
|
||||||
|
|
||||||
#define MMU_USER_IDX 0
|
#define MMU_USER_IDX 0
|
||||||
|
@ -2283,8 +2294,7 @@ static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
|
||||||
case ARM_MMU_IDX_A:
|
case ARM_MMU_IDX_A:
|
||||||
return mmu_idx & 3;
|
return mmu_idx & 3;
|
||||||
case ARM_MMU_IDX_M:
|
case ARM_MMU_IDX_M:
|
||||||
return (mmu_idx == ARMMMUIdx_MUser || mmu_idx == ARMMMUIdx_MSUser)
|
return mmu_idx & ARM_MMU_IDX_M_PRIV;
|
||||||
? 0 : 1;
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@ -2295,21 +2305,23 @@ static inline ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env,
|
||||||
bool secstate)
|
bool secstate)
|
||||||
{
|
{
|
||||||
int el = arm_current_el(env);
|
int el = arm_current_el(env);
|
||||||
ARMMMUIdx mmu_idx;
|
ARMMMUIdx mmu_idx = ARM_MMU_IDX_M;
|
||||||
|
|
||||||
if (el == 0) {
|
if (el != 0) {
|
||||||
mmu_idx = secstate ? ARMMMUIdx_MSUser : ARMMMUIdx_MUser;
|
mmu_idx |= ARM_MMU_IDX_M_PRIV;
|
||||||
} else {
|
|
||||||
mmu_idx = secstate ? ARMMMUIdx_MSPriv : ARMMMUIdx_MPriv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: if'd out
|
// Unicorn: if'd out
|
||||||
#if 0
|
#if 0
|
||||||
if (armv7m_nvic_neg_prio_requested(env->nvic, secstate)) {
|
if (armv7m_nvic_neg_prio_requested(env->nvic, secstate)) {
|
||||||
mmu_idx = secstate ? ARMMMUIdx_MSNegPri : ARMMMUIdx_MNegPri;
|
mmu_idx |= ARM_MMU_IDX_M_NEGPRI;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (secstate) {
|
||||||
|
mmu_idx |= ARM_MMU_IDX_M_S;
|
||||||
|
}
|
||||||
|
|
||||||
return mmu_idx;
|
return mmu_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7046,11 +7046,13 @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||||
case ARMMMUIdx_S1SE1:
|
case ARMMMUIdx_S1SE1:
|
||||||
case ARMMMUIdx_S1NSE0:
|
case ARMMMUIdx_S1NSE0:
|
||||||
case ARMMMUIdx_S1NSE1:
|
case ARMMMUIdx_S1NSE1:
|
||||||
|
case ARMMMUIdx_MPrivNegPri:
|
||||||
|
case ARMMMUIdx_MUserNegPri:
|
||||||
case ARMMMUIdx_MPriv:
|
case ARMMMUIdx_MPriv:
|
||||||
case ARMMMUIdx_MNegPri:
|
|
||||||
case ARMMMUIdx_MUser:
|
case ARMMMUIdx_MUser:
|
||||||
|
case ARMMMUIdx_MSPrivNegPri:
|
||||||
|
case ARMMMUIdx_MSUserNegPri:
|
||||||
case ARMMMUIdx_MSPriv:
|
case ARMMMUIdx_MSPriv:
|
||||||
case ARMMMUIdx_MSNegPri:
|
|
||||||
case ARMMMUIdx_MSUser:
|
case ARMMMUIdx_MSUser:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
|
@ -7073,8 +7075,7 @@ static inline bool regime_translation_disabled(CPUARMState *env,
|
||||||
(R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) {
|
(R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) {
|
||||||
case R_V7M_MPU_CTRL_ENABLE_MASK:
|
case R_V7M_MPU_CTRL_ENABLE_MASK:
|
||||||
/* Enabled, but not for HardFault and NMI */
|
/* Enabled, but not for HardFault and NMI */
|
||||||
return mmu_idx == ARMMMUIdx_MNegPri ||
|
return mmu_idx & ARM_MMU_IDX_M_NEGPRI;
|
||||||
mmu_idx == ARMMMUIdx_MSNegPri;
|
|
||||||
case R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK:
|
case R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK:
|
||||||
/* Enabled for all cases */
|
/* Enabled for all cases */
|
||||||
return false;
|
return false;
|
||||||
|
@ -7207,6 +7208,8 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||||
case ARMMMUIdx_S1NSE0:
|
case ARMMMUIdx_S1NSE0:
|
||||||
case ARMMMUIdx_MUser:
|
case ARMMMUIdx_MUser:
|
||||||
case ARMMMUIdx_MSUser:
|
case ARMMMUIdx_MSUser:
|
||||||
|
case ARMMMUIdx_MUserNegPri:
|
||||||
|
case ARMMMUIdx_MSUserNegPri:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -546,15 +546,17 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||||
case ARMMMUIdx_S1NSE1:
|
case ARMMMUIdx_S1NSE1:
|
||||||
case ARMMMUIdx_S1E2:
|
case ARMMMUIdx_S1E2:
|
||||||
case ARMMMUIdx_S2NS:
|
case ARMMMUIdx_S2NS:
|
||||||
|
case ARMMMUIdx_MPrivNegPri:
|
||||||
|
case ARMMMUIdx_MUserNegPri:
|
||||||
case ARMMMUIdx_MPriv:
|
case ARMMMUIdx_MPriv:
|
||||||
case ARMMMUIdx_MNegPri:
|
|
||||||
case ARMMMUIdx_MUser:
|
case ARMMMUIdx_MUser:
|
||||||
return false;
|
return false;
|
||||||
case ARMMMUIdx_S1E3:
|
case ARMMMUIdx_S1E3:
|
||||||
case ARMMMUIdx_S1SE0:
|
case ARMMMUIdx_S1SE0:
|
||||||
case ARMMMUIdx_S1SE1:
|
case ARMMMUIdx_S1SE1:
|
||||||
|
case ARMMMUIdx_MSPrivNegPri:
|
||||||
|
case ARMMMUIdx_MSUserNegPri:
|
||||||
case ARMMMUIdx_MSPriv:
|
case ARMMMUIdx_MSPriv:
|
||||||
case ARMMMUIdx_MSNegPri:
|
|
||||||
case ARMMMUIdx_MSUser:
|
case ARMMMUIdx_MSUser:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -149,12 +149,16 @@ static inline int get_a32_user_mem_index(DisasContext *s)
|
||||||
return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
|
return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
|
||||||
case ARMMMUIdx_MUser:
|
case ARMMMUIdx_MUser:
|
||||||
case ARMMMUIdx_MPriv:
|
case ARMMMUIdx_MPriv:
|
||||||
case ARMMMUIdx_MNegPri:
|
|
||||||
return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
|
return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
|
||||||
|
case ARMMMUIdx_MUserNegPri:
|
||||||
|
case ARMMMUIdx_MPrivNegPri:
|
||||||
|
return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
|
||||||
case ARMMMUIdx_MSUser:
|
case ARMMMUIdx_MSUser:
|
||||||
case ARMMMUIdx_MSPriv:
|
case ARMMMUIdx_MSPriv:
|
||||||
case ARMMMUIdx_MSNegPri:
|
|
||||||
return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
|
return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
|
||||||
|
case ARMMMUIdx_MSUserNegPri:
|
||||||
|
case ARMMMUIdx_MSPrivNegPri:
|
||||||
|
return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
|
||||||
case ARMMMUIdx_S2NS:
|
case ARMMMUIdx_S2NS:
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
|
|
Loading…
Reference in a new issue