aarch64: fix debug entry from EL0 61/4461/8
authorMatthias Welwarsky <matthias.welwarsky@sysgo.com>
Mon, 12 Mar 2018 15:56:05 +0000 (16:56 +0100)
committerMatthias Welwarsky <matthias@welwarsky.de>
Fri, 16 Mar 2018 08:58:06 +0000 (08:58 +0000)
If we enter debug state from EL0, some registers are not accessible.
Temporarily move to EL1H and back to gain access. Also, fix
armv8_dpm_modeswitch() to not immediately restore the previous state
on elevating the privilege level.

Change-Id: Ic2a92109230ff4eb6834c00ef544397a5b7ad56a
Signed-off-by: Matthias Welwarsky <matthias.welwarsky@sysgo.com>
Reviewed-on: http://openocd.zylin.com/4461
Tested-by: jenkins
Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>
src/target/aarch64.c
src/target/armv8.c
src/target/armv8_cache.c
src/target/armv8_dpm.c
src/target/armv8_dpm.h

index 0630ffb9bd00a0abc5f9fc64c629c197476e122a..b586e24eb9aebd5828ce12afa7ba5f23dff939fb 100644 (file)
@@ -1861,7 +1861,7 @@ static int aarch64_write_cpu_memory(struct target *target,
        if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) {
                /* Abort occurred - clear it and exit */
                LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr);
        if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) {
                /* Abort occurred - clear it and exit */
                LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr);
-               armv8_dpm_handle_exception(dpm);
+               armv8_dpm_handle_exception(dpm, true);
                return ERROR_FAIL;
        }
 
                return ERROR_FAIL;
        }
 
@@ -2080,7 +2080,7 @@ static int aarch64_read_cpu_memory(struct target *target,
        if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) {
                /* Abort occurred - clear it and exit */
                LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr);
        if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) {
                /* Abort occurred - clear it and exit */
                LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr);
-               armv8_dpm_handle_exception(dpm);
+               armv8_dpm_handle_exception(dpm, true);
                return ERROR_FAIL;
        }
 
                return ERROR_FAIL;
        }
 
index 86bb8707e43e3f7d13279bfbe4bced0ab148eb2a..e8c700af35d8da9ca166a34f77f5597ae5fffd02 100644 (file)
@@ -620,6 +620,7 @@ void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64)
 int armv8_read_mpidr(struct armv8_common *armv8)
 {
        int retval = ERROR_FAIL;
 int armv8_read_mpidr(struct armv8_common *armv8)
 {
        int retval = ERROR_FAIL;
+       struct arm *arm = &armv8->arm;
        struct arm_dpm *dpm = armv8->arm.dpm;
        uint32_t mpidr;
 
        struct arm_dpm *dpm = armv8->arm.dpm;
        uint32_t mpidr;
 
@@ -627,6 +628,13 @@ int armv8_read_mpidr(struct armv8_common *armv8)
        if (retval != ERROR_OK)
                goto done;
 
        if (retval != ERROR_OK)
                goto done;
 
+       /* check if we're in an unprivileged mode */
+       if (armv8_curel_from_core_mode(arm->core_mode) < SYSTEM_CUREL_EL1) {
+               retval = armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
        retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_MPIDR), &mpidr);
        if (retval != ERROR_OK)
                goto done;
        retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_MPIDR), &mpidr);
        if (retval != ERROR_OK)
                goto done;
@@ -642,6 +650,7 @@ int armv8_read_mpidr(struct armv8_common *armv8)
                LOG_ERROR("mpidr not in multiprocessor format");
 
 done:
                LOG_ERROR("mpidr not in multiprocessor format");
 
 done:
+       armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
        dpm->finish(dpm);
        return retval;
 }
        dpm->finish(dpm);
        return retval;
 }
index 7f610c953536714f3e36eecbce102929bb4f282c..40965ebd831091f26aa97e1435ccbf99d32aa77b 100644 (file)
@@ -310,6 +310,7 @@ int armv8_identify_cache(struct armv8_common *armv8)
 {
        /*  read cache descriptor */
        int retval = ERROR_FAIL;
 {
        /*  read cache descriptor */
        int retval = ERROR_FAIL;
+       struct arm *arm = &armv8->arm;
        struct arm_dpm *dpm = armv8->arm.dpm;
        uint32_t csselr, clidr, ctr;
        uint32_t cache_reg;
        struct arm_dpm *dpm = armv8->arm.dpm;
        uint32_t csselr, clidr, ctr;
        uint32_t cache_reg;
@@ -320,6 +321,13 @@ int armv8_identify_cache(struct armv8_common *armv8)
        if (retval != ERROR_OK)
                goto done;
 
        if (retval != ERROR_OK)
                goto done;
 
+       /* check if we're in an unprivileged mode */
+       if (armv8_curel_from_core_mode(arm->core_mode) < SYSTEM_CUREL_EL1) {
+               retval = armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
        /* retrieve CTR */
        retval = dpm->instr_read_data_r0(dpm,
                        armv8_opcode(armv8, READ_REG_CTR), &ctr);
        /* retrieve CTR */
        retval = dpm->instr_read_data_r0(dpm,
                        armv8_opcode(armv8, READ_REG_CTR), &ctr);
@@ -417,6 +425,7 @@ int armv8_identify_cache(struct armv8_common *armv8)
        }
 
 done:
        }
 
 done:
+       armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
        dpm->finish(dpm);
        return retval;
 
        dpm->finish(dpm);
        return retval;
 
index 91b2f51718e6c0ac45feeea19764a7baf7eb628b..3c941fa2db17b97f09683dcdaee1c9675d4a164d 100644 (file)
@@ -258,7 +258,7 @@ static int dpmv8_exec_opcode(struct arm_dpm *dpm,
 
        if (dscr & DSCR_ERR) {
                LOG_ERROR("Opcode 0x%08"PRIx32", DSCR.ERR=1, DSCR.EL=%i", opcode, dpm->last_el);
 
        if (dscr & DSCR_ERR) {
                LOG_ERROR("Opcode 0x%08"PRIx32", DSCR.ERR=1, DSCR.EL=%i", opcode, dpm->last_el);
-               armv8_dpm_handle_exception(dpm);
+               armv8_dpm_handle_exception(dpm, true);
                retval = ERROR_FAIL;
        }
 
                retval = ERROR_FAIL;
        }
 
@@ -600,7 +600,7 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
                                armv8_opcode(armv8, ARMV8_OPC_DCPS) | target_el);
 
                /* DCPS clobbers registers just like an exception taken */
                                armv8_opcode(armv8, ARMV8_OPC_DCPS) | target_el);
 
                /* DCPS clobbers registers just like an exception taken */
-               armv8_dpm_handle_exception(dpm);
+               armv8_dpm_handle_exception(dpm, false);
        } else {
                core_state = armv8_dpm_get_core_state(dpm);
                if (core_state != ARM_STATE_AARCH64) {
        } else {
                core_state = armv8_dpm_get_core_state(dpm);
                if (core_state != ARM_STATE_AARCH64) {
@@ -1298,7 +1298,7 @@ void armv8_dpm_report_wfar(struct arm_dpm *dpm, uint64_t addr)
  * This function must not perform any actions that trigger another exception
  * or a recursion will happen.
  */
  * This function must not perform any actions that trigger another exception
  * or a recursion will happen.
  */
-void armv8_dpm_handle_exception(struct arm_dpm *dpm)
+void armv8_dpm_handle_exception(struct arm_dpm *dpm, bool do_restore)
 {
        struct armv8_common *armv8 = dpm->arm->arch_info;
        struct reg_cache *cache = dpm->arm->core_cache;
 {
        struct armv8_common *armv8 = dpm->arm->arch_info;
        struct reg_cache *cache = dpm->arm->core_cache;
@@ -1344,7 +1344,8 @@ void armv8_dpm_handle_exception(struct arm_dpm *dpm)
        armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64);
        armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64);
 
        armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64);
        armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64);
 
-       armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
+       if (do_restore)
+               armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
 }
 
 /*----------------------------------------------------------------------*/
 }
 
 /*----------------------------------------------------------------------*/
index c03935928b95ce6d9e492e8104b63c887e35d087..f40440370f0f4addafe98f60a9a0019c4adea205 100644 (file)
@@ -116,7 +116,7 @@ void armv8_dpm_report_wfar(struct arm_dpm *, uint64_t wfar);
 #define PRCR_COREPURQ                  (1 << 3)
 
 void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr);
 #define PRCR_COREPURQ                  (1 << 3)
 
 void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr);
-void armv8_dpm_handle_exception(struct arm_dpm *dpm);
+void armv8_dpm_handle_exception(struct arm_dpm *dpm, bool do_restore);
 enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm);
 
 #endif /* OPENOCD_TARGET_ARM_DPM_H */
 enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm);
 
 #endif /* OPENOCD_TARGET_ARM_DPM_H */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)