summaryrefslogtreecommitdiffstats
path: root/target-arm/helper.c
diff options
context:
space:
mode:
authorPeter Maydell2016-02-18 15:16:15 +0100
committerPeter Maydell2016-02-18 15:16:15 +0100
commit755026728abb19fba70e6b4396a27fa2e7550d74 (patch)
treed6339e9eb6347eee2be7c8758abac29d03b0b843 /target-arm/helper.c
parentMerge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.6-20160218' into... (diff)
downloadqemu-755026728abb19fba70e6b4396a27fa2e7550d74.tar.gz
qemu-755026728abb19fba70e6b4396a27fa2e7550d74.tar.xz
qemu-755026728abb19fba70e6b4396a27fa2e7550d74.zip
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 <peter.maydell@linaro.org> Reviewed-by: Sergey Fedorov <serge.fdrv@gmail.com> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Diffstat (limited to 'target-arm/helper.c')
-rw-r--r--target-arm/helper.c29
1 files changed, 26 insertions, 3 deletions
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;
}