qemu/target-arm/machine.c
Peter Maydell 891a2fe720 target-arm: Add 64 bit PAR, TTBR0, TTBR1 for LPAE
Under LPAE, the cp15 registers PAR, TTBR0 and TTBR1 are extended
to 64 bits, with a 64 bit (MRRC/MCRR) access path to read the
full width of the register. Add the state fields for the top
half and the 64 bit access path. Actual use of the top half of
the register will come with the addition of the long-descriptor
translation table format support.

For the PAR we also need to correct the masking applied for
32 bit writes (there are no bits reserved if LPAE is implemented)
and clear the high half when doing a 32 bit result VA-to-PA
lookup.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2012-07-12 10:59:54 +00:00

238 lines
7.8 KiB
C

#include "hw/hw.h"
#include "hw/boards.h"
void cpu_save(QEMUFile *f, void *opaque)
{
int i;
CPUARMState *env = (CPUARMState *)opaque;
for (i = 0; i < 16; i++) {
qemu_put_be32(f, env->regs[i]);
}
qemu_put_be32(f, cpsr_read(env));
qemu_put_be32(f, env->spsr);
for (i = 0; i < 6; i++) {
qemu_put_be32(f, env->banked_spsr[i]);
qemu_put_be32(f, env->banked_r13[i]);
qemu_put_be32(f, env->banked_r14[i]);
}
for (i = 0; i < 5; i++) {
qemu_put_be32(f, env->usr_regs[i]);
qemu_put_be32(f, env->fiq_regs[i]);
}
qemu_put_be32(f, env->cp15.c0_cpuid);
qemu_put_be32(f, env->cp15.c0_cssel);
qemu_put_be32(f, env->cp15.c1_sys);
qemu_put_be32(f, env->cp15.c1_coproc);
qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
qemu_put_be32(f, env->cp15.c1_scr);
qemu_put_be32(f, env->cp15.c2_base0);
qemu_put_be32(f, env->cp15.c2_base0_hi);
qemu_put_be32(f, env->cp15.c2_base1);
qemu_put_be32(f, env->cp15.c2_base1_hi);
qemu_put_be32(f, env->cp15.c2_control);
qemu_put_be32(f, env->cp15.c2_mask);
qemu_put_be32(f, env->cp15.c2_base_mask);
qemu_put_be32(f, env->cp15.c2_data);
qemu_put_be32(f, env->cp15.c2_insn);
qemu_put_be32(f, env->cp15.c3);
qemu_put_be32(f, env->cp15.c5_insn);
qemu_put_be32(f, env->cp15.c5_data);
for (i = 0; i < 8; i++) {
qemu_put_be32(f, env->cp15.c6_region[i]);
}
qemu_put_be32(f, env->cp15.c6_insn);
qemu_put_be32(f, env->cp15.c6_data);
qemu_put_be32(f, env->cp15.c7_par);
qemu_put_be32(f, env->cp15.c7_par_hi);
qemu_put_be32(f, env->cp15.c9_insn);
qemu_put_be32(f, env->cp15.c9_data);
qemu_put_be32(f, env->cp15.c9_pmcr);
qemu_put_be32(f, env->cp15.c9_pmcnten);
qemu_put_be32(f, env->cp15.c9_pmovsr);
qemu_put_be32(f, env->cp15.c9_pmxevtyper);
qemu_put_be32(f, env->cp15.c9_pmuserenr);
qemu_put_be32(f, env->cp15.c9_pminten);
qemu_put_be32(f, env->cp15.c13_fcse);
qemu_put_be32(f, env->cp15.c13_context);
qemu_put_be32(f, env->cp15.c13_tls1);
qemu_put_be32(f, env->cp15.c13_tls2);
qemu_put_be32(f, env->cp15.c13_tls3);
qemu_put_be32(f, env->cp15.c15_cpar);
qemu_put_be32(f, env->cp15.c15_power_control);
qemu_put_be32(f, env->cp15.c15_diagnostic);
qemu_put_be32(f, env->cp15.c15_power_diagnostic);
qemu_put_be64(f, env->features);
if (arm_feature(env, ARM_FEATURE_VFP)) {
for (i = 0; i < 16; i++) {
CPU_DoubleU u;
u.d = env->vfp.regs[i];
qemu_put_be32(f, u.l.upper);
qemu_put_be32(f, u.l.lower);
}
for (i = 0; i < 16; i++) {
qemu_put_be32(f, env->vfp.xregs[i]);
}
/* TODO: Should use proper FPSCR access functions. */
qemu_put_be32(f, env->vfp.vec_len);
qemu_put_be32(f, env->vfp.vec_stride);
if (arm_feature(env, ARM_FEATURE_VFP3)) {
for (i = 16; i < 32; i++) {
CPU_DoubleU u;
u.d = env->vfp.regs[i];
qemu_put_be32(f, u.l.upper);
qemu_put_be32(f, u.l.lower);
}
}
}
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
for (i = 0; i < 16; i++) {
qemu_put_be64(f, env->iwmmxt.regs[i]);
}
for (i = 0; i < 16; i++) {
qemu_put_be32(f, env->iwmmxt.cregs[i]);
}
}
if (arm_feature(env, ARM_FEATURE_M)) {
qemu_put_be32(f, env->v7m.other_sp);
qemu_put_be32(f, env->v7m.vecbase);
qemu_put_be32(f, env->v7m.basepri);
qemu_put_be32(f, env->v7m.control);
qemu_put_be32(f, env->v7m.current_sp);
qemu_put_be32(f, env->v7m.exception);
}
if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
qemu_put_be32(f, env->teecr);
qemu_put_be32(f, env->teehbr);
}
}
int cpu_load(QEMUFile *f, void *opaque, int version_id)
{
CPUARMState *env = (CPUARMState *)opaque;
int i;
uint32_t val;
if (version_id != CPU_SAVE_VERSION)
return -EINVAL;
for (i = 0; i < 16; i++) {
env->regs[i] = qemu_get_be32(f);
}
val = qemu_get_be32(f);
/* Avoid mode switch when restoring CPSR. */
env->uncached_cpsr = val & CPSR_M;
cpsr_write(env, val, 0xffffffff);
env->spsr = qemu_get_be32(f);
for (i = 0; i < 6; i++) {
env->banked_spsr[i] = qemu_get_be32(f);
env->banked_r13[i] = qemu_get_be32(f);
env->banked_r14[i] = qemu_get_be32(f);
}
for (i = 0; i < 5; i++) {
env->usr_regs[i] = qemu_get_be32(f);
env->fiq_regs[i] = qemu_get_be32(f);
}
env->cp15.c0_cpuid = qemu_get_be32(f);
env->cp15.c0_cssel = qemu_get_be32(f);
env->cp15.c1_sys = qemu_get_be32(f);
env->cp15.c1_coproc = qemu_get_be32(f);
env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
env->cp15.c1_scr = qemu_get_be32(f);
env->cp15.c2_base0 = qemu_get_be32(f);
env->cp15.c2_base0_hi = qemu_get_be32(f);
env->cp15.c2_base1 = qemu_get_be32(f);
env->cp15.c2_base1_hi = qemu_get_be32(f);
env->cp15.c2_control = qemu_get_be32(f);
env->cp15.c2_mask = qemu_get_be32(f);
env->cp15.c2_base_mask = qemu_get_be32(f);
env->cp15.c2_data = qemu_get_be32(f);
env->cp15.c2_insn = qemu_get_be32(f);
env->cp15.c3 = qemu_get_be32(f);
env->cp15.c5_insn = qemu_get_be32(f);
env->cp15.c5_data = qemu_get_be32(f);
for (i = 0; i < 8; i++) {
env->cp15.c6_region[i] = qemu_get_be32(f);
}
env->cp15.c6_insn = qemu_get_be32(f);
env->cp15.c6_data = qemu_get_be32(f);
env->cp15.c7_par = qemu_get_be32(f);
env->cp15.c7_par_hi = qemu_get_be32(f);
env->cp15.c9_insn = qemu_get_be32(f);
env->cp15.c9_data = qemu_get_be32(f);
env->cp15.c9_pmcr = qemu_get_be32(f);
env->cp15.c9_pmcnten = qemu_get_be32(f);
env->cp15.c9_pmovsr = qemu_get_be32(f);
env->cp15.c9_pmxevtyper = qemu_get_be32(f);
env->cp15.c9_pmuserenr = qemu_get_be32(f);
env->cp15.c9_pminten = qemu_get_be32(f);
env->cp15.c13_fcse = qemu_get_be32(f);
env->cp15.c13_context = qemu_get_be32(f);
env->cp15.c13_tls1 = qemu_get_be32(f);
env->cp15.c13_tls2 = qemu_get_be32(f);
env->cp15.c13_tls3 = qemu_get_be32(f);
env->cp15.c15_cpar = qemu_get_be32(f);
env->cp15.c15_power_control = qemu_get_be32(f);
env->cp15.c15_diagnostic = qemu_get_be32(f);
env->cp15.c15_power_diagnostic = qemu_get_be32(f);
env->features = qemu_get_be64(f);
if (arm_feature(env, ARM_FEATURE_VFP)) {
for (i = 0; i < 16; i++) {
CPU_DoubleU u;
u.l.upper = qemu_get_be32(f);
u.l.lower = qemu_get_be32(f);
env->vfp.regs[i] = u.d;
}
for (i = 0; i < 16; i++) {
env->vfp.xregs[i] = qemu_get_be32(f);
}
/* TODO: Should use proper FPSCR access functions. */
env->vfp.vec_len = qemu_get_be32(f);
env->vfp.vec_stride = qemu_get_be32(f);
if (arm_feature(env, ARM_FEATURE_VFP3)) {
for (i = 16; i < 32; i++) {
CPU_DoubleU u;
u.l.upper = qemu_get_be32(f);
u.l.lower = qemu_get_be32(f);
env->vfp.regs[i] = u.d;
}
}
}
if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
for (i = 0; i < 16; i++) {
env->iwmmxt.regs[i] = qemu_get_be64(f);
}
for (i = 0; i < 16; i++) {
env->iwmmxt.cregs[i] = qemu_get_be32(f);
}
}
if (arm_feature(env, ARM_FEATURE_M)) {
env->v7m.other_sp = qemu_get_be32(f);
env->v7m.vecbase = qemu_get_be32(f);
env->v7m.basepri = qemu_get_be32(f);
env->v7m.control = qemu_get_be32(f);
env->v7m.current_sp = qemu_get_be32(f);
env->v7m.exception = qemu_get_be32(f);
}
if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
env->teecr = qemu_get_be32(f);
env->teehbr = qemu_get_be32(f);
}
return 0;
}