target-arm: add CPREG secure state support

Prepare ARMCPRegInfo to support specifying two fieldoffsets per
register definition. This will allow us to keep one register
definition for banked registers (different offsets for secure/
non-secure world).

Also added secure state tracking field and flags. This allows for
identification of the register info secure state.

Backports commit c3e302606253a17568dc3ef30238f102468f7ee1 from qemu
This commit is contained in:
Fabian Aggeler 2018-02-11 17:52:55 -05:00 committed by Lioncash
parent acdd665668
commit 4f5106b56d
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
4 changed files with 298 additions and 266 deletions

View file

@ -654,9 +654,9 @@ static void arm_v7m_class_init(struct uc_struct *uc, ObjectClass *oc, void *data
static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
{ "L2LOCKDOWN", 15,9,0, 0,1,0, 0,
ARM_CP_CONST, PL1_RW, NULL, 0, },
ARM_CP_CONST, PL1_RW, 0, NULL, 0, },
{ "L2AUXCR", 15,9,0, 0,1,2, 0,
ARM_CP_CONST, PL1_RW, NULL, 0, },
ARM_CP_CONST, PL1_RW, 0, NULL, 0, },
REGINFO_SENTINEL
};
@ -703,24 +703,24 @@ static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
* default to 0 and set by private hook
*/
{ "A9_PWRCTL", 15,15,0, 0,0,0, 0,
0, PL1_RW, NULL, 0, offsetof(CPUARMState, cp15.c15_power_control) },
0, PL1_RW, 0, NULL, 0, offsetof(CPUARMState, cp15.c15_power_control) },
{ "A9_DIAG", 15,15,0, 0,0,1, 0,
0, PL1_RW, NULL, 0, offsetof(CPUARMState, cp15.c15_diagnostic) },
0, PL1_RW, 0, NULL, 0, offsetof(CPUARMState, cp15.c15_diagnostic) },
{ "A9_PWRDIAG",15,15,0, 0,0,2, 0,
0, PL1_RW, NULL, 0, offsetof(CPUARMState, cp15.c15_power_diagnostic) },
0, PL1_RW, 0, NULL, 0, offsetof(CPUARMState, cp15.c15_power_diagnostic) },
{ "NEONBUSY", 15,15,1, 0,0,0, 0,
ARM_CP_CONST, PL1_RW, NULL, 0, },
ARM_CP_CONST, PL1_RW, 0, NULL, 0, },
/* TLB lockdown control */
{ "TLB_LOCKR", 15,15,4, 0,5,2, 0,
ARM_CP_NOP, PL1_W, NULL, 0 },
ARM_CP_NOP, PL1_W, 0, NULL, 0 },
{ "TLB_LOCKW", 15,15,4, 0,5,4, 0,
ARM_CP_NOP, PL1_W, NULL, 0, },
ARM_CP_NOP, PL1_W, 0, NULL, 0, },
{ "TLB_VA", 15,15,5, 0,5,2, 0,
ARM_CP_CONST, PL1_RW, NULL, 0, },
ARM_CP_CONST, PL1_RW, 0, NULL, 0, },
{ "TLB_PA", 15,15,6, 0,5,2, 0,
ARM_CP_CONST, PL1_RW, NULL, 0 },
ARM_CP_CONST, PL1_RW, 0, NULL, 0 },
{ "TLB_ATTR", 15,15,7, 0,5,2, 0,
ARM_CP_CONST, PL1_RW, NULL, 0, },
ARM_CP_CONST, PL1_RW, 0, NULL, 0, },
REGINFO_SENTINEL
};
@ -779,11 +779,11 @@ static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
#ifndef CONFIG_USER_ONLY
{ "L2CTLR", 15,9,0, 0,1,2, 0,
0, PL1_RW, NULL, 0, 0,
0, PL1_RW, 0, NULL, 0, 0, {0, 0},
NULL, a15_l2ctlr_read, arm_cp_write_ignore, },
#endif
{ "L2ECTLR", 15,9,0, 0,1,3, 0,
ARM_CP_CONST, PL1_RW, NULL, 0 },
ARM_CP_CONST, PL1_RW, 0, NULL, 0 },
REGINFO_SENTINEL
};

View file

@ -1007,6 +1007,21 @@ enum {
ARM_CP_STATE_BOTH = 2,
};
/* ARM CP register secure state flags. These flags identify security state
* attributes for a given CP register entry.
* The existence of both or neither secure and non-secure flags indicates that
* the register has both a secure and non-secure hash entry. A single one of
* these flags causes the register to only be hashed for the specified
* security state.
* Although definitions may have any combination of the S/NS bits, each
* registered entry will only have one to identify whether the entry is secure
* or non-secure.
*/
enum {
ARM_CP_SECSTATE_S = (1 << 0), /* bit[0]: Secure state register */
ARM_CP_SECSTATE_NS = (1 << 1), /* bit[1]: Non-secure state register */
};
/* Return true if cptype is a valid type field. This is used to try to
* catch errors where the sentinel has been accidentally left off the end
* of a list of registers.
@ -1141,6 +1156,8 @@ struct ARMCPRegInfo {
int type;
/* Access rights: PL*_[RW] */
int access;
/* Security state: ARM_CP_SECSTATE_* bits/values */
int secure;
/* The opaque pointer passed to define_arm_cp_regs_with_opaque() when
* this register was defined: can be used to hand data through to the
* register read/write functions, since they are passed the ARMCPRegInfo*.
@ -1150,12 +1167,27 @@ struct ARMCPRegInfo {
* fieldoffset is non-zero, the reset value of the register.
*/
uint64_t resetvalue;
/* Offset of the field in CPUARMState for this register. This is not
* needed if either:
/* Offset of the field in CPUARMState for this register.
*
* This is not needed if either:
* 1. type is ARM_CP_CONST or one of the ARM_CP_SPECIALs
* 2. both readfn and writefn are specified
*/
ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */
/* Offsets of the secure and non-secure fields in CPUARMState for the
* register if it is banked. These fields are only used during the static
* registration of a register. During hashing the bank associated
* with a given security state is copied to fieldoffset which is used from
* there on out.
*
* It is expected that register definitions use either fieldoffset or
* bank_fieldoffsets in the definition but not both. It is also expected
* that both bank offsets are set when defining a banked register. This
* use indicates that a register is banked.
*/
ptrdiff_t bank_fieldoffsets[2];
/* Function for making any access checks for this register in addition to
* those specified by the 'access' permissions bits. If NULL, no extra
* checks required. The access check is performed at runtime, not at
@ -1200,7 +1232,7 @@ struct ARMCPRegInfo {
#define CPREG_FIELD64(env, ri) \
(*(uint64_t *)((char *)(env) + (ri)->fieldoffset))
#define REGINFO_SENTINEL { NULL, 0,0,0,0,0,0, 0, ARM_CP_SENTINEL, 0, NULL, 0,0,0,0,0,0,0,0, }
#define REGINFO_SENTINEL { NULL, 0,0,0,0,0,0, 0, ARM_CP_SENTINEL, 0, 0, NULL, 0,0, {0, 0}, 0,0,0,0,0,0, }
void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
const ARMCPRegInfo *regs, void *opaque);

View file

@ -39,34 +39,34 @@ static uint64_t a57_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
static const ARMCPRegInfo cortexa57_cp_reginfo[] = {
#ifndef CONFIG_USER_ONLY
{ "L2CTLR_EL1", 0,11,0, 3,1,2, ARM_CP_STATE_AA64,
0, PL1_RW, NULL, 0, 0,
0, PL1_RW, 0, NULL, 0, 0, {0, 0},
NULL, a57_l2ctlr_read, arm_cp_write_ignore, },
{ "L2CTLR", 15,9,0, 0,1,2, 0,
0, PL1_RW, NULL, 0, 0,
0, PL1_RW, 0, NULL, 0, 0, {0, 0},
NULL, a57_l2ctlr_read, arm_cp_write_ignore, },
#endif
{ "L2ECTLR_EL1", 0,11,0, 3,1,3, ARM_CP_STATE_AA64,
ARM_CP_CONST, PL1_RW, NULL, 0, },
ARM_CP_CONST, PL1_RW, 0, NULL, 0, },
{ "L2ECTLR", 15,9,0, 0,1,3, 0,
ARM_CP_CONST, PL1_RW, NULL, 0, },
ARM_CP_CONST, PL1_RW, 0, NULL, 0, },
{ "L2ACTLR", 0,15,0, 3,1,0, ARM_CP_STATE_BOTH,
ARM_CP_CONST, PL1_RW, NULL, 0 },
ARM_CP_CONST, PL1_RW, 0, NULL, 0 },
{ "CPUACTLR_EL1", 0,15,2, 3,1,0, ARM_CP_STATE_AA64,
ARM_CP_CONST, PL1_RW, NULL, 0 },
ARM_CP_CONST, PL1_RW, 0, NULL, 0 },
{ "CPUACTLR", 15,0,15, 0,0,0, 0,
ARM_CP_CONST | ARM_CP_64BIT, PL1_RW, NULL, 0, },
ARM_CP_CONST | ARM_CP_64BIT, PL1_RW, 0, NULL, 0, },
{ "CPUECTLR_EL1", 0,15,2, 3,1,1, ARM_CP_STATE_AA64,
ARM_CP_CONST, PL1_RW, NULL, 0, },
ARM_CP_CONST, PL1_RW, 0, NULL, 0, },
{ "CPUECTLR", 15,0,15, 0,1,0, 0,
ARM_CP_CONST | ARM_CP_64BIT, PL1_RW, NULL, 0, },
ARM_CP_CONST | ARM_CP_64BIT, PL1_RW, 0, NULL, 0, },
{ "CPUMERRSR_EL1", 0,15,2, 3,1,2, ARM_CP_STATE_AA64,
ARM_CP_CONST, PL1_RW, NULL, 0 },
ARM_CP_CONST, PL1_RW, 0, NULL, 0 },
{ "CPUMERRSR", 15,0,15, 0,2,0, 0,
ARM_CP_CONST | ARM_CP_64BIT, PL1_RW, NULL, 0 },
ARM_CP_CONST | ARM_CP_64BIT, PL1_RW, 0, NULL, 0 },
{ "L2MERRSR_EL1", 0,15,2, 3,1,3, ARM_CP_STATE_AA64,
ARM_CP_CONST, PL1_RW, NULL, 0 },
ARM_CP_CONST, PL1_RW, 0, NULL, 0 },
{ "L2MERRSR", 15,0,15, 0,3,0, 0,
ARM_CP_CONST | ARM_CP_64BIT, PL1_RW, NULL, 0 },
ARM_CP_CONST | ARM_CP_64BIT, PL1_RW, 0, NULL, 0 },
REGINFO_SENTINEL
};

File diff suppressed because it is too large Load diff