target-arm: add secure state bit to CPREG hash

Added additional NS-bit to CPREG hash encoding. Updated hash lookup
locations to specify hash bit currently set to non-secure.

Backports commit 51a79b039728277e35fd19f7a7b4bc6cb323697f from qemu
This commit is contained in:
Peter Maydell 2018-02-11 18:32:39 -05:00 committed by Lioncash
parent 4f5106b56d
commit fb78e79d72
No known key found for this signature in database
GPG Key ID: 4E3C3CC1031BA9C7
3 changed files with 33 additions and 13 deletions

View File

@ -893,6 +893,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq);
* Crn, Crm, opc1, opc2 fields * Crn, Crm, opc1, opc2 fields
* 32 or 64 bit register (ie is it accessed via MRC/MCR * 32 or 64 bit register (ie is it accessed via MRC/MCR
* or via MRRC/MCRR?) * or via MRRC/MCRR?)
* non-secure/secure bank (AArch32 only)
* We allow 4 bits for opc1 because MRRC/MCRR have a 4 bit field. * We allow 4 bits for opc1 because MRRC/MCRR have a 4 bit field.
* (In this case crn and opc2 should be zero.) * (In this case crn and opc2 should be zero.)
* For AArch64, there is no 32/64 bit size distinction; * For AArch64, there is no 32/64 bit size distinction;
@ -910,9 +911,16 @@ void armv7m_nvic_complete_irq(void *opaque, int irq);
#define CP_REG_AA64_SHIFT 28 #define CP_REG_AA64_SHIFT 28
#define CP_REG_AA64_MASK (1 << CP_REG_AA64_SHIFT) #define CP_REG_AA64_MASK (1 << CP_REG_AA64_SHIFT)
#define ENCODE_CP_REG(cp, is64, crn, crm, opc1, opc2) \ /* To enable banking of coprocessor registers depending on ns-bit we
(((cp) << 16) | ((is64) << 15) | ((crn) << 11) | \ * add a bit to distinguish between secure and non-secure cpregs in the
((crm) << 7) | ((opc1) << 3) | (opc2)) * hashtable.
*/
#define CP_REG_NS_SHIFT 29
#define CP_REG_NS_MASK (1 << CP_REG_NS_SHIFT)
#define ENCODE_CP_REG(cp, is64, ns, crn, crm, opc1, opc2) \
((ns) << CP_REG_NS_SHIFT | ((cp) << 16) | ((is64) << 15) | \
((crn) << 11) | ((crm) << 7) | ((opc1) << 3) | (opc2))
#define ENCODE_AA64_CP_REG(cp, crn, crm, op0, op1, op2) \ #define ENCODE_AA64_CP_REG(cp, crn, crm, op0, op1, op2) \
(CP_REG_AA64_MASK | \ (CP_REG_AA64_MASK | \
@ -931,9 +939,16 @@ static inline uint32_t kvm_to_cpreg_id(uint64_t kvmid)
uint32_t cpregid = kvmid; uint32_t cpregid = kvmid;
if ((kvmid & CP_REG_ARCH_MASK) == CP_REG_ARM64) { if ((kvmid & CP_REG_ARCH_MASK) == CP_REG_ARM64) {
cpregid |= CP_REG_AA64_MASK; cpregid |= CP_REG_AA64_MASK;
} else if ((kvmid & CP_REG_SIZE_MASK) == CP_REG_SIZE_U64) { } else {
if ((kvmid & CP_REG_SIZE_MASK) == CP_REG_SIZE_U64) {
cpregid |= (1 << 15); cpregid |= (1 << 15);
} }
/* KVM is always non-secure so add the NS flag on AArch32 register
* entries.
*/
cpregid |= 1 << CP_REG_NS_SHIFT;
}
return cpregid; return cpregid;
} }

View File

@ -2802,7 +2802,7 @@ void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
} }
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r, static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
void *opaque, int state, void *opaque, int state, int secstate,
int crm, int opc1, int opc2) int crm, int opc1, int opc2)
{ {
/* Private utility function for define_one_arm_cp_reg_with_opaque(): /* Private utility function for define_one_arm_cp_reg_with_opaque():
@ -2811,6 +2811,7 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
uint32_t *key = g_new(uint32_t, 1); uint32_t *key = g_new(uint32_t, 1);
ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo)); ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0; int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
int ns = (r->secure & ARM_CP_SECSTATE_NS) ? 1 : 0;
if (r->state == ARM_CP_STATE_BOTH && state == ARM_CP_STATE_AA32) { if (r->state == ARM_CP_STATE_BOTH && state == ARM_CP_STATE_AA32) {
/* The AArch32 view of a shared register sees the lower 32 bits /* The AArch32 view of a shared register sees the lower 32 bits
* of a 64 bit backing field. It is not migratable as the AArch64 * of a 64 bit backing field. It is not migratable as the AArch64
@ -2842,7 +2843,7 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
*key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm, *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
r2->opc0, opc1, opc2); r2->opc0, opc1, opc2);
} else { } else {
*key = ENCODE_CP_REG(r2->cp, is64, r2->crn, crm, opc1, opc2); *key = ENCODE_CP_REG(r2->cp, is64, ns, r2->crn, crm, opc1, opc2);
} }
if (opaque) { if (opaque) {
r2->opaque = opaque; r2->opaque = opaque;
@ -2992,7 +2993,7 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
continue; continue;
} }
add_cpreg_to_hashtable(cpu, r, opaque, state, add_cpreg_to_hashtable(cpu, r, opaque, state,
crm, opc1, opc2); ARM_CP_SECSTATE_NS, crm, opc1, opc2);
} }
} }
} }

View File

@ -7252,7 +7252,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
rt = (insn >> 12) & 0xf; rt = (insn >> 12) & 0xf;
ri = get_arm_cp_reginfo(s->cp_regs, ri = get_arm_cp_reginfo(s->cp_regs,
ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2)); ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
if (ri) { if (ri) {
/* Check access permissions */ /* Check access permissions */
if (!cp_access_ok(s->current_el, ri, isread)) { if (!cp_access_ok(s->current_el, ri, isread)) {
@ -7434,12 +7434,16 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
*/ */
if (is64) { if (is64) {
qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 " qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
"64 bit system register cp:%d opc1: %d crm:%d\n", "64 bit system register cp:%d opc1: %d crm:%d "
isread ? "read" : "write", cpnum, opc1, crm); "(%s)\n",
isread ? "read" : "write", cpnum, opc1, crm,
s->ns ? "non-secure" : "secure");
} else { } else {
qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 " qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
"system register cp:%d opc1:%d crn:%d crm:%d opc2:%d\n", "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
isread ? "read" : "write", cpnum, opc1, crn, crm, opc2); "(%s)\n",
isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
s->ns ? "non-secure" : "secure");
} }
return 1; return 1;