Skip to content

Commit

Permalink
target-arm: Implement AArch64 SPSR_EL1
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
pm215 committed Apr 17, 2014
1 parent f502cfc commit a65f1de
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 11 deletions.
2 changes: 1 addition & 1 deletion target-arm/cpu.h
Expand Up @@ -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];

Expand Down
4 changes: 4 additions & 0 deletions target-arm/helper.c
Expand Up @@ -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.
Expand Down
18 changes: 13 additions & 5 deletions target-arm/kvm32.c
Expand Up @@ -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]),
Expand All @@ -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]),
Expand All @@ -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 */
Expand Down
19 changes: 18 additions & 1 deletion target-arm/kvm64.c
Expand Up @@ -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, &reg);
if (ret) {
return ret;
}
}

/* TODO:
* SPSR[]
* FP state
* system registers
*/
Expand Down Expand Up @@ -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, &reg);
if (ret) {
return ret;
}
}

/* TODO: other registers */
return ret;
}
Expand Down
8 changes: 4 additions & 4 deletions target-arm/machine.c
Expand Up @@ -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[]) {
Expand All @@ -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),
Expand Down

0 comments on commit a65f1de

Please sign in to comment.