mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-15 22:21:57 -06:00
target-arm: Implement AArch64 SPSR_EL1
Implement the AArch64 SPSR_EL1. For compatibility with how KVM handles SPSRs and with the architectural mapping between AArch32 and AArch64, we put this in the banked_spsr[] array in the slot that is used for SVC in AArch32. This means we need to extend the array from uint32_t to uint64_t, which requires some reworking of the 32 bit KVM save/restore code. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Acked-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
This commit is contained in:
parent
f502cfc207
commit
a65f1de982
5 changed files with 40 additions and 11 deletions
|
@ -143,7 +143,7 @@ typedef struct CPUARMState {
|
||||||
uint32_t spsr;
|
uint32_t spsr;
|
||||||
|
|
||||||
/* Banked registers. */
|
/* Banked registers. */
|
||||||
uint32_t banked_spsr[6];
|
uint64_t banked_spsr[6];
|
||||||
uint32_t banked_r13[6];
|
uint32_t banked_r13[6];
|
||||||
uint32_t banked_r14[6];
|
uint32_t banked_r14[6];
|
||||||
|
|
||||||
|
|
|
@ -1936,6 +1936,10 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
|
||||||
.type = ARM_CP_NO_MIGRATE,
|
.type = ARM_CP_NO_MIGRATE,
|
||||||
.opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1,
|
.opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1,
|
||||||
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, elr_el1) },
|
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, elr_el1) },
|
||||||
|
{ .name = "SPSR_EL1", .state = ARM_CP_STATE_AA64,
|
||||||
|
.type = ARM_CP_NO_MIGRATE,
|
||||||
|
.opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 0,
|
||||||
|
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[0]) },
|
||||||
/* We rely on the access checks not allowing the guest to write to the
|
/* We rely on the access checks not allowing the guest to write to the
|
||||||
* state field when SPSel indicates that it's being used as the stack
|
* state field when SPSel indicates that it's being used as the stack
|
||||||
* pointer.
|
* pointer.
|
||||||
|
|
|
@ -295,6 +295,14 @@ typedef struct Reg {
|
||||||
offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \
|
offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Like COREREG, but handle fields which are in a uint64_t in CPUARMState. */
|
||||||
|
#define COREREG64(KERNELNAME, QEMUFIELD) \
|
||||||
|
{ \
|
||||||
|
KVM_REG_ARM | KVM_REG_SIZE_U32 | \
|
||||||
|
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
|
||||||
|
offsetoflow32(CPUARMState, QEMUFIELD) \
|
||||||
|
}
|
||||||
|
|
||||||
static const Reg regs[] = {
|
static const Reg regs[] = {
|
||||||
/* R0_usr .. R14_usr */
|
/* R0_usr .. R14_usr */
|
||||||
COREREG(usr_regs.uregs[0], regs[0]),
|
COREREG(usr_regs.uregs[0], regs[0]),
|
||||||
|
@ -315,16 +323,16 @@ static const Reg regs[] = {
|
||||||
/* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
|
/* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
|
||||||
COREREG(svc_regs[0], banked_r13[1]),
|
COREREG(svc_regs[0], banked_r13[1]),
|
||||||
COREREG(svc_regs[1], banked_r14[1]),
|
COREREG(svc_regs[1], banked_r14[1]),
|
||||||
COREREG(svc_regs[2], banked_spsr[1]),
|
COREREG64(svc_regs[2], banked_spsr[1]),
|
||||||
COREREG(abt_regs[0], banked_r13[2]),
|
COREREG(abt_regs[0], banked_r13[2]),
|
||||||
COREREG(abt_regs[1], banked_r14[2]),
|
COREREG(abt_regs[1], banked_r14[2]),
|
||||||
COREREG(abt_regs[2], banked_spsr[2]),
|
COREREG64(abt_regs[2], banked_spsr[2]),
|
||||||
COREREG(und_regs[0], banked_r13[3]),
|
COREREG(und_regs[0], banked_r13[3]),
|
||||||
COREREG(und_regs[1], banked_r14[3]),
|
COREREG(und_regs[1], banked_r14[3]),
|
||||||
COREREG(und_regs[2], banked_spsr[3]),
|
COREREG64(und_regs[2], banked_spsr[3]),
|
||||||
COREREG(irq_regs[0], banked_r13[4]),
|
COREREG(irq_regs[0], banked_r13[4]),
|
||||||
COREREG(irq_regs[1], banked_r14[4]),
|
COREREG(irq_regs[1], banked_r14[4]),
|
||||||
COREREG(irq_regs[2], banked_spsr[4]),
|
COREREG64(irq_regs[2], banked_spsr[4]),
|
||||||
/* R8_fiq .. R14_fiq and SPSR_fiq */
|
/* R8_fiq .. R14_fiq and SPSR_fiq */
|
||||||
COREREG(fiq_regs[0], fiq_regs[0]),
|
COREREG(fiq_regs[0], fiq_regs[0]),
|
||||||
COREREG(fiq_regs[1], fiq_regs[1]),
|
COREREG(fiq_regs[1], fiq_regs[1]),
|
||||||
|
@ -333,7 +341,7 @@ static const Reg regs[] = {
|
||||||
COREREG(fiq_regs[4], fiq_regs[4]),
|
COREREG(fiq_regs[4], fiq_regs[4]),
|
||||||
COREREG(fiq_regs[5], banked_r13[5]),
|
COREREG(fiq_regs[5], banked_r13[5]),
|
||||||
COREREG(fiq_regs[6], banked_r14[5]),
|
COREREG(fiq_regs[6], banked_r14[5]),
|
||||||
COREREG(fiq_regs[7], banked_spsr[5]),
|
COREREG64(fiq_regs[7], banked_spsr[5]),
|
||||||
/* R15 */
|
/* R15 */
|
||||||
COREREG(usr_regs.uregs[15], regs[15]),
|
COREREG(usr_regs.uregs[15], regs[15]),
|
||||||
/* VFP system registers */
|
/* VFP system registers */
|
||||||
|
|
|
@ -167,8 +167,16 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < KVM_NR_SPSR; i++) {
|
||||||
|
reg.id = AARCH64_CORE_REG(spsr[i]);
|
||||||
|
reg.addr = (uintptr_t) &env->banked_spsr[i - 1];
|
||||||
|
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
* SPSR[]
|
|
||||||
* FP state
|
* FP state
|
||||||
* system registers
|
* system registers
|
||||||
*/
|
*/
|
||||||
|
@ -239,6 +247,15 @@ int kvm_arch_get_registers(CPUState *cs)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < KVM_NR_SPSR; i++) {
|
||||||
|
reg.id = AARCH64_CORE_REG(spsr[i]);
|
||||||
|
reg.addr = (uintptr_t) &env->banked_spsr[i - 1];
|
||||||
|
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: other registers */
|
/* TODO: other registers */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,9 +222,9 @@ static int cpu_post_load(void *opaque, int version_id)
|
||||||
|
|
||||||
const VMStateDescription vmstate_arm_cpu = {
|
const VMStateDescription vmstate_arm_cpu = {
|
||||||
.name = "cpu",
|
.name = "cpu",
|
||||||
.version_id = 16,
|
.version_id = 17,
|
||||||
.minimum_version_id = 16,
|
.minimum_version_id = 17,
|
||||||
.minimum_version_id_old = 16,
|
.minimum_version_id_old = 17,
|
||||||
.pre_save = cpu_pre_save,
|
.pre_save = cpu_pre_save,
|
||||||
.post_load = cpu_post_load,
|
.post_load = cpu_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
|
@ -238,7 +238,7 @@ const VMStateDescription vmstate_arm_cpu = {
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
},
|
},
|
||||||
VMSTATE_UINT32(env.spsr, ARMCPU),
|
VMSTATE_UINT32(env.spsr, ARMCPU),
|
||||||
VMSTATE_UINT32_ARRAY(env.banked_spsr, ARMCPU, 6),
|
VMSTATE_UINT64_ARRAY(env.banked_spsr, ARMCPU, 6),
|
||||||
VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 6),
|
VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 6),
|
||||||
VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 6),
|
VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 6),
|
||||||
VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
|
VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue