mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 09:43:56 -06:00
nvic: Add banked exception states
For the v8M security extension, some exceptions must be banked between security states. Add the new vecinfo array which holds the state for the banked exceptions and migrate it if the CPU the NVIC is attached to implements the security extension. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
50f11062d4
commit
17906a162a
2 changed files with 66 additions and 1 deletions
|
@ -47,7 +47,7 @@
|
|||
* For historical reasons QEMU tends to use "interrupt" and
|
||||
* "exception" more or less interchangeably.
|
||||
*/
|
||||
#define NVIC_FIRST_IRQ 16
|
||||
#define NVIC_FIRST_IRQ NVIC_INTERNAL_VECTORS
|
||||
#define NVIC_MAX_IRQ (NVIC_MAX_VECTORS - NVIC_FIRST_IRQ)
|
||||
|
||||
/* Effective running priority of the CPU when no exception is active
|
||||
|
@ -1158,6 +1158,43 @@ static const VMStateDescription vmstate_VecInfo = {
|
|||
}
|
||||
};
|
||||
|
||||
static bool nvic_security_needed(void *opaque)
|
||||
{
|
||||
NVICState *s = opaque;
|
||||
|
||||
return arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY);
|
||||
}
|
||||
|
||||
static int nvic_security_post_load(void *opaque, int version_id)
|
||||
{
|
||||
NVICState *s = opaque;
|
||||
int i;
|
||||
|
||||
/* Check for out of range priority settings */
|
||||
if (s->sec_vectors[ARMV7M_EXCP_HARD].prio != -1) {
|
||||
return 1;
|
||||
}
|
||||
for (i = ARMV7M_EXCP_MEM; i < ARRAY_SIZE(s->sec_vectors); i++) {
|
||||
if (s->sec_vectors[i].prio & ~0xff) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_nvic_security = {
|
||||
.name = "nvic/m-security",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = nvic_security_needed,
|
||||
.post_load = &nvic_security_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT_ARRAY(sec_vectors, NVICState, NVIC_INTERNAL_VECTORS, 1,
|
||||
vmstate_VecInfo, VecInfo),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_nvic = {
|
||||
.name = "armv7m_nvic",
|
||||
.version_id = 4,
|
||||
|
@ -1168,6 +1205,10 @@ static const VMStateDescription vmstate_nvic = {
|
|||
vmstate_VecInfo, VecInfo),
|
||||
VMSTATE_UINT32(prigroup, NVICState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (const VMStateDescription*[]) {
|
||||
&vmstate_nvic_security,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1195,6 +1236,16 @@ static void armv7m_nvic_reset(DeviceState *dev)
|
|||
s->vectors[ARMV7M_EXCP_NMI].prio = -2;
|
||||
s->vectors[ARMV7M_EXCP_HARD].prio = -1;
|
||||
|
||||
if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY)) {
|
||||
s->sec_vectors[ARMV7M_EXCP_HARD].enabled = 1;
|
||||
s->sec_vectors[ARMV7M_EXCP_SVC].enabled = 1;
|
||||
s->sec_vectors[ARMV7M_EXCP_PENDSV].enabled = 1;
|
||||
s->sec_vectors[ARMV7M_EXCP_SYSTICK].enabled = 1;
|
||||
|
||||
/* AIRCR.BFHFNMINS resets to 0 so Secure HF is priority -1 (R_CMTC) */
|
||||
s->sec_vectors[ARMV7M_EXCP_HARD].prio = -1;
|
||||
}
|
||||
|
||||
/* Strictly speaking the reset handler should be enabled.
|
||||
* However, we don't simulate soft resets through the NVIC,
|
||||
* and the reset vector should never be pended.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue