mirror of https://github.com/xemu-project/xemu.git
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
|
@ -143,7 +143,7 @@ typedef struct CPUARMState {
|
|||
uint32_t spsr;
|
||||
|
||||
/* Banked registers. */
|
||||
uint32_t banked_spsr[6];
|
||||
uint64_t banked_spsr[6];
|
||||
uint32_t banked_r13[6];
|
||||
uint32_t banked_r14[6];
|
||||
|
||||
|
|
|
@ -1936,6 +1936,10 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
|
|||
.type = ARM_CP_NO_MIGRATE,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1,
|
||||
.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
|
||||
* state field when SPSel indicates that it's being used as the stack
|
||||
* pointer.
|
||||
|
|
|
@ -295,6 +295,14 @@ typedef struct Reg {
|
|||
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[] = {
|
||||
/* R0_usr .. R14_usr */
|
||||
COREREG(usr_regs.uregs[0], regs[0]),
|
||||
|
@ -315,16 +323,16 @@ static const Reg regs[] = {
|
|||
/* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
|
||||
COREREG(svc_regs[0], banked_r13[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[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[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[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 */
|
||||
COREREG(fiq_regs[0], fiq_regs[0]),
|
||||
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[5], banked_r13[5]),
|
||||
COREREG(fiq_regs[6], banked_r14[5]),
|
||||
COREREG(fiq_regs[7], banked_spsr[5]),
|
||||
COREREG64(fiq_regs[7], banked_spsr[5]),
|
||||
/* R15 */
|
||||
COREREG(usr_regs.uregs[15], regs[15]),
|
||||
/* VFP system registers */
|
||||
|
|
|
@ -167,8 +167,16 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
|||
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:
|
||||
* SPSR[]
|
||||
* FP state
|
||||
* system registers
|
||||
*/
|
||||
|
@ -239,6 +247,15 @@ int kvm_arch_get_registers(CPUState *cs)
|
|||
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 */
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -222,9 +222,9 @@ static int cpu_post_load(void *opaque, int version_id)
|
|||
|
||||
const VMStateDescription vmstate_arm_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 16,
|
||||
.minimum_version_id = 16,
|
||||
.minimum_version_id_old = 16,
|
||||
.version_id = 17,
|
||||
.minimum_version_id = 17,
|
||||
.minimum_version_id_old = 17,
|
||||
.pre_save = cpu_pre_save,
|
||||
.post_load = cpu_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
|
@ -238,7 +238,7 @@ const VMStateDescription vmstate_arm_cpu = {
|
|||
.offset = 0,
|
||||
},
|
||||
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_r14, ARMCPU, 6),
|
||||
VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
|
||||
|
|
Loading…
Reference in New Issue