Define appropriate coprocessor registers with banked type. The register state fields are defined with BANKED_CP_REG() macro.
Banked coprocessor registers with a special behaviour is adjusted to correctly use its active or banked non-secure state. Signed-off-by: Sergey Fedorov <s.fedo...@samsung.com> --- target-arm/cpu.c | 2 +- target-arm/cpu.h | 62 +++++++++++++++++--------- target-arm/helper.c | 120 +++++++++++++++++++++++++++++---------------------- 3 files changed, 111 insertions(+), 73 deletions(-) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 4607ca8..3bb3deb 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -356,7 +356,7 @@ static void arm1026_initfn(Object *obj) /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */ ARMCPRegInfo ifar = { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1, - .access = PL1_RW, + .access = PL1_RW, .type = ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c6_insn), .resetvalue = 0 }; diff --git a/target-arm/cpu.h b/target-arm/cpu.h index fe3a646..b4500b4 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -84,6 +84,26 @@ typedef uint32_t ARMReadCPFunc(void *opaque, int cp_info, type banked_##name[2]; \ } +/* Whether a co-processor access instruction should use a banked Non-secure + * copy of a register instead of active one */ +#define USE_NS_REG(env) ( \ + unlikely( \ + ((env)->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON && \ + ((env)->cp15.c1_scr & 1/*NS*/))) +/* Get a banked CP15 register in co-processor access instruction handler */ +#define BANKED_CP15_REG_GET(env, regname) \ + (!USE_NS_REG(env) ? (env)->cp15.regname : \ + (env)->cp15.banked_##regname[1]) +/* Set a banked CP15 register in co-processor access instruction handler */ +#define BANKED_CP15_REG_SET(env, regname, val) \ + do { \ + if (!USE_NS_REG(env)) { \ + (env)->cp15.regname = (val); \ + } else { \ + (env)->cp15.banked_##regname[1] = (val); \ + } \ + } while (0) + struct arm_boot_info; #define NB_MMU_MODES 4 @@ -156,31 +176,31 @@ typedef struct CPUARMState { /* System control coprocessor (cp15) */ struct { uint32_t c0_cpuid; - uint32_t c0_cssel; /* Cache size selection. */ - uint32_t c1_sys; /* System control register. */ + BANKED_CP_REG(uint32_t, c0_cssel); /* Cache size selection. */ + BANKED_CP_REG(uint32_t, c1_sys); /* System control register. */ uint32_t c1_coproc; /* Coprocessor access register. */ uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */ uint32_t c1_scr; /* secure config register. */ uint32_t c1_sder; /* Secure debug enable register. */ uint32_t c1_nsacr; /* Non-secure access control register. */ - uint32_t c2_base0; /* MMU translation table base 0. */ - 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. */ + BANKED_CP_REG(uint32_t, c2_base0); /* MMU translation table base 0. */ + BANKED_CP_REG(uint32_t, c2_base0_hi); /* MMU translation table base 0, high 32 bits */ + BANKED_CP_REG(uint32_t, c2_base1); /* MMU translation table base 0. */ + BANKED_CP_REG(uint32_t, c2_base1_hi); /* MMU translation table base 1, high 32 bits */ + BANKED_CP_REG(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. */ uint32_t c2_data; /* MPU data cachable bits. */ uint32_t c2_insn; /* MPU instruction cachable bits. */ - uint32_t c3; /* MMU domain access control register - MPU write buffer control. */ - uint32_t c5_insn; /* Fault status registers. */ - uint32_t c5_data; + BANKED_CP_REG(uint32_t, c3); /* MMU domain access control register + MPU write buffer control. */ + BANKED_CP_REG(uint32_t, c5_insn); /* Fault status registers. */ + BANKED_CP_REG(uint32_t, c5_data); uint32_t c6_region[8]; /* MPU base/size registers. */ - 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 */ + BANKED_CP_REG(uint32_t, c6_insn); /* Fault address registers. */ + BANKED_CP_REG(uint32_t, c6_data); + BANKED_CP_REG(uint32_t, c7_par); /* Translation result. */ + BANKED_CP_REG(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 */ @@ -189,12 +209,12 @@ typedef struct CPUARMState { uint32_t c9_pmxevtyper; /* perf monitor event type */ uint32_t c9_pmuserenr; /* perf monitor user enable */ uint32_t c9_pminten; /* perf monitor interrupt enables */ - uint32_t c12_vbar; /* vector base address register */ - uint32_t c13_fcse; /* FCSE PID. */ - uint32_t c13_context; /* Context ID. */ - uint32_t c13_tls1; /* User RW Thread register. */ - uint32_t c13_tls2; /* User RO Thread register. */ - uint32_t c13_tls3; /* Privileged Thread register. */ + BANKED_CP_REG(uint32_t, c12_vbar); /* vector base address register */ + BANKED_CP_REG(uint32_t, c13_fcse); /* FCSE PID. */ + BANKED_CP_REG(uint32_t, c13_context); /* Context ID. */ + BANKED_CP_REG(uint32_t, c13_tls1); /* User RW Thread register. */ + BANKED_CP_REG(uint32_t, c13_tls2); /* User RO Thread register. */ + BANKED_CP_REG(uint32_t, c13_tls3); /* Privileged Thread register. */ uint32_t c14_cntfrq; /* Counter Frequency register */ uint32_t c14_cntkctl; /* Timer Control register */ ARMGenericTimer c14_timer[NUM_GTIMERS]; diff --git a/target-arm/helper.c b/target-arm/helper.c index c145cfe..9442e08 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -277,33 +277,34 @@ void init_cpreg_list(ARMCPU *cpu) static int dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - env->cp15.c3 = value; + BANKED_CP15_REG_SET(env, c3, value); tlb_flush(env, 1); /* Flush TLB as domain not tracked in TLB */ return 0; } static int fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - if (env->cp15.c13_fcse != value) { + if (BANKED_CP15_REG_GET(env, c13_fcse) != value) { /* Unlike real hardware the qemu TLB uses virtual addresses, * not modified virtual addresses, so this causes a TLB flush. */ tlb_flush(env, 1); - env->cp15.c13_fcse = value; + BANKED_CP15_REG_SET(env, c13_fcse, value); } return 0; } static int contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - if (env->cp15.c13_context != value && !arm_feature(env, ARM_FEATURE_MPU)) { + if (BANKED_CP15_REG_GET(env, c13_context) != value && + !arm_feature(env, ARM_FEATURE_MPU)) { /* For VMSA (when not using the LPAE long descriptor page table * format) this register includes the ASID, so do a TLB flush. * For PMSA it is purely a process ID and no action is needed. */ tlb_flush(env, 1); } - env->cp15.c13_context = value; + BANKED_CP15_REG_SET(env, c13_context, value); return 0; } @@ -349,13 +350,16 @@ static const ARMCPRegInfo cp_reginfo[] = { /* MMU Domain access control / MPU write buffer control */ { .name = "DACR", .cp = 15, .crn = 3, .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c3), + .access = PL1_RW, .type = ARM_CP_BANKED, + .fieldoffset = offsetof(CPUARMState, cp15.c3), .resetvalue = 0, .writefn = dacr_write, .raw_writefn = raw_write, }, { .name = "FCSEIDR", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse), + .access = PL1_RW, .type = ARM_CP_BANKED, + .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse), .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, }, { .name = "CONTEXTIDR", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 1, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse), + .access = PL1_RW, .type = ARM_CP_BANKED, + .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse), .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, }, /* ??? This covers not just the impdef TLB lockdown registers but also * some v7VMSA registers relating to TEX remap, so it is overly broad. @@ -455,7 +459,8 @@ static const ARMCPRegInfo v6_cp_reginfo[] = { { .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5, .access = PL0_W, .type = ARM_CP_NOP }, { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c6_insn), + .access = PL1_RW, .type = ARM_CP_BANKED, + .fieldoffset = offsetof(CPUARMState, cp15.c6_insn), .resetvalue = 0, }, /* Watchpoint Fault Address Register : should actually only be present * for 1136, 1176, 11MPCore. @@ -564,7 +569,7 @@ static int ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t *value) { ARMCPU *cpu = arm_env_get_cpu(env); - *value = cpu->ccsidr[env->cp15.c0_cssel]; + *value = cpu->ccsidr[BANKED_CP15_REG_GET(env, c0_cssel)]; return 0; } @@ -648,7 +653,8 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { { .name = "CCSIDR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0, .access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_MIGRATE }, { .name = "CSSELR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 2, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c0_cssel), + .access = PL1_RW, .type = ARM_CP_BANKED, + .fieldoffset = offsetof(CPUARMState, cp15.c0_cssel), .writefn = csselr_write, .resetvalue = 0 }, /* Auxiliary ID register: this actually has an IMPDEF value but for now * just RAZ for all cores: @@ -702,15 +708,15 @@ static const ARMCPRegInfo t2ee_cp_reginfo[] = { static const ARMCPRegInfo v6k_cp_reginfo[] = { { .name = "TPIDRURW", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 2, - .access = PL0_RW, + .access = PL0_RW, .type = ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c13_tls1), .resetvalue = 0 }, { .name = "TPIDRURO", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 3, - .access = PL0_R|PL1_W, + .access = PL0_R|PL1_W, .type = ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c13_tls2), .resetvalue = 0 }, { .name = "TPIDRPRW", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 4, - .access = PL1_RW, + .access = PL1_RW, .type = ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c13_tls3), .resetvalue = 0 }, REGINFO_SENTINEL @@ -974,11 +980,11 @@ 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_LPAE)) { - env->cp15.c7_par = value; + BANKED_CP15_REG_SET(env, c7_par, value); } else if (arm_feature(env, ARM_FEATURE_V7)) { - env->cp15.c7_par = value & 0xfffff6ff; + BANKED_CP15_REG_SET(env, c7_par, value & 0xfffff6ff); } else { - env->cp15.c7_par = value & 0xfffff1ff; + BANKED_CP15_REG_SET(env, c7_par, value & 0xfffff1ff); } return 0; } @@ -1027,8 +1033,8 @@ static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) * fault. */ } - env->cp15.c7_par = par64; - env->cp15.c7_par_hi = par64 >> 32; + BANKED_CP15_REG_SET(env, c7_par, par64); + BANKED_CP15_REG_SET(env, c7_par_hi, par64 >> 32); } else { /* ret is a DFSR/IFSR value for the short descriptor * translation table format (with WnR always clear). @@ -1038,16 +1044,17 @@ static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) /* We do not set any attribute bits in the PAR */ if (page_size == (1 << 24) && arm_feature(env, ARM_FEATURE_V7)) { - env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1; + BANKED_CP15_REG_SET(env, c7_par, + (phys_addr & 0xff000000) | 1 << 1); } else { - env->cp15.c7_par = phys_addr & 0xfffff000; + BANKED_CP15_REG_SET(env, c7_par, phys_addr & 0xfffff000); } } else { - env->cp15.c7_par = ((ret & (10 << 1)) >> 5) | + BANKED_CP15_REG_SET(env, c7_par, ((ret & (10 << 1)) >> 5) | ((ret & (12 << 1)) >> 6) | - ((ret & 0xf) << 1) | 1; + ((ret & 0xf) << 1) | 1); } - env->cp15.c7_par_hi = 0; + BANKED_CP15_REG_SET(env, c7_par_hi, 0); } return 0; } @@ -1055,7 +1062,7 @@ static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) static const ARMCPRegInfo vapa_cp_reginfo[] = { { .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .resetvalue = 0, + .access = PL1_RW, .type = ARM_CP_BANKED, .resetvalue = 0, .fieldoffset = offsetof(CPUARMState, cp15.c7_par), .writefn = par_write }, #ifndef CONFIG_USER_ONLY @@ -1145,18 +1152,18 @@ static int arm946_prbs_write(CPUARMState *env, const ARMCPRegInfo *ri, static const ARMCPRegInfo pmsav5_cp_reginfo[] = { { .name = "DATA_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .type = ARM_CP_NO_MIGRATE, + .access = PL1_RW, .type = ARM_CP_NO_MIGRATE | ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, .readfn = pmsav5_data_ap_read, .writefn = pmsav5_data_ap_write, }, { .name = "INSN_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1, - .access = PL1_RW, .type = ARM_CP_NO_MIGRATE, + .access = PL1_RW, .type = ARM_CP_NO_MIGRATE | ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0, .readfn = pmsav5_insn_ap_read, .writefn = pmsav5_insn_ap_write, }, { .name = "DATA_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 2, - .access = PL1_RW, + .access = PL1_RW, .type = ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, }, { .name = "INSN_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 3, - .access = PL1_RW, + .access = PL1_RW, .type = ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0, }, { .name = "DCACHE_CFG", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0, .access = PL1_RW, @@ -1188,9 +1195,11 @@ static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, * for long-descriptor tables the TTBCR fields are used differently * and the c2_mask and c2_base_mask values are meaningless. */ - env->cp15.c2_control = value; - env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> maskshift); - env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> maskshift); + BANKED_CP15_REG_SET(env, c2_control, value); + if (!USE_NS_REG(env)) { + env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> maskshift); + env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> maskshift); + } return 0; } @@ -1215,23 +1224,24 @@ static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri) static const ARMCPRegInfo vmsa_cp_reginfo[] = { { .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, + .access = PL1_RW, .type = ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, }, { .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1, - .access = PL1_RW, + .access = PL1_RW, .type = ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0, }, { .name = "TTBR0", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, + .access = PL1_RW, .type = ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c2_base0), .resetvalue = 0, }, { .name = "TTBR1", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1, - .access = PL1_RW, + .access = PL1_RW, .type = ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c2_base1), .resetvalue = 0, }, { .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2, - .access = PL1_RW, .writefn = vmsa_ttbcr_write, + .access = PL1_RW, .type = ARM_CP_BANKED, .writefn = vmsa_ttbcr_write, .resetfn = vmsa_ttbcr_reset, .raw_writefn = vmsa_ttbcr_raw_write, .fieldoffset = offsetof(CPUARMState, cp15.c2_control) }, { .name = "DFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c6_data), + .access = PL1_RW, .type = ARM_CP_BANKED, + .fieldoffset = offsetof(CPUARMState, cp15.c6_data), .resetvalue = 0, }, REGINFO_SENTINEL }; @@ -1274,7 +1284,8 @@ static int omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri, static const ARMCPRegInfo omap_cp_reginfo[] = { { .name = "DFSR", .cp = 15, .crn = 5, .crm = CP_ANY, - .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_OVERRIDE, + .opc1 = CP_ANY, .opc2 = CP_ANY, + .access = PL1_RW, .type = ARM_CP_OVERRIDE | ARM_CP_BANKED, .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, }, { .name = "", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0, .access = PL1_RW, .type = ARM_CP_NOP }, @@ -1427,14 +1438,16 @@ static const ARMCPRegInfo mpidr_cp_reginfo[] = { 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; + *value = BANKED_CP15_REG_GET(env, c7_par_hi); + *value <<= 32; + *value |= BANKED_CP15_REG_GET(env, 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; + BANKED_CP15_REG_SET(env, c7_par_hi, value >> 32); + BANKED_CP15_REG_SET(env, c7_par, value); return 0; } @@ -1447,15 +1460,17 @@ static void par64_reset(CPUARMState *env, const ARMCPRegInfo *ri) 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; + *value = BANKED_CP15_REG_GET(env, c2_base0_hi); + *value <<= 32; + *value |= BANKED_CP15_REG_GET(env, c2_base0); return 0; } static int ttbr064_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { - env->cp15.c2_base0_hi = value >> 32; - env->cp15.c2_base0 = value; + BANKED_CP15_REG_SET(env, c2_base0_hi, value >> 32); + BANKED_CP15_REG_SET(env, c2_base0, value); return 0; } @@ -1476,15 +1491,17 @@ static void ttbr064_reset(CPUARMState *env, const ARMCPRegInfo *ri) 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; + *value = BANKED_CP15_REG_GET(env, c2_base1_hi); + *value <<= 32; + *value |= BANKED_CP15_REG_GET(env, 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; + BANKED_CP15_REG_SET(env, c2_base1_hi, value >> 32); + BANKED_CP15_REG_SET(env, c2_base1, value); return 0; } @@ -1528,7 +1545,7 @@ static int sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) value = value | 0x00c50078; /* This bits are RAO/WI */ } - env->cp15.c1_sys = value; + BANKED_CP15_REG_SET(env, c1_sys, value); /* ??? Lots of these bits are not implemented. */ /* This may enable/disable the MMU, so do a TLB flush. */ tlb_flush(env, 1); @@ -1557,7 +1574,7 @@ static const ARMCPRegInfo tz_cp_reginfo[] = { .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_scr), .resetvalue = 0 }, { .name = "VBAR", .cp = 15, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .writefn = vbar_write, + .access = PL1_RW, .type = ARM_CP_BANKED, .writefn = vbar_write, .fieldoffset = offsetof(CPUARMState, cp15.c12_vbar), .resetvalue = 0 }, { .name = "SDER", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 1, @@ -1795,7 +1812,8 @@ void register_cp_regs_for_features(ARMCPU *cpu) { ARMCPRegInfo sctlr = { .name = "SCTLR", .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_sys), + .access = PL1_RW, .type = ARM_CP_BANKED, + .fieldoffset = offsetof(CPUARMState, cp15.c1_sys), .writefn = sctlr_write, .resetvalue = cpu->reset_sctlr, .raw_writefn = raw_write, }; -- 1.7.9.5