From 755026728abb19fba70e6b4396a27fa2e7550d74 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Feb 2016 14:16:15 +0000 Subject: target-arm: correct CNTFRQ access rights Correct some corner cases we were getting wrong for CNTFRQ access rights: * should UNDEF from 32-bit Secure EL1 * only writable from the highest implemented exception level, which might not be EL1 now To clarify the code, provide a new utility function arm_highest_el() which returns the highest implemented exception level. Signed-off-by: Peter Maydell Reviewed-by: Sergey Fedorov Reviewed-by: Edgar E. Iglesias --- target-arm/helper.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'target-arm/helper.c') diff --git a/target-arm/helper.c b/target-arm/helper.c index 2f9db72806..4d27c004d8 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1218,10 +1218,33 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = { static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri, bool isread) { - /* CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero */ - if (arm_current_el(env) == 0 && !extract32(env->cp15.c14_cntkctl, 0, 2)) { - return CP_ACCESS_TRAP; + /* CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero. + * Writable only at the highest implemented exception level. + */ + int el = arm_current_el(env); + + switch (el) { + case 0: + if (!extract32(env->cp15.c14_cntkctl, 0, 2)) { + return CP_ACCESS_TRAP; + } + break; + case 1: + if (!isread && ri->state == ARM_CP_STATE_AA32 && + arm_is_secure_below_el3(env)) { + /* Accesses from 32-bit Secure EL1 UNDEF (*not* trap to EL3!) */ + return CP_ACCESS_TRAP_UNCATEGORIZED; + } + break; + case 2: + case 3: + break; } + + if (!isread && el < arm_highest_el(env)) { + return CP_ACCESS_TRAP_UNCATEGORIZED; + } + return CP_ACCESS_OK; } -- cgit 1.4.1 From 187f678d5c28251dba2b44127e59966b14518ef7 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Feb 2016 14:16:15 +0000 Subject: target-arm: Implement MDCR_EL3.TDOSA and MDCR_EL2.TDOSA traps Implement the traps to EL2 and EL3 controlled by the bits MDCR_EL2.TDOSA MDCR_EL3.TDOSA. These can configurably trap accesses to the "powerdown debug" registers. Signed-off-by: Peter Maydell Reviewed-by: Sergey Fedorov --- target-arm/cpu.h | 12 ++++++++++++ target-arm/helper.c | 23 ++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'target-arm/helper.c') diff --git a/target-arm/cpu.h b/target-arm/cpu.h index afbf3661eb..77f9b51b76 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -595,6 +595,18 @@ void pmccntr_sync(CPUARMState *env); #define CPTR_TTA (1U << 20) #define CPTR_TFP (1U << 10) +#define MDCR_EPMAD (1U << 21) +#define MDCR_EDAD (1U << 20) +#define MDCR_SPME (1U << 17) +#define MDCR_SDD (1U << 16) +#define MDCR_TDRA (1U << 11) +#define MDCR_TDOSA (1U << 10) +#define MDCR_TDA (1U << 9) +#define MDCR_TDE (1U << 8) +#define MDCR_HPME (1U << 7) +#define MDCR_TPM (1U << 6) +#define MDCR_TPMCR (1U << 5) + #define CPSR_M (0x1fU) #define CPSR_T (1U << 5) #define CPSR_F (1U << 6) diff --git a/target-arm/helper.c b/target-arm/helper.c index 4d27c004d8..b45d596982 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -385,6 +385,24 @@ static CPAccessResult access_trap_aa32s_el1(CPUARMState *env, return CP_ACCESS_TRAP_UNCATEGORIZED; } +/* Check for traps to "powerdown debug" registers, which are controlled + * by MDCR.TDOSA + */ +static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + int el = arm_current_el(env); + + if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TDOSA) + && !arm_is_secure_below_el3(env)) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { ARMCPU *cpu = arm_env_get_cpu(env); @@ -3778,15 +3796,18 @@ static const ARMCPRegInfo debug_cp_reginfo[] = { { .name = "OSLAR_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4, .access = PL1_W, .type = ARM_CP_NO_RAW, + .accessfn = access_tdosa, .writefn = oslar_write }, { .name = "OSLSR_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 4, .access = PL1_R, .resetvalue = 10, + .accessfn = access_tdosa, .fieldoffset = offsetof(CPUARMState, cp15.oslsr_el1) }, /* Dummy OSDLR_EL1: 32-bit Linux will read this */ { .name = "OSDLR_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 4, - .access = PL1_RW, .type = ARM_CP_NOP }, + .access = PL1_RW, .accessfn = access_tdosa, + .type = ARM_CP_NOP }, /* Dummy DBGVCR: Linux wants to clear this on startup, but we don't * implement vector catch debug events yet. */ -- cgit 1.4.1 From 91b0a23865558e2ce9c2e7042d404e8bf2e4b817 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Feb 2016 14:16:15 +0000 Subject: target-arm: Implement MDCR_EL2.TDRA traps Implement trapping of the "debug ROM" registers, which are controlled by MDCR_EL2.TDRA for EL2 but by the more general MDCR_EL3.TDA for EL3. Signed-off-by: Peter Maydell Reviewed-by: Sergey Fedorov --- target-arm/helper.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'target-arm/helper.c') diff --git a/target-arm/helper.c b/target-arm/helper.c index b45d596982..11eb77ab10 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -403,6 +403,24 @@ static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *ri, return CP_ACCESS_OK; } +/* Check for traps to "debug ROM" registers, which are controlled + * by MDCR_EL2.TDRA for EL2 but by the more general MDCR_EL3.TDA for EL3. + */ +static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + int el = arm_current_el(env); + + if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TDRA) + && !arm_is_secure_below_el3(env)) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { ARMCPU *cpu = arm_env_get_cpu(env); @@ -3773,12 +3791,15 @@ static const ARMCPRegInfo debug_cp_reginfo[] = { * accessor. */ { .name = "DBGDRAR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 }, + .access = PL0_R, .accessfn = access_tdra, + .type = ARM_CP_CONST, .resetvalue = 0 }, { .name = "MDRAR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0, - .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 }, + .access = PL1_R, .accessfn = access_tdra, + .type = ARM_CP_CONST, .resetvalue = 0 }, { .name = "DBGDSAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 }, + .access = PL0_R, .accessfn = access_tdra, + .type = ARM_CP_CONST, .resetvalue = 0 }, /* Monitor debug system control register; the 32-bit alias is DBGDSCRext. */ { .name = "MDSCR_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2, -- cgit 1.4.1 From d6c8cf815171e35e0b1ef4e0cff602ab3d575747 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Feb 2016 14:16:15 +0000 Subject: target-arm: Implement MDCR_EL3.TDA and MDCR_EL2.TDA traps Implement the debug register traps controlled by MDCR_EL2.TDA and MDCR_EL3.TDA. Signed-off-by: Peter Maydell Reviewed-by: Sergey Fedorov --- target-arm/helper.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'target-arm/helper.c') diff --git a/target-arm/helper.c b/target-arm/helper.c index 11eb77ab10..e2b72389be 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -421,6 +421,24 @@ static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri, return CP_ACCESS_OK; } +/* Check for traps to general debug registers, which are controlled + * by MDCR_EL2.TDA for EL2 and MDCR_EL3.TDA for EL3. + */ +static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + int el = arm_current_el(env); + + if (el < 2 && (env->cp15.mdcr_el2 & MDCR_TDA) + && !arm_is_secure_below_el3(env)) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { ARMCPU *cpu = arm_env_get_cpu(env); @@ -3384,7 +3402,8 @@ static const ARMCPRegInfo el3_no_el2_cp_reginfo[] = { .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, { .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1, - .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + .access = PL2_RW, .accessfn = access_tda, + .type = ARM_CP_CONST, .resetvalue = 0 }, { .name = "HPFAR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 4, .access = PL2_RW, .accessfn = access_el3_aa32ns_aa64any, @@ -3803,7 +3822,7 @@ static const ARMCPRegInfo debug_cp_reginfo[] = { /* Monitor debug system control register; the 32-bit alias is DBGDSCRext. */ { .name = "MDSCR_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2, - .access = PL1_RW, + .access = PL1_RW, .accessfn = access_tda, .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), .resetvalue = 0 }, /* MDCCSR_EL0, aka DBGDSCRint. This is a read-only mirror of MDSCR_EL1. @@ -3812,7 +3831,7 @@ static const ARMCPRegInfo debug_cp_reginfo[] = { { .name = "MDCCSR_EL0", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0, .type = ARM_CP_ALIAS, - .access = PL1_R, + .access = PL1_R, .accessfn = access_tda, .fieldoffset = offsetof(CPUARMState, cp15.mdscr_el1), }, { .name = "OSLAR_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4, @@ -3834,7 +3853,8 @@ static const ARMCPRegInfo debug_cp_reginfo[] = { */ { .name = "DBGVCR", .cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0, - .access = PL1_RW, .type = ARM_CP_NOP }, + .access = PL1_RW, .accessfn = access_tda, + .type = ARM_CP_NOP }, REGINFO_SENTINEL }; @@ -4099,7 +4119,8 @@ static void define_debug_regs(ARMCPU *cpu) int wrps, brps, ctx_cmps; ARMCPRegInfo dbgdidr = { .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = cpu->dbgdidr, + .access = PL0_R, .accessfn = access_tda, + .type = ARM_CP_CONST, .resetvalue = cpu->dbgdidr, }; /* Note that all these register fields hold "number of Xs minus 1". */ @@ -4130,13 +4151,13 @@ static void define_debug_regs(ARMCPU *cpu) ARMCPRegInfo dbgregs[] = { { .name = "DBGBVR", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4, - .access = PL1_RW, + .access = PL1_RW, .accessfn = access_tda, .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]), .writefn = dbgbvr_write, .raw_writefn = raw_write }, { .name = "DBGBCR", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5, - .access = PL1_RW, + .access = PL1_RW, .accessfn = access_tda, .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]), .writefn = dbgbcr_write, .raw_writefn = raw_write }, @@ -4149,13 +4170,13 @@ static void define_debug_regs(ARMCPU *cpu) ARMCPRegInfo dbgregs[] = { { .name = "DBGWVR", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6, - .access = PL1_RW, + .access = PL1_RW, .accessfn = access_tda, .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]), .writefn = dbgwvr_write, .raw_writefn = raw_write }, { .name = "DBGWCR", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 7, - .access = PL1_RW, + .access = PL1_RW, .accessfn = access_tda, .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]), .writefn = dbgwcr_write, .raw_writefn = raw_write }, -- cgit 1.4.1 From f2cae6092767aaf418778eada15be444c23883be Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Feb 2016 14:16:16 +0000 Subject: target-arm: Report correct syndrome for FPEXC32_EL2 traps If access to FPEXC32_EL2 is trapped by CPTR_EL2.TFP or CPTR_EL3.TFP, this should be reported with a syndrome register indicating an FP access trap, not one indicating a system register access trap. Signed-off-by: Peter Maydell Reviewed-by: Sergey Fedorov --- target-arm/cpu.h | 5 +++++ target-arm/helper.c | 4 ++-- target-arm/op_helper.c | 13 +++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'target-arm/helper.c') diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 77f9b51b76..16238216f4 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1334,6 +1334,11 @@ typedef enum CPAccessResult { /* As CP_ACCESS_UNCATEGORIZED, but for traps directly to EL2 or EL3 */ CP_ACCESS_TRAP_UNCATEGORIZED_EL2 = 5, CP_ACCESS_TRAP_UNCATEGORIZED_EL3 = 6, + /* Access fails and results in an exception syndrome for an FP access, + * trapped directly to EL2 or EL3 + */ + CP_ACCESS_TRAP_FP_EL2 = 7, + CP_ACCESS_TRAP_FP_EL3 = 8, } CPAccessResult; /* Access functions for coprocessor registers. These cannot fail and diff --git a/target-arm/helper.c b/target-arm/helper.c index e2b72389be..bb913c6e17 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -3011,10 +3011,10 @@ static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri, bool isread) { if ((env->cp15.cptr_el[2] & CPTR_TFP) && arm_current_el(env) == 2) { - return CP_ACCESS_TRAP_EL2; + return CP_ACCESS_TRAP_FP_EL2; } if (env->cp15.cptr_el[3] & CPTR_TFP) { - return CP_ACCESS_TRAP_EL3; + return CP_ACCESS_TRAP_FP_EL3; } return CP_ACCESS_OK; } diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 4c0980e5a5..049b52158b 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -500,6 +500,19 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome, target_el = 3; syndrome = syn_uncategorized(); break; + case CP_ACCESS_TRAP_FP_EL2: + target_el = 2; + /* Since we are an implementation that takes exceptions on a trapped + * conditional insn only if the insn has passed its condition code + * check, we take the IMPDEF choice to always report CV=1 COND=0xe + * (which is also the required value for AArch64 traps). + */ + syndrome = syn_fp_access_trap(1, 0xe, false); + break; + case CP_ACCESS_TRAP_FP_EL3: + target_el = 3; + syndrome = syn_fp_access_trap(1, 0xe, false); + break; default: g_assert_not_reached(); } -- cgit 1.4.1 From 72309cee482868d6c4711931c3f7e02ab9dec229 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Feb 2016 14:16:16 +0000 Subject: target-arm: Move get/set_r13_banked() to op_helper.c Move get/set_r13_banked() from helper.c to op_helper.c. This will let us add exception-raising code to them, and also puts them in the same file as get/set_user_reg(), which makes some conceptual sense. (The original reason for the helper.c/op_helper.c split was that only op_helper.c had access to the CPU env pointer; this distinction has not been true for a long time, though, and so the split is now rather arbitrary.) Signed-off-by: Peter Maydell Reviewed-by: Sergey Fedorov Reviewed-by: Edgar E. Iglesias --- target-arm/helper.c | 33 --------------------------------- target-arm/op_helper.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 33 deletions(-) (limited to 'target-arm/helper.c') diff --git a/target-arm/helper.c b/target-arm/helper.c index bb913c6e17..c46e3d0d09 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -5365,21 +5365,6 @@ void switch_mode(CPUARMState *env, int mode) } } -void HELPER(set_r13_banked)(CPUARMState *env, uint32_t mode, uint32_t val) -{ - ARMCPU *cpu = arm_env_get_cpu(env); - - cpu_abort(CPU(cpu), "banked r13 write\n"); -} - -uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode) -{ - ARMCPU *cpu = arm_env_get_cpu(env); - - cpu_abort(CPU(cpu), "banked r13 read\n"); - return 0; -} - uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, uint32_t cur_el, bool secure) { @@ -7762,24 +7747,6 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, return phys_addr; } -void HELPER(set_r13_banked)(CPUARMState *env, uint32_t mode, uint32_t val) -{ - if ((env->uncached_cpsr & CPSR_M) == mode) { - env->regs[13] = val; - } else { - env->banked_r13[bank_number(mode)] = val; - } -} - -uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode) -{ - if ((env->uncached_cpsr & CPSR_M) == mode) { - return env->regs[13]; - } else { - return env->banked_r13[bank_number(mode)]; - } -} - uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) { ARMCPU *cpu = arm_env_get_cpu(env); diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 049b52158b..053e9b62bc 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -457,6 +457,43 @@ void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val) } } +#if defined(CONFIG_USER_ONLY) +void HELPER(set_r13_banked)(CPUARMState *env, uint32_t mode, uint32_t val) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + + cpu_abort(CPU(cpu), "banked r13 write\n"); +} + +uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + + cpu_abort(CPU(cpu), "banked r13 read\n"); + return 0; +} + +#else + +void HELPER(set_r13_banked)(CPUARMState *env, uint32_t mode, uint32_t val) +{ + if ((env->uncached_cpsr & CPSR_M) == mode) { + env->regs[13] = val; + } else { + env->banked_r13[bank_number(mode)] = val; + } +} + +uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode) +{ + if ((env->uncached_cpsr & CPSR_M) == mode) { + return env->regs[13]; + } else { + return env->banked_r13[bank_number(mode)]; + } +} +#endif + void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome, uint32_t isread) { -- cgit 1.4.1 From c766568d3604082c6fd45cbabe42c48e4861a13f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Feb 2016 14:16:16 +0000 Subject: target-arm: Move bank_number() into internals.h Move bank_number()'s implementation into internals.h, so it's available in the user-mode-only compile as well. Signed-off-by: Peter Maydell Reviewed-by: Sergey Fedorov --- target-arm/helper.c | 25 ------------------------- target-arm/internals.h | 26 +++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 26 deletions(-) (limited to 'target-arm/helper.c') diff --git a/target-arm/helper.c b/target-arm/helper.c index c46e3d0d09..a420a2a331 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -5378,31 +5378,6 @@ void aarch64_sync_64_to_32(CPUARMState *env) #else -/* Map CPU modes onto saved register banks. */ -int bank_number(int mode) -{ - switch (mode) { - case ARM_CPU_MODE_USR: - case ARM_CPU_MODE_SYS: - return BANK_USRSYS; - case ARM_CPU_MODE_SVC: - return BANK_SVC; - case ARM_CPU_MODE_ABT: - return BANK_ABT; - case ARM_CPU_MODE_UND: - return BANK_UND; - case ARM_CPU_MODE_IRQ: - return BANK_IRQ; - case ARM_CPU_MODE_FIQ: - return BANK_FIQ; - case ARM_CPU_MODE_HYP: - return BANK_HYP; - case ARM_CPU_MODE_MON: - return BANK_MON; - } - g_assert_not_reached(); -} - void switch_mode(CPUARMState *env, int mode) { int old_mode; diff --git a/target-arm/internals.h b/target-arm/internals.h index 70bec4a4d2..2e70272be2 100644 --- a/target-arm/internals.h +++ b/target-arm/internals.h @@ -109,7 +109,31 @@ static inline unsigned int aarch64_banked_spsr_index(unsigned int el) return map[el]; } -int bank_number(int mode); +/* Map CPU modes onto saved register banks. */ +static inline int bank_number(int mode) +{ + switch (mode) { + case ARM_CPU_MODE_USR: + case ARM_CPU_MODE_SYS: + return BANK_USRSYS; + case ARM_CPU_MODE_SVC: + return BANK_SVC; + case ARM_CPU_MODE_ABT: + return BANK_ABT; + case ARM_CPU_MODE_UND: + return BANK_UND; + case ARM_CPU_MODE_IRQ: + return BANK_IRQ; + case ARM_CPU_MODE_FIQ: + return BANK_FIQ; + case ARM_CPU_MODE_HYP: + return BANK_HYP; + case ARM_CPU_MODE_MON: + return BANK_MON; + } + g_assert_not_reached(); +} + void switch_mode(CPUARMState *, int); void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu); void arm_translate_init(void); -- cgit 1.4.1 From 4054bfa9e7986c9b7d2bf70f9e10af9647e376fc Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 18 Feb 2016 14:16:17 +0000 Subject: target-arm: Add the pmceid0 and pmceid1 registers Signed-off-by: Aaron Lindsay Signed-off-by: Alistair Francis Tested-by: Nathan Rossi Message-id: da0563119a9f56fd5fbdc26e7ed19a8a8457c5b9.1455060548.git.alistair.francis@xilinx.com [PMM: Use 0 for PMCEID0 values for A15 and A57 since our PMU does not currently implement any events.] Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target-arm/cpu-qom.h | 2 ++ target-arm/cpu.c | 2 ++ target-arm/cpu64.c | 2 ++ target-arm/helper.c | 16 ++++++++++++++++ 4 files changed, 22 insertions(+) (limited to 'target-arm/helper.c') diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h index 07c0a71942..1cc4502fc4 100644 --- a/target-arm/cpu-qom.h +++ b/target-arm/cpu-qom.h @@ -148,6 +148,8 @@ typedef struct ARMCPU { uint32_t id_pfr0; uint32_t id_pfr1; uint32_t id_dfr0; + uint32_t pmceid0; + uint32_t pmceid1; uint32_t id_afr0; uint32_t id_mmfr0; uint32_t id_mmfr1; diff --git a/target-arm/cpu.c b/target-arm/cpu.c index f2393cd9f2..e95b0307a6 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -1156,6 +1156,8 @@ static void cortex_a15_initfn(Object *obj) cpu->id_pfr0 = 0x00001131; cpu->id_pfr1 = 0x00011011; cpu->id_dfr0 = 0x02010555; + cpu->pmceid0 = 0x0000000; + cpu->pmceid1 = 0x00000000; cpu->id_afr0 = 0x00000000; cpu->id_mmfr0 = 0x10201105; cpu->id_mmfr1 = 0x20000000; diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c index c5bc19a405..fa5eda2cd1 100644 --- a/target-arm/cpu64.c +++ b/target-arm/cpu64.c @@ -135,6 +135,8 @@ static void aarch64_a57_initfn(Object *obj) cpu->id_isar5 = 0x00011121; cpu->id_aa64pfr0 = 0x00002222; cpu->id_aa64dfr0 = 0x10305106; + cpu->pmceid0 = 0x00000000; + cpu->pmceid1 = 0x00000000; cpu->id_aa64isar0 = 0x00011120; cpu->id_aa64mmfr0 = 0x00001124; cpu->dbgdidr = 0x3516d000; diff --git a/target-arm/helper.c b/target-arm/helper.c index a420a2a331..6a4ec018fb 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -4380,6 +4380,22 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->mvfr2 }, + { .name = "PMCEID0", .state = ARM_CP_STATE_AA32, + .cp = 15, .opc1 = 0, .crn = 9, .crm = 12, .opc2 = 6, + .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST, + .resetvalue = cpu->pmceid0 }, + { .name = "PMCEID0_EL0", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 6, + .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST, + .resetvalue = cpu->pmceid0 }, + { .name = "PMCEID1", .state = ARM_CP_STATE_AA32, + .cp = 15, .opc1 = 0, .crn = 9, .crm = 12, .opc2 = 7, + .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST, + .resetvalue = cpu->pmceid1 }, + { .name = "PMCEID1_EL0", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 7, + .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST, + .resetvalue = cpu->pmceid1 }, REGINFO_SENTINEL }; /* RVBAR_EL1 is only implemented if EL1 is the highest EL */ -- cgit 1.4.1 From 978364f12adebb4b8d90fdeb71242cb3c1405740 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 18 Feb 2016 14:16:17 +0000 Subject: target-arm: Add the pmovsclr_el0 and pmintenclr_el1 registers Signed-off-by: Aaron Lindsay Signed-off-by: Alistair Francis Tested-by: Nathan Rossi Reviewed-by: Peter Maydell Message-id: 50deeafb24958a5b6d7f594b5dda399a022c0e5b.1455060548.git.alistair.francis@xilinx.com Signed-off-by: Peter Maydell --- target-arm/helper.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'target-arm/helper.c') diff --git a/target-arm/helper.c b/target-arm/helper.c index 6a4ec018fb..9e47f3d8cb 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1057,6 +1057,13 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { .accessfn = pmreg_access, .writefn = pmovsr_write, .raw_writefn = raw_write }, + { .name = "PMOVSCLR_EL0", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 3, + .access = PL0_RW, .accessfn = pmreg_access, + .type = ARM_CP_ALIAS, + .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr), + .writefn = pmovsr_write, + .raw_writefn = raw_write }, /* Unimplemented so WI. */ { .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4, .access = PL0_W, .accessfn = pmreg_access, .type = ARM_CP_NOP }, @@ -1107,6 +1114,11 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { .access = PL1_RW, .type = ARM_CP_ALIAS, .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), .writefn = pmintenclr_write, }, + { .name = "PMINTENCLR_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 2, + .access = PL1_RW, .type = ARM_CP_ALIAS, + .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), + .writefn = pmintenclr_write }, { .name = "VBAR", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0, .access = PL1_RW, .writefn = vbar_write, -- cgit 1.4.1 From 8a83ffc2dafad3499b87a736b17ab1b203fdb00b Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 18 Feb 2016 14:16:17 +0000 Subject: target-arm: Add PMUSERENR_EL0 register The Linux kernel accesses this register early in its setup. Signed-off-by: Christopher Covington Signed-off-by: Alistair Francis Reviewed-by: Peter Maydell Message-id: b30d536cb16ec57b4412172bb6dbc3f00d293e7d.1455060548.git.alistair.francis@xilinx.com Signed-off-by: Peter Maydell --- target-arm/helper.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'target-arm/helper.c') diff --git a/target-arm/helper.c b/target-arm/helper.c index 9e47f3d8cb..5a0447b93a 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -1105,6 +1105,12 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr), .resetvalue = 0, .writefn = pmuserenr_write, .raw_writefn = raw_write }, + { .name = "PMUSERENR_EL0", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 14, .opc2 = 0, + .access = PL0_R | PL1_RW, .type = ARM_CP_ALIAS, + .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr), + .resetvalue = 0, + .writefn = pmuserenr_write, .raw_writefn = raw_write }, { .name = "PMINTENSET", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 1, .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), -- cgit 1.4.1