target/cortex_a: Use bool data type
[fw/openocd] / src / target / cortex_a.c
index 2768e18cf91055f8d19b2572d7b07dd71b6f6973..ec02d179f748d6875ebba499055741b79efcd3ed 100644 (file)
@@ -23,6 +23,9 @@
  *   Copyright (C) 2013 Kamal Dasu                                         *
  *   kdasu.kdev@gmail.com                                                  *
  *                                                                         *
+ *   Copyright (C) 2016 Chengyu Zheng                                      *
+ *   chengyu.zheng@polimi.it : watchpoint support                          *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
 #include "breakpoints.h"
 #include "cortex_a.h"
 #include "register.h"
+#include "armv7a_mmu.h"
 #include "target_request.h"
 #include "target_type.h"
 #include "arm_opcodes.h"
 #include "arm_semihosting.h"
+#include "jtag/interface.h"
 #include "transport/transport.h"
+#include "smp.h"
+#include <helper/bits.h>
 #include <helper/time_support.h>
 
-#define foreach_smp_target(pos, head) \
-       for (pos = head; (pos != NULL); pos = pos->next)
-
 static int cortex_a_poll(struct target *target);
 static int cortex_a_debug_entry(struct target *target);
 static int cortex_a_restore_context(struct target *target, bool bpwp);
@@ -71,10 +75,8 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target,
        struct breakpoint *breakpoint);
 static int cortex_a_unset_breakpoint(struct target *target,
        struct breakpoint *breakpoint);
-static int cortex_a_dap_read_coreregister_u32(struct target *target,
-       uint32_t *value, int regnum);
-static int cortex_a_dap_write_coreregister_u32(struct target *target,
-       uint32_t value, int regnum);
+static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask,
+       uint32_t value, uint32_t *dscr);
 static int cortex_a_mmu(struct target *target, int *enabled);
 static int cortex_a_mmu_modify(struct target *target, int enable);
 static int cortex_a_virt2phys(struct target *target,
@@ -82,6 +84,16 @@ static int cortex_a_virt2phys(struct target *target,
 static int cortex_a_read_cpu_memory(struct target *target,
        uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
 
+static unsigned int ilog2(unsigned int x)
+{
+       unsigned int y = 0;
+       x /= 2;
+       while (x) {
+               ++y;
+               x /= 2;
+               }
+       return y;
+}
 
 /*  restore cp15_control_reg at resume */
 static int cortex_a_restore_cp15_control_reg(struct target *target)
@@ -113,7 +125,7 @@ static int cortex_a_prep_memaccess(struct target *target, int phys_access)
        int mmu_enabled = 0;
 
        if (phys_access == 0) {
-               dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
+               arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
                cortex_a_mmu(target, &mmu_enabled);
                if (mmu_enabled)
                        cortex_a_mmu_modify(target, 1);
@@ -148,7 +160,7 @@ static int cortex_a_post_memaccess(struct target *target, int phys_access)
                                        0, 0, 3, 0,
                                        cortex_a->cp15_dacr_reg);
                }
-               dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
+               arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        } else {
                int mmu_enabled = 0;
                cortex_a_mmu(target, &mmu_enabled);
@@ -205,6 +217,7 @@ static int cortex_a_mmu_modify(struct target *target, int enable)
 static int cortex_a_init_debug_access(struct target *target)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
+       uint32_t dscr;
        int retval;
 
        /* lock memory-mapped access to debug registers to prevent
@@ -234,6 +247,16 @@ static int cortex_a_init_debug_access(struct target *target)
 
        /* Resync breakpoint registers */
 
+       /* Enable halt for breakpoint, watchpoint and vector catch */
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                       armv7a->debug_base + CPUDBG_DSCR, &dscr);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+                       armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE);
+       if (retval != ERROR_OK)
+               return retval;
+
        /* Since this is likely called from init or reset, update target state information*/
        return cortex_a_poll(target);
 }
@@ -244,21 +267,21 @@ static int cortex_a_wait_instrcmpl(struct target *target, uint32_t *dscr, bool f
         * Writes final value of DSCR into *dscr. Pass force to force always
         * reading DSCR at least once. */
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       int64_t then = timeval_ms();
-       while ((*dscr & DSCR_INSTR_COMP) == 0 || force) {
-               force = false;
-               int retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+       int retval;
+
+       if (force) {
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, dscr);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Could not read DSCR register");
                        return retval;
                }
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for InstrCompl=1");
-                       return ERROR_FAIL;
-               }
        }
-       return ERROR_OK;
+
+       retval = cortex_a_wait_dscr_bits(target, DSCR_INSTR_COMP, DSCR_INSTR_COMP, dscr);
+       if (retval != ERROR_OK)
+               LOG_ERROR("Error waiting for InstrCompl=1");
+       return retval;
 }
 
 /* To reduce needless round-trips, pass in a pointer to the current
@@ -287,163 +310,15 @@ static int cortex_a_exec_opcode(struct target *target,
        if (retval != ERROR_OK)
                return retval;
 
-       int64_t then = timeval_ms();
-       do {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               if (retval != ERROR_OK) {
-                       LOG_ERROR("Could not read DSCR register");
-                       return retval;
-               }
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for cortex_a_exec_opcode");
-                       return ERROR_FAIL;
-               }
-       } while ((dscr & DSCR_INSTR_COMP) == 0);        /* Wait for InstrCompl bit to be set */
-
-       if (dscr_p)
-               *dscr_p = dscr;
-
-       return retval;
-}
-
-static int cortex_a_dap_read_coreregister_u32(struct target *target,
-       uint32_t *value, int regnum)
-{
-       int retval = ERROR_OK;
-       uint8_t reg = regnum&0xFF;
-       uint32_t dscr = 0;
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-
-       if (reg > 17)
-               return retval;
-
-       if (reg < 15) {
-               /* Rn to DCCTX, "MCR p14, 0, Rn, c0, c5, 0"  0xEE00nE15 */
-               retval = cortex_a_exec_opcode(target,
-                               ARMV4_5_MCR(14, 0, reg, 0, 5, 0),
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-       } else if (reg == 15) {
-               /* "MOV r0, r15"; then move r0 to DCCTX */
-               retval = cortex_a_exec_opcode(target, 0xE1A0000F, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = cortex_a_exec_opcode(target,
-                               ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-       } else {
-               /* "MRS r0, CPSR" or "MRS r0, SPSR"
-                * then move r0 to DCCTX
-                */
-               retval = cortex_a_exec_opcode(target, ARMV4_5_MRS(0, reg & 1), &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = cortex_a_exec_opcode(target,
-                               ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-       }
-
-       /* Wait for DTRRXfull then read DTRRTX */
-       int64_t then = timeval_ms();
-       while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for cortex_a_exec_opcode");
-                       return ERROR_FAIL;
-               }
-       }
-
-       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DTRTX, value);
-       LOG_DEBUG("read DCC 0x%08" PRIx32, *value);
-
-       return retval;
-}
-
-__attribute__((unused))
-static int cortex_a_dap_write_coreregister_u32(struct target *target,
-       uint32_t value, int regnum)
-{
-       int retval = ERROR_OK;
-       uint8_t Rd = regnum&0xFF;
-       uint32_t dscr;
-       struct armv7a_common *armv7a = target_to_armv7a(target);
-
-       LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value);
-
-       /* Check that DCCRX is not full */
-       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DSCR, &dscr);
-       if (retval != ERROR_OK)
+       /* Wait for InstrCompl bit to be set */
+       retval = cortex_a_wait_instrcmpl(target, &dscr, true);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for cortex_a_exec_opcode");
                return retval;
-       if (dscr & DSCR_DTR_RX_FULL) {
-               LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
-               /* Clear DCCRX with MRC(p14, 0, Rd, c0, c5, 0), opcode  0xEE100E15 */
-               retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
        }
 
-       if (Rd > 17)
-               return retval;
-
-       /* Write DTRRX ... sets DSCR.DTRRXfull but exec_opcode() won't care */
-       LOG_DEBUG("write DCC 0x%08" PRIx32, value);
-       retval = mem_ap_write_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DTRRX, value);
-       if (retval != ERROR_OK)
-               return retval;
-
-       if (Rd < 15) {
-               /* DCCRX to Rn, "MRC p14, 0, Rn, c0, c5, 0", 0xEE10nE15 */
-               retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0),
-                               &dscr);
-
-               if (retval != ERROR_OK)
-                       return retval;
-       } else if (Rd == 15) {
-               /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15
-                * then "mov r15, r0"
-                */
-               retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = cortex_a_exec_opcode(target, 0xE1A0F000, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-       } else {
-               /* DCCRX to R0, "MRC p14, 0, R0, c0, c5, 0", 0xEE100E15
-                * then "MSR CPSR_cxsf, r0" or "MSR SPSR_cxsf, r0" (all fields)
-                */
-               retval = cortex_a_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = cortex_a_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1),
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               /* "Prefetch flush" after modifying execution status in CPSR */
-               if (Rd == 16) {
-                       retval = cortex_a_exec_opcode(target,
-                                       ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
-                                       &dscr);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
-       }
+       if (dscr_p)
+               *dscr_p = dscr;
 
        return retval;
 }
@@ -494,17 +369,11 @@ static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data,
                dscr = *dscr_p;
 
        /* Wait for DTRRXfull */
-       int64_t then = timeval_ms();
-       while ((dscr & DSCR_DTR_TX_FULL) == 0) {
-               retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
-                               a->armv7a_common.debug_base + CPUDBG_DSCR,
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for read dcc");
-                       return ERROR_FAIL;
-               }
+       retval = cortex_a_wait_dscr_bits(a->armv7a_common.arm.target,
+                       DSCR_DTR_TX_FULL, DSCR_DTR_TX_FULL, &dscr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for read dcc");
+               return retval;
        }
 
        retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
@@ -526,19 +395,10 @@ static int cortex_a_dpm_prepare(struct arm_dpm *dpm)
        int retval;
 
        /* set up invariant:  INSTR_COMP is set after ever DPM operation */
-       int64_t then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap,
-                               a->armv7a_common.debug_base + CPUDBG_DSCR,
-                               &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               if ((dscr & DSCR_INSTR_COMP) != 0)
-                       break;
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for dpm prepare");
-                       return ERROR_FAIL;
-               }
+       retval = cortex_a_wait_instrcmpl(dpm->arm->target, &dscr, true);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for dpm prepare");
+               return retval;
        }
 
        /* this "should never happen" ... */
@@ -579,22 +439,35 @@ static int cortex_a_instr_write_data_dcc(struct arm_dpm *dpm,
                        &dscr);
 }
 
-static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
-       uint32_t opcode, uint32_t data)
+static int cortex_a_instr_write_data_rt_dcc(struct arm_dpm *dpm,
+       uint8_t rt, uint32_t data)
 {
        struct cortex_a_common *a = dpm_to_a(dpm);
        uint32_t dscr = DSCR_INSTR_COMP;
        int retval;
 
+       if (rt > 15)
+               return ERROR_TARGET_INVALID;
+
        retval = cortex_a_write_dcc(a, data);
        if (retval != ERROR_OK)
                return retval;
 
-       /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
-       retval = cortex_a_exec_opcode(
+       /* DCCRX to Rt, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
+       return cortex_a_exec_opcode(
                        a->armv7a_common.arm.target,
-                       ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+                       ARMV4_5_MRC(14, 0, rt, 0, 5, 0),
                        &dscr);
+}
+
+static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
+       uint32_t opcode, uint32_t data)
+{
+       struct cortex_a_common *a = dpm_to_a(dpm);
+       uint32_t dscr = DSCR_INSTR_COMP;
+       int retval;
+
+       retval = cortex_a_instr_write_data_rt_dcc(dpm, 0, data);
        if (retval != ERROR_OK)
                return retval;
 
@@ -636,31 +509,43 @@ static int cortex_a_instr_read_data_dcc(struct arm_dpm *dpm,
        return cortex_a_read_dcc(a, data, &dscr);
 }
 
-
-static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm,
-       uint32_t opcode, uint32_t *data)
+static int cortex_a_instr_read_data_rt_dcc(struct arm_dpm *dpm,
+       uint8_t rt, uint32_t *data)
 {
        struct cortex_a_common *a = dpm_to_a(dpm);
        uint32_t dscr = DSCR_INSTR_COMP;
        int retval;
 
-       /* the opcode, writing data to R0 */
+       if (rt > 15)
+               return ERROR_TARGET_INVALID;
+
        retval = cortex_a_exec_opcode(
                        a->armv7a_common.arm.target,
-                       opcode,
+                       ARMV4_5_MCR(14, 0, rt, 0, 5, 0),
                        &dscr);
        if (retval != ERROR_OK)
                return retval;
 
-       /* write R0 to DCC */
+       return cortex_a_read_dcc(a, data, &dscr);
+}
+
+static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm,
+       uint32_t opcode, uint32_t *data)
+{
+       struct cortex_a_common *a = dpm_to_a(dpm);
+       uint32_t dscr = DSCR_INSTR_COMP;
+       int retval;
+
+       /* the opcode, writing data to R0 */
        retval = cortex_a_exec_opcode(
                        a->armv7a_common.arm.target,
-                       ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
+                       opcode,
                        &dscr);
        if (retval != ERROR_OK)
                return retval;
 
-       return cortex_a_read_dcc(a, data, &dscr);
+       /* write R0 to DCC */
+       return cortex_a_instr_read_data_rt_dcc(dpm, 0, data);
 }
 
 static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
@@ -858,39 +743,26 @@ static int cortex_a_poll(struct target *target)
                        /* We have a halting debug event */
                        LOG_DEBUG("Target halted");
                        target->state = TARGET_HALTED;
-                       if ((prev_target_state == TARGET_RUNNING)
-                               || (prev_target_state == TARGET_UNKNOWN)
-                               || (prev_target_state == TARGET_RESET)) {
-                               retval = cortex_a_debug_entry(target);
+
+                       retval = cortex_a_debug_entry(target);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       if (target->smp) {
+                               retval = update_halt_gdb(target);
                                if (retval != ERROR_OK)
                                        return retval;
-                               if (target->smp) {
-                                       retval = update_halt_gdb(target);
-                                       if (retval != ERROR_OK)
-                                               return retval;
-                               }
+                       }
 
+                       if (prev_target_state == TARGET_DEBUG_RUNNING) {
+                               target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
+                       } else { /* prev_target_state is RUNNING, UNKNOWN or RESET */
                                if (arm_semihosting(target, &retval) != 0)
                                        return retval;
 
                                target_call_event_callbacks(target,
                                        TARGET_EVENT_HALTED);
                        }
-                       if (prev_target_state == TARGET_DEBUG_RUNNING) {
-                               LOG_DEBUG(" ");
-
-                               retval = cortex_a_debug_entry(target);
-                               if (retval != ERROR_OK)
-                                       return retval;
-                               if (target->smp) {
-                                       retval = update_halt_gdb(target);
-                                       if (retval != ERROR_OK)
-                                               return retval;
-                               }
-
-                               target_call_event_callbacks(target,
-                                       TARGET_EVENT_DEBUG_HALTED);
-                       }
                }
        } else
                target->state = TARGET_RUNNING;
@@ -900,7 +772,7 @@ static int cortex_a_poll(struct target *target)
 
 static int cortex_a_halt(struct target *target)
 {
-       int retval = ERROR_OK;
+       int retval;
        uint32_t dscr;
        struct armv7a_common *armv7a = target_to_armv7a(target);
 
@@ -913,31 +785,12 @@ static int cortex_a_halt(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
-       /*
-        * enter halting debug mode
-        */
-       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DSCR, &dscr);
-       if (retval != ERROR_OK)
-               return retval;
-
-       retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
-                       armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE);
-       if (retval != ERROR_OK)
+       dscr = 0; /* force read of dscr */
+       retval = cortex_a_wait_dscr_bits(target, DSCR_CORE_HALTED,
+                       DSCR_CORE_HALTED, &dscr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for halt");
                return retval;
-
-       int64_t then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               if ((dscr & DSCR_CORE_HALTED) != 0)
-                       break;
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for halt");
-                       return ERROR_FAIL;
-               }
        }
 
        target->debug_reason = DBG_REASON_DBGRQ;
@@ -965,15 +818,15 @@ static int cortex_a_internal_restore(struct target *target, int current,
                 * C_MASKINTS in parallel with disabled interrupts can cause
                 * local faults to not be taken. */
                buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
-               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
-               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;
+               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = true;
+               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = true;
 
                /* Make sure we are in Thumb mode */
                buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32,
                        buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0,
                        32) | (1 << 24));
-               armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
-               armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
+               armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = true;
+               armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = true;
        }
 #endif
 
@@ -1002,16 +855,16 @@ static int cortex_a_internal_restore(struct target *target, int current,
                        LOG_ERROR("How do I resume into Jazelle state??");
                        return ERROR_FAIL;
                case ARM_STATE_AARCH64:
-                       LOG_ERROR("Shoudn't be in AARCH64 state");
+                       LOG_ERROR("Shouldn't be in AARCH64 state");
                        return ERROR_FAIL;
        }
        LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
        buf_set_u32(arm->pc->value, 0, 32, resume_pc);
-       arm->pc->dirty = 1;
-       arm->pc->valid = 1;
+       arm->pc->dirty = true;
+       arm->pc->valid = true;
 
        /* restore dpm_mode at system halt */
-       dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
+       arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        /* called it now before restoring context because it uses cpu
         * register r0 for restoring cp15 control register */
        retval = cortex_a_restore_cp15_control_reg(target);
@@ -1076,18 +929,12 @@ static int cortex_a_internal_restart(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
-       int64_t then = timeval_ms();
-       for (;; ) {
-               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
-                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
-               if (retval != ERROR_OK)
-                       return retval;
-               if ((dscr & DSCR_CORE_RESTARTED) != 0)
-                       break;
-               if (timeval_ms() > then + 1000) {
-                       LOG_ERROR("Timeout waiting for resume");
-                       return ERROR_FAIL;
-               }
+       dscr = 0; /* force read of dscr */
+       retval = cortex_a_wait_dscr_bits(target, DSCR_CORE_RESTARTED,
+                       DSCR_CORE_RESTARTED, &dscr);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error waiting for resume");
+               return retval;
        }
 
        target->debug_reason = DBG_REASON_NOTHALTED;
@@ -1158,12 +1005,11 @@ static int cortex_a_resume(struct target *target, int current,
 
 static int cortex_a_debug_entry(struct target *target)
 {
-       uint32_t spsr, dscr;
+       uint32_t dscr;
        int retval = ERROR_OK;
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *arm = &armv7a->arm;
-       struct reg *reg;
 
        LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a->cpudbg_dscr);
 
@@ -1206,16 +1052,10 @@ static int cortex_a_debug_entry(struct target *target)
                return retval;
 
        if (arm->spsr) {
-               /* read Saved PSR */
-               retval = cortex_a_dap_read_coreregister_u32(target, &spsr, 17);
-               /*  store current spsr */
+               /* read SPSR */
+               retval = arm_dpm_read_reg(&armv7a->dpm, arm->spsr, 17);
                if (retval != ERROR_OK)
                        return retval;
-
-               reg = arm->spsr;
-               buf_set_u32(reg->value, 0, 32, spsr);
-               reg->valid = 1;
-               reg->dirty = 0;
        }
 
 #if 0
@@ -1277,7 +1117,7 @@ static int cortex_a_post_debug_entry(struct target *target)
        cortex_a->curr_mode = armv7a->arm.core_mode;
 
        /* switch to SVC mode to read DACR */
-       dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
+       arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_SVC);
        armv7a->arm.mrc(target, 15,
                        0, 0, 3, 0,
                        &cortex_a->cp15_dacr_reg);
@@ -1285,11 +1125,12 @@ static int cortex_a_post_debug_entry(struct target *target)
        LOG_DEBUG("cp15_dacr_reg: %8.8" PRIx32,
                        cortex_a->cp15_dacr_reg);
 
-       dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
+       arm_dpm_modeswitch(&armv7a->dpm, ARM_MODE_ANY);
        return ERROR_OK;
 }
 
-int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsigned long value)
+static int cortex_a_set_dscr_bits(struct target *target,
+               unsigned long bit_mask, unsigned long value)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
        uint32_t dscr;
@@ -1374,6 +1215,8 @@ static int cortex_a_step(struct target *target, int current, target_addr_t addre
                retval = cortex_a_poll(target);
                if (retval != ERROR_OK)
                        return retval;
+               if (target->state == TARGET_HALTED)
+                       break;
                if (timeval_ms() > then + 1000) {
                        LOG_ERROR("timeout waiting for target halt");
                        return ERROR_FAIL;
@@ -1447,7 +1290,7 @@ static int cortex_a_set_breakpoint(struct target *target,
                control = ((matchmode & 0x7) << 20)
                        | (byte_addr_select << 5)
                        | (3 << 1) | 1;
-               brp_list[brp_i].used = 1;
+               brp_list[brp_i].used = true;
                brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
                brp_list[brp_i].control = control;
                retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
@@ -1541,7 +1384,7 @@ static int cortex_a_set_context_breakpoint(struct target *target,
        control = ((matchmode & 0x7) << 20)
                | (byte_addr_select << 5)
                | (3 << 1) | 1;
-       brp_list[brp_i].used = 1;
+       brp_list[brp_i].used = true;
        brp_list[brp_i].value = (breakpoint->asid);
        brp_list[brp_i].control = control;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
@@ -1607,7 +1450,7 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
                | (0 << 14)
                | (CTX_byte_addr_select << 5)
                | (3 << 1) | 1;
-       brp_list[brp_1].used = 1;
+       brp_list[brp_1].used = true;
        brp_list[brp_1].value = (breakpoint->asid);
        brp_list[brp_1].control = control_CTX;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
@@ -1625,7 +1468,7 @@ static int cortex_a_set_hybrid_breakpoint(struct target *target, struct breakpoi
                | (brp_1 << 16)
                | (IVA_byte_addr_select << 5)
                | (3 << 1) | 1;
-       brp_list[brp_2].used = 1;
+       brp_list[brp_2].used = true;
        brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC);
        brp_list[brp_2].control = control_IVA;
        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
@@ -1664,7 +1507,7 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
                        }
                        LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
                                brp_list[brp_i].control, brp_list[brp_i].value);
-                       brp_list[brp_i].used = 0;
+                       brp_list[brp_i].used = false;
                        brp_list[brp_i].value = 0;
                        brp_list[brp_i].control = 0;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
@@ -1683,7 +1526,7 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
                        }
                        LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_j,
                                brp_list[brp_j].control, brp_list[brp_j].value);
-                       brp_list[brp_j].used = 0;
+                       brp_list[brp_j].used = false;
                        brp_list[brp_j].value = 0;
                        brp_list[brp_j].control = 0;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
@@ -1708,7 +1551,7 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
                        }
                        LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
                                brp_list[brp_i].control, brp_list[brp_i].value);
-                       brp_list[brp_i].used = 0;
+                       brp_list[brp_i].used = false;
                        brp_list[brp_i].value = 0;
                        brp_list[brp_i].control = 0;
                        retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
@@ -1829,6 +1672,200 @@ static int cortex_a_remove_breakpoint(struct target *target, struct breakpoint *
        return ERROR_OK;
 }
 
+/**
+ * Sets a watchpoint for an Cortex-A target in one of the watchpoint units.  It is
+ * considered a bug to call this function when there are no available watchpoint
+ * units.
+ *
+ * @param target Pointer to an Cortex-A target to set a watchpoint on
+ * @param watchpoint Pointer to the watchpoint to be set
+ * @return Error status if watchpoint set fails or the result of executing the
+ * JTAG queue
+ */
+static int cortex_a_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       int retval = ERROR_OK;
+       int wrp_i = 0;
+       uint32_t control;
+       uint32_t address;
+       uint8_t address_mask;
+       uint8_t byte_address_select;
+       uint8_t load_store_access_control = 0x3;
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+       struct armv7a_common *armv7a = &cortex_a->armv7a_common;
+       struct cortex_a_wrp *wrp_list = cortex_a->wrp_list;
+
+       if (watchpoint->set) {
+               LOG_WARNING("watchpoint already set");
+               return retval;
+       }
+
+       /* check available context WRPs */
+       while (wrp_list[wrp_i].used && (wrp_i < cortex_a->wrp_num))
+               wrp_i++;
+
+       if (wrp_i >= cortex_a->wrp_num) {
+               LOG_ERROR("ERROR Can not find free Watchpoint Register Pair");
+               return ERROR_FAIL;
+       }
+
+       if (watchpoint->length == 0 || watchpoint->length > 0x80000000U ||
+                       (watchpoint->length & (watchpoint->length - 1))) {
+               LOG_WARNING("watchpoint length must be a power of 2");
+               return ERROR_FAIL;
+       }
+
+       if (watchpoint->address & (watchpoint->length - 1)) {
+               LOG_WARNING("watchpoint address must be aligned at length");
+               return ERROR_FAIL;
+       }
+
+       /* FIXME: ARM DDI 0406C: address_mask is optional. What to do if it's missing?  */
+       /* handle wp length 1 and 2 through byte select */
+       switch (watchpoint->length) {
+       case 1:
+               byte_address_select = BIT(watchpoint->address & 0x3);
+               address = watchpoint->address & ~0x3;
+               address_mask = 0;
+               break;
+
+       case 2:
+               byte_address_select = 0x03 << (watchpoint->address & 0x2);
+               address = watchpoint->address & ~0x3;
+               address_mask = 0;
+               break;
+
+       case 4:
+               byte_address_select = 0x0f;
+               address = watchpoint->address;
+               address_mask = 0;
+               break;
+
+       default:
+               byte_address_select = 0xff;
+               address = watchpoint->address;
+               address_mask = ilog2(watchpoint->length);
+               break;
+       }
+
+       watchpoint->set = wrp_i + 1;
+       control = (address_mask << 24) |
+               (byte_address_select << 5) |
+               (load_store_access_control << 3) |
+               (0x3 << 1) | 1;
+       wrp_list[wrp_i].used = true;
+       wrp_list[wrp_i].value = address;
+       wrp_list[wrp_i].control = control;
+
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].WRPn,
+                       wrp_list[wrp_i].value);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].WRPn,
+                       wrp_list[wrp_i].control);
+       if (retval != ERROR_OK)
+               return retval;
+
+       LOG_DEBUG("wp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, wrp_i,
+                       wrp_list[wrp_i].control,
+                       wrp_list[wrp_i].value);
+
+       return ERROR_OK;
+}
+
+/**
+ * Unset an existing watchpoint and clear the used watchpoint unit.
+ *
+ * @param target Pointer to the target to have the watchpoint removed
+ * @param watchpoint Pointer to the watchpoint to be removed
+ * @return Error status while trying to unset the watchpoint or the result of
+ *         executing the JTAG queue
+ */
+static int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       int retval;
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+       struct armv7a_common *armv7a = &cortex_a->armv7a_common;
+       struct cortex_a_wrp *wrp_list = cortex_a->wrp_list;
+
+       if (!watchpoint->set) {
+               LOG_WARNING("watchpoint not set");
+               return ERROR_OK;
+       }
+
+       int wrp_i = watchpoint->set - 1;
+       if (wrp_i < 0 || wrp_i >= cortex_a->wrp_num) {
+               LOG_DEBUG("Invalid WRP number in watchpoint");
+               return ERROR_OK;
+       }
+       LOG_DEBUG("wrp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, wrp_i,
+                       wrp_list[wrp_i].control, wrp_list[wrp_i].value);
+       wrp_list[wrp_i].used = false;
+       wrp_list[wrp_i].value = 0;
+       wrp_list[wrp_i].control = 0;
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].WRPn,
+                       wrp_list[wrp_i].control);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = cortex_a_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].WRPn,
+                       wrp_list[wrp_i].value);
+       if (retval != ERROR_OK)
+               return retval;
+       watchpoint->set = 0;
+
+       return ERROR_OK;
+}
+
+/**
+ * Add a watchpoint to an Cortex-A target.  If there are no watchpoint units
+ * available, an error response is returned.
+ *
+ * @param target Pointer to the Cortex-A target to add a watchpoint to
+ * @param watchpoint Pointer to the watchpoint to be added
+ * @return Error status while trying to add the watchpoint
+ */
+static int cortex_a_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+
+       if (cortex_a->wrp_num_available < 1) {
+               LOG_INFO("no hardware watchpoint available");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       int retval = cortex_a_set_watchpoint(target, watchpoint);
+       if (retval != ERROR_OK)
+               return retval;
+
+       cortex_a->wrp_num_available--;
+       return ERROR_OK;
+}
+
+/**
+ * Remove a watchpoint from an Cortex-A target.  The watchpoint will be unset and
+ * the used watchpoint unit will be reopened.
+ *
+ * @param target Pointer to the target to remove a watchpoint from
+ * @param watchpoint Pointer to the watchpoint to be removed
+ * @return Result of trying to unset the watchpoint
+ */
+static int cortex_a_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       struct cortex_a_common *cortex_a = target_to_cortex_a(target);
+
+       if (watchpoint->set) {
+               cortex_a->wrp_num_available++;
+               cortex_a_unset_watchpoint(target, watchpoint);
+       }
+       return ERROR_OK;
+}
+
+
 /*
  * Cortex-A Reset functions
  */
@@ -1852,12 +1889,12 @@ static int cortex_a_assert_reset(struct target *target)
                 */
 
                /*
-                * FIXME: fix reset when transport is SWD. This is a temporary
+                * FIXME: fix reset when transport is not JTAG. This is a temporary
                 * work-around for release v0.10 that is not intended to stay!
                 */
-               if (transport_is_swd() ||
+               if (!transport_is_jtag() ||
                                (target->reset_halt && (jtag_get_reset_config() & RESET_SRST_NO_GATING)))
-                       jtag_add_reset(0, 1);
+                       adapter_assert_reset();
 
        } else {
                LOG_ERROR("%s: how to reset?", target_name(target));
@@ -1875,12 +1912,13 @@ static int cortex_a_assert_reset(struct target *target)
 
 static int cortex_a_deassert_reset(struct target *target)
 {
+       struct armv7a_common *armv7a = target_to_armv7a(target);
        int retval;
 
        LOG_DEBUG(" ");
 
        /* be certain SRST is off */
-       jtag_add_reset(0, 0);
+       adapter_deassert_reset();
 
        if (target_was_examined(target)) {
                retval = cortex_a_poll(target);
@@ -1893,7 +1931,8 @@ static int cortex_a_deassert_reset(struct target *target)
                        LOG_WARNING("%s: ran after reset and before halt ...",
                                target_name(target));
                        if (target_was_examined(target)) {
-                               retval = target_halt(target);
+                               retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+                                               armv7a->debug_base + CPUDBG_DRCR, DRCR_HALT);
                                if (retval != ERROR_OK)
                                        return retval;
                        } else
@@ -1931,14 +1970,22 @@ static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask,
 {
        /* Waits until the specified bit(s) of DSCR take on a specified value. */
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       int64_t then = timeval_ms();
+       int64_t then;
        int retval;
 
-       while ((*dscr & mask) != value) {
+       if ((*dscr & mask) == value)
+               return ERROR_OK;
+
+       then = timeval_ms();
+       while (1) {
                retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                                armv7a->debug_base + CPUDBG_DSCR, dscr);
-               if (retval != ERROR_OK)
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Could not read DSCR register");
                        return retval;
+               }
+               if ((*dscr & mask) == value)
+                       break;
                if (timeval_ms() > then + 1000) {
                        LOG_ERROR("timeout waiting for DSCR bit change");
                        return ERROR_FAIL;
@@ -2082,7 +2129,8 @@ static int cortex_a_write_cpu_memory_slow(struct target *target,
 {
        /* Writes count objects of size size from *buffer. Old value of DSCR must
         * be in *dscr; updated to new value. This is slow because it works for
-        * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and
+        * non-word-sized objects. Avoid unaligned accesses as they do not work
+        * on memory address space without "Normal" attribute. If size == 4 and
         * the address is aligned, cortex_a_write_cpu_memory_fast should be
         * preferred.
         * Preconditions:
@@ -2239,7 +2287,22 @@ static int cortex_a_write_cpu_memory(struct target *target,
                /* We are doing a word-aligned transfer, so use fast mode. */
                retval = cortex_a_write_cpu_memory_fast(target, count, buffer, &dscr);
        } else {
-               /* Use slow path. */
+               /* Use slow path. Adjust size for aligned accesses */
+               switch (address % 4) {
+                       case 1:
+                       case 3:
+                               count *= size;
+                               size = 1;
+                               break;
+                       case 2:
+                               if (size == 4) {
+                                       count *= 2;
+                                       size = 2;
+                               }
+                       case 0:
+                       default:
+                               break;
+               }
                retval = cortex_a_write_cpu_memory_slow(target, size, count, buffer, &dscr);
        }
 
@@ -2325,7 +2388,8 @@ static int cortex_a_read_cpu_memory_slow(struct target *target,
 {
        /* Reads count objects of size size into *buffer. Old value of DSCR must be
         * in *dscr; updated to new value. This is slow because it works for
-        * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and
+        * non-word-sized objects. Avoid unaligned accesses as they do not work
+        * on memory address space without "Normal" attribute. If size == 4 and
         * the address is aligned, cortex_a_read_cpu_memory_fast should be
         * preferred.
         * Preconditions:
@@ -2541,7 +2605,23 @@ static int cortex_a_read_cpu_memory(struct target *target,
                /* We are doing a word-aligned transfer, so use fast mode. */
                retval = cortex_a_read_cpu_memory_fast(target, count, buffer, &dscr);
        } else {
-               /* Use slow path. */
+               /* Use slow path. Adjust size for aligned accesses */
+               switch (address % 4) {
+                       case 1:
+                       case 3:
+                               count *= size;
+                               size = 1;
+                               break;
+                       case 2:
+                               if (size == 4) {
+                                       count *= 2;
+                                       size = 2;
+                               }
+                               break;
+                       case 0:
+                       default:
+                               break;
+               }
                retval = cortex_a_read_cpu_memory_slow(target, size, count, buffer, &dscr);
        }
 
@@ -2627,7 +2707,7 @@ static int cortex_a_read_phys_memory(struct target *target,
        if (!count || !buffer)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32,
+       LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
                address, size, count);
 
        /* read memory through the CPU */
@@ -2644,7 +2724,7 @@ static int cortex_a_read_memory(struct target *target, target_addr_t address,
        int retval;
 
        /* cortex_a handles unaligned memory access */
-       LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32,
+       LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
                address, size, count);
 
        cortex_a_prep_memaccess(target, 0);
@@ -2663,7 +2743,7 @@ static int cortex_a_write_phys_memory(struct target *target,
        if (!count || !buffer)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32,
+       LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
                address, size, count);
 
        /* write memory through the CPU */
@@ -2680,7 +2760,7 @@ static int cortex_a_write_memory(struct target *target, target_addr_t address,
        int retval;
 
        /* cortex_a handles unaligned memory access */
-       LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32,
+       LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRIu32 "; count %" PRIu32,
                address, size, count);
 
        /* memory writes bypass the caches, must flush before writing */
@@ -2809,7 +2889,7 @@ static int cortex_a_examine_first(struct target *target)
 
        int i;
        int retval = ERROR_OK;
-       uint32_t didr, cpuid, dbg_osreg;
+       uint32_t didr, cpuid, dbg_osreg, dbg_idpfr1;
 
        /* Search for the APB-AP - it is needed for access to debug registers */
        retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap);
@@ -2849,6 +2929,10 @@ static int cortex_a_examine_first(struct target *target)
        } else
                armv7a->debug_base = target->dbgbase;
 
+       if ((armv7a->debug_base & (1UL<<31)) == 0)
+               LOG_WARNING("Debug base address for target %s has bit 31 set to 0. Access to debug registers will likely fail!\n"
+                           "Please fix the target configuration.", target_name(target));
+
        retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
                        armv7a->debug_base + CPUDBG_DIDR, &didr);
        if (retval != ERROR_OK) {
@@ -2914,7 +2998,25 @@ static int cortex_a_examine_first(struct target *target)
                }
        }
 
-       armv7a->arm.core_type = ARM_MODE_MON;
+       retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                                armv7a->debug_base + CPUDBG_ID_PFR1, &dbg_idpfr1);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (dbg_idpfr1 & 0x000000f0) {
+               LOG_DEBUG("target->coreid %" PRId32 " has security extensions",
+                               target->coreid);
+               armv7a->arm.core_type = ARM_CORE_TYPE_SEC_EXT;
+       }
+       if (dbg_idpfr1 & 0x0000f000) {
+               LOG_DEBUG("target->coreid %" PRId32 " has virtualization extensions",
+                               target->coreid);
+               /*
+                * overwrite and simplify the checks.
+                * virtualization extensions require implementation of security extension
+                */
+               armv7a->arm.core_type = ARM_CORE_TYPE_VIRT_EXT;
+       }
 
        /* Avoid recreating the registers cache */
        if (!target_was_examined(target)) {
@@ -2931,7 +3033,7 @@ static int cortex_a_examine_first(struct target *target)
        cortex_a->brp_list = calloc(cortex_a->brp_num, sizeof(struct cortex_a_brp));
 /*     cortex_a->brb_enabled = ????; */
        for (i = 0; i < cortex_a->brp_num; i++) {
-               cortex_a->brp_list[i].used = 0;
+               cortex_a->brp_list[i].used = false;
                if (i < (cortex_a->brp_num-cortex_a->brp_num_context))
                        cortex_a->brp_list[i].type = BRP_NORMAL;
                else
@@ -2943,6 +3045,20 @@ static int cortex_a_examine_first(struct target *target)
 
        LOG_DEBUG("Configured %i hw breakpoints", cortex_a->brp_num);
 
+       /* Setup Watchpoint Register Pairs */
+       cortex_a->wrp_num = ((didr >> 28) & 0x0F) + 1;
+       cortex_a->wrp_num_available = cortex_a->wrp_num;
+       free(cortex_a->wrp_list);
+       cortex_a->wrp_list = calloc(cortex_a->wrp_num, sizeof(struct cortex_a_wrp));
+       for (i = 0; i < cortex_a->wrp_num; i++) {
+               cortex_a->wrp_list[i].used = false;
+               cortex_a->wrp_list[i].value = 0;
+               cortex_a->wrp_list[i].control = 0;
+               cortex_a->wrp_list[i].WRPn = i;
+       }
+
+       LOG_DEBUG("Configured %i hw watchpoints", cortex_a->wrp_num);
+
        /* select debug_ap as default */
        swjdp->apsel = armv7a->debug_ap->ap_num;
 
@@ -2999,15 +3115,15 @@ static int cortex_a_init_arch_info(struct target *target,
 
        /* REVISIT v7a setup should be in a v7a-specific routine */
        armv7a_init_arch_info(target, armv7a);
-       target_register_timer_callback(cortex_a_handle_target_request, 1, 1, target);
+       target_register_timer_callback(cortex_a_handle_target_request, 1,
+               TARGET_TIMER_TYPE_PERIODIC, target);
 
        return ERROR_OK;
 }
 
 static int cortex_a_target_create(struct target *target, Jim_Interp *interp)
 {
-       struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common));
-       cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
+       struct cortex_a_common *cortex_a;
        struct adiv5_private_config *pc;
 
        if (target->private_config == NULL)
@@ -3015,8 +3131,13 @@ static int cortex_a_target_create(struct target *target, Jim_Interp *interp)
 
        pc = (struct adiv5_private_config *)target->private_config;
 
+       cortex_a = calloc(1, sizeof(struct cortex_a_common));
+       if (cortex_a == NULL) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+       cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
        cortex_a->armv7a_common.is_armv7r = false;
-
        cortex_a->armv7a_common.arm.arm_vfp_version = ARM_VFP_V3;
 
        return cortex_a_init_arch_info(target, cortex_a, pc->dap);
@@ -3024,14 +3145,19 @@ static int cortex_a_target_create(struct target *target, Jim_Interp *interp)
 
 static int cortex_r4_target_create(struct target *target, Jim_Interp *interp)
 {
-       struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common));
-       cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
+       struct cortex_a_common *cortex_a;
        struct adiv5_private_config *pc;
 
        pc = (struct adiv5_private_config *)target->private_config;
        if (adiv5_verify_config(pc) != ERROR_OK)
                return ERROR_FAIL;
 
+       cortex_a = calloc(1, sizeof(struct cortex_a_common));
+       if (cortex_a == NULL) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+       cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
        cortex_a->armv7a_common.is_armv7r = true;
 
        return cortex_a_init_arch_info(target, cortex_a, pc->dap);
@@ -3040,9 +3166,24 @@ static int cortex_r4_target_create(struct target *target, Jim_Interp *interp)
 static void cortex_a_deinit_target(struct target *target)
 {
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
-       struct arm_dpm *dpm = &cortex_a->armv7a_common.dpm;
+       struct armv7a_common *armv7a = &cortex_a->armv7a_common;
+       struct arm_dpm *dpm = &armv7a->dpm;
+       uint32_t dscr;
+       int retval;
 
+       if (target_was_examined(target)) {
+               /* Disable halt for breakpoint, watchpoint and vector catch */
+               retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
+                               armv7a->debug_base + CPUDBG_DSCR, &dscr);
+               if (retval == ERROR_OK)
+                       mem_ap_write_atomic_u32(armv7a->debug_ap,
+                                       armv7a->debug_base + CPUDBG_DSCR,
+                                       dscr & ~DSCR_HALT_DBG_MODE);
+       }
+
+       free(cortex_a->wrp_list);
        free(cortex_a->brp_list);
+       arm_free_reg_cache(dpm->arm);
        free(dpm->dbp);
        free(dpm->dwp);
        free(target->private_config);
@@ -3089,7 +3230,7 @@ static int cortex_a_virt2phys(struct target *target,
        if (retval != ERROR_OK)
                return retval;
        return armv7a_mmu_translate_va_pa(target, (uint32_t)virt,
-                                                   (uint32_t *)phys, 1);
+                                                   phys, 1);
 }
 
 COMMAND_HANDLER(cortex_a_handle_cache_info_command)
@@ -3097,7 +3238,7 @@ COMMAND_HANDLER(cortex_a_handle_cache_info_command)
        struct target *target = get_current_target(CMD_CTX);
        struct armv7a_common *armv7a = target_to_armv7a(target);
 
-       return armv7a_handle_cache_info_command(CMD_CTX,
+       return armv7a_handle_cache_info_command(CMD,
                        &armv7a->armv7a_mmu.armv7a_cache);
 }
 
@@ -3112,78 +3253,21 @@ COMMAND_HANDLER(cortex_a_handle_dbginit_command)
 
        return cortex_a_init_debug_access(target);
 }
-COMMAND_HANDLER(cortex_a_handle_smp_off_command)
-{
-       struct target *target = get_current_target(CMD_CTX);
-       /* check target is an smp target */
-       struct target_list *head;
-       struct target *curr;
-       head = target->head;
-       target->smp = 0;
-       if (head != (struct target_list *)NULL) {
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       curr->smp = 0;
-                       head = head->next;
-               }
-               /*  fixes the target display to the debugger */
-               target->gdb_service->target = target;
-       }
-       return ERROR_OK;
-}
-
-COMMAND_HANDLER(cortex_a_handle_smp_on_command)
-{
-       struct target *target = get_current_target(CMD_CTX);
-       struct target_list *head;
-       struct target *curr;
-       head = target->head;
-       if (head != (struct target_list *)NULL) {
-               target->smp = 1;
-               while (head != (struct target_list *)NULL) {
-                       curr = head->target;
-                       curr->smp = 1;
-                       head = head->next;
-               }
-       }
-       return ERROR_OK;
-}
-
-COMMAND_HANDLER(cortex_a_handle_smp_gdb_command)
-{
-       struct target *target = get_current_target(CMD_CTX);
-       int retval = ERROR_OK;
-       struct target_list *head;
-       head = target->head;
-       if (head != (struct target_list *)NULL) {
-               if (CMD_ARGC == 1) {
-                       int coreid = 0;
-                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid);
-                       if (ERROR_OK != retval)
-                               return retval;
-                       target->gdb_service->core[1] = coreid;
-
-               }
-               command_print(CMD_CTX, "gdb coreid  %" PRId32 " -> %" PRId32, target->gdb_service->core[0]
-                       , target->gdb_service->core[1]);
-       }
-       return ERROR_OK;
-}
 
 COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
 {
        struct target *target = get_current_target(CMD_CTX);
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
 
-       static const Jim_Nvp nvp_maskisr_modes[] = {
+       static const struct jim_nvp nvp_maskisr_modes[] = {
                { .name = "off", .value = CORTEX_A_ISRMASK_OFF },
                { .name = "on", .value = CORTEX_A_ISRMASK_ON },
                { .name = NULL, .value = -1 },
        };
-       const Jim_Nvp *n;
+       const struct jim_nvp *n;
 
        if (CMD_ARGC > 0) {
-               n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[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;
@@ -3192,8 +3276,8 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command)
                cortex_a->isrmasking_mode = n->value;
        }
 
-       n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_a->isrmasking_mode);
-       command_print(CMD_CTX, "cortex_a interrupt mask %s", n->name);
+       n = jim_nvp_value2name_simple(nvp_maskisr_modes, cortex_a->isrmasking_mode);
+       command_print(CMD, "cortex_a interrupt mask %s", n->name);
 
        return ERROR_OK;
 }
@@ -3203,23 +3287,23 @@ COMMAND_HANDLER(handle_cortex_a_dacrfixup_command)
        struct target *target = get_current_target(CMD_CTX);
        struct cortex_a_common *cortex_a = target_to_cortex_a(target);
 
-       static const Jim_Nvp nvp_dacrfixup_modes[] = {
+       static const struct jim_nvp nvp_dacrfixup_modes[] = {
                { .name = "off", .value = CORTEX_A_DACRFIXUP_OFF },
                { .name = "on", .value = CORTEX_A_DACRFIXUP_ON },
                { .name = NULL, .value = -1 },
        };
-       const Jim_Nvp *n;
+       const struct jim_nvp *n;
 
        if (CMD_ARGC > 0) {
-               n = Jim_Nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]);
+               n = jim_nvp_name2value_simple(nvp_dacrfixup_modes, CMD_ARGV[0]);
                if (n->name == NULL)
                        return ERROR_COMMAND_SYNTAX_ERROR;
                cortex_a->dacrfixup_mode = n->value;
 
        }
 
-       n = Jim_Nvp_value2name_simple(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
-       command_print(CMD_CTX, "cortex_a domain access control fixup %s", n->name);
+       n = jim_nvp_value2name_simple(nvp_dacrfixup_modes, cortex_a->dacrfixup_mode);
+       command_print(CMD, "cortex_a domain access control fixup %s", n->name);
 
        return ERROR_OK;
 }
@@ -3239,25 +3323,6 @@ static const struct command_registration cortex_a_exec_command_handlers[] = {
                .help = "Initialize core debug",
                .usage = "",
        },
-       {   .name = "smp_off",
-           .handler = cortex_a_handle_smp_off_command,
-           .mode = COMMAND_EXEC,
-           .help = "Stop smp handling",
-           .usage = "",},
-       {
-               .name = "smp_on",
-               .handler = cortex_a_handle_smp_on_command,
-               .mode = COMMAND_EXEC,
-               .help = "Restart smp handling",
-               .usage = "",
-       },
-       {
-               .name = "smp_gdb",
-               .handler = cortex_a_handle_smp_gdb_command,
-               .mode = COMMAND_EXEC,
-               .help = "display/fix current core played to gdb",
-               .usage = "",
-       },
        {
                .name = "maskisr",
                .handler = handle_cortex_a_mask_interrupts_command,
@@ -3273,6 +3338,12 @@ static const struct command_registration cortex_a_exec_command_handlers[] = {
                        "on memory access",
                .usage = "['on'|'off']",
        },
+       {
+               .chain = armv7a_mmu_command_handlers,
+       },
+       {
+               .chain = smp_command_handlers,
+       },
 
        COMMAND_REGISTRATION_DONE
 };
@@ -3295,7 +3366,6 @@ static const struct command_registration cortex_a_command_handlers[] = {
 
 struct target_type cortexa_target = {
        .name = "cortex_a",
-       .deprecated_name = "cortex_a8",
 
        .poll = cortex_a_poll,
        .arch_state = armv7a_arch_state,
@@ -3308,6 +3378,7 @@ struct target_type cortexa_target = {
        .deassert_reset = cortex_a_deassert_reset,
 
        /* REVISIT allow exporting VFP3 registers ... */
+       .get_gdb_arch = arm_get_gdb_arch,
        .get_gdb_reg_list = arm_get_gdb_reg_list,
 
        .read_memory = cortex_a_read_memory,
@@ -3325,8 +3396,8 @@ struct target_type cortexa_target = {
        .add_context_breakpoint = cortex_a_add_context_breakpoint,
        .add_hybrid_breakpoint = cortex_a_add_hybrid_breakpoint,
        .remove_breakpoint = cortex_a_remove_breakpoint,
-       .add_watchpoint = NULL,
-       .remove_watchpoint = NULL,
+       .add_watchpoint = cortex_a_add_watchpoint,
+       .remove_watchpoint = cortex_a_remove_watchpoint,
 
        .commands = cortex_a_command_handlers,
        .target_create = cortex_a_target_create,
@@ -3387,6 +3458,7 @@ struct target_type cortexr4_target = {
        .deassert_reset = cortex_a_deassert_reset,
 
        /* REVISIT allow exporting VFP3 registers ... */
+       .get_gdb_arch = arm_get_gdb_arch,
        .get_gdb_reg_list = arm_get_gdb_reg_list,
 
        .read_memory = cortex_a_read_phys_memory,
@@ -3401,8 +3473,8 @@ struct target_type cortexr4_target = {
        .add_context_breakpoint = cortex_a_add_context_breakpoint,
        .add_hybrid_breakpoint = cortex_a_add_hybrid_breakpoint,
        .remove_breakpoint = cortex_a_remove_breakpoint,
-       .add_watchpoint = NULL,
-       .remove_watchpoint = NULL,
+       .add_watchpoint = cortex_a_add_watchpoint,
+       .remove_watchpoint = cortex_a_remove_watchpoint,
 
        .commands = cortex_r4_command_handlers,
        .target_create = cortex_r4_target_create,