target-microblaze: Preserve the pvr registers during reset

Move the Microblaze PVR registers to the end of the CPUMBState
and preserve them during reset. This is similar to what the
QEMU ARM model does with some of it's registers.

This allows the Microblaze PVR registers to only be set once
at realise instead of constantly at reset.

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 67e3182..95be540 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -63,13 +63,34 @@
 
     mcc->parent_reset(s);
 
-    memset(env, 0, sizeof(CPUMBState));
+    memset(env, 0, offsetof(CPUMBState, pvr));
     env->res_addr = RES_ADDR_NONE;
     tlb_flush(s, 1);
 
     /* Disable stack protector.  */
     env->shr = ~0;
 
+#if defined(CONFIG_USER_ONLY)
+    /* start in user mode with interrupts enabled.  */
+    env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM;
+#else
+    env->sregs[SR_MSR] = 0;
+    mmu_init(&env->mmu);
+    env->mmu.c_mmu = 3;
+    env->mmu.c_mmu_tlb_access = 3;
+    env->mmu.c_mmu_zones = 16;
+#endif
+}
+
+static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
+{
+    CPUState *cs = CPU(dev);
+    MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(dev);
+    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+    CPUMBState *env = &cpu->env;
+
+    qemu_init_vcpu(cs);
+
     env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
                        | PVR0_USE_BARREL_MASK \
                        | PVR0_USE_DIV_MASK \
@@ -99,25 +120,8 @@
     env->sregs[SR_PC] = cpu->base_vectors;
 
 #if defined(CONFIG_USER_ONLY)
-    /* start in user mode with interrupts enabled.  */
-    env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM;
     env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp.  */
-#else
-    env->sregs[SR_MSR] = 0;
-    mmu_init(&env->mmu);
-    env->mmu.c_mmu = 3;
-    env->mmu.c_mmu_tlb_access = 3;
-    env->mmu.c_mmu_zones = 16;
 #endif
-}
-
-static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
-{
-    CPUState *cs = CPU(dev);
-    MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(dev);
-
-    cpu_reset(cs);
-    qemu_init_vcpu(cs);
 
     mcc->parent_realize(dev, errp);
 }
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index d73e1c7..534e1cf 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -260,16 +260,18 @@
 #define IFLAGS_TB_MASK  (D_FLAG | IMM_FLAG | DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)
     uint32_t iflags;
 
-    struct {
-        uint32_t regs[16];
-    } pvr;
-
 #if !defined(CONFIG_USER_ONLY)
     /* Unified MMU.  */
     struct microblaze_mmu mmu;
 #endif
 
     CPU_COMMON
+
+    /* These fields are preserved on reset.  */
+
+    struct {
+        uint32_t regs[16];
+    } pvr;
 };
 
 #include "cpu-qom.h"