aarch64: implement mmu on/off for aarch32
[openocd.git] / src / target / aarch64.c
index e647bba13649c99d9a27b3fb359ea84ca570090e..bcfce659244af6ca099623c1a8dc277e3f1d7877 100644 (file)
@@ -30,8 +30,6 @@
 #include "armv8_cache.h"
 #include <helper/time_support.h>
 
-#define __unused __attribute((unused))
-
 enum restart_mode {
        RESTART_LAZY,
        RESTART_SYNC,
@@ -56,7 +54,7 @@ static int aarch64_unset_breakpoint(struct target *target,
 static int aarch64_mmu(struct target *target, int *enabled);
 static int aarch64_virt2phys(struct target *target,
        target_addr_t virt, target_addr_t *phys);
-static int aarch64_read_apb_ap_memory(struct target *target,
+static int aarch64_read_cpu_memory(struct target *target,
        uint64_t address, uint32_t size, uint32_t count, uint8_t *buffer);
 
 #define foreach_smp_target(pos, head) \
@@ -163,8 +161,16 @@ static int aarch64_mmu_modify(struct target *target, int enable)
        case ARMV8_64_EL3T:
                instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL3, 0);
                break;
+
+       case ARM_MODE_SVC:
+       case ARM_MODE_ABT:
+       case ARM_MODE_FIQ:
+       case ARM_MODE_IRQ:
+               instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0);
+               break;
+
        default:
-               LOG_DEBUG("unknown cpu state 0x%x" PRIx32, armv8->arm.core_state);
+               LOG_DEBUG("unknown cpu state 0x%" PRIx32, armv8->arm.core_mode);
                break;
        }
 
@@ -182,7 +188,7 @@ static int aarch64_init_debug_access(struct target *target)
        int retval;
        uint32_t dummy;
 
-       LOG_DEBUG(" ");
+       LOG_DEBUG("%s", target_name(target));
 
        retval = mem_ap_write_atomic_u32(armv8->debug_ap,
                        armv8->debug_base + CPUV8_DBG_OSLAR, 0);
@@ -772,6 +778,9 @@ static int aarch64_step_restart_smp(struct target *target)
                        if (curr == target)
                                continue;
 
+                       if (!target_was_examined(curr))
+                               continue;
+
                        retval = aarch64_check_state_one(curr,
                                        PRSR_SDR, PRSR_SDR, &resumed, &prsr);
                        if (retval != ERROR_OK || (!resumed && (prsr & PRSR_HALT))) {
@@ -1048,6 +1057,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
        int handle_breakpoints)
 {
        struct armv8_common *armv8 = target_to_armv8(target);
+       struct aarch64_common *aarch64 = target_to_aarch64(target);
        int saved_retval = ERROR_OK;
        int retval;
        uint32_t edecr;
@@ -1068,7 +1078,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
                                armv8->debug_base + CPUV8_DBG_EDECR, (edecr|0x4));
        }
        /* disable interrupts while stepping */
-       if (retval == ERROR_OK)
+       if (retval == ERROR_OK && aarch64->isrmasking_mode == AARCH64_ISRMASK_ON)
                retval = aarch64_set_dscr_bits(target, 0x3 << 22, 0x3 << 22);
        /* bail out if stepping setup has failed */
        if (retval != ERROR_OK)
@@ -1112,7 +1122,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
                if (retval != ERROR_OK || stepped)
                        break;
 
-               if (timeval_ms() > then + 1000) {
+               if (timeval_ms() > then + 100) {
                        LOG_ERROR("timeout waiting for target %s halt after step",
                                        target_name(target));
                        retval = ERROR_TARGET_TIMEOUT;
@@ -1120,8 +1130,14 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
                }
        }
 
+       /*
+        * At least on one SoC (Renesas R8A7795) stepping over a WFI instruction
+        * causes a timeout. The core takes the step but doesn't complete it and so
+        * debug state is never entered. However, you can manually halt the core
+        * as an external debug even is also a WFI wakeup event.
+        */
        if (retval == ERROR_TARGET_TIMEOUT)
-               saved_retval = retval;
+               saved_retval = aarch64_halt_one(target, HALT_SYNC);
 
        /* restore EDECR */
        retval = mem_ap_write_atomic_u32(armv8->debug_ap,
@@ -1130,9 +1146,11 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
                return retval;
 
        /* restore interrupts */
-       retval = aarch64_set_dscr_bits(target, 0x3 << 22, 0);
-       if (retval != ERROR_OK)
-               return ERROR_OK;
+       if (aarch64->isrmasking_mode == AARCH64_ISRMASK_ON) {
+               retval = aarch64_set_dscr_bits(target, 0x3 << 22, 0);
+               if (retval != ERROR_OK)
+                       return ERROR_OK;
+       }
 
        if (saved_retval != ERROR_OK)
                return saved_retval;
@@ -1670,7 +1688,99 @@ static int aarch64_deassert_reset(struct target *target)
        return aarch64_init_debug_access(target);
 }
 
-static int aarch64_write_apb_ap_memory(struct target *target,
+static int aarch64_write_cpu_memory_slow(struct target *target,
+       uint32_t size, uint32_t count, const uint8_t *buffer, uint32_t *dscr)
+{
+       struct armv8_common *armv8 = target_to_armv8(target);
+       struct arm_dpm *dpm = &armv8->dpm;
+       struct arm *arm = &armv8->arm;
+       int retval;
+
+       armv8_reg_current(arm, 1)->dirty = true;
+
+       /* change DCC to normal mode if necessary */
+       if (*dscr & DSCR_MA) {
+               *dscr &= ~DSCR_MA;
+               retval =  mem_ap_write_atomic_u32(armv8->debug_ap,
+                               armv8->debug_base + CPUV8_DBG_DSCR, *dscr);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       while (count) {
+               uint32_t data, opcode;
+
+               /* write the data to store into DTRRX */
+               if (size == 1)
+                       data = *buffer;
+               else if (size == 2)
+                       data = target_buffer_get_u16(target, buffer);
+               else
+                       data = target_buffer_get_u32(target, buffer);
+               retval = mem_ap_write_atomic_u32(armv8->debug_ap,
+                               armv8->debug_base + CPUV8_DBG_DTRRX, data);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               if (arm->core_state == ARM_STATE_AARCH64)
+                       retval = dpm->instr_execute(dpm, ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0, 1));
+               else
+                       retval = dpm->instr_execute(dpm, ARMV4_5_MRC(14, 0, 1, 0, 5, 0));
+               if (retval != ERROR_OK)
+                       return retval;
+
+               if (size == 1)
+                       opcode = armv8_opcode(armv8, ARMV8_OPC_STRB_IP);
+               else if (size == 2)
+                       opcode = armv8_opcode(armv8, ARMV8_OPC_STRH_IP);
+               else
+                       opcode = armv8_opcode(armv8, ARMV8_OPC_STRW_IP);
+               retval = dpm->instr_execute(dpm, opcode);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* Advance */
+               buffer += size;
+               --count;
+       }
+
+       return ERROR_OK;
+}
+
+static int aarch64_write_cpu_memory_fast(struct target *target,
+       uint32_t count, const uint8_t *buffer, uint32_t *dscr)
+{
+       struct armv8_common *armv8 = target_to_armv8(target);
+       struct arm *arm = &armv8->arm;
+       int retval;
+
+       armv8_reg_current(arm, 1)->dirty = true;
+
+       /* Step 1.d   - Change DCC to memory mode */
+       *dscr |= DSCR_MA;
+       retval =  mem_ap_write_atomic_u32(armv8->debug_ap,
+                       armv8->debug_base + CPUV8_DBG_DSCR, *dscr);
+       if (retval != ERROR_OK)
+               return retval;
+
+
+       /* Step 2.a   - Do the write */
+       retval = mem_ap_write_buf_noincr(armv8->debug_ap,
+                                       buffer, 4, count, armv8->debug_base + CPUV8_DBG_DTRRX);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* Step 3.a   - Switch DTR mode back to Normal mode */
+       *dscr &= ~DSCR_MA;
+       retval = mem_ap_write_atomic_u32(armv8->debug_ap,
+                               armv8->debug_base + CPUV8_DBG_DSCR, *dscr);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return ERROR_OK;
+}
+
+static int aarch64_write_cpu_memory(struct target *target,
        uint64_t address, uint32_t size,
        uint32_t count, const uint8_t *buffer)
 {
@@ -1679,71 +1789,27 @@ static int aarch64_write_apb_ap_memory(struct target *target,
        struct armv8_common *armv8 = target_to_armv8(target);
        struct arm_dpm *dpm = &armv8->dpm;
        struct arm *arm = &armv8->arm;
-       int total_bytes = count * size;
-       int total_u32;
-       int start_byte = address & 0x3;
-       int end_byte   = (address + total_bytes) & 0x3;
-       struct reg *reg;
        uint32_t dscr;
-       uint8_t *tmp_buff = NULL;
 
        if (target->state != TARGET_HALTED) {
                LOG_WARNING("target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       total_u32 = DIV_ROUND_UP((address & 3) + total_bytes, 4);
-
-       /* Mark register R0 as dirty, as it will be used
+       /* Mark register X0 as dirty, as it will be used
         * for transferring the data.
         * It will be restored automatically when exiting
         * debug mode
         */
-       reg = armv8_reg_current(arm, 1);
-       reg->dirty = true;
-
-       reg = armv8_reg_current(arm, 0);
-       reg->dirty = true;
+       armv8_reg_current(arm, 0)->dirty = true;
 
        /* This algorithm comes from DDI0487A.g, chapter J9.1 */
 
-       /* The algorithm only copies 32 bit words, so the buffer
-        * should be expanded to include the words at either end.
-        * The first and last words will be read first to avoid
-        * corruption if needed.
-        */
-       tmp_buff = malloc(total_u32 * 4);
-
-       if ((start_byte != 0) && (total_u32 > 1)) {
-               /* First bytes not aligned - read the 32 bit word to avoid corrupting
-                * the other bytes in the word.
-                */
-               retval = aarch64_read_apb_ap_memory(target, (address & ~0x3), 4, 1, tmp_buff);
-               if (retval != ERROR_OK)
-                       goto error_free_buff_w;
-       }
-
-       /* If end of write is not aligned, or the write is less than 4 bytes */
-       if ((end_byte != 0) ||
-               ((total_u32 == 1) && (total_bytes != 4))) {
-
-               /* Read the last word to avoid corruption during 32 bit write */
-               int mem_offset = (total_u32-1) * 4;
-               retval = aarch64_read_apb_ap_memory(target, (address & ~0x3) + mem_offset, 4, 1, &tmp_buff[mem_offset]);
-               if (retval != ERROR_OK)
-                       goto error_free_buff_w;
-       }
-
-       /* Copy the write buffer over the top of the temporary buffer */
-       memcpy(&tmp_buff[start_byte], buffer, total_bytes);
-
-       /* We now have a 32 bit aligned buffer that can be written */
-
        /* Read DSCR */
        retval = mem_ap_read_atomic_u32(armv8->debug_ap,
                        armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
        if (retval != ERROR_OK)
-               goto error_free_buff_w;
+               return retval;
 
        /* Set Normal access mode  */
        dscr = (dscr & ~DSCR_MA);
@@ -1755,68 +1821,168 @@ static int aarch64_write_apb_ap_memory(struct target *target,
                /* Step 1.a+b - Write the address for read access into DBGDTR_EL0 */
                /* Step 1.c   - Copy value from DTR to R0 using instruction mrs DBGDTR_EL0, x0 */
                retval = dpm->instr_write_data_dcc_64(dpm,
-                               ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), address & ~0x3ULL);
+                               ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), address);
        } else {
                /* Write R0 with value 'address' using write procedure */
                /* Step 1.a+b - Write the address for read access into DBGDTRRX */
                /* Step 1.c   - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */
                dpm->instr_write_data_dcc(dpm,
-                               ARMV4_5_MRC(14, 0, 0, 0, 5, 0), address & ~0x3ULL);
-
+                               ARMV4_5_MRC(14, 0, 0, 0, 5, 0), address);
        }
-       /* Step 1.d   - Change DCC to memory mode */
-       dscr = dscr | DSCR_MA;
-       retval +=  mem_ap_write_atomic_u32(armv8->debug_ap,
-                       armv8->debug_base + CPUV8_DBG_DSCR, dscr);
-       if (retval != ERROR_OK)
-               goto error_unset_dtr_w;
 
+       if (size == 4 && (address % 4) == 0)
+               retval = aarch64_write_cpu_memory_fast(target, count, buffer, &dscr);
+       else
+               retval = aarch64_write_cpu_memory_slow(target, size, count, buffer, &dscr);
 
-       /* Step 2.a   - Do the write */
-       retval = mem_ap_write_buf_noincr(armv8->debug_ap,
-                                       tmp_buff, 4, total_u32, armv8->debug_base + CPUV8_DBG_DTRRX);
-       if (retval != ERROR_OK)
-               goto error_unset_dtr_w;
-
-       /* Step 3.a   - Switch DTR mode back to Normal mode */
-       dscr = (dscr & ~DSCR_MA);
-       retval = mem_ap_write_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DSCR, dscr);
-       if (retval != ERROR_OK)
-               goto error_unset_dtr_w;
+       if (retval != ERROR_OK) {
+               /* Unset DTR mode */
+               mem_ap_read_atomic_u32(armv8->debug_ap,
+                                       armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
+               dscr &= ~DSCR_MA;
+               mem_ap_write_atomic_u32(armv8->debug_ap,
+                                       armv8->debug_base + CPUV8_DBG_DSCR, dscr);
+       }
 
        /* Check for sticky abort flags in the DSCR */
        retval = mem_ap_read_atomic_u32(armv8->debug_ap,
                                armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
        if (retval != ERROR_OK)
-               goto error_free_buff_w;
+               return retval;
 
        dpm->dscr = 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);
-               goto error_free_buff_w;
+               return ERROR_FAIL;
        }
 
        /* Done */
-       free(tmp_buff);
        return ERROR_OK;
+}
 
-error_unset_dtr_w:
-       /* Unset DTR mode */
-       mem_ap_read_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
-       dscr = (dscr & ~DSCR_MA);
-       mem_ap_write_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DSCR, dscr);
-error_free_buff_w:
-       LOG_ERROR("error");
-       free(tmp_buff);
-       return ERROR_FAIL;
+static int aarch64_read_cpu_memory_slow(struct target *target,
+       uint32_t size, uint32_t count, uint8_t *buffer, uint32_t *dscr)
+{
+       struct armv8_common *armv8 = target_to_armv8(target);
+       struct arm_dpm *dpm = &armv8->dpm;
+       struct arm *arm = &armv8->arm;
+       int retval;
+
+       armv8_reg_current(arm, 1)->dirty = true;
+
+       /* change DCC to normal mode (if necessary) */
+       if (*dscr & DSCR_MA) {
+               *dscr &= DSCR_MA;
+               retval =  mem_ap_write_atomic_u32(armv8->debug_ap,
+                               armv8->debug_base + CPUV8_DBG_DSCR, *dscr);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       while (count) {
+               uint32_t opcode, data;
+
+               if (size == 1)
+                       opcode = armv8_opcode(armv8, ARMV8_OPC_LDRB_IP);
+               else if (size == 2)
+                       opcode = armv8_opcode(armv8, ARMV8_OPC_LDRH_IP);
+               else
+                       opcode = armv8_opcode(armv8, ARMV8_OPC_LDRW_IP);
+               retval = dpm->instr_execute(dpm, opcode);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               if (arm->core_state == ARM_STATE_AARCH64)
+                       retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 1));
+               else
+                       retval = dpm->instr_execute(dpm, ARMV4_5_MCR(14, 0, 1, 0, 5, 0));
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+                               armv8->debug_base + CPUV8_DBG_DTRTX, &data);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               if (size == 1)
+                       *buffer = (uint8_t)data;
+               else if (size == 2)
+                       target_buffer_set_u16(target, buffer, (uint16_t)data);
+               else
+                       target_buffer_set_u32(target, buffer, data);
+
+               /* Advance */
+               buffer += size;
+               --count;
+       }
+
+       return ERROR_OK;
 }
 
-static int aarch64_read_apb_ap_memory(struct target *target,
+static int aarch64_read_cpu_memory_fast(struct target *target,
+       uint32_t count, uint8_t *buffer, uint32_t *dscr)
+{
+       struct armv8_common *armv8 = target_to_armv8(target);
+       struct arm_dpm *dpm = &armv8->dpm;
+       struct arm *arm = &armv8->arm;
+       int retval;
+       uint32_t value;
+
+       /* Mark X1 as dirty */
+       armv8_reg_current(arm, 1)->dirty = true;
+
+       if (arm->core_state == ARM_STATE_AARCH64) {
+               /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */
+               retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0));
+       } else {
+               /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */
+               retval = dpm->instr_execute(dpm, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
+       }
+
+       /* Step 1.e - Change DCC to memory mode */
+       *dscr |= DSCR_MA;
+       retval =  mem_ap_write_atomic_u32(armv8->debug_ap,
+                       armv8->debug_base + CPUV8_DBG_DSCR, *dscr);
+       /* Step 1.f - read DBGDTRTX and discard the value */
+       retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+                       armv8->debug_base + CPUV8_DBG_DTRTX, &value);
+
+       count--;
+       /* Read the data - Each read of the DTRTX register causes the instruction to be reissued
+        * Abort flags are sticky, so can be read at end of transactions
+        *
+        * This data is read in aligned to 32 bit boundary.
+        */
+
+       if (count) {
+               /* Step 2.a - Loop n-1 times, each read of DBGDTRTX reads the data from [X0] and
+                * increments X0 by 4. */
+               retval = mem_ap_read_buf_noincr(armv8->debug_ap, buffer, 4, count,
+                                                                       armv8->debug_base + CPUV8_DBG_DTRTX);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       /* Step 3.a - set DTR access mode back to Normal mode   */
+       *dscr &= ~DSCR_MA;
+       retval =  mem_ap_write_atomic_u32(armv8->debug_ap,
+                                       armv8->debug_base + CPUV8_DBG_DSCR, *dscr);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* Step 3.b - read DBGDTRTX for the final value */
+       retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+                       armv8->debug_base + CPUV8_DBG_DTRTX, &value);
+       if (retval != ERROR_OK)
+               return retval;
+
+       target_buffer_set_u32(target, buffer + count * 4, value);
+       return retval;
+}
+
+static int aarch64_read_cpu_memory(struct target *target,
        target_addr_t address, uint32_t size,
        uint32_t count, uint8_t *buffer)
 {
@@ -1825,32 +1991,22 @@ static int aarch64_read_apb_ap_memory(struct target *target,
        struct armv8_common *armv8 = target_to_armv8(target);
        struct arm_dpm *dpm = &armv8->dpm;
        struct arm *arm = &armv8->arm;
-       int total_bytes = count * size;
-       int total_u32;
-       int start_byte = address & 0x3;
-       int end_byte   = (address + total_bytes) & 0x3;
-       struct reg *reg;
        uint32_t dscr;
-       uint8_t *tmp_buff = NULL;
-       uint8_t *u8buf_ptr;
-       uint32_t value;
+
+       LOG_DEBUG("Reading CPU memory address 0x%016" PRIx64 " size %" PRIu32 " count %" PRIu32,
+                       address, size, count);
 
        if (target->state != TARGET_HALTED) {
                LOG_WARNING("target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       total_u32 = DIV_ROUND_UP((address & 3) + total_bytes, 4);
-       /* Mark register X0, X1 as dirty, as it will be used
+       /* Mark register X0 as dirty, as it will be used
         * for transferring the data.
         * It will be restored automatically when exiting
         * debug mode
         */
-       reg = armv8_reg_current(arm, 1);
-       reg->dirty = true;
-
-       reg = armv8_reg_current(arm, 0);
-       reg->dirty = true;
+       armv8_reg_current(arm, 0)->dirty = true;
 
        /* Read DSCR */
        retval = mem_ap_read_atomic_u32(armv8->debug_ap,
@@ -1859,7 +2015,7 @@ static int aarch64_read_apb_ap_memory(struct target *target,
        /* This algorithm comes from DDI0487A.g, chapter J9.1 */
 
        /* Set Normal access mode  */
-       dscr = (dscr & ~DSCR_MA);
+       dscr &= ~DSCR_MA;
        retval +=  mem_ap_write_atomic_u32(armv8->debug_ap,
                        armv8->debug_base + CPUV8_DBG_DSCR, dscr);
 
@@ -1868,83 +2024,34 @@ static int aarch64_read_apb_ap_memory(struct target *target,
                /* Step 1.a+b - Write the address for read access into DBGDTR_EL0 */
                /* Step 1.c   - Copy value from DTR to R0 using instruction mrs DBGDTR_EL0, x0 */
                retval += dpm->instr_write_data_dcc_64(dpm,
-                               ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), address & ~0x3ULL);
-               /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */
-               retval += dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0));
-               /* Step 1.e - Change DCC to memory mode */
-               dscr = dscr | DSCR_MA;
-               retval +=  mem_ap_write_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DSCR, dscr);
-               /* Step 1.f - read DBGDTRTX and discard the value */
-               retval += mem_ap_read_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DTRTX, &value);
+                               ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), address);
        } else {
                /* Write R0 with value 'address' using write procedure */
                /* Step 1.a+b - Write the address for read access into DBGDTRRXint */
                /* Step 1.c   - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */
                retval += dpm->instr_write_data_dcc(dpm,
-                               ARMV4_5_MRC(14, 0, 0, 0, 5, 0), address & ~0x3ULL);
-               /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */
-               retval += dpm->instr_execute(dpm, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
-               /* Step 1.e - Change DCC to memory mode */
-               dscr = dscr | DSCR_MA;
-               retval +=  mem_ap_write_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DSCR, dscr);
-               /* Step 1.f - read DBGDTRTX and discard the value */
-               retval += mem_ap_read_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DTRTX, &value);
-
+                               ARMV4_5_MRC(14, 0, 0, 0, 5, 0), address);
        }
-       if (retval != ERROR_OK)
-               goto error_unset_dtr_r;
-
-       /* Optimize the read as much as we can, either way we read in a single pass  */
-       if ((start_byte) || (end_byte)) {
-               /* The algorithm only copies 32 bit words, so the buffer
-                * should be expanded to include the words at either end.
-                * The first and last words will be read into a temp buffer
-                * to avoid corruption
-                */
-               tmp_buff = malloc(total_u32 * 4);
-               if (!tmp_buff)
-                       goto error_unset_dtr_r;
-
-               /* use the tmp buffer to read the entire data */
-               u8buf_ptr = tmp_buff;
-       } else
-               /* address and read length are aligned so read directly into the passed buffer */
-               u8buf_ptr = buffer;
-
-       /* Read the data - Each read of the DTRTX register causes the instruction to be reissued
-        * Abort flags are sticky, so can be read at end of transactions
-        *
-        * This data is read in aligned to 32 bit boundary.
-        */
 
-       /* Step 2.a - Loop n-1 times, each read of DBGDTRTX reads the data from [X0] and
-        * increments X0 by 4. */
-       retval = mem_ap_read_buf_noincr(armv8->debug_ap, u8buf_ptr, 4, total_u32-1,
-                                                                       armv8->debug_base + CPUV8_DBG_DTRTX);
-       if (retval != ERROR_OK)
-                       goto error_unset_dtr_r;
+       if (size == 4 && (address % 4) == 0)
+               retval = aarch64_read_cpu_memory_fast(target, count, buffer, &dscr);
+       else
+               retval = aarch64_read_cpu_memory_slow(target, size, count, buffer, &dscr);
 
-       /* Step 3.a - set DTR access mode back to Normal mode   */
-       dscr = (dscr & ~DSCR_MA);
-       retval =  mem_ap_write_atomic_u32(armv8->debug_ap,
+       if (dscr & DSCR_MA) {
+               dscr &= ~DSCR_MA;
+               mem_ap_write_atomic_u32(armv8->debug_ap,
                                        armv8->debug_base + CPUV8_DBG_DSCR, dscr);
-       if (retval != ERROR_OK)
-               goto error_free_buff_r;
+       }
 
-       /* Step 3.b - read DBGDTRTX for the final value */
-       retval = mem_ap_read_atomic_u32(armv8->debug_ap,
-                       armv8->debug_base + CPUV8_DBG_DTRTX, &value);
-       memcpy(u8buf_ptr + (total_u32-1) * 4, &value, 4);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* Check for sticky abort flags in the DSCR */
        retval = mem_ap_read_atomic_u32(armv8->debug_ap,
                                armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
        if (retval != ERROR_OK)
-               goto error_free_buff_r;
+               return retval;
 
        dpm->dscr = dscr;
 
@@ -1952,29 +2059,11 @@ static int aarch64_read_apb_ap_memory(struct target *target,
                /* Abort occurred - clear it and exit */
                LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr);
                armv8_dpm_handle_exception(dpm);
-               goto error_free_buff_r;
-       }
-
-       /* check if we need to copy aligned data by applying any shift necessary */
-       if (tmp_buff) {
-               memcpy(buffer, tmp_buff + start_byte, total_bytes);
-               free(tmp_buff);
+               return ERROR_FAIL;
        }
 
        /* Done */
        return ERROR_OK;
-
-error_unset_dtr_r:
-       /* Unset DTR mode */
-       mem_ap_read_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
-       dscr = (dscr & ~DSCR_MA);
-       mem_ap_write_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DSCR, dscr);
-error_free_buff_r:
-       LOG_ERROR("error");
-       free(tmp_buff);
-       return ERROR_FAIL;
 }
 
 static int aarch64_read_phys_memory(struct target *target,
@@ -1988,7 +2077,7 @@ static int aarch64_read_phys_memory(struct target *target,
                retval = aarch64_mmu_modify(target, 0);
                if (retval != ERROR_OK)
                        return retval;
-               retval = aarch64_read_apb_ap_memory(target, address, size, count, buffer);
+               retval = aarch64_read_cpu_memory(target, address, size, count, buffer);
        }
        return retval;
 }
@@ -2010,7 +2099,7 @@ static int aarch64_read_memory(struct target *target, target_addr_t address,
                if (retval != ERROR_OK)
                        return retval;
        }
-       return aarch64_read_apb_ap_memory(target, address, size, count, buffer);
+       return aarch64_read_cpu_memory(target, address, size, count, buffer);
 }
 
 static int aarch64_write_phys_memory(struct target *target,
@@ -2024,7 +2113,7 @@ static int aarch64_write_phys_memory(struct target *target,
                retval = aarch64_mmu_modify(target, 0);
                if (retval != ERROR_OK)
                        return retval;
-               return aarch64_write_apb_ap_memory(target, address, size, count, buffer);
+               return aarch64_write_cpu_memory(target, address, size, count, buffer);
        }
 
        return retval;
@@ -2047,7 +2136,7 @@ static int aarch64_write_memory(struct target *target, target_addr_t address,
                if (retval != ERROR_OK)
                        return retval;
        }
-       return aarch64_write_apb_ap_memory(target, address, size, count, buffer);
+       return aarch64_write_cpu_memory(target, address, size, count, buffer);
 }
 
 static int aarch64_handle_target_request(void *priv)
@@ -2092,7 +2181,7 @@ static int aarch64_examine_first(struct target *target)
        int retval = ERROR_OK;
        uint64_t debug, ttypr;
        uint32_t cpuid;
-       uint32_t tmp0, tmp1;
+       uint32_t tmp0, tmp1, tmp2, tmp3;
        debug = ttypr = cpuid = 0;
 
        retval = dap_dp_init(swjdp);
@@ -2132,32 +2221,6 @@ static int aarch64_examine_first(struct target *target)
        } else
                armv8->debug_base = target->dbgbase;
 
-       uint32_t prsr;
-       int64_t then = timeval_ms();
-       do {
-               retval = mem_ap_read_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_PRSR, &prsr);
-               if (retval == ERROR_OK) {
-                       retval = mem_ap_write_atomic_u32(armv8->debug_ap,
-                                       armv8->debug_base + CPUV8_DBG_PRCR, PRCR_COREPURQ|PRCR_CORENPDRQ);
-                       if (retval != ERROR_OK) {
-                               LOG_DEBUG("write to PRCR failed");
-                               break;
-                       }
-               }
-
-               if (timeval_ms() > then + 1000) {
-                       retval = ERROR_TARGET_TIMEOUT;
-                       break;
-               }
-
-       } while ((prsr & PRSR_PU) == 0);
-
-       if (retval != ERROR_OK) {
-               LOG_ERROR("target %s: failed to set power state of the core.", target_name(target));
-               return retval;
-       }
-
        retval = mem_ap_write_atomic_u32(armv8->debug_ap,
                        armv8->debug_base + CPUV8_DBG_OSLAR, 0);
        if (retval != ERROR_OK) {
@@ -2165,34 +2228,40 @@ static int aarch64_examine_first(struct target *target)
                return retval;
        }
 
-       retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+       retval = mem_ap_read_u32(armv8->debug_ap,
                        armv8->debug_base + CPUV8_DBG_MAINID0, &cpuid);
        if (retval != ERROR_OK) {
                LOG_DEBUG("Examine %s failed", "CPUID");
                return retval;
        }
 
-       retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+       retval = mem_ap_read_u32(armv8->debug_ap,
                        armv8->debug_base + CPUV8_DBG_MEMFEATURE0, &tmp0);
-       retval += mem_ap_read_atomic_u32(armv8->debug_ap,
+       retval += mem_ap_read_u32(armv8->debug_ap,
                        armv8->debug_base + CPUV8_DBG_MEMFEATURE0 + 4, &tmp1);
        if (retval != ERROR_OK) {
                LOG_DEBUG("Examine %s failed", "Memory Model Type");
                return retval;
        }
-       ttypr |= tmp1;
-       ttypr = (ttypr << 32) | tmp0;
-
-       retval = mem_ap_read_atomic_u32(armv8->debug_ap,
-                       armv8->debug_base + CPUV8_DBG_DBGFEATURE0, &tmp0);
-       retval += mem_ap_read_atomic_u32(armv8->debug_ap,
-                       armv8->debug_base + CPUV8_DBG_DBGFEATURE0 + 4, &tmp1);
+       retval = mem_ap_read_u32(armv8->debug_ap,
+                       armv8->debug_base + CPUV8_DBG_DBGFEATURE0, &tmp2);
+       retval += mem_ap_read_u32(armv8->debug_ap,
+                       armv8->debug_base + CPUV8_DBG_DBGFEATURE0 + 4, &tmp3);
        if (retval != ERROR_OK) {
                LOG_DEBUG("Examine %s failed", "ID_AA64DFR0_EL1");
                return retval;
        }
-       debug |= tmp1;
-       debug = (debug << 32) | tmp0;
+
+       retval = dap_run(armv8->debug_ap->dap);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("%s: examination failed\n", target_name(target));
+               return retval;
+       }
+
+       ttypr |= tmp1;
+       ttypr = (ttypr << 32) | tmp0;
+       debug |= tmp3;
+       debug = (debug << 32) | tmp2;
 
        LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid);
        LOG_DEBUG("ttypr = 0x%08" PRIx64, ttypr);
@@ -2231,9 +2300,9 @@ static int aarch64_examine_first(struct target *target)
 
        LOG_DEBUG("Configured %i hw breakpoints", aarch64->brp_num);
 
-       target->state = TARGET_RUNNING;
+       target->state = TARGET_UNKNOWN;
        target->debug_reason = DBG_REASON_NOTHALTED;
-
+       aarch64->isrmasking_mode = AARCH64_ISRMASK_ON;
        target_set_examined(target);
        return ERROR_OK;
 }
@@ -2371,6 +2440,34 @@ COMMAND_HANDLER(aarch64_handle_smp_on_command)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(aarch64_mask_interrupts_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct aarch64_common *aarch64 = target_to_aarch64(target);
+
+       static const Jim_Nvp nvp_maskisr_modes[] = {
+               { .name = "off", .value = AARCH64_ISRMASK_OFF },
+               { .name = "on", .value = AARCH64_ISRMASK_ON },
+               { .name = NULL, .value = -1 },
+       };
+       const Jim_Nvp *n;
+
+       if (CMD_ARGC > 0) {
+               n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
+               if (n->name == NULL) {
+                       LOG_ERROR("Unknown parameter: %s - should be off or on", CMD_ARGV[0]);
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               }
+
+               aarch64->isrmasking_mode = n->value;
+       }
+
+       n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, aarch64->isrmasking_mode);
+       command_print(CMD_CTX, "aarch64 interrupt mask %s", n->name);
+
+       return ERROR_OK;
+}
+
 static const struct command_registration aarch64_exec_command_handlers[] = {
        {
                .name = "cache_info",
@@ -2399,6 +2496,13 @@ static const struct command_registration aarch64_exec_command_handlers[] = {
                .help = "Restart smp handling",
                .usage = "",
        },
+       {
+               .name = "maskisr",
+               .handler = aarch64_mask_interrupts_command,
+               .mode = COMMAND_ANY,
+               .help = "mask aarch64 interrupts during single-step",
+               .usage = "['on'|'off']",
+       },
 
        COMMAND_REGISTRATION_DONE
 };

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)