From 4bf69e19c651bc43c855c231fa43c6ba43766359 Mon Sep 17 00:00:00 2001 From: Fabian Aggeler Date: Mon, 12 Feb 2018 09:42:08 -0500 Subject: [PATCH] target-arm: make c13 cp regs banked (FCSEIDR, ...) When EL3 is running in AArch32 (or ARMv7 with Security Extensions) FCSEIDR, CONTEXTIDR, TPIDRURW, TPIDRURO and TPIDRPRW have a secure and a non-secure instance. Backports commit 54bf36ed351c526cde0c853079f9ff1ab7e2ff89 from qemu --- qemu/target-arm/cpu.h | 36 ++++++++++++++++++--- qemu/target-arm/helper.c | 52 +++++++++++++++++++++++-------- qemu/target-arm/op_helper.c | 2 +- qemu/target-arm/unicorn_aarch64.c | 12 +++---- 4 files changed, 77 insertions(+), 25 deletions(-) diff --git a/qemu/target-arm/cpu.h b/qemu/target-arm/cpu.h index 42a308bb..75b093d7 100644 --- a/qemu/target-arm/cpu.h +++ b/qemu/target-arm/cpu.h @@ -309,11 +309,37 @@ typedef struct CPUARMState { uint64_t vbar_el[4]; }; uint32_t mvbar; /* (monitor) vector base address register */ - uint32_t c13_fcse; /* FCSE PID. */ - uint64_t contextidr_el1; /* Context ID. */ - uint64_t tpidr_el0; /* User RW Thread register. */ - uint64_t tpidrro_el0; /* User RO Thread register. */ - uint64_t tpidr_el1; /* Privileged Thread register. */ + struct { /* FCSE PID. */ + uint32_t fcseidr_ns; + uint32_t fcseidr_s; + }; + union { /* Context ID. */ + struct { + uint64_t _unused_contextidr_0; + uint64_t contextidr_ns; + uint64_t _unused_contextidr_1; + uint64_t contextidr_s; + }; + uint64_t contextidr_el[4]; + }; + union { /* User RW Thread register. */ + struct { + uint64_t tpidrurw_ns; + uint64_t tpidrprw_ns; + uint64_t htpidr; + uint64_t _tpidr_el3; + }; + uint64_t tpidr_el[4]; + }; + /* The secure banks of these registers don't map anywhere */ + uint64_t tpidrurw_s; + uint64_t tpidrprw_s; + uint64_t tpidruro_s; + + union { /* User RO Thread register. */ + uint64_t tpidruro_ns; + uint64_t tpidrro_el[1]; + }; uint64_t c14_cntfrq; /* Counter Frequency register */ uint64_t c14_cntkctl; /* Timer Control register */ ARMGenericTimer c14_timer[NUM_GTIMERS]; diff --git a/qemu/target-arm/helper.c b/qemu/target-arm/helper.c index 81c3f618..cecfe1e1 100644 --- a/qemu/target-arm/helper.c +++ b/qemu/target-arm/helper.c @@ -319,11 +319,31 @@ static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, } static const ARMCPRegInfo cp_reginfo[] = { - { "FCSEIDR", 15,13,0, 0,0,0, 0, - 0, PL1_RW, 0, NULL, 0, offsetof(CPUARMState, cp15.c13_fcse), {0, 0}, - NULL, NULL, fcse_write, NULL, raw_write, NULL, }, - { "CONTEXTIDR", 0,13,0, 3,0,1, ARM_CP_STATE_BOTH, - 0, PL1_RW, 0, NULL, 0, offsetof(CPUARMState, cp15.contextidr_el1), {0, 0}, + /* Define the secure and non-secure FCSE identifier CP registers + * separately because there is no secure bank in V8 (no _EL3). This allows + * the secure register to be properly reset and migrated. There is also no + * v8 EL1 version of the register so the non-secure instance stands alone. + */ + { "FCSEIDR(NS)", 15,13,0, 0,0,0, 0,0, + PL1_RW, ARM_CP_SECSTATE_NS, NULL, 0, + offsetof(CPUARMState, cp15.fcseidr_ns), {0, 0}, + NULL, NULL, fcse_write, NULL, raw_write, }, + { "FCSEIDR(S)", 15,13,0, 0,0,0, 0,0, + PL1_RW, ARM_CP_SECSTATE_S, NULL, 0, + offsetof(CPUARMState, cp15.fcseidr_s), {0, 0}, + NULL, NULL, fcse_write, NULL, raw_write, }, + /* Define the secure and non-secure context identifier CP registers + * separately because there is no secure bank in V8 (no _EL3). This allows + * the secure register to be properly reset and migrated. In the + * non-secure case, the 32-bit register will have reset and migration + * disabled during registration as it is handled by the 64-bit instance. + */ + { "CONTEXTIDR_EL1", 0,13,0, 3,0,1, ARM_CP_STATE_BOTH, + 0, PL1_RW, ARM_CP_SECSTATE_NS, NULL, 0, offsetof(CPUARMState, cp15.contextidr_el[1]), {0, 0}, + NULL, NULL, contextidr_write, NULL, raw_write, NULL, }, + { "CONTEXTIDR(S)", 15,13,0, 0,0,1, ARM_CP_STATE_AA32,0, + PL1_RW, ARM_CP_SECSTATE_S, NULL, 0, + offsetof(CPUARMState, cp15.contextidr_s), {0, 0}, NULL, NULL, contextidr_write, NULL, raw_write, NULL, }, REGINFO_SENTINEL }; @@ -883,17 +903,22 @@ static const ARMCPRegInfo t2ee_cp_reginfo[] = { static const ARMCPRegInfo v6k_cp_reginfo[] = { { "TPIDR_EL0", 0,13,0, 3,3,2, ARM_CP_STATE_AA64, - 0, PL0_RW, 0, NULL, 0, offsetof(CPUARMState, cp15.tpidr_el0), }, + 0, PL0_RW, 0, NULL, 0, offsetof(CPUARMState, cp15.tpidr_el[0]), }, { "TPIDRURW", 15,13,0, 0,0,2, 0, - 0, PL0_RW, 0, NULL, 0, offsetoflow32(CPUARMState, cp15.tpidr_el0), {0, 0}, + 0, PL0_RW, 0, NULL, 0, 0, + { offsetoflow32(CPUARMState, cp15.tpidrurw_s), offsetoflow32(CPUARMState, cp15.tpidrurw_ns) }, NULL, NULL, NULL, NULL, NULL, arm_cp_reset_ignore }, { "TPIDRRO_EL0", 0,13,0, 3,3,3, ARM_CP_STATE_AA64, - 0, PL0_R|PL1_W, 0, NULL, 0, offsetof(CPUARMState, cp15.tpidrro_el0) }, + 0, PL0_R|PL1_W, 0, NULL, 0, offsetof(CPUARMState, cp15.tpidrro_el[0]) }, { "TPIDRURO", 15,13,0, 0,0,3, 0, - 0, PL0_R|PL1_W, 0, NULL, 0, offsetoflow32(CPUARMState, cp15.tpidrro_el0), {0, 0}, + 0, PL0_R|PL1_W, 0, NULL, 0, 0, + {offsetoflow32(CPUARMState, cp15.tpidruro_s), offsetoflow32(CPUARMState, cp15.tpidruro_ns) }, NULL, NULL, NULL, NULL, NULL, arm_cp_reset_ignore }, - { "TPIDR_EL1", 0,13,0, 3,0,4, ARM_CP_STATE_BOTH, - 0, PL1_RW, 0, NULL, 0, offsetof(CPUARMState, cp15.tpidr_el1), }, + { "TPIDR_EL1", 0,13,0, 3,0,4, ARM_CP_STATE_AA64, + 0, PL1_RW, 0, NULL, 0, offsetof(CPUARMState, cp15.tpidr_el[1]) }, + { "TPIDRPRW", 15,13,0, 0,0,4, 0,0, + PL1_RW, 0, NULL, 0,0, + { offsetoflow32(CPUARMState, cp15.tpidrprw_s), offsetoflow32(CPUARMState, cp15.tpidrprw_ns)} }, REGINFO_SENTINEL }; @@ -4548,8 +4573,9 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address, uint32_t sctlr = A32_BANKED_CURRENT_REG_GET(env, sctlr); /* Fast Context Switch Extension. */ - if (address < 0x02000000) - address += env->cp15.c13_fcse; + if (address < 0x02000000) { + address += A32_BANKED_CURRENT_REG_GET(env, fcseidr); + } if ((sctlr & SCTLR_M) == 0) { /* MMU/MPU disabled. */ diff --git a/qemu/target-arm/op_helper.c b/qemu/target-arm/op_helper.c index 8f8e3483..ce137901 100644 --- a/qemu/target-arm/op_helper.c +++ b/qemu/target-arm/op_helper.c @@ -575,7 +575,7 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn) * short descriptor format (in which case it holds both PROCID and ASID), * since we don't implement the optional v7 context ID masking. */ - contextidr = extract64(env->cp15.contextidr_el1, 0, 32); + contextidr = extract64(env->cp15.contextidr_el[1], 0, 32); switch (bt) { case 3: /* linked context ID match */ diff --git a/qemu/target-arm/unicorn_aarch64.c b/qemu/target-arm/unicorn_aarch64.c index 0e92a378..32f9d772 100644 --- a/qemu/target-arm/unicorn_aarch64.c +++ b/qemu/target-arm/unicorn_aarch64.c @@ -83,13 +83,13 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co *(uint32_t *)value = ARM_CPU(uc, mycpu)->env.exception.syndrome; break; case UC_ARM64_REG_TPIDR_EL0: - *(int64_t *)value = ARM_CPU(uc, mycpu)->env.cp15.tpidr_el0; + *(int64_t *)value = ARM_CPU(uc, mycpu)->env.cp15.tpidr_el[0]; break; case UC_ARM64_REG_TPIDRRO_EL0: - *(int64_t *)value = ARM_CPU(uc, mycpu)->env.cp15.tpidrro_el0; + *(int64_t *)value = ARM_CPU(uc, mycpu)->env.cp15.tpidrro_el[0]; break; case UC_ARM64_REG_TPIDR_EL1: - *(int64_t *)value = ARM_CPU(uc, mycpu)->env.cp15.tpidr_el1; + *(int64_t *)value = ARM_CPU(uc, mycpu)->env.cp15.tpidr_el[1]; break; case UC_ARM64_REG_X29: *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[29]; @@ -157,13 +157,13 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, ARM_CPU(uc, mycpu)->env.cp15.c1_coproc = *(uint32_t *)value; break; case UC_ARM64_REG_TPIDR_EL0: - ARM_CPU(uc, mycpu)->env.cp15.tpidr_el0 = *(uint64_t *)value; + ARM_CPU(uc, mycpu)->env.cp15.tpidr_el[0] = *(uint64_t *)value; break; case UC_ARM64_REG_TPIDRRO_EL0: - ARM_CPU(uc, mycpu)->env.cp15.tpidrro_el0 = *(uint64_t *)value; + ARM_CPU(uc, mycpu)->env.cp15.tpidrro_el[0] = *(uint64_t *)value; break; case UC_ARM64_REG_TPIDR_EL1: - ARM_CPU(uc, mycpu)->env.cp15.tpidr_el1 = *(uint64_t *)value; + ARM_CPU(uc, mycpu)->env.cp15.tpidr_el[1] = *(uint64_t *)value; break; case UC_ARM64_REG_X29: ARM_CPU(uc, mycpu)->env.xregs[29] = *(uint64_t *)value;