diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 6190091f20..f8534a78b3 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -220,6 +220,8 @@ static void arm926_initfn(Object *obj) ARMCPU *cpu = ARM_CPU(obj); set_feature(&cpu->env, ARM_FEATURE_V5); set_feature(&cpu->env, ARM_FEATURE_VFP); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); + set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN); cpu->midr = ARM_CPUID_ARM926; cpu->reset_fpsid = 0x41011090; cpu->ctr = 0x1dd20d2; @@ -231,6 +233,7 @@ static void arm946_initfn(Object *obj) ARMCPU *cpu = ARM_CPU(obj); set_feature(&cpu->env, ARM_FEATURE_V5); set_feature(&cpu->env, ARM_FEATURE_MPU); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); cpu->midr = ARM_CPUID_ARM946; cpu->ctr = 0x0f004006; cpu->reset_sctlr = 0x00000078; @@ -242,6 +245,8 @@ static void arm1026_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_V5); set_feature(&cpu->env, ARM_FEATURE_VFP); set_feature(&cpu->env, ARM_FEATURE_AUXCR); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); + set_feature(&cpu->env, ARM_FEATURE_CACHE_TEST_CLEAN); cpu->midr = ARM_CPUID_ARM1026; cpu->reset_fpsid = 0x410110a0; cpu->ctr = 0x1dd20d2; @@ -260,6 +265,9 @@ static void arm1136_r2_initfn(Object *obj) */ set_feature(&cpu->env, ARM_FEATURE_V6); set_feature(&cpu->env, ARM_FEATURE_VFP); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); + set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG); + set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); cpu->midr = ARM_CPUID_ARM1136_R2; cpu->reset_fpsid = 0x410120b4; cpu->mvfr0 = 0x11111111; @@ -286,6 +294,9 @@ static void arm1136_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_V6K); set_feature(&cpu->env, ARM_FEATURE_V6); set_feature(&cpu->env, ARM_FEATURE_VFP); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); + set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG); + set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); cpu->midr = ARM_CPUID_ARM1136; cpu->reset_fpsid = 0x410120b4; cpu->mvfr0 = 0x11111111; @@ -312,6 +323,9 @@ static void arm1176_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_V6K); set_feature(&cpu->env, ARM_FEATURE_VFP); set_feature(&cpu->env, ARM_FEATURE_VAPA); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); + set_feature(&cpu->env, ARM_FEATURE_CACHE_DIRTY_REG); + set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); cpu->midr = ARM_CPUID_ARM1176; cpu->reset_fpsid = 0x410120b5; cpu->mvfr0 = 0x11111111; @@ -338,6 +352,7 @@ static void arm11mpcore_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_V6K); set_feature(&cpu->env, ARM_FEATURE_VFP); set_feature(&cpu->env, ARM_FEATURE_VAPA); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); cpu->midr = ARM_CPUID_ARM11MPCORE; cpu->reset_fpsid = 0x410120b4; cpu->mvfr0 = 0x11111111; @@ -372,6 +387,7 @@ static void cortex_a8_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_VFP3); set_feature(&cpu->env, ARM_FEATURE_NEON); set_feature(&cpu->env, ARM_FEATURE_THUMB2EE); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); cpu->midr = ARM_CPUID_CORTEXA8; cpu->reset_fpsid = 0x410330c0; cpu->mvfr0 = 0x11110222; @@ -483,6 +499,7 @@ static void cortex_a15_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_ARM_DIV); set_feature(&cpu->env, ARM_FEATURE_V7MP); set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); cpu->midr = ARM_CPUID_CORTEXA15; cpu->reset_fpsid = 0x410430f0; cpu->mvfr0 = 0x10110222; @@ -522,6 +539,7 @@ static void sa1100_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); set_feature(&cpu->env, ARM_FEATURE_STRONGARM); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); cpu->midr = ARM_CPUID_SA1100; cpu->reset_sctlr = 0x00000070; } @@ -530,6 +548,7 @@ static void sa1110_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); set_feature(&cpu->env, ARM_FEATURE_STRONGARM); + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); cpu->midr = ARM_CPUID_SA1110; cpu->reset_sctlr = 0x00000070; } diff --git a/target-arm/cpu.h b/target-arm/cpu.h index b94503d774..02d86ca8aa 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -387,6 +387,9 @@ enum arm_features { ARM_FEATURE_GENERIC_TIMER, ARM_FEATURE_MVFR, /* Media and VFP Feature Registers 0 and 1 */ ARM_FEATURE_DUMMY_C15_REGS, /* RAZ/WI all of cp15 crn=15 */ + ARM_FEATURE_CACHE_TEST_CLEAN, /* 926/1026 style test-and-clean ops */ + ARM_FEATURE_CACHE_DIRTY_REG, /* 1136/1176 cache dirty status register */ + ARM_FEATURE_CACHE_BLOCK_OPS, /* v6 optional cache block operations */ }; static inline int arm_feature(CPUARMState *env, int feature) diff --git a/target-arm/helper.c b/target-arm/helper.c index b7fc2dbf0f..907ccbf9e6 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -161,6 +161,10 @@ static const ARMCPRegInfo cp_reginfo[] = { .opc1 = CP_ANY, .opc2 = 2, .access = PL1_W, .writefn = tlbiasid_write, }, { .name = "TLBIMVAA", .cp = 15, .crn = 8, .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = 3, .access = PL1_W, .writefn = tlbimvaa_write, }, + /* Cache maintenance ops; some of this space may be overridden later. */ + { .name = "CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY, + .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W, + .type = ARM_CP_NOP | ARM_CP_OVERRIDE }, REGINFO_SENTINEL }; @@ -622,6 +626,17 @@ static int omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri, return 0; } +static int omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* On OMAP there are registers indicating the max/min index of dcache lines + * containing a dirty line; cache flush operations have to reset these. + */ + env->cp15.c15_i_max = 0x000; + env->cp15.c15_i_min = 0xff0; + return 0; +} + 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, @@ -650,6 +665,9 @@ static const ARMCPRegInfo omap_cp_reginfo[] = { * base address at $rn & ~0xfff and map size of 0x200 << ($rn & 0xfff), * when MMU is off. */ + { .name = "OMAP_CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY, + .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W, .type = ARM_CP_OVERRIDE, + .writefn = omap_cachemaint_write }, REGINFO_SENTINEL }; @@ -685,6 +703,31 @@ static const ARMCPRegInfo dummy_c15_cp_reginfo[] = { REGINFO_SENTINEL }; +static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = { + /* Cache status: RAZ because we have no cache so it's always clean */ + { .name = "CDSR", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 6, + .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 }, + REGINFO_SENTINEL +}; + +static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = { + /* We never have a a block transfer operation in progress */ + { .name = "BXSR", .cp = 15, .crn = 7, .crm = 12, .opc1 = 0, .opc2 = 4, + .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 }, + REGINFO_SENTINEL +}; + +static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = { + /* The cache test-and-clean instructions always return (1 << 30) + * to indicate that there are no dirty cache lines. + */ + { .name = "TC_DCACHE", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 3, + .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = (1 << 30) }, + { .name = "TCI_DCACHE", .cp = 15, .crn = 7, .crm = 14, .opc1 = 0, .opc2 = 3, + .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = (1 << 30) }, + REGINFO_SENTINEL +}; + void register_cp_regs_for_features(ARMCPU *cpu) { /* Register all the coprocessor registers based on feature bits */ @@ -738,6 +781,15 @@ void register_cp_regs_for_features(ARMCPU *cpu) if (arm_feature(env, ARM_FEATURE_VAPA)) { define_arm_cp_regs(cpu, vapa_cp_reginfo); } + if (arm_feature(env, ARM_FEATURE_CACHE_TEST_CLEAN)) { + define_arm_cp_regs(cpu, cache_test_clean_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_CACHE_DIRTY_REG)) { + define_arm_cp_regs(cpu, cache_dirty_status_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_CACHE_BLOCK_OPS)) { + define_arm_cp_regs(cpu, cache_block_ops_cp_reginfo); + } if (arm_feature(env, ARM_FEATURE_OMAPCP)) { define_arm_cp_regs(cpu, omap_cp_reginfo); } @@ -1896,13 +1948,6 @@ void HELPER(set_cp15)(CPUARMState *env, uint32_t insn, uint32_t val) } } break; - case 7: /* Cache control. */ - env->cp15.c15_i_max = 0x000; - env->cp15.c15_i_min = 0xff0; - if (op1 != 0) { - goto bad_reg; - } - break; case 9: if (arm_feature(env, ARM_FEATURE_OMAPCP)) break; @@ -2108,10 +2153,6 @@ uint32_t HELPER(get_cp15)(CPUARMState *env, uint32_t insn) goto bad_reg; } } - case 7: /* Cache control. */ - /* FIXME: Should only clear Z flag if destination is r15. */ - env->ZF = 0; - return 0; case 9: switch (crm) { case 0: /* Cache lockdown */