diff options
author | Edgar E. Iglesias <edgar.iglesias@xilinx.com> | 2015-09-14 14:39:50 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-09-14 14:39:50 +0100 |
commit | 68e9c2fe65bca7fc1bdc2411923333c3e87544a3 (patch) | |
tree | 064471c06e5b575c8a3835394f3ff6f4205711d3 | |
parent | 6533a1fcc2efa08570aa6d85851638783dddf2c6 (diff) |
target-arm: Add VTCR_EL2
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1442135278-25281-3-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: fixed typo in comment]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | target-arm/cpu.h | 1 | ||||
-rw-r--r-- | target-arm/helper.c | 43 |
2 files changed, 42 insertions, 2 deletions
diff --git a/target-arm/cpu.h b/target-arm/cpu.h index b9068c9dad..f91b7933b6 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -224,6 +224,7 @@ typedef struct CPUARMState { }; /* MMU translation table base control. */ TCR tcr_el[4]; + TCR vtcr_el2; /* Virtualization Translation Control. */ uint32_t c2_data; /* MPU data cacheable bits. */ uint32_t c2_insn; /* MPU instruction cacheable bits. */ union { /* MMU domain access control register diff --git a/target-arm/helper.c b/target-arm/helper.c index 2c6ec9d6cf..b250ed0e61 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -325,6 +325,34 @@ void init_cpreg_list(ARMCPU *cpu) g_list_free(keys); } +/* + * Some registers are not accessible if EL3.NS=0 and EL3 is using AArch32 but + * they are accessible when EL3 is using AArch64 regardless of EL3.NS. + * + * access_el3_aa32ns: Used to check AArch32 register views. + * access_el3_aa32ns_aa64any: Used to check both AArch32/64 register views. + */ +static CPAccessResult access_el3_aa32ns(CPUARMState *env, + const ARMCPRegInfo *ri) +{ + bool secure = arm_is_secure_below_el3(env); + + assert(!arm_el_is_aa64(env, 3)); + if (secure) { + return CP_ACCESS_TRAP_UNCATEGORIZED; + } + return CP_ACCESS_OK; +} + +static CPAccessResult access_el3_aa32ns_aa64any(CPUARMState *env, + const ARMCPRegInfo *ri) +{ + if (!arm_el_is_aa64(env, 3)) { + return access_el3_aa32ns(env, ri); + } + return CP_ACCESS_OK; +} + static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { ARMCPU *cpu = arm_env_get_cpu(env); @@ -3112,6 +3140,10 @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = { { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2, .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "VTCR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2, + .access = PL2_RW, .accessfn = access_el3_aa32ns_aa64any, + .type = ARM_CP_CONST, .resetvalue = 0 }, { .name = "SCTLR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 0, .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, @@ -3246,6 +3278,14 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .access = PL2_RW, .writefn = vmsa_tcr_el1_write, .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write, .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[2]) }, + { .name = "VTCR", .state = ARM_CP_STATE_AA32, + .cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2, + .access = PL2_RW, .accessfn = access_el3_aa32ns, + .fieldoffset = offsetof(CPUARMState, cp15.vtcr_el2) }, + { .name = "VTCR_EL2", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2, + .access = PL2_RW, .type = ARM_CP_ALIAS, + .fieldoffset = offsetof(CPUARMState, cp15.vtcr_el2) }, { .name = "SCTLR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 0, .access = PL2_RW, .raw_writefn = raw_write, .writefn = sctlr_write, @@ -5741,8 +5781,7 @@ static inline bool regime_translation_disabled(CPUARMState *env, static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx) { if (mmu_idx == ARMMMUIdx_S2NS) { - /* TODO: return VTCR_EL2 */ - g_assert_not_reached(); + return &env->cp15.vtcr_el2; } return &env->cp15.tcr_el[regime_el(env, mmu_idx)]; } |