aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-arm/cpu.h7
-rw-r--r--target-arm/helper.c77
-rw-r--r--target-arm/machine.c6
3 files changed, 87 insertions, 3 deletions
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 3c5d2be1c1..191895cca8 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -113,7 +113,9 @@ typedef struct CPUARMState {
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
uint32_t c1_scr; /* secure config register. */
uint32_t c2_base0; /* MMU translation table base 0. */
- uint32_t c2_base1; /* MMU translation table base 1. */
+ uint32_t c2_base0_hi; /* MMU translation table base 0, high 32 bits */
+ uint32_t c2_base1; /* MMU translation table base 0. */
+ uint32_t c2_base1_hi; /* MMU translation table base 1, high 32 bits */
uint32_t c2_control; /* MMU translation table base control. */
uint32_t c2_mask; /* MMU translation table base selection mask. */
uint32_t c2_base_mask; /* MMU translation table base 0 mask. */
@@ -127,6 +129,7 @@ typedef struct CPUARMState {
uint32_t c6_insn; /* Fault address registers. */
uint32_t c6_data;
uint32_t c7_par; /* Translation result. */
+ uint32_t c7_par_hi; /* Translation result, high 32 bits */
uint32_t c9_insn; /* Cache lockdown registers. */
uint32_t c9_data;
uint32_t c9_pmcr; /* performance monitor control register */
@@ -638,7 +641,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
#define cpu_signal_handler cpu_arm_signal_handler
#define cpu_list arm_cpu_list
-#define CPU_SAVE_VERSION 8
+#define CPU_SAVE_VERSION 9
/* MMU modes definitions */
#define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 0cf7b8dd77..6bb6767bc2 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -491,7 +491,9 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
static int par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
- if (arm_feature(env, ARM_FEATURE_V7)) {
+ if (arm_feature(env, ARM_FEATURE_LPAE)) {
+ env->cp15.c7_par = value;
+ } else if (arm_feature(env, ARM_FEATURE_V7)) {
env->cp15.c7_par = value & 0xfffff6ff;
} else {
env->cp15.c7_par = value & 0xfffff1ff;
@@ -528,6 +530,7 @@ static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
((ret & (12 << 1)) >> 6) |
((ret & 0xf) << 1) | 1;
}
+ env->cp15.c7_par_hi = 0;
return 0;
}
#endif
@@ -871,6 +874,69 @@ static const ARMCPRegInfo mpidr_cp_reginfo[] = {
REGINFO_SENTINEL
};
+static int par64_read(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t *value)
+{
+ *value = ((uint64_t)env->cp15.c7_par_hi << 32) | env->cp15.c7_par;
+ return 0;
+}
+
+static int par64_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+ env->cp15.c7_par_hi = value >> 32;
+ env->cp15.c7_par = value;
+ return 0;
+}
+
+static void par64_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ env->cp15.c7_par_hi = 0;
+ env->cp15.c7_par = 0;
+}
+
+static int ttbr064_read(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+ *value = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0;
+ return 0;
+}
+
+static int ttbr064_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->cp15.c2_base0_hi = value >> 32;
+ env->cp15.c2_base0 = value;
+ /* Writes to the 64 bit format TTBRs may change the ASID */
+ tlb_flush(env, 1);
+ return 0;
+}
+
+static void ttbr064_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ env->cp15.c2_base0_hi = 0;
+ env->cp15.c2_base0 = 0;
+}
+
+static int ttbr164_read(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+ *value = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1;
+ return 0;
+}
+
+static int ttbr164_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->cp15.c2_base1_hi = value >> 32;
+ env->cp15.c2_base1 = value;
+ return 0;
+}
+
+static void ttbr164_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ env->cp15.c2_base1_hi = 0;
+ env->cp15.c2_base1 = 0;
+}
+
static const ARMCPRegInfo lpae_cp_reginfo[] = {
/* NOP AMAIR0/1: the override is because these clash with tha rather
* broadly specified TLB_LOCKDOWN entry in the generic cp_reginfo.
@@ -886,6 +952,15 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
{ .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0,
.access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
+ { .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0,
+ .access = PL1_RW, .type = ARM_CP_64BIT,
+ .readfn = par64_read, .writefn = par64_write, .resetfn = par64_reset },
+ { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0,
+ .access = PL1_RW, .type = ARM_CP_64BIT, .readfn = ttbr064_read,
+ .writefn = ttbr064_write, .resetfn = ttbr064_reset },
+ { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
+ .access = PL1_RW, .type = ARM_CP_64BIT, .readfn = ttbr164_read,
+ .writefn = ttbr164_write, .resetfn = ttbr164_reset },
REGINFO_SENTINEL
};
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 429cbc8bcb..68dca7ffb2 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -27,7 +27,9 @@ void cpu_save(QEMUFile *f, void *opaque)
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);
@@ -42,6 +44,7 @@ void cpu_save(QEMUFile *f, void *opaque)
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);
@@ -144,7 +147,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
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);
@@ -159,6 +164,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
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);