From ca76c14ec4db0c52ac5928cb671712b16a53a094 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 9 Oct 2023 14:44:52 +0100 Subject: [PATCH 01/22] cortexar: Renamed cortexr.c ready to unify the Cortex-A and Cortex-R support --- src/Makefile | 8 ++++---- src/platforms/hosted/Makefile.inc | 2 +- src/target/{cortexr.c => cortexar.c} | 0 3 files changed, 5 insertions(+), 5 deletions(-) rename src/target/{cortexr.c => cortexar.c} (100%) diff --git a/src/Makefile b/src/Makefile index 85f35d3c4bc..ca67f86bb7d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ PROBE_HOST ?= native PLATFORM_DIR = platforms/$(PROBE_HOST) VPATH += $(PLATFORM_DIR) target ENABLE_DEBUG ?= 0 -ENABLE_CORTEXR ?= 0 +ENABLE_CORTEXAR ?= 0 SYS = $(shell $(CC) -dumpmachine) @@ -90,9 +90,9 @@ ifeq (,$(filter all_platforms,$(MAKECMDGOALS))) include $(PLATFORM_DIR)/Makefile.inc endif -ifeq ($(ENABLE_CORTEXR), 1) -CFLAGS += -DENABLE_CORTEXR -SRC += cortexr.c +ifeq ($(ENABLE_CORTEXAR), 1) +CFLAGS += -DENABLE_CORTEXAR +SRC += cortexar.c endif ifneq ($(PC_HOSTED),1) diff --git a/src/platforms/hosted/Makefile.inc b/src/platforms/hosted/Makefile.inc index f73cc319af7..1d00a0264d7 100644 --- a/src/platforms/hosted/Makefile.inc +++ b/src/platforms/hosted/Makefile.inc @@ -5,7 +5,7 @@ SYS := $(shell $(CC) -dumpmachine) CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG CFLAGS +=-I ./target -ENABLE_CORTEXR := 1 +ENABLE_CORTEXAR := 1 # Clang requires some special handling here: -gnu means MinGW # while -msvc means Clang/CL. We don't currently support the latter diff --git a/src/target/cortexr.c b/src/target/cortexar.c similarity index 100% rename from src/target/cortexr.c rename to src/target/cortexar.c From 635818f94776cbec72ecb81db5cd0b7d519e3923 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 11 Oct 2023 20:05:41 +0100 Subject: [PATCH 02/22] cortexar: Implemented handling for i-cache flushing VMSA parts for resume --- src/target/cortexar.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 4110b738900..89ed0c143d8 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -238,9 +238,10 @@ static const uint16_t cortexr_spsr_encodings[5] = { #define ARM_STRH_R1_R0_INSN 0xe0e010b2U /* Coprocessor register definitions */ -#define CORTEXR_CPACR 15U, ENCODE_CP_REG(1U, 0U, 0U, 2U) -#define CORTEXR_DFSR 15U, ENCODE_CP_REG(5U, 0U, 0U, 0U) -#define CORTEXR_DFAR 15U, ENCODE_CP_REG(6U, 0U, 0U, 0U) +#define CORTEXR_CPACR 15U, ENCODE_CP_REG(1U, 0U, 0U, 2U) +#define CORTEXR_DFSR 15U, ENCODE_CP_REG(5U, 0U, 0U, 0U) +#define CORTEXR_DFAR 15U, ENCODE_CP_REG(6U, 0U, 0U, 0U) +#define CORTEXR_ICIALLU 15U, ENCODE_CP_REG(7U, 5U, 0U, 0U) #define CORTEXR_CPACR_CP10_FULL_ACCESS 0x00300000U #define CORTEXR_CPACR_CP11_FULL_ACCESS 0x00c00000U @@ -1077,6 +1078,10 @@ static void cortexr_halt_resume(target_s *const target, const bool step) dscr &= ~CORTEXR_DBG_DSCR_INTERRUPT_DISABLE; } + /* Invalidate all the instruction caches if we're on a VMSA model device */ + if (target->target_options & TOPT_FLAVOUR_VIRT_MEM) + cortexr_coproc_write(target, CORTEXR_ICIALLU, 0U); + cortex_dbg_write32(target, CORTEXR_DBG_DSCR, dscr & ~CORTEXR_DBG_DSCR_ITR_ENABLE); /* Ask to resume the core */ cortex_dbg_write32(target, CORTEXR_DBG_DRCR, CORTEXR_DBG_DRCR_CLR_STICKY_EXC | CORTEXR_DBG_DRCR_RESTART_REQ); From d843faf7c1dc620d7e5ffc8e5ed062f57d2b8efa Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sat, 14 Oct 2023 22:51:38 +0100 Subject: [PATCH 03/22] cortexar: Renamed the private structure as it's common to both -A and -R support --- src/target/cortexar.c | 46 +++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 89ed0c143d8..b16f0c9d81c 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -56,7 +56,7 @@ #include -typedef struct cortexr_priv { +typedef struct cortexar_priv { /* Base core information */ cortex_priv_s base; @@ -71,7 +71,7 @@ typedef struct cortexr_priv { /* Control and status information */ uint8_t core_status; -} cortexr_priv_s; +} cortexar_priv_s; #define CORTEXR_DBG_IDR 0x000U #define CORTEXR_DBG_WFAR 0x018U @@ -322,7 +322,7 @@ static bool cortexr_run_insn(target_s *const target, const uint32_t insn) status = cortex_dbg_read32(target, CORTEXR_DBG_DSCR); /* If the instruction triggered a synchronous data abort, signal failure having cleared it */ if (status & CORTEXR_DBG_DSCR_SYNC_DATA_ABORT) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; priv->core_status |= CORTEXR_STATUS_DATA_FAULT; cortex_dbg_write32(target, CORTEXR_DBG_DRCR, CORTEXR_DBG_DRCR_CLR_STICKY_EXC); } @@ -340,7 +340,7 @@ static bool cortexr_run_read_insn(target_s *const target, const uint32_t insn, u status = cortex_dbg_read32(target, CORTEXR_DBG_DSCR); /* If the instruction triggered a synchronous data abort, signal failure having cleared it */ if (status & CORTEXR_DBG_DSCR_SYNC_DATA_ABORT) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; priv->core_status |= CORTEXR_STATUS_DATA_FAULT; cortex_dbg_write32(target, CORTEXR_DBG_DRCR, CORTEXR_DBG_DRCR_CLR_STICKY_EXC); return false; @@ -367,7 +367,7 @@ static bool cortexr_run_write_insn(target_s *const target, const uint32_t insn, status = cortex_dbg_read32(target, CORTEXR_DBG_DSCR); /* If the instruction triggered a synchronous data abort, signal failure having cleared it */ if (status & CORTEXR_DBG_DSCR_SYNC_DATA_ABORT) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; priv->core_status |= CORTEXR_STATUS_DATA_FAULT; cortex_dbg_write32(target, CORTEXR_DBG_DRCR, CORTEXR_DBG_DRCR_CLR_STICKY_EXC); return false; @@ -396,7 +396,7 @@ static inline uint32_t cortexr_core_reg_read(target_s *const target, const uint8 static void cortexr_core_regs_save(target_s *const target) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Save out r0-r15 in that order (r15, aka pc, clobbers r0) */ for (size_t i = 0U; i < ARRAY_LENGTH(priv->core_regs.r); ++i) priv->core_regs.r[i] = cortexr_core_reg_read(target, i); @@ -415,7 +415,7 @@ static void cortexr_core_regs_save(target_s *const target) static void cortexr_float_regs_save(target_s *const target) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Read FPCSR to r0 and retrieve it */ cortexr_run_insn(target, ARM_VMRS_R0_FPCSR_INSN); priv->core_regs.fpcsr = cortexr_core_reg_read(target, 0U); @@ -453,7 +453,7 @@ static inline void cortexr_core_reg_write(target_s *const target, const uint8_t static void cortexr_core_regs_restore(target_s *const target) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Load the values for each of the SPSRs in turn into r0 and shove them back into place */ for (size_t i = 0; i < ARRAY_LENGTH(priv->core_regs.spsr); ++i) { cortexr_core_reg_write(target, 0U, priv->core_regs.spsr[i]); @@ -475,7 +475,7 @@ static void cortexr_core_regs_restore(target_s *const target) static void cortexr_float_regs_restore(target_s *const target) { - const cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Step through each double-precision float register, writing it back via r0,r1 */ for (size_t i = 0; i < ARRAY_LENGTH(priv->core_regs.d); ++i) { /* Load the low 32 bits into r0, and the high into r1 */ @@ -545,7 +545,7 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre target->part_id = ap->partno; } - cortexr_priv_s *const priv = calloc(1, sizeof(*priv)); + cortexar_priv_s *const priv = calloc(1, sizeof(*priv)); if (!priv) { /* calloc failed: heap exhaustion */ DEBUG_ERROR("calloc: failed in %s\n", __func__); return false; @@ -681,7 +681,7 @@ bool cortexr_attach(target_s *const target) return false; } - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Clear any stale breakpoints */ priv->base.breakpoints_mask = 0U; for (size_t i = 0; i <= priv->base.breakpoints_available; ++i) { @@ -701,7 +701,7 @@ bool cortexr_attach(target_s *const target) void cortexr_detach(target_s *const target) { - const cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Clear any set breakpoints */ for (size_t i = 0; i <= priv->base.breakpoints_available; ++i) { @@ -720,7 +720,7 @@ void cortexr_detach(target_s *const target) static bool cortexr_check_error(target_s *const target) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; const bool fault = priv->core_status & (CORTEXR_STATUS_DATA_FAULT | CORTEXR_STATUS_MMU_FAULT); priv->core_status = 0; return fault || cortex_check_error(target); @@ -778,7 +778,7 @@ static bool cortexr_mem_read_slow(target_s *const target, uint8_t *const data, t static void cortexr_mem_handle_fault( target_s *const target, const char *const func, const uint32_t orig_fault_status, const uint32_t orig_fault_addr) { - const cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* If we suffered a fault of some kind, grab the reason and restore DFSR/DFAR */ if (priv->core_status & CORTEXR_STATUS_DATA_FAULT) { #ifdef ENABLE_DEBUG @@ -801,7 +801,7 @@ static void cortexr_mem_handle_fault( */ static void cortexr_mem_read(target_s *const target, void *const dest, const target_addr_t src, const size_t len) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Cache DFSR and DFAR in case we wind up triggering a data fault */ const uint32_t fault_status = cortexr_coproc_read(target, CORTEXR_DFSR); const uint32_t fault_addr = cortexr_coproc_read(target, CORTEXR_DFAR); @@ -877,7 +877,7 @@ static bool cortexr_mem_write_slow( */ static void cortexr_mem_write(target_s *const target, const target_addr_t dest, const void *const src, const size_t len) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; DEBUG_TARGET("%s: Writing %zu bytes @0x%" PRIx32 "\n", __func__, len, dest); /* Cache DFSR and DFAR in case we wind up triggering a data fault */ const uint32_t fault_status = cortexr_coproc_read(target, CORTEXR_DFSR); @@ -899,7 +899,7 @@ static void cortexr_mem_write(target_s *const target, const target_addr_t dest, static void cortexr_regs_read(target_s *const target, void *const data) { - const cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; uint32_t *const regs = (uint32_t *)data; /* Copy the register values out from our cache */ memcpy(regs, priv->core_regs.r, sizeof(priv->core_regs.r)); @@ -912,7 +912,7 @@ static void cortexr_regs_read(target_s *const target, void *const data) static void cortexr_regs_write(target_s *const target, const void *const data) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; const uint32_t *const regs = (const uint32_t *)data; /* Copy the new register values into our cache */ memcpy(priv->core_regs.r, regs, sizeof(priv->core_regs.r)); @@ -925,7 +925,7 @@ static void cortexr_regs_write(target_s *const target, const void *const data) static void *cortexr_reg_ptr(target_s *const target, const size_t reg) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* r0-r15 */ if (reg < 16U) return &priv->core_regs.r[reg]; @@ -1036,7 +1036,7 @@ static target_halt_reason_e cortexr_halt_poll(target_s *const target, target_add break; case CORTEXR_DBG_DSCR_MOE_SYNC_WATCH: case CORTEXR_DBG_DSCR_MOE_ASYNC_WATCH: { - const cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; if (priv->base.watchpoints_mask == 1U) { for (const breakwatch_s *breakwatch = target->bw_list; breakwatch; breakwatch = breakwatch->next) { if (breakwatch->type != TARGET_WATCH_READ && breakwatch->type != TARGET_WATCH_WRITE && @@ -1057,7 +1057,7 @@ static target_halt_reason_e cortexr_halt_poll(target_s *const target, target_add static void cortexr_halt_resume(target_s *const target, const bool step) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Restore the core's registers so the running program doesn't know we've been in there */ cortexr_regs_restore(target); @@ -1147,7 +1147,7 @@ static void cortexr_config_watchpoint(target_s *const target, const size_t slot, static int cortexr_breakwatch_set(target_s *const target, breakwatch_s *const breakwatch) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; switch (breakwatch->type) { case TARGET_BREAK_HARD: { @@ -1199,7 +1199,7 @@ static int cortexr_breakwatch_set(target_s *const target, breakwatch_s *const br static int cortexr_breakwatch_clear(target_s *const target, breakwatch_s *const breakwatch) { - cortexr_priv_s *const priv = (cortexr_priv_s *)target->priv; + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; switch (breakwatch->type) { case TARGET_BREAK_HARD: { From 62f01d61c13ef0ee8397a6685ea2d43106c7a6f4 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sat, 14 Oct 2023 22:58:58 +0100 Subject: [PATCH 04/22] cortexar: Renamed all the common macros --- src/target/cortexar.c | 348 +++++++++++++++++++++--------------------- 1 file changed, 175 insertions(+), 173 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index b16f0c9d81c..ddbb91c89c8 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -73,70 +73,71 @@ typedef struct cortexar_priv { uint8_t core_status; } cortexar_priv_s; -#define CORTEXR_DBG_IDR 0x000U -#define CORTEXR_DBG_WFAR 0x018U -#define CORTEXR_DBG_VCR 0x01cU -#define CORTEXR_DBG_DSCCR 0x028U -#define CORTEXR_DBG_DTRTX 0x080U -#define CORTEXR_DBG_ITR 0x084U -#define CORTEXR_DBG_DSCR 0x088U -#define CORTEXR_DBG_DTRRX 0x08cU -#define CORTEXR_DBG_DRCR 0x090U -#define CORTEXR_DBG_BVR 0x100U -#define CORTEXR_DBG_BCR 0x140U -#define CORTEXR_DBG_WVR 0x180U -#define CORTEXR_DBG_WCR 0x1c0U - -#define CORTEXR_CPUID 0xd00U -#define CORTEXR_CTR 0xd04U -#define CORTEXR_PFR1 0xd24U -#define CORTEXR_MMFR0 0xd30U - -#define CORTEXR_DBG_IDR_BREAKPOINT_MASK 0xfU -#define CORTEXR_DBG_IDR_BREAKPOINT_SHIFT 24U -#define CORTEXR_DBG_IDR_WATCHPOINT_MASK 0xfU -#define CORTEXR_DBG_IDR_WATCHPOINT_SHIFT 28U - -#define CORTEXR_DBG_DSCR_HALTED (1U << 0U) -#define CORTEXR_DBG_DSCR_RESTARTED (1U << 1U) -#define CORTEXR_DBG_DSCR_MOE_MASK 0x0000003cU -#define CORTEXR_DBG_DSCR_MOE_HALT_REQUEST 0x00000000U -#define CORTEXR_DBG_DSCR_MOE_BREAKPOINT 0x00000004U -#define CORTEXR_DBG_DSCR_MOE_ASYNC_WATCH 0x00000008U -#define CORTEXR_DBG_DSCR_MOE_BKPT_INSN 0x0000000cU -#define CORTEXR_DBG_DSCR_MOE_EXTERNAL_DBG 0x00000010U -#define CORTEXR_DBG_DSCR_MOE_VEC_CATCH 0x00000014U -#define CORTEXR_DBG_DSCR_MOE_SYNC_WATCH 0x00000028U -#define CORTEXR_DBG_DSCR_SYNC_DATA_ABORT (1U << 6U) -#define CORTEXR_DBG_DSCR_INTERRUPT_DISABLE (1U << 11U) -#define CORTEXR_DBG_DSCR_ITR_ENABLE (1U << 13U) -#define CORTEXR_DBG_DSCR_HALTING_DBG_ENABLE (1U << 14U) -#define CORTEXR_DBG_DSCR_INSN_COMPLETE (1U << 24U) -#define CORTEXR_DBG_DSCR_DTR_READ_READY (1U << 29U) -#define CORTEXR_DBG_DSCR_DTR_WRITE_DONE (1U << 30U) - -#define CORTEXR_DBG_DRCR_HALT_REQ (1U << 0U) -#define CORTEXR_DBG_DRCR_RESTART_REQ (1U << 1U) -#define CORTEXR_DBG_DRCR_CLR_STICKY_EXC (1U << 2U) -#define CORTEXR_DBG_DRCR_CLR_STICKY_PIPEADV (1U << 3U) -#define CORTEXR_DBG_DRCR_CANCEL_BUS_REQ (1U << 4U) - -#define CORTEXR_DBG_BCR_ENABLE 0x00000001U -#define CORTEXR_DBG_BCR_TYPE_UNLINKED_INSN_MATCH 0x00000000U -#define CORTEXR_DBG_BCR_TYPE_UNLINKED_INSN_MISMATCH 0x00400000U -#define CORTEXR_DBG_BCR_ALL_MODES 0x00002006U -#define CORTEXR_DBG_BCR_BYTE_SELECT_ALL 0x000001e0U -#define CORTEXR_DBG_BCR_BYTE_SELECT_LOW_HALF 0x00000060U -#define CORTEXR_DBG_BCR_BYTE_SELECT_HIGH_HALF 0x00000180U - -#define CORTEXR_DBG_WCR_ENABLE 0x00000001U -#define CORTEXR_DBG_WCR_MATCH_ON_LOAD 0x00000008U -#define CORTEXR_DBG_WCR_MATCH_ON_STORE 0x00000010U -#define CORTEXR_DBG_WCR_MATCH_ANY_ACCESS 0x00000018U -#define CORTEXR_DBG_WCR_ALL_MODES 0x00002006U -#define CORTEXR_DBG_WCR_BYTE_SELECT_OFFSET 5U -#define CORTEXR_DBG_WCR_BYTE_SELECT_MASK 0x00001fe0U -#define CORTEXR_DBG_WCR_BYTE_SELECT(x) (((x) << CORTEXR_DBG_WCR_BYTE_SELECT_OFFSET) & CORTEXR_DBG_WCR_BYTE_SELECT_MASK) +#define CORTEXAR_DBG_IDR 0x000U +#define CORTEXAR_DBG_WFAR 0x018U +#define CORTEXAR_DBG_VCR 0x01cU +#define CORTEXAR_DBG_DSCCR 0x028U +#define CORTEXAR_DBG_DTRTX 0x080U +#define CORTEXAR_DBG_ITR 0x084U +#define CORTEXAR_DBG_DSCR 0x088U +#define CORTEXAR_DBG_DTRRX 0x08cU +#define CORTEXAR_DBG_DRCR 0x090U +#define CORTEXAR_DBG_BVR 0x100U +#define CORTEXAR_DBG_BCR 0x140U +#define CORTEXAR_DBG_WVR 0x180U +#define CORTEXAR_DBG_WCR 0x1c0U + +#define CORTEXAR_CPUID 0xd00U +#define CORTEXAR_CTR 0xd04U +#define CORTEXAR_PFR1 0xd24U +#define CORTEXAR_MMFR0 0xd30U + +#define CORTEXAR_DBG_IDR_BREAKPOINT_MASK 0xfU +#define CORTEXAR_DBG_IDR_BREAKPOINT_SHIFT 24U +#define CORTEXAR_DBG_IDR_WATCHPOINT_MASK 0xfU +#define CORTEXAR_DBG_IDR_WATCHPOINT_SHIFT 28U + +#define CORTEXAR_DBG_DSCR_HALTED (1U << 0U) +#define CORTEXAR_DBG_DSCR_RESTARTED (1U << 1U) +#define CORTEXAR_DBG_DSCR_MOE_MASK 0x0000003cU +#define CORTEXAR_DBG_DSCR_MOE_HALT_REQUEST 0x00000000U +#define CORTEXAR_DBG_DSCR_MOE_BREAKPOINT 0x00000004U +#define CORTEXAR_DBG_DSCR_MOE_ASYNC_WATCH 0x00000008U +#define CORTEXAR_DBG_DSCR_MOE_BKPT_INSN 0x0000000cU +#define CORTEXAR_DBG_DSCR_MOE_EXTERNAL_DBG 0x00000010U +#define CORTEXAR_DBG_DSCR_MOE_VEC_CATCH 0x00000014U +#define CORTEXAR_DBG_DSCR_MOE_SYNC_WATCH 0x00000028U +#define CORTEXAR_DBG_DSCR_SYNC_DATA_ABORT (1U << 6U) +#define CORTEXAR_DBG_DSCR_INTERRUPT_DISABLE (1U << 11U) +#define CORTEXAR_DBG_DSCR_ITR_ENABLE (1U << 13U) +#define CORTEXAR_DBG_DSCR_HALTING_DBG_ENABLE (1U << 14U) +#define CORTEXAR_DBG_DSCR_INSN_COMPLETE (1U << 24U) +#define CORTEXAR_DBG_DSCR_DTR_READ_READY (1U << 29U) +#define CORTEXAR_DBG_DSCR_DTR_WRITE_DONE (1U << 30U) + +#define CORTEXAR_DBG_DRCR_HALT_REQ (1U << 0U) +#define CORTEXAR_DBG_DRCR_RESTART_REQ (1U << 1U) +#define CORTEXAR_DBG_DRCR_CLR_STICKY_EXC (1U << 2U) +#define CORTEXAR_DBG_DRCR_CLR_STICKY_PIPEADV (1U << 3U) +#define CORTEXAR_DBG_DRCR_CANCEL_BUS_REQ (1U << 4U) + +#define CORTEXAR_DBG_BCR_ENABLE 0x00000001U +#define CORTEXAR_DBG_BCR_TYPE_UNLINKED_INSN_MATCH 0x00000000U +#define CORTEXAR_DBG_BCR_TYPE_UNLINKED_INSN_MISMATCH 0x00400000U +#define CORTEXAR_DBG_BCR_ALL_MODES 0x00002006U +#define CORTEXAR_DBG_BCR_BYTE_SELECT_ALL 0x000001e0U +#define CORTEXAR_DBG_BCR_BYTE_SELECT_LOW_HALF 0x00000060U +#define CORTEXAR_DBG_BCR_BYTE_SELECT_HIGH_HALF 0x00000180U + +#define CORTEXAR_DBG_WCR_ENABLE 0x00000001U +#define CORTEXAR_DBG_WCR_MATCH_ON_LOAD 0x00000008U +#define CORTEXAR_DBG_WCR_MATCH_ON_STORE 0x00000010U +#define CORTEXAR_DBG_WCR_MATCH_ANY_ACCESS 0x00000018U +#define CORTEXAR_DBG_WCR_ALL_MODES 0x00002006U +#define CORTEXAR_DBG_WCR_BYTE_SELECT_OFFSET 5U +#define CORTEXAR_DBG_WCR_BYTE_SELECT_MASK 0x00001fe0U +#define CORTEXAR_DBG_WCR_BYTE_SELECT(x) \ + (((x) << CORTEXAR_DBG_WCR_BYTE_SELECT_OFFSET) & CORTEXAR_DBG_WCR_BYTE_SELECT_MASK) /* * Instruction encodings for reading/writing the program counter to/from r0, @@ -150,7 +151,7 @@ typedef struct cortexar_priv { #define ARM_MSR_SPSR_R0_INSN 0xe160f200U /* CPSR register definitions */ -#define CORTEXR_CPSR_THUMB (1U << 5U) +#define CORTEXAR_CPSR_THUMB (1U << 5U) /* * Table of encodings for the banked SPSRs - These are encoded in the following format: @@ -238,27 +239,27 @@ static const uint16_t cortexr_spsr_encodings[5] = { #define ARM_STRH_R1_R0_INSN 0xe0e010b2U /* Coprocessor register definitions */ -#define CORTEXR_CPACR 15U, ENCODE_CP_REG(1U, 0U, 0U, 2U) -#define CORTEXR_DFSR 15U, ENCODE_CP_REG(5U, 0U, 0U, 0U) -#define CORTEXR_DFAR 15U, ENCODE_CP_REG(6U, 0U, 0U, 0U) -#define CORTEXR_ICIALLU 15U, ENCODE_CP_REG(7U, 5U, 0U, 0U) +#define CORTEXAR_CPACR 15U, ENCODE_CP_REG(1U, 0U, 0U, 2U) +#define CORTEXAR_DFSR 15U, ENCODE_CP_REG(5U, 0U, 0U, 0U) +#define CORTEXAR_DFAR 15U, ENCODE_CP_REG(6U, 0U, 0U, 0U) +#define CORTEXAR_ICIALLU 15U, ENCODE_CP_REG(7U, 5U, 0U, 0U) -#define CORTEXR_CPACR_CP10_FULL_ACCESS 0x00300000U -#define CORTEXR_CPACR_CP11_FULL_ACCESS 0x00c00000U +#define CORTEXAR_CPACR_CP10_FULL_ACCESS 0x00300000U +#define CORTEXAR_CPACR_CP11_FULL_ACCESS 0x00c00000U -#define CORTEXR_PFR1_SEC_EXT_MASK 0x000000f0U -#define CORTEXR_PFR1_VIRT_EXT_MASK 0x0000f000U +#define CORTEXAR_PFR1_SEC_EXT_MASK 0x000000f0U +#define CORTEXAR_PFR1_VIRT_EXT_MASK 0x0000f000U -#define CORTEXR_MMFR0_VMSA_MASK 0x0000000fU -#define CORTEXR_MMFR0_PMSA_MASK 0x000000f0U +#define CORTEXAR_MMFR0_VMSA_MASK 0x0000000fU +#define CORTEXAR_MMFR0_PMSA_MASK 0x000000f0U #define TOPT_FLAVOUR_FLOAT (1U << 1U) /* If set, core has a hardware FPU */ #define TOPT_FLAVOUR_SEC_EXT (1U << 2U) /* If set, core has security extensions */ #define TOPT_FLAVOUR_VIRT_EXT (1U << 3U) /* If set, core has virtualisation extensions */ #define TOPT_FLAVOUR_VIRT_MEM (1U << 4U) /* If set, core uses the virtual memory model, not protected */ -#define CORTEXR_STATUS_DATA_FAULT (1U << 0U) -#define CORTEXR_STATUS_MMU_FAULT (1U << 1U) +#define CORTEXAR_STATUS_DATA_FAULT (1U << 0U) +#define CORTEXAR_STATUS_MMU_FAULT (1U << 1U) /* * Fields for Cortex-R special-purpose registers, used in the generation of GDB's target description XML. @@ -315,61 +316,61 @@ static const char *cortexr_target_description(target_s *target); static bool cortexr_run_insn(target_s *const target, const uint32_t insn) { /* Issue the requested instruction to the core */ - cortex_dbg_write32(target, CORTEXR_DBG_ITR, insn); + cortex_dbg_write32(target, CORTEXAR_DBG_ITR, insn); /* Poll for the instruction to complete */ uint32_t status = 0; - while (!(status & CORTEXR_DBG_DSCR_INSN_COMPLETE)) - status = cortex_dbg_read32(target, CORTEXR_DBG_DSCR); + while (!(status & CORTEXAR_DBG_DSCR_INSN_COMPLETE)) + status = cortex_dbg_read32(target, CORTEXAR_DBG_DSCR); /* If the instruction triggered a synchronous data abort, signal failure having cleared it */ - if (status & CORTEXR_DBG_DSCR_SYNC_DATA_ABORT) { + if (status & CORTEXAR_DBG_DSCR_SYNC_DATA_ABORT) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; - priv->core_status |= CORTEXR_STATUS_DATA_FAULT; - cortex_dbg_write32(target, CORTEXR_DBG_DRCR, CORTEXR_DBG_DRCR_CLR_STICKY_EXC); + priv->core_status |= CORTEXAR_STATUS_DATA_FAULT; + cortex_dbg_write32(target, CORTEXAR_DBG_DRCR, CORTEXAR_DBG_DRCR_CLR_STICKY_EXC); } - return !(status & CORTEXR_DBG_DSCR_SYNC_DATA_ABORT); + return !(status & CORTEXAR_DBG_DSCR_SYNC_DATA_ABORT); } static bool cortexr_run_read_insn(target_s *const target, const uint32_t insn, uint32_t *const result) { /* Issue the requested instruction to the core */ - cortex_dbg_write32(target, CORTEXR_DBG_ITR, insn); + cortex_dbg_write32(target, CORTEXAR_DBG_ITR, insn); /* Poll for the instruction to complete and the data to become ready in the DTR */ uint32_t status = 0; - while ((status & (CORTEXR_DBG_DSCR_INSN_COMPLETE | CORTEXR_DBG_DSCR_DTR_READ_READY)) != - (CORTEXR_DBG_DSCR_INSN_COMPLETE | CORTEXR_DBG_DSCR_DTR_READ_READY)) { - status = cortex_dbg_read32(target, CORTEXR_DBG_DSCR); + while ((status & (CORTEXAR_DBG_DSCR_INSN_COMPLETE | CORTEXAR_DBG_DSCR_DTR_READ_READY)) != + (CORTEXAR_DBG_DSCR_INSN_COMPLETE | CORTEXAR_DBG_DSCR_DTR_READ_READY)) { + status = cortex_dbg_read32(target, CORTEXAR_DBG_DSCR); /* If the instruction triggered a synchronous data abort, signal failure having cleared it */ - if (status & CORTEXR_DBG_DSCR_SYNC_DATA_ABORT) { + if (status & CORTEXAR_DBG_DSCR_SYNC_DATA_ABORT) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; - priv->core_status |= CORTEXR_STATUS_DATA_FAULT; - cortex_dbg_write32(target, CORTEXR_DBG_DRCR, CORTEXR_DBG_DRCR_CLR_STICKY_EXC); + priv->core_status |= CORTEXAR_STATUS_DATA_FAULT; + cortex_dbg_write32(target, CORTEXAR_DBG_DRCR, CORTEXAR_DBG_DRCR_CLR_STICKY_EXC); return false; } } /* Read back the DTR to complete the read and signal success */ - *result = cortex_dbg_read32(target, CORTEXR_DBG_DTRRX); + *result = cortex_dbg_read32(target, CORTEXAR_DBG_DTRRX); return true; } static bool cortexr_run_write_insn(target_s *const target, const uint32_t insn, const uint32_t data) { /* Set up the data in the DTR for the transaction */ - cortex_dbg_write32(target, CORTEXR_DBG_DTRTX, data); + cortex_dbg_write32(target, CORTEXAR_DBG_DTRTX, data); /* Poll for the data to become ready in the DTR */ - while (!(cortex_dbg_read32(target, CORTEXR_DBG_DSCR) & CORTEXR_DBG_DSCR_DTR_WRITE_DONE)) + while (!(cortex_dbg_read32(target, CORTEXAR_DBG_DSCR) & CORTEXAR_DBG_DSCR_DTR_WRITE_DONE)) continue; /* Issue the requested instruction to the core */ - cortex_dbg_write32(target, CORTEXR_DBG_ITR, insn); + cortex_dbg_write32(target, CORTEXAR_DBG_ITR, insn); /* Poll for the instruction to complete and the data to be consumed from the DTR */ uint32_t status = 0; - while ((status & (CORTEXR_DBG_DSCR_INSN_COMPLETE | CORTEXR_DBG_DSCR_DTR_WRITE_DONE)) != - CORTEXR_DBG_DSCR_INSN_COMPLETE) { - status = cortex_dbg_read32(target, CORTEXR_DBG_DSCR); + while ((status & (CORTEXAR_DBG_DSCR_INSN_COMPLETE | CORTEXAR_DBG_DSCR_DTR_WRITE_DONE)) != + CORTEXAR_DBG_DSCR_INSN_COMPLETE) { + status = cortex_dbg_read32(target, CORTEXAR_DBG_DSCR); /* If the instruction triggered a synchronous data abort, signal failure having cleared it */ - if (status & CORTEXR_DBG_DSCR_SYNC_DATA_ABORT) { + if (status & CORTEXAR_DBG_DSCR_SYNC_DATA_ABORT) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; - priv->core_status |= CORTEXR_STATUS_DATA_FAULT; - cortex_dbg_write32(target, CORTEXR_DBG_DRCR, CORTEXR_DBG_DRCR_CLR_STICKY_EXC); + priv->core_status |= CORTEXAR_STATUS_DATA_FAULT; + cortex_dbg_write32(target, CORTEXAR_DBG_DRCR, CORTEXAR_DBG_DRCR_CLR_STICKY_EXC); return false; } } @@ -404,7 +405,7 @@ static void cortexr_core_regs_save(target_s *const target) cortexr_run_insn(target, ARM_MRS_R0_CPSR_INSN); priv->core_regs.cpsr = cortexr_core_reg_read(target, 0U); /* Adjust the program counter according to the mode */ - priv->core_regs.r[CORTEX_REG_PC] -= (priv->core_regs.cpsr & CORTEXR_CPSR_THUMB) ? 4U : 8U; + priv->core_regs.r[CORTEX_REG_PC] -= (priv->core_regs.cpsr & CORTEXAR_CPSR_THUMB) ? 4U : 8U; /* Read the SPSRs into r0 and retrieve them */ for (size_t i = 0; i < ARRAY_LENGTH(priv->core_regs.spsr); ++i) { /* Build and issue the banked MRS for the required SPSR */ @@ -464,7 +465,7 @@ static void cortexr_core_regs_restore(target_s *const target) cortexr_core_reg_write(target, 0U, priv->core_regs.cpsr); cortexr_run_insn(target, ARM_MSR_CPSR_R0_INSN); /* Fix up the program counter for the mode */ - if (priv->core_regs.cpsr & CORTEXR_CPSR_THUMB) + if (priv->core_regs.cpsr & CORTEXAR_CPSR_THUMB) priv->core_regs.r[CORTEX_REG_PC] |= 1U; /* Restore r1-15 in that order. Ignore r0 for the moment as it gets clobbered repeatedly */ for (size_t i = 1U; i < ARRAY_LENGTH(priv->core_regs.r); ++i) @@ -574,21 +575,22 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre cortex_read_cpuid(target); /* The format of the debug identification register is described in DDI0406C §C11.11.15 pg2217 */ - const uint32_t debug_id = cortex_dbg_read32(target, CORTEXR_DBG_IDR); + const uint32_t debug_id = cortex_dbg_read32(target, CORTEXAR_DBG_IDR); /* Reserve the last available breakpoint for our use to implement single-stepping */ - priv->base.breakpoints_available = (debug_id >> CORTEXR_DBG_IDR_BREAKPOINT_SHIFT) & CORTEXR_DBG_IDR_BREAKPOINT_MASK; + priv->base.breakpoints_available = + (debug_id >> CORTEXAR_DBG_IDR_BREAKPOINT_SHIFT) & CORTEXAR_DBG_IDR_BREAKPOINT_MASK; priv->base.watchpoints_available = - ((debug_id >> CORTEXR_DBG_IDR_WATCHPOINT_SHIFT) & CORTEXR_DBG_IDR_WATCHPOINT_MASK) + 1U; + ((debug_id >> CORTEXAR_DBG_IDR_WATCHPOINT_SHIFT) & CORTEXAR_DBG_IDR_WATCHPOINT_MASK) + 1U; DEBUG_TARGET("%s %s core has %u breakpoint and %u watchpoint units available\n", target->driver, target->core, priv->base.breakpoints_available + 1U, priv->base.watchpoints_available); /* Read out processor feature register 1 and check for the security and virtualisation extensions */ - const uint32_t proc_features = cortex_dbg_read32(target, CORTEXR_PFR1); - if (proc_features & CORTEXR_PFR1_SEC_EXT_MASK) { + const uint32_t proc_features = cortex_dbg_read32(target, CORTEXAR_PFR1); + if (proc_features & CORTEXAR_PFR1_SEC_EXT_MASK) { target->target_options |= TOPT_FLAVOUR_SEC_EXT; DEBUG_TARGET("%s: Core has security extensions\n", __func__); } - if (proc_features & CORTEXR_PFR1_VIRT_EXT_MASK) { + if (proc_features & CORTEXAR_PFR1_VIRT_EXT_MASK) { target->target_options |= TOPT_FLAVOUR_VIRT_EXT; DEBUG_TARGET("%s: Core has virtualisation extensions\n", __func__); } @@ -597,11 +599,11 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre * Read out memory model feature register 0 and check for VMSA vs PMSA memory models to * configure address translation and determine which cp15 registers we can poke. */ - const uint32_t memory_model = cortex_dbg_read32(target, CORTEXR_MMFR0); + const uint32_t memory_model = cortex_dbg_read32(target, CORTEXAR_MMFR0); /* The manual says this cannot happen, if it does then assume VMSA */ - if ((memory_model & CORTEXR_MMFR0_VMSA_MASK) && (memory_model & CORTEXR_MMFR0_PMSA_MASK)) + if ((memory_model & CORTEXAR_MMFR0_VMSA_MASK) && (memory_model & CORTEXAR_MMFR0_PMSA_MASK)) DEBUG_ERROR("%s: Core claims to support both virtual and protected memory modes!\n", __func__); - if (memory_model & CORTEXR_MMFR0_VMSA_MASK) + if (memory_model & CORTEXAR_MMFR0_VMSA_MASK) target->target_options |= TOPT_FLAVOUR_VIRT_MEM; DEBUG_TARGET( "%s: Core uses the %cMSA memory model\n", __func__, target->target_options & TOPT_FLAVOUR_VIRT_MEM ? 'V' : 'P'); @@ -610,10 +612,10 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre target->detach = cortexr_detach; /* Probe for FP extension. */ - uint32_t cpacr = cortexr_coproc_read(target, CORTEXR_CPACR); - cpacr |= CORTEXR_CPACR_CP10_FULL_ACCESS | CORTEXR_CPACR_CP11_FULL_ACCESS; - cortexr_coproc_write(target, CORTEXR_CPACR, cpacr); - const bool core_has_fpu = cortexr_coproc_read(target, CORTEXR_CPACR) == cpacr; + uint32_t cpacr = cortexr_coproc_read(target, CORTEXAR_CPACR); + cpacr |= CORTEXAR_CPACR_CP10_FULL_ACCESS | CORTEXAR_CPACR_CP11_FULL_ACCESS; + cortexr_coproc_write(target, CORTEXAR_CPACR, cpacr); + const bool core_has_fpu = cortexr_coproc_read(target, CORTEXAR_CPACR) == cpacr; DEBUG_TARGET("%s: FPU present? %s\n", __func__, core_has_fpu ? "yes" : "no"); target->regs_description = cortexr_target_description; @@ -637,7 +639,7 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre target->breakwatch_clear = cortexr_breakwatch_clear; /* Check cache type */ - const uint32_t cache_type = cortex_dbg_read32(target, CORTEXR_CTR); + const uint32_t cache_type = cortex_dbg_read32(target, CORTEXAR_CTR); if (cache_type >> CORTEX_CTR_FORMAT_SHIFT == CORTEX_CTR_FORMAT_ARMv7) { /* If there is an ICache defined, decompress its length to a uint32_t count */ if (cache_type & CORTEX_CTR_ICACHE_LINE_MASK) @@ -685,15 +687,15 @@ bool cortexr_attach(target_s *const target) /* Clear any stale breakpoints */ priv->base.breakpoints_mask = 0U; for (size_t i = 0; i <= priv->base.breakpoints_available; ++i) { - cortex_dbg_write32(target, CORTEXR_DBG_BVR + (i << 2U), 0U); - cortex_dbg_write32(target, CORTEXR_DBG_BCR + (i << 2U), 0U); + cortex_dbg_write32(target, CORTEXAR_DBG_BVR + (i << 2U), 0U); + cortex_dbg_write32(target, CORTEXAR_DBG_BCR + (i << 2U), 0U); } /* Clear any stale watchpoints */ priv->base.watchpoints_mask = 0U; for (size_t i = 0; i < priv->base.watchpoints_available; ++i) { - cortex_dbg_write32(target, CORTEXR_DBG_WVR + (i << 2U), 0U); - cortex_dbg_write32(target, CORTEXR_DBG_WCR + (i << 2U), 0U); + cortex_dbg_write32(target, CORTEXAR_DBG_WVR + (i << 2U), 0U); + cortex_dbg_write32(target, CORTEXAR_DBG_WCR + (i << 2U), 0U); } return true; @@ -705,14 +707,14 @@ void cortexr_detach(target_s *const target) /* Clear any set breakpoints */ for (size_t i = 0; i <= priv->base.breakpoints_available; ++i) { - cortex_dbg_write32(target, CORTEXR_DBG_BVR + (i << 2U), 0U); - cortex_dbg_write32(target, CORTEXR_DBG_BCR + (i << 2U), 0U); + cortex_dbg_write32(target, CORTEXAR_DBG_BVR + (i << 2U), 0U); + cortex_dbg_write32(target, CORTEXAR_DBG_BCR + (i << 2U), 0U); } /* Clear any set watchpoints */ for (size_t i = 0; i < priv->base.watchpoints_available; ++i) { - cortex_dbg_write32(target, CORTEXR_DBG_WVR + (i << 2U), 0U); - cortex_dbg_write32(target, CORTEXR_DBG_WCR + (i << 2U), 0U); + cortex_dbg_write32(target, CORTEXAR_DBG_WVR + (i << 2U), 0U); + cortex_dbg_write32(target, CORTEXAR_DBG_WCR + (i << 2U), 0U); } target_halt_resume(target, false); @@ -721,7 +723,7 @@ void cortexr_detach(target_s *const target) static bool cortexr_check_error(target_s *const target) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; - const bool fault = priv->core_status & (CORTEXR_STATUS_DATA_FAULT | CORTEXR_STATUS_MMU_FAULT); + const bool fault = priv->core_status & (CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); priv->core_status = 0; return fault || cortex_check_error(target); } @@ -780,15 +782,15 @@ static void cortexr_mem_handle_fault( { const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* If we suffered a fault of some kind, grab the reason and restore DFSR/DFAR */ - if (priv->core_status & CORTEXR_STATUS_DATA_FAULT) { + if (priv->core_status & CORTEXAR_STATUS_DATA_FAULT) { #ifdef ENABLE_DEBUG - const uint32_t fault_status = cortexr_coproc_read(target, CORTEXR_DFSR); - const uint32_t fault_addr = cortexr_coproc_read(target, CORTEXR_DFAR); + const uint32_t fault_status = cortexr_coproc_read(target, CORTEXAR_DFSR); + const uint32_t fault_addr = cortexr_coproc_read(target, CORTEXAR_DFAR); #else (void)func; #endif - cortexr_coproc_write(target, CORTEXR_DFAR, orig_fault_addr); - cortexr_coproc_write(target, CORTEXR_DFSR, orig_fault_status); + cortexr_coproc_write(target, CORTEXAR_DFAR, orig_fault_addr); + cortexr_coproc_write(target, CORTEXAR_DFSR, orig_fault_status); DEBUG_WARN("%s: Failed at 0x%08" PRIx32 " (%08" PRIx32 ")\n", func, fault_addr, fault_status); } @@ -803,10 +805,10 @@ static void cortexr_mem_read(target_s *const target, void *const dest, const tar { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Cache DFSR and DFAR in case we wind up triggering a data fault */ - const uint32_t fault_status = cortexr_coproc_read(target, CORTEXR_DFSR); - const uint32_t fault_addr = cortexr_coproc_read(target, CORTEXR_DFAR); + const uint32_t fault_status = cortexr_coproc_read(target, CORTEXAR_DFSR); + const uint32_t fault_addr = cortexr_coproc_read(target, CORTEXAR_DFAR); /* Clear any existing fault state */ - priv->core_status &= ~(CORTEXR_STATUS_DATA_FAULT | CORTEXR_STATUS_MMU_FAULT); + priv->core_status &= ~(CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); /* Move the start address into the core's r0 */ cortexr_core_reg_write(target, 0U, src); @@ -880,10 +882,10 @@ static void cortexr_mem_write(target_s *const target, const target_addr_t dest, cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; DEBUG_TARGET("%s: Writing %zu bytes @0x%" PRIx32 "\n", __func__, len, dest); /* Cache DFSR and DFAR in case we wind up triggering a data fault */ - const uint32_t fault_status = cortexr_coproc_read(target, CORTEXR_DFSR); - const uint32_t fault_addr = cortexr_coproc_read(target, CORTEXR_DFAR); + const uint32_t fault_status = cortexr_coproc_read(target, CORTEXAR_DFSR); + const uint32_t fault_addr = cortexr_coproc_read(target, CORTEXAR_DFAR); /* Clear any existing fault state */ - priv->core_status &= ~(CORTEXR_STATUS_DATA_FAULT | CORTEXR_STATUS_MMU_FAULT); + priv->core_status &= ~(CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); /* Move the start address into the core's r0 */ cortexr_core_reg_write(target, 0U, dest); @@ -987,7 +989,7 @@ static void cortexr_halt_request(target_s *const target) { volatile exception_s error; TRY_CATCH (error, EXCEPTION_TIMEOUT) { - cortex_dbg_write32(target, CORTEXR_DBG_DRCR, CORTEXR_DBG_DRCR_HALT_REQ); + cortex_dbg_write32(target, CORTEXAR_DBG_DRCR, CORTEXAR_DBG_DRCR_HALT_REQ); } if (error.type) tc_printf(target, "Timeout sending interrupt, is target in WFI?\n"); @@ -999,7 +1001,7 @@ static target_halt_reason_e cortexr_halt_poll(target_s *const target, target_add volatile exception_s error; TRY_CATCH (error, EXCEPTION_ALL) { /* If this times out because the target is in WFI then the target is still running. */ - dscr = cortex_dbg_read32(target, CORTEXR_DBG_DSCR); + dscr = cortex_dbg_read32(target, CORTEXAR_DBG_DSCR); } switch (error.type) { case EXCEPTION_ERROR: @@ -1012,30 +1014,30 @@ static target_halt_reason_e cortexr_halt_poll(target_s *const target, target_add } /* Check that the core actually halted */ - if (!(dscr & CORTEXR_DBG_DSCR_HALTED)) + if (!(dscr & CORTEXAR_DBG_DSCR_HALTED)) return TARGET_HALT_RUNNING; /* Make sure ITR is enabled and likewise halting debug (so breakpoints work) */ cortex_dbg_write32( - target, CORTEXR_DBG_DSCR, dscr | CORTEXR_DBG_DSCR_ITR_ENABLE | CORTEXR_DBG_DSCR_HALTING_DBG_ENABLE); + target, CORTEXAR_DBG_DSCR, dscr | CORTEXAR_DBG_DSCR_ITR_ENABLE | CORTEXAR_DBG_DSCR_HALTING_DBG_ENABLE); /* Save the target core's registers as debugging operations clobber them */ cortexr_regs_save(target); target_halt_reason_e reason = TARGET_HALT_FAULT; /* Determine why we halted exactly from the Method Of Entry bits */ - switch (dscr & CORTEXR_DBG_DSCR_MOE_MASK) { - case CORTEXR_DBG_DSCR_MOE_HALT_REQUEST: + switch (dscr & CORTEXAR_DBG_DSCR_MOE_MASK) { + case CORTEXAR_DBG_DSCR_MOE_HALT_REQUEST: reason = TARGET_HALT_REQUEST; break; - case CORTEXR_DBG_DSCR_MOE_EXTERNAL_DBG: - case CORTEXR_DBG_DSCR_MOE_BREAKPOINT: - case CORTEXR_DBG_DSCR_MOE_BKPT_INSN: - case CORTEXR_DBG_DSCR_MOE_VEC_CATCH: + case CORTEXAR_DBG_DSCR_MOE_EXTERNAL_DBG: + case CORTEXAR_DBG_DSCR_MOE_BREAKPOINT: + case CORTEXAR_DBG_DSCR_MOE_BKPT_INSN: + case CORTEXAR_DBG_DSCR_MOE_VEC_CATCH: reason = TARGET_HALT_BREAKPOINT; break; - case CORTEXR_DBG_DSCR_MOE_SYNC_WATCH: - case CORTEXR_DBG_DSCR_MOE_ASYNC_WATCH: { + case CORTEXAR_DBG_DSCR_MOE_SYNC_WATCH: + case CORTEXAR_DBG_DSCR_MOE_ASYNC_WATCH: { const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; if (priv->base.watchpoints_mask == 1U) { for (const breakwatch_s *breakwatch = target->bw_list; breakwatch; breakwatch = breakwatch->next) { @@ -1061,7 +1063,7 @@ static void cortexr_halt_resume(target_s *const target, const bool step) /* Restore the core's registers so the running program doesn't know we've been in there */ cortexr_regs_restore(target); - uint32_t dscr = cortex_dbg_read32(target, CORTEXR_DBG_DSCR); + uint32_t dscr = cortex_dbg_read32(target, CORTEXAR_DBG_DSCR); /* * If we're setting up to single-step the core, configure the final breakpoint slot approrpriately. * We always keep the final supported breakpoint reserved for this purpose so @@ -1070,28 +1072,28 @@ static void cortexr_halt_resume(target_s *const target, const bool step) */ if (step) { cortexr_config_breakpoint(target, priv->base.breakpoints_available, - CORTEXR_DBG_BCR_TYPE_UNLINKED_INSN_MISMATCH | ((priv->core_regs.cpsr & CORTEXR_CPSR_THUMB) ? 2 : 4), + CORTEXAR_DBG_BCR_TYPE_UNLINKED_INSN_MISMATCH | ((priv->core_regs.cpsr & CORTEXAR_CPSR_THUMB) ? 2 : 4), priv->core_regs.r[CORTEX_REG_PC]); - dscr |= CORTEXR_DBG_DSCR_INTERRUPT_DISABLE; + dscr |= CORTEXAR_DBG_DSCR_INTERRUPT_DISABLE; } else { - cortex_dbg_write32(target, CORTEXR_DBG_BCR + (priv->base.breakpoints_available << 2U), 0U); - dscr &= ~CORTEXR_DBG_DSCR_INTERRUPT_DISABLE; + cortex_dbg_write32(target, CORTEXAR_DBG_BCR + (priv->base.breakpoints_available << 2U), 0U); + dscr &= ~CORTEXAR_DBG_DSCR_INTERRUPT_DISABLE; } /* Invalidate all the instruction caches if we're on a VMSA model device */ if (target->target_options & TOPT_FLAVOUR_VIRT_MEM) - cortexr_coproc_write(target, CORTEXR_ICIALLU, 0U); + cortexr_coproc_write(target, CORTEXAR_ICIALLU, 0U); - cortex_dbg_write32(target, CORTEXR_DBG_DSCR, dscr & ~CORTEXR_DBG_DSCR_ITR_ENABLE); + cortex_dbg_write32(target, CORTEXAR_DBG_DSCR, dscr & ~CORTEXAR_DBG_DSCR_ITR_ENABLE); /* Ask to resume the core */ - cortex_dbg_write32(target, CORTEXR_DBG_DRCR, CORTEXR_DBG_DRCR_CLR_STICKY_EXC | CORTEXR_DBG_DRCR_RESTART_REQ); + cortex_dbg_write32(target, CORTEXAR_DBG_DRCR, CORTEXAR_DBG_DRCR_CLR_STICKY_EXC | CORTEXAR_DBG_DRCR_RESTART_REQ); /* Then poll for when the core actually resumes */ platform_timeout_s timeout; platform_timeout_set(&timeout, 250); - uint32_t status = CORTEXR_DBG_DSCR_HALTED; - while (!(status & CORTEXR_DBG_DSCR_RESTARTED) && !platform_timeout_is_expired(&timeout)) - status = cortex_dbg_read32(target, CORTEXR_DBG_DSCR); + uint32_t status = CORTEXAR_DBG_DSCR_HALTED; + while (!(status & CORTEXAR_DBG_DSCR_RESTARTED) && !platform_timeout_is_expired(&timeout)) + status = cortex_dbg_read32(target, CORTEXAR_DBG_DSCR); } static void cortexr_config_breakpoint( @@ -1103,25 +1105,25 @@ static void cortexr_config_breakpoint( */ const bool thumb_breakpoint = (mode & 7U) == 2U; if (thumb_breakpoint) - mode |= (addr & 2U) ? CORTEXR_DBG_BCR_BYTE_SELECT_HIGH_HALF : CORTEXR_DBG_BCR_BYTE_SELECT_LOW_HALF; + mode |= (addr & 2U) ? CORTEXAR_DBG_BCR_BYTE_SELECT_HIGH_HALF : CORTEXAR_DBG_BCR_BYTE_SELECT_LOW_HALF; else - mode |= CORTEXR_DBG_BCR_BYTE_SELECT_ALL; + mode |= CORTEXAR_DBG_BCR_BYTE_SELECT_ALL; /* Configure the breakpoint slot */ - cortex_dbg_write32(target, CORTEXR_DBG_BVR + (slot << 2U), addr & ~3U); + cortex_dbg_write32(target, CORTEXAR_DBG_BVR + (slot << 2U), addr & ~3U); cortex_dbg_write32( - target, CORTEXR_DBG_BCR + (slot << 2U), CORTEXR_DBG_BCR_ENABLE | CORTEXR_DBG_BCR_ALL_MODES | (mode & ~7U)); + target, CORTEXAR_DBG_BCR + (slot << 2U), CORTEXAR_DBG_BCR_ENABLE | CORTEXAR_DBG_BCR_ALL_MODES | (mode & ~7U)); } static uint32_t cortexr_watchpoint_mode(const target_breakwatch_e type) { switch (type) { case TARGET_WATCH_READ: - return CORTEXR_DBG_WCR_MATCH_ON_LOAD; + return CORTEXAR_DBG_WCR_MATCH_ON_LOAD; case TARGET_WATCH_WRITE: - return CORTEXR_DBG_WCR_MATCH_ON_STORE; + return CORTEXAR_DBG_WCR_MATCH_ON_STORE; case TARGET_WATCH_ACCESS: - return CORTEXR_DBG_WCR_MATCH_ANY_ACCESS; + return CORTEXAR_DBG_WCR_MATCH_ANY_ACCESS; default: return 0U; } @@ -1137,12 +1139,12 @@ static void cortexr_config_watchpoint(target_s *const target, const size_t slot, * Which set of bits need to be 1's depends on the address low bits. */ const uint32_t byte_mask = ((1U << breakwatch->size) - 1U) << (breakwatch->addr & 3U); - const uint32_t mode = cortexr_watchpoint_mode(breakwatch->type) | CORTEXR_DBG_WCR_BYTE_SELECT(byte_mask); + const uint32_t mode = cortexr_watchpoint_mode(breakwatch->type) | CORTEXAR_DBG_WCR_BYTE_SELECT(byte_mask); /* Configure the watchpoint slot */ - cortex_dbg_write32(target, CORTEXR_DBG_WVR + (slot << 2U), breakwatch->addr & ~3U); + cortex_dbg_write32(target, CORTEXAR_DBG_WVR + (slot << 2U), breakwatch->addr & ~3U); cortex_dbg_write32( - target, CORTEXR_DBG_WCR + (slot << 2U), CORTEXR_DBG_WCR_ENABLE | CORTEXR_DBG_WCR_ALL_MODES | mode); + target, CORTEXAR_DBG_WCR + (slot << 2U), CORTEXAR_DBG_WCR_ENABLE | CORTEXAR_DBG_WCR_ALL_MODES | mode); } static int cortexr_breakwatch_set(target_s *const target, breakwatch_s *const breakwatch) @@ -1164,7 +1166,7 @@ static int cortexr_breakwatch_set(target_s *const target, breakwatch_s *const br /* Set the breakpoint slot up and mark it used */ cortexr_config_breakpoint( - target, breakpoint, CORTEXR_DBG_BCR_TYPE_UNLINKED_INSN_MATCH | (breakwatch->size & 7U), breakwatch->addr); + target, breakpoint, CORTEXAR_DBG_BCR_TYPE_UNLINKED_INSN_MATCH | (breakwatch->size & 7U), breakwatch->addr); priv->base.breakpoints_mask |= 1U << breakpoint; breakwatch->reserved[0] = breakpoint; /* Tell the debugger that it was successfully able to set the breakpoint */ @@ -1205,7 +1207,7 @@ static int cortexr_breakwatch_clear(target_s *const target, breakwatch_s *const case TARGET_BREAK_HARD: { /* Clear the breakpoint slot this used */ const size_t breakpoint = breakwatch->reserved[0]; - cortex_dbg_write32(target, CORTEXR_DBG_BCR + (breakpoint << 2U), 0); + cortex_dbg_write32(target, CORTEXAR_DBG_BCR + (breakpoint << 2U), 0); priv->base.breakpoints_mask &= ~(1U << breakpoint); /* Tell the debugger that it was successfully able to clear the breakpoint */ return 0; @@ -1215,7 +1217,7 @@ static int cortexr_breakwatch_clear(target_s *const target, breakwatch_s *const case TARGET_WATCH_ACCESS: { /* Clear the watchpoint slot this used */ const size_t watchpoint = breakwatch->reserved[0]; - cortex_dbg_write32(target, CORTEXR_DBG_WCR + (watchpoint << 2U), 0); + cortex_dbg_write32(target, CORTEXAR_DBG_WCR + (watchpoint << 2U), 0); priv->base.watchpoints_mask &= ~(1U << watchpoint); /* Tell the debugger that it was successfully able to clear the watchpoint */ return 0; From db6025f5bc4f75bbcae3b6bb30b033cda4518cf7 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sat, 14 Oct 2023 23:03:43 +0100 Subject: [PATCH 05/22] cortexar: Renamed all the register and instruction access machinary as that's all common too --- src/target/cortexar.c | 204 +++++++++++++++++++++--------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index ddbb91c89c8..d63f20ccde2 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -160,7 +160,7 @@ typedef struct cortexar_priv { * This allows these values to simply be shifted up a little to put them in the right spot * for use in the banked MRS/MSR instructions. */ -static const uint16_t cortexr_spsr_encodings[5] = { +static const uint16_t cortexar_spsr_encodings[5] = { 0xc001U, /* FIQ */ 0x1000U, /* IRQ */ 0x5000U, /* SVC */ @@ -295,10 +295,10 @@ static bool cortexr_check_error(target_s *target); static void cortexr_mem_read(target_s *target, void *dest, target_addr_t src, size_t len); static void cortexr_mem_write(target_s *target, target_addr_t dest, const void *src, size_t len); -static void cortexr_regs_read(target_s *target, void *data); -static void cortexr_regs_write(target_s *target, const void *data); -static ssize_t cortexr_reg_read(target_s *target, uint32_t reg, void *data, size_t max); -static ssize_t cortexr_reg_write(target_s *target, uint32_t reg, const void *data, size_t max); +static void cortexar_regs_read(target_s *target, void *data); +static void cortexar_regs_write(target_s *target, const void *data); +static ssize_t cortexar_reg_read(target_s *target, uint32_t reg, void *data, size_t max); +static ssize_t cortexar_reg_write(target_s *target, uint32_t reg, const void *data, size_t max); static target_halt_reason_e cortexr_halt_poll(target_s *target, target_addr_t *watch); static void cortexr_halt_request(target_s *target); @@ -313,7 +313,7 @@ void cortexr_detach(target_s *target); static const char *cortexr_target_description(target_s *target); -static bool cortexr_run_insn(target_s *const target, const uint32_t insn) +static bool cortexar_run_insn(target_s *const target, const uint32_t insn) { /* Issue the requested instruction to the core */ cortex_dbg_write32(target, CORTEXAR_DBG_ITR, insn); @@ -330,7 +330,7 @@ static bool cortexr_run_insn(target_s *const target, const uint32_t insn) return !(status & CORTEXAR_DBG_DSCR_SYNC_DATA_ABORT); } -static bool cortexr_run_read_insn(target_s *const target, const uint32_t insn, uint32_t *const result) +static bool cortexar_run_read_insn(target_s *const target, const uint32_t insn, uint32_t *const result) { /* Issue the requested instruction to the core */ cortex_dbg_write32(target, CORTEXAR_DBG_ITR, insn); @@ -352,7 +352,7 @@ static bool cortexr_run_read_insn(target_s *const target, const uint32_t insn, u return true; } -static bool cortexr_run_write_insn(target_s *const target, const uint32_t insn, const uint32_t data) +static bool cortexar_run_write_insn(target_s *const target, const uint32_t insn, const uint32_t data) { /* Set up the data in the DTR for the transaction */ cortex_dbg_write32(target, CORTEXAR_DBG_DTRTX, data); @@ -377,127 +377,127 @@ static bool cortexr_run_write_insn(target_s *const target, const uint32_t insn, return true; } -static inline uint32_t cortexr_core_reg_read(target_s *const target, const uint8_t reg) +static inline uint32_t cortexar_core_reg_read(target_s *const target, const uint8_t reg) { /* If the register is a GPR and not the program counter, use a "simple" MCR to read */ if (reg < 15U) { uint32_t value = 0; /* Build an issue a core to coprocessor transfer for the requested register and read back the result */ - (void)cortexr_run_read_insn(target, ARM_MCR_INSN | ENCODE_CP_ACCESS(14, 0, reg, 0, 5, 0), &value); + (void)cortexar_run_read_insn(target, ARM_MCR_INSN | ENCODE_CP_ACCESS(14, 0, reg, 0, 5, 0), &value); /* Return whatever value was read as we don't care about DCSR.SDABORT here */ return value; } /* If the register is the program counter, we first have to extract it to r0 */ else if (reg == 15U) { - cortexr_run_insn(target, ARM_MOV_R0_PC_INSN); - return cortexr_core_reg_read(target, 0U); + cortexar_run_insn(target, ARM_MOV_R0_PC_INSN); + return cortexar_core_reg_read(target, 0U); } return 0U; } -static void cortexr_core_regs_save(target_s *const target) +static void cortexar_core_regs_save(target_s *const target) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Save out r0-r15 in that order (r15, aka pc, clobbers r0) */ for (size_t i = 0U; i < ARRAY_LENGTH(priv->core_regs.r); ++i) - priv->core_regs.r[i] = cortexr_core_reg_read(target, i); + priv->core_regs.r[i] = cortexar_core_reg_read(target, i); /* Read CPSR to r0 and retrieve it */ - cortexr_run_insn(target, ARM_MRS_R0_CPSR_INSN); - priv->core_regs.cpsr = cortexr_core_reg_read(target, 0U); + cortexar_run_insn(target, ARM_MRS_R0_CPSR_INSN); + priv->core_regs.cpsr = cortexar_core_reg_read(target, 0U); /* Adjust the program counter according to the mode */ priv->core_regs.r[CORTEX_REG_PC] -= (priv->core_regs.cpsr & CORTEXAR_CPSR_THUMB) ? 4U : 8U; /* Read the SPSRs into r0 and retrieve them */ for (size_t i = 0; i < ARRAY_LENGTH(priv->core_regs.spsr); ++i) { /* Build and issue the banked MRS for the required SPSR */ - cortexr_run_insn(target, ARM_MRS_R0_SPSR_INSN | (cortexr_spsr_encodings[i] << 4U)); - priv->core_regs.spsr[i] = cortexr_core_reg_read(target, 0U); + cortexar_run_insn(target, ARM_MRS_R0_SPSR_INSN | (cortexar_spsr_encodings[i] << 4U)); + priv->core_regs.spsr[i] = cortexar_core_reg_read(target, 0U); } } -static void cortexr_float_regs_save(target_s *const target) +static void cortexar_float_regs_save(target_s *const target) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Read FPCSR to r0 and retrieve it */ - cortexr_run_insn(target, ARM_VMRS_R0_FPCSR_INSN); - priv->core_regs.fpcsr = cortexr_core_reg_read(target, 0U); + cortexar_run_insn(target, ARM_VMRS_R0_FPCSR_INSN); + priv->core_regs.fpcsr = cortexar_core_reg_read(target, 0U); /* Now step through each double-precision float register, reading it back to r0,r1 */ for (size_t i = 0; i < ARRAY_LENGTH(priv->core_regs.d); ++i) { /* The float register to read slots into the bottom 4 bits of the instruction */ - cortexr_run_insn(target, ARM_VMOV_R0_R1_DN_INSN | i); + cortexar_run_insn(target, ARM_VMOV_R0_R1_DN_INSN | i); /* Read back the data */ - const uint32_t d_low = cortexr_core_reg_read(target, 0U); - const uint32_t d_high = cortexr_core_reg_read(target, 1U); + const uint32_t d_low = cortexar_core_reg_read(target, 0U); + const uint32_t d_high = cortexar_core_reg_read(target, 1U); /* Reassemble it as a full 64-bit value */ priv->core_regs.d[i] = d_low | ((uint64_t)d_high << 32U); } } -static void cortexr_regs_save(target_s *const target) +static void cortexar_regs_save(target_s *const target) { - cortexr_core_regs_save(target); + cortexar_core_regs_save(target); if (target->target_options & TOPT_FLAVOUR_FLOAT) - cortexr_float_regs_save(target); + cortexar_float_regs_save(target); } -static inline void cortexr_core_reg_write(target_s *const target, const uint8_t reg, const uint32_t value) +static inline void cortexar_core_reg_write(target_s *const target, const uint8_t reg, const uint32_t value) { /* If the register is a GPR and not the program counter, use a "simple" MCR to read */ if (reg < 15U) /* Build and issue a coprocessor to core transfer for the requested register and send the new data */ - cortexr_run_write_insn(target, ARM_MRC_INSN | ENCODE_CP_ACCESS(14, 0, reg, 0, 5, 0), value); + cortexar_run_write_insn(target, ARM_MRC_INSN | ENCODE_CP_ACCESS(14, 0, reg, 0, 5, 0), value); /* If the register is the program counter, we first have to write it to r0 */ else if (reg == 15U) { - cortexr_core_reg_write(target, 0U, value); - cortexr_run_insn(target, ARM_MOV_PC_R0_INSN); + cortexar_core_reg_write(target, 0U, value); + cortexar_run_insn(target, ARM_MOV_PC_R0_INSN); } } -static void cortexr_core_regs_restore(target_s *const target) +static void cortexar_core_regs_restore(target_s *const target) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Load the values for each of the SPSRs in turn into r0 and shove them back into place */ for (size_t i = 0; i < ARRAY_LENGTH(priv->core_regs.spsr); ++i) { - cortexr_core_reg_write(target, 0U, priv->core_regs.spsr[i]); + cortexar_core_reg_write(target, 0U, priv->core_regs.spsr[i]); /* Build and issue the banked MSR for the required SPSR */ - cortexr_run_insn(target, ARM_MSR_SPSR_R0_INSN | (cortexr_spsr_encodings[i] << 4U)); + cortexar_run_insn(target, ARM_MSR_SPSR_R0_INSN | (cortexar_spsr_encodings[i] << 4U)); } /* Load the value for CPSR to r0 and then shove it back into place */ - cortexr_core_reg_write(target, 0U, priv->core_regs.cpsr); - cortexr_run_insn(target, ARM_MSR_CPSR_R0_INSN); + cortexar_core_reg_write(target, 0U, priv->core_regs.cpsr); + cortexar_run_insn(target, ARM_MSR_CPSR_R0_INSN); /* Fix up the program counter for the mode */ if (priv->core_regs.cpsr & CORTEXAR_CPSR_THUMB) priv->core_regs.r[CORTEX_REG_PC] |= 1U; /* Restore r1-15 in that order. Ignore r0 for the moment as it gets clobbered repeatedly */ for (size_t i = 1U; i < ARRAY_LENGTH(priv->core_regs.r); ++i) - cortexr_core_reg_write(target, i, priv->core_regs.r[i]); + cortexar_core_reg_write(target, i, priv->core_regs.r[i]); /* Now we're done with the rest of the registers, restore r0 */ - cortexr_core_reg_write(target, 0U, priv->core_regs.r[0U]); + cortexar_core_reg_write(target, 0U, priv->core_regs.r[0U]); } -static void cortexr_float_regs_restore(target_s *const target) +static void cortexar_float_regs_restore(target_s *const target) { const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Step through each double-precision float register, writing it back via r0,r1 */ for (size_t i = 0; i < ARRAY_LENGTH(priv->core_regs.d); ++i) { /* Load the low 32 bits into r0, and the high into r1 */ - cortexr_core_reg_write(target, 0U, priv->core_regs.d[i] & UINT32_MAX); - cortexr_core_reg_write(target, 1U, priv->core_regs.d[i] >> 32U); + cortexar_core_reg_write(target, 0U, priv->core_regs.d[i] & UINT32_MAX); + cortexar_core_reg_write(target, 1U, priv->core_regs.d[i] >> 32U); /* The float register to write slots into the bottom 4 bits of the instruction */ - cortexr_run_insn(target, ARM_VMOV_DN_R0_R1_INSN | i); + cortexar_run_insn(target, ARM_VMOV_DN_R0_R1_INSN | i); } /* Load the value for FPCSR to r0 and then shove it back into place */ - cortexr_core_reg_write(target, 0U, priv->core_regs.fpcsr); - cortexr_run_insn(target, ARM_VMSR_FPCSR_R0_INSN); + cortexar_core_reg_write(target, 0U, priv->core_regs.fpcsr); + cortexar_run_insn(target, ARM_VMSR_FPCSR_R0_INSN); } -static void cortexr_regs_restore(target_s *const target) +static void cortexar_regs_restore(target_s *const target) { if (target->target_options & TOPT_FLAVOUR_FLOAT) - cortexr_float_regs_restore(target); - cortexr_core_regs_restore(target); + cortexar_float_regs_restore(target); + cortexar_core_regs_restore(target); } -static uint32_t cortexr_coproc_read(target_s *const target, const uint8_t coproc, const uint16_t op) +static uint32_t cortexar_coproc_read(target_s *const target, const uint8_t coproc, const uint16_t op) { /* * Perform a read of a coprocessor - which one (between 0 and 15) is given by the coproc parameter @@ -507,13 +507,13 @@ static uint32_t cortexr_coproc_read(target_s *const target, const uint8_t coproc * Encode the MCR (Move to ARM core register from Coprocessor) instruction in ARM ISA format * using core reg r0 as the read target. */ - cortexr_run_insn(target, + cortexar_run_insn(target, ARM_MRC_INSN | ENCODE_CP_ACCESS(coproc & 0xfU, (op >> 8U) & 0x7U, 0U, (op >> 4U) & 0xfU, op & 0xfU, (op >> 12U) & 0x7U)); - return cortexr_core_reg_read(target, 0U); + return cortexar_core_reg_read(target, 0U); } -static void cortexr_coproc_write(target_s *const target, const uint8_t coproc, const uint16_t op, const uint32_t value) +static void cortexar_coproc_write(target_s *const target, const uint8_t coproc, const uint16_t op, const uint32_t value) { /* * Perform a write of a coprocessor - which one (between 0 and 15) is given by the coproc parameter @@ -523,8 +523,8 @@ static void cortexr_coproc_write(target_s *const target, const uint8_t coproc, c * Encode the MRC (Move to Coprocessor from ARM core register) instruction in ARM ISA format * using core reg r0 as the write data source. */ - cortexr_core_reg_write(target, 0U, value); - cortexr_run_insn(target, + cortexar_core_reg_write(target, 0U, value); + cortexar_run_insn(target, ARM_MCR_INSN | ENCODE_CP_ACCESS(coproc & 0xfU, (op >> 8U) & 0x7U, 0U, (op >> 4U) & 0xfU, op & 0xfU, (op >> 12U) & 0x7U)); } @@ -612,23 +612,23 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre target->detach = cortexr_detach; /* Probe for FP extension. */ - uint32_t cpacr = cortexr_coproc_read(target, CORTEXAR_CPACR); + uint32_t cpacr = cortexar_coproc_read(target, CORTEXAR_CPACR); cpacr |= CORTEXAR_CPACR_CP10_FULL_ACCESS | CORTEXAR_CPACR_CP11_FULL_ACCESS; - cortexr_coproc_write(target, CORTEXAR_CPACR, cpacr); - const bool core_has_fpu = cortexr_coproc_read(target, CORTEXAR_CPACR) == cpacr; + cortexar_coproc_write(target, CORTEXAR_CPACR, cpacr); + const bool core_has_fpu = cortexar_coproc_read(target, CORTEXAR_CPACR) == cpacr; DEBUG_TARGET("%s: FPU present? %s\n", __func__, core_has_fpu ? "yes" : "no"); target->regs_description = cortexr_target_description; - target->regs_read = cortexr_regs_read; - target->regs_write = cortexr_regs_write; - target->reg_read = cortexr_reg_read; - target->reg_write = cortexr_reg_write; + target->regs_read = cortexar_regs_read; + target->regs_write = cortexar_regs_write; + target->reg_read = cortexar_reg_read; + target->reg_write = cortexar_reg_write; target->regs_size = sizeof(uint32_t) * CORTEXAR_GENERAL_REG_COUNT; if (core_has_fpu) { target->target_options |= TOPT_FLAVOUR_FLOAT; target->regs_size += sizeof(uint32_t) * CORTEX_FLOAT_REG_COUNT; - cortexr_float_regs_save(target); + cortexar_float_regs_save(target); } target->check_error = cortexr_check_error; @@ -733,7 +733,7 @@ static inline bool cortexr_mem_read_fast(target_s *const target, uint32_t *const { /* Read each of the uint32_t's checking for failure */ for (size_t offset = 0; offset < count; ++offset) { - if (!cortexr_run_read_insn(target, ARM_LDC_R0_POSTINC4_DTRTX_INSN, dest + offset)) + if (!cortexar_run_read_insn(target, ARM_LDC_R0_POSTINC4_DTRTX_INSN, dest + offset)) return false; /* Propagate failure if it happens */ } return true; /* Signal success */ @@ -745,16 +745,16 @@ static bool cortexr_mem_read_slow(target_s *const target, uint8_t *const data, t size_t offset = 0; /* If the address is odd, read a byte to get onto an even address */ if (addr & 1U) { - if (!cortexr_run_insn(target, ARM_LDRB_R0_R1_INSN)) + if (!cortexar_run_insn(target, ARM_LDRB_R0_R1_INSN)) return false; - data[offset++] = (uint8_t)cortexr_core_reg_read(target, 1U); + data[offset++] = (uint8_t)cortexar_core_reg_read(target, 1U); ++addr; } /* If the address is now even but only 16-bit aligned, read a uint16_t to get onto 32-bit alignment */ if ((addr & 2U) && length - offset >= 2U) { - if (!cortexr_run_insn(target, ARM_LDRH_R0_R1_INSN)) + if (!cortexar_run_insn(target, ARM_LDRH_R0_R1_INSN)) return false; - write_le2(data, offset, (uint16_t)cortexr_core_reg_read(target, 1U)); + write_le2(data, offset, (uint16_t)cortexar_core_reg_read(target, 1U)); offset += 2U; } /* Use the fast path to read as much as possible before doing a slow path fixup at the end */ @@ -763,16 +763,16 @@ static bool cortexr_mem_read_slow(target_s *const target, uint8_t *const data, t const uint8_t remainder = (length - offset) & 3U; /* If the remainder needs at least 2 more bytes read, do this first */ if (remainder & 2U) { - if (!cortexr_run_insn(target, ARM_LDRH_R0_R1_INSN)) + if (!cortexar_run_insn(target, ARM_LDRH_R0_R1_INSN)) return false; - write_le2(data, offset, (uint16_t)cortexr_core_reg_read(target, 1U)); + write_le2(data, offset, (uint16_t)cortexar_core_reg_read(target, 1U)); offset += 2U; } /* Finally, fix things up if a final byte is required. */ if (remainder & 1U) { - if (!cortexr_run_insn(target, ARM_LDRB_R0_R1_INSN)) + if (!cortexar_run_insn(target, ARM_LDRB_R0_R1_INSN)) return false; - data[offset] = (uint8_t)cortexr_core_reg_read(target, 1U); + data[offset] = (uint8_t)cortexar_core_reg_read(target, 1U); } return true; /* Signal success */ } @@ -784,13 +784,13 @@ static void cortexr_mem_handle_fault( /* If we suffered a fault of some kind, grab the reason and restore DFSR/DFAR */ if (priv->core_status & CORTEXAR_STATUS_DATA_FAULT) { #ifdef ENABLE_DEBUG - const uint32_t fault_status = cortexr_coproc_read(target, CORTEXAR_DFSR); - const uint32_t fault_addr = cortexr_coproc_read(target, CORTEXAR_DFAR); + const uint32_t fault_status = cortexar_coproc_read(target, CORTEXAR_DFSR); + const uint32_t fault_addr = cortexar_coproc_read(target, CORTEXAR_DFAR); #else (void)func; #endif - cortexr_coproc_write(target, CORTEXAR_DFAR, orig_fault_addr); - cortexr_coproc_write(target, CORTEXAR_DFSR, orig_fault_status); + cortexar_coproc_write(target, CORTEXAR_DFAR, orig_fault_addr); + cortexar_coproc_write(target, CORTEXAR_DFSR, orig_fault_status); DEBUG_WARN("%s: Failed at 0x%08" PRIx32 " (%08" PRIx32 ")\n", func, fault_addr, fault_status); } @@ -805,13 +805,13 @@ static void cortexr_mem_read(target_s *const target, void *const dest, const tar { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Cache DFSR and DFAR in case we wind up triggering a data fault */ - const uint32_t fault_status = cortexr_coproc_read(target, CORTEXAR_DFSR); - const uint32_t fault_addr = cortexr_coproc_read(target, CORTEXAR_DFAR); + const uint32_t fault_status = cortexar_coproc_read(target, CORTEXAR_DFSR); + const uint32_t fault_addr = cortexar_coproc_read(target, CORTEXAR_DFAR); /* Clear any existing fault state */ priv->core_status &= ~(CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); /* Move the start address into the core's r0 */ - cortexr_core_reg_write(target, 0U, src); + cortexar_core_reg_write(target, 0U, src); /* If the address is 32-bit aligned and we're reading 32 bits at a time, use the fast path */ if ((src & 3U) == 0U && (len & 3U) == 0U) @@ -827,7 +827,7 @@ static inline bool cortexr_mem_write_fast(target_s *const target, const uint32_t { /* Read each of the uint32_t's checking for failure */ for (size_t offset = 0; offset < count; ++offset) { - if (!cortexr_run_write_insn(target, ARM_STC_DTRRX_R0_POSTINC4_INSN, src[offset])) + if (!cortexar_run_write_insn(target, ARM_STC_DTRRX_R0_POSTINC4_INSN, src[offset])) return false; /* Propagate failure if it happens */ } return true; /* Signal success */ @@ -840,15 +840,15 @@ static bool cortexr_mem_write_slow( size_t offset = 0; /* If the address is odd, write a byte to get onto an even address */ if (addr & 1U) { - cortexr_core_reg_write(target, 1U, data[offset++]); - if (!cortexr_run_insn(target, ARM_STRB_R1_R0_INSN)) + cortexar_core_reg_write(target, 1U, data[offset++]); + if (!cortexar_run_insn(target, ARM_STRB_R1_R0_INSN)) return false; ++addr; } /* If the address is now even but only 16-bit aligned, write a uint16_t to get onto 32-bit alignment */ if ((addr & 2U) && length - offset >= 2U) { - cortexr_core_reg_write(target, 1U, read_le2(data, offset)); - if (!cortexr_run_insn(target, ARM_STRH_R1_R0_INSN)) + cortexar_core_reg_write(target, 1U, read_le2(data, offset)); + if (!cortexar_run_insn(target, ARM_STRH_R1_R0_INSN)) return false; offset += 2U; } @@ -858,15 +858,15 @@ static bool cortexr_mem_write_slow( const uint8_t remainder = (length - offset) & 3U; /* If the remainder needs at least 2 more bytes write, do this first */ if (remainder & 2U) { - cortexr_core_reg_write(target, 1U, read_le2(data, offset)); - if (!cortexr_run_insn(target, ARM_STRH_R1_R0_INSN)) + cortexar_core_reg_write(target, 1U, read_le2(data, offset)); + if (!cortexar_run_insn(target, ARM_STRH_R1_R0_INSN)) return false; offset += 2U; } /* Finally, fix things up if a final byte is required. */ if (remainder & 1U) { - cortexr_core_reg_write(target, 1U, data[offset]); - if (!cortexr_run_insn(target, ARM_STRB_R1_R0_INSN)) + cortexar_core_reg_write(target, 1U, data[offset]); + if (!cortexar_run_insn(target, ARM_STRB_R1_R0_INSN)) return false; } return true; /* Signal success */ @@ -882,13 +882,13 @@ static void cortexr_mem_write(target_s *const target, const target_addr_t dest, cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; DEBUG_TARGET("%s: Writing %zu bytes @0x%" PRIx32 "\n", __func__, len, dest); /* Cache DFSR and DFAR in case we wind up triggering a data fault */ - const uint32_t fault_status = cortexr_coproc_read(target, CORTEXAR_DFSR); - const uint32_t fault_addr = cortexr_coproc_read(target, CORTEXAR_DFAR); + const uint32_t fault_status = cortexar_coproc_read(target, CORTEXAR_DFSR); + const uint32_t fault_addr = cortexar_coproc_read(target, CORTEXAR_DFAR); /* Clear any existing fault state */ priv->core_status &= ~(CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); /* Move the start address into the core's r0 */ - cortexr_core_reg_write(target, 0U, dest); + cortexar_core_reg_write(target, 0U, dest); /* If the address is 32-bit aligned and we're writing 32 bits at a time, use the fast path */ if ((dest & 3U) == 0U && (len & 3U) == 0U) @@ -899,7 +899,7 @@ static void cortexr_mem_write(target_s *const target, const target_addr_t dest, cortexr_mem_handle_fault(target, __func__, fault_status, fault_addr); } -static void cortexr_regs_read(target_s *const target, void *const data) +static void cortexar_regs_read(target_s *const target, void *const data) { const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; uint32_t *const regs = (uint32_t *)data; @@ -912,7 +912,7 @@ static void cortexr_regs_read(target_s *const target, void *const data) } } -static void cortexr_regs_write(target_s *const target, const void *const data) +static void cortexar_regs_write(target_s *const target, const void *const data) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; const uint32_t *const regs = (const uint32_t *)data; @@ -925,7 +925,7 @@ static void cortexr_regs_write(target_s *const target, const void *const data) } } -static void *cortexr_reg_ptr(target_s *const target, const size_t reg) +static void *cortexar_reg_ptr(target_s *const target, const size_t reg) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* r0-r15 */ @@ -946,7 +946,7 @@ static void *cortexr_reg_ptr(target_s *const target, const size_t reg) return NULL; } -static size_t cortexr_reg_width(const size_t reg) +static size_t cortexar_reg_width(const size_t reg) { /* r0-r15, cpsr, fpcsr */ if (reg < CORTEXAR_GENERAL_REG_COUNT || reg == 33U) @@ -955,14 +955,14 @@ static size_t cortexr_reg_width(const size_t reg) return 8U; } -static ssize_t cortexr_reg_read(target_s *const target, const uint32_t reg, void *const data, const size_t max) +static ssize_t cortexar_reg_read(target_s *const target, const uint32_t reg, void *const data, const size_t max) { /* Try to get a pointer to the storage for the requested register, and return -1 if that fails */ - const void *const reg_ptr = cortexr_reg_ptr(target, reg); + const void *const reg_ptr = cortexar_reg_ptr(target, reg); if (!reg_ptr) return -1; /* Now we have a valid register, get its width in bytes, and check that against max */ - const size_t reg_width = cortexr_reg_width(reg); + const size_t reg_width = cortexar_reg_width(reg); if (max < reg_width) return -1; /* Finally, copy the register data out and return the width */ @@ -970,14 +970,14 @@ static ssize_t cortexr_reg_read(target_s *const target, const uint32_t reg, void return reg_width; } -static ssize_t cortexr_reg_write(target_s *const target, const uint32_t reg, const void *const data, const size_t max) +static ssize_t cortexar_reg_write(target_s *const target, const uint32_t reg, const void *const data, const size_t max) { /* Try to get a poitner to the storage for the requested register, and return -1 if that fails */ - void *const reg_ptr = cortexr_reg_ptr(target, reg); + void *const reg_ptr = cortexar_reg_ptr(target, reg); if (!reg_ptr) return -1; /* Now we have a valid register, get its width in bytes, and check that against max */ - const size_t reg_width = cortexr_reg_width(reg); + const size_t reg_width = cortexar_reg_width(reg); if (max < reg_width) return -1; /* Finally, copy the new register data in and return the width */ @@ -1022,7 +1022,7 @@ static target_halt_reason_e cortexr_halt_poll(target_s *const target, target_add target, CORTEXAR_DBG_DSCR, dscr | CORTEXAR_DBG_DSCR_ITR_ENABLE | CORTEXAR_DBG_DSCR_HALTING_DBG_ENABLE); /* Save the target core's registers as debugging operations clobber them */ - cortexr_regs_save(target); + cortexar_regs_save(target); target_halt_reason_e reason = TARGET_HALT_FAULT; /* Determine why we halted exactly from the Method Of Entry bits */ @@ -1061,7 +1061,7 @@ static void cortexr_halt_resume(target_s *const target, const bool step) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Restore the core's registers so the running program doesn't know we've been in there */ - cortexr_regs_restore(target); + cortexar_regs_restore(target); uint32_t dscr = cortex_dbg_read32(target, CORTEXAR_DBG_DSCR); /* @@ -1082,7 +1082,7 @@ static void cortexr_halt_resume(target_s *const target, const bool step) /* Invalidate all the instruction caches if we're on a VMSA model device */ if (target->target_options & TOPT_FLAVOUR_VIRT_MEM) - cortexr_coproc_write(target, CORTEXAR_ICIALLU, 0U); + cortexar_coproc_write(target, CORTEXAR_ICIALLU, 0U); cortex_dbg_write32(target, CORTEXAR_DBG_DSCR, dscr & ~CORTEXAR_DBG_DSCR_ITR_ENABLE); /* Ask to resume the core */ From 42e577ba3dc0b06265c6a29c503cbebec7894a2f Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sat, 14 Oct 2023 23:05:02 +0100 Subject: [PATCH 06/22] cortexar: Renamed the memory access machinary --- src/target/cortexar.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index d63f20ccde2..0e27dc6b73b 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -291,9 +291,9 @@ static_assert(ARRAY_LENGTH(cortexr_spr_types) == ARRAY_LENGTH(cortexr_spr_names) ); /* clang-format on */ -static bool cortexr_check_error(target_s *target); -static void cortexr_mem_read(target_s *target, void *dest, target_addr_t src, size_t len); -static void cortexr_mem_write(target_s *target, target_addr_t dest, const void *src, size_t len); +static bool cortexar_check_error(target_s *target); +static void cortexar_mem_read(target_s *target, void *dest, target_addr_t src, size_t len); +static void cortexar_mem_write(target_s *target, target_addr_t dest, const void *src, size_t len); static void cortexar_regs_read(target_s *target, void *data); static void cortexar_regs_write(target_s *target, const void *data); @@ -631,9 +631,9 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre cortexar_float_regs_save(target); } - target->check_error = cortexr_check_error; - target->mem_read = cortexr_mem_read; - target->mem_write = cortexr_mem_write; + target->check_error = cortexar_check_error; + target->mem_read = cortexar_mem_read; + target->mem_write = cortexar_mem_write; target->breakwatch_set = cortexr_breakwatch_set; target->breakwatch_clear = cortexr_breakwatch_clear; @@ -720,7 +720,7 @@ void cortexr_detach(target_s *const target) target_halt_resume(target, false); } -static bool cortexr_check_error(target_s *const target) +static bool cortexar_check_error(target_s *const target) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; const bool fault = priv->core_status & (CORTEXAR_STATUS_DATA_FAULT | CORTEXAR_STATUS_MMU_FAULT); @@ -728,7 +728,7 @@ static bool cortexr_check_error(target_s *const target) return fault || cortex_check_error(target); } -/* Fast path for cortexr_mem_read(). Assumes the address to read data from is already loaded in r0. */ +/* Fast path for cortexar_mem_read(). Assumes the address to read data from is already loaded in r0. */ static inline bool cortexr_mem_read_fast(target_s *const target, uint32_t *const dest, const size_t count) { /* Read each of the uint32_t's checking for failure */ @@ -739,7 +739,7 @@ static inline bool cortexr_mem_read_fast(target_s *const target, uint32_t *const return true; /* Signal success */ } -/* Slow path for cortexr_mem_read(). Trashes r0 and r1. */ +/* Slow path for cortexar_mem_read(). Trashes r0 and r1. */ static bool cortexr_mem_read_slow(target_s *const target, uint8_t *const data, target_addr_t addr, const size_t length) { size_t offset = 0; @@ -801,7 +801,7 @@ static void cortexr_mem_handle_fault( * NB: This requires the core to be halted! Uses instruction launches on * the core and requires we're in debug mode to work. Trashes r0. */ -static void cortexr_mem_read(target_s *const target, void *const dest, const target_addr_t src, const size_t len) +static void cortexar_mem_read(target_s *const target, void *const dest, const target_addr_t src, const size_t len) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Cache DFSR and DFAR in case we wind up triggering a data fault */ @@ -822,7 +822,7 @@ static void cortexr_mem_read(target_s *const target, void *const dest, const tar cortexr_mem_handle_fault(target, __func__, fault_status, fault_addr); } -/* Fast path for cortexr_mem_write(). Assumes the address to read data from is already loaded in r0. */ +/* Fast path for cortexar_mem_write(). Assumes the address to read data from is already loaded in r0. */ static inline bool cortexr_mem_write_fast(target_s *const target, const uint32_t *const src, const size_t count) { /* Read each of the uint32_t's checking for failure */ @@ -833,7 +833,7 @@ static inline bool cortexr_mem_write_fast(target_s *const target, const uint32_t return true; /* Signal success */ } -/* Slow path for cortexr_mem_write(). Trashes r0 and r1. */ +/* Slow path for cortexar_mem_write(). Trashes r0 and r1. */ static bool cortexr_mem_write_slow( target_s *const target, target_addr_t addr, const uint8_t *const data, const size_t length) { @@ -877,7 +877,8 @@ static bool cortexr_mem_write_slow( * NB: This requires the core to be halted! Uses instruction launches on * the core and requires we're in debug mode to work. Trashes r0. */ -static void cortexr_mem_write(target_s *const target, const target_addr_t dest, const void *const src, const size_t len) +static void cortexar_mem_write( + target_s *const target, const target_addr_t dest, const void *const src, const size_t len) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; DEBUG_TARGET("%s: Writing %zu bytes @0x%" PRIx32 "\n", __func__, len, dest); From 2232692dd38aedff25f067e4fbded8c95367b569 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sat, 14 Oct 2023 23:07:28 +0100 Subject: [PATCH 07/22] cortexar: Renamed the halt/resume machinary --- src/target/cortexar.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 0e27dc6b73b..463e79ab647 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -300,9 +300,9 @@ static void cortexar_regs_write(target_s *target, const void *data); static ssize_t cortexar_reg_read(target_s *target, uint32_t reg, void *data, size_t max); static ssize_t cortexar_reg_write(target_s *target, uint32_t reg, const void *data, size_t max); -static target_halt_reason_e cortexr_halt_poll(target_s *target, target_addr_t *watch); -static void cortexr_halt_request(target_s *target); -static void cortexr_halt_resume(target_s *target, bool step); +static target_halt_reason_e cortexar_halt_poll(target_s *target, target_addr_t *watch); +static void cortexar_halt_request(target_s *target); +static void cortexar_halt_resume(target_s *target, bool step); static int cortexr_breakwatch_set(target_s *target, breakwatch_s *breakwatch); static int cortexr_breakwatch_clear(target_s *target, breakwatch_s *breakwatch); @@ -558,9 +558,9 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre priv->base.ap = ap; priv->base.base_addr = base_address; - target->halt_request = cortexr_halt_request; - target->halt_poll = cortexr_halt_poll; - target->halt_resume = cortexr_halt_resume; + target->halt_request = cortexar_halt_request; + target->halt_poll = cortexar_halt_poll; + target->halt_resume = cortexar_halt_resume; /* Try to halt the target core */ target_halt_request(target); @@ -986,7 +986,7 @@ static ssize_t cortexar_reg_write(target_s *const target, const uint32_t reg, co return reg_width; } -static void cortexr_halt_request(target_s *const target) +static void cortexar_halt_request(target_s *const target) { volatile exception_s error; TRY_CATCH (error, EXCEPTION_TIMEOUT) { @@ -996,7 +996,7 @@ static void cortexr_halt_request(target_s *const target) tc_printf(target, "Timeout sending interrupt, is target in WFI?\n"); } -static target_halt_reason_e cortexr_halt_poll(target_s *const target, target_addr_t *const watch) +static target_halt_reason_e cortexar_halt_poll(target_s *const target, target_addr_t *const watch) { volatile uint32_t dscr = 0; volatile exception_s error; @@ -1058,7 +1058,7 @@ static target_halt_reason_e cortexr_halt_poll(target_s *const target, target_add return reason; } -static void cortexr_halt_resume(target_s *const target, const bool step) +static void cortexar_halt_resume(target_s *const target, const bool step) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; /* Restore the core's registers so the running program doesn't know we've been in there */ From 1c050effd47cec2e097e5ad6b85f4a772bec1b41 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sat, 14 Oct 2023 23:09:09 +0100 Subject: [PATCH 08/22] cortexar: Renamed the breakwatch machinary --- src/target/cortexar.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 463e79ab647..737e5662aa1 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -304,9 +304,9 @@ static target_halt_reason_e cortexar_halt_poll(target_s *target, target_addr_t * static void cortexar_halt_request(target_s *target); static void cortexar_halt_resume(target_s *target, bool step); -static int cortexr_breakwatch_set(target_s *target, breakwatch_s *breakwatch); -static int cortexr_breakwatch_clear(target_s *target, breakwatch_s *breakwatch); -static void cortexr_config_breakpoint(target_s *target, size_t slot, uint32_t mode, target_addr_t addr); +static int cortexar_breakwatch_set(target_s *target, breakwatch_s *breakwatch); +static int cortexar_breakwatch_clear(target_s *target, breakwatch_s *breakwatch); +static void cortexar_config_breakpoint(target_s *target, size_t slot, uint32_t mode, target_addr_t addr); bool cortexr_attach(target_s *target); void cortexr_detach(target_s *target); @@ -635,8 +635,8 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre target->mem_read = cortexar_mem_read; target->mem_write = cortexar_mem_write; - target->breakwatch_set = cortexr_breakwatch_set; - target->breakwatch_clear = cortexr_breakwatch_clear; + target->breakwatch_set = cortexar_breakwatch_set; + target->breakwatch_clear = cortexar_breakwatch_clear; /* Check cache type */ const uint32_t cache_type = cortex_dbg_read32(target, CORTEXAR_CTR); @@ -1072,7 +1072,7 @@ static void cortexar_halt_resume(target_s *const target, const bool step) * Additionally, adjust DSCR to disable interrupts as necessary. */ if (step) { - cortexr_config_breakpoint(target, priv->base.breakpoints_available, + cortexar_config_breakpoint(target, priv->base.breakpoints_available, CORTEXAR_DBG_BCR_TYPE_UNLINKED_INSN_MISMATCH | ((priv->core_regs.cpsr & CORTEXAR_CPSR_THUMB) ? 2 : 4), priv->core_regs.r[CORTEX_REG_PC]); dscr |= CORTEXAR_DBG_DSCR_INTERRUPT_DISABLE; @@ -1097,7 +1097,7 @@ static void cortexar_halt_resume(target_s *const target, const bool step) status = cortex_dbg_read32(target, CORTEXAR_DBG_DSCR); } -static void cortexr_config_breakpoint( +static void cortexar_config_breakpoint( target_s *const target, const size_t slot, uint32_t mode, const target_addr_t addr) { /* @@ -1116,7 +1116,7 @@ static void cortexr_config_breakpoint( target, CORTEXAR_DBG_BCR + (slot << 2U), CORTEXAR_DBG_BCR_ENABLE | CORTEXAR_DBG_BCR_ALL_MODES | (mode & ~7U)); } -static uint32_t cortexr_watchpoint_mode(const target_breakwatch_e type) +static uint32_t cortexar_watchpoint_mode(const target_breakwatch_e type) { switch (type) { case TARGET_WATCH_READ: @@ -1130,7 +1130,7 @@ static uint32_t cortexr_watchpoint_mode(const target_breakwatch_e type) } } -static void cortexr_config_watchpoint(target_s *const target, const size_t slot, const breakwatch_s *const breakwatch) +static void cortexar_config_watchpoint(target_s *const target, const size_t slot, const breakwatch_s *const breakwatch) { /* * Construct the access and bytes masks - starting with the bytes mask which uses the fact @@ -1140,7 +1140,7 @@ static void cortexr_config_watchpoint(target_s *const target, const size_t slot, * Which set of bits need to be 1's depends on the address low bits. */ const uint32_t byte_mask = ((1U << breakwatch->size) - 1U) << (breakwatch->addr & 3U); - const uint32_t mode = cortexr_watchpoint_mode(breakwatch->type) | CORTEXAR_DBG_WCR_BYTE_SELECT(byte_mask); + const uint32_t mode = cortexar_watchpoint_mode(breakwatch->type) | CORTEXAR_DBG_WCR_BYTE_SELECT(byte_mask); /* Configure the watchpoint slot */ cortex_dbg_write32(target, CORTEXAR_DBG_WVR + (slot << 2U), breakwatch->addr & ~3U); @@ -1148,7 +1148,7 @@ static void cortexr_config_watchpoint(target_s *const target, const size_t slot, target, CORTEXAR_DBG_WCR + (slot << 2U), CORTEXAR_DBG_WCR_ENABLE | CORTEXAR_DBG_WCR_ALL_MODES | mode); } -static int cortexr_breakwatch_set(target_s *const target, breakwatch_s *const breakwatch) +static int cortexar_breakwatch_set(target_s *const target, breakwatch_s *const breakwatch) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; @@ -1166,7 +1166,7 @@ static int cortexr_breakwatch_set(target_s *const target, breakwatch_s *const br return -1; /* Set the breakpoint slot up and mark it used */ - cortexr_config_breakpoint( + cortexar_config_breakpoint( target, breakpoint, CORTEXAR_DBG_BCR_TYPE_UNLINKED_INSN_MATCH | (breakwatch->size & 7U), breakwatch->addr); priv->base.breakpoints_mask |= 1U << breakpoint; breakwatch->reserved[0] = breakpoint; @@ -1188,7 +1188,7 @@ static int cortexr_breakwatch_set(target_s *const target, breakwatch_s *const br return -1; /* Set the watchpoint slot up and mark it used */ - cortexr_config_watchpoint(target, watchpoint, breakwatch); + cortexar_config_watchpoint(target, watchpoint, breakwatch); priv->base.watchpoints_mask |= 1U << watchpoint; breakwatch->reserved[0] = watchpoint; /* Tell the debugger that it was successfully able to set the watchpoint */ @@ -1200,7 +1200,7 @@ static int cortexr_breakwatch_set(target_s *const target, breakwatch_s *const br } } -static int cortexr_breakwatch_clear(target_s *const target, breakwatch_s *const breakwatch) +static int cortexar_breakwatch_clear(target_s *const target, breakwatch_s *const breakwatch) { cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; From dc637fada8a3d5e0354b5a123c6bd58b1fbb14b5 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sat, 14 Oct 2023 23:09:56 +0100 Subject: [PATCH 09/22] cortexar: Renamed the target XML description machinary --- src/target/cortexar.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 737e5662aa1..ad89d0b2aeb 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -311,7 +311,7 @@ static void cortexar_config_breakpoint(target_s *target, size_t slot, uint32_t m bool cortexr_attach(target_s *target); void cortexr_detach(target_s *target); -static const char *cortexr_target_description(target_s *target); +static const char *cortexar_target_description(target_s *target); static bool cortexar_run_insn(target_s *const target, const uint32_t insn) { @@ -618,7 +618,7 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre const bool core_has_fpu = cortexar_coproc_read(target, CORTEXAR_CPACR) == cpacr; DEBUG_TARGET("%s: FPU present? %s\n", __func__, core_has_fpu ? "yes" : "no"); - target->regs_description = cortexr_target_description; + target->regs_description = cortexar_target_description; target->regs_read = cortexar_regs_read; target->regs_write = cortexar_regs_write; target->reg_read = cortexar_reg_read; @@ -1231,7 +1231,7 @@ static int cortexar_breakwatch_clear(target_s *const target, breakwatch_s *const /* * This function creates the target description XML substring for the FPU (VFPv2) on - * a Cortex-R part. This has the same rationale as the function below. + * a Cortex-A/R part. This has the same rationale as the function below. * * The string it creates is conceptually the following: * @@ -1254,7 +1254,7 @@ static int cortexar_breakwatch_clear(target_s *const target, breakwatch_s *const * * */ -static size_t cortexr_build_target_fpu_description(char *const buffer, size_t max_length) +static size_t cortexar_build_target_fpu_description(char *const buffer, size_t max_length) { size_t print_size = max_length; /* Terminate the previous feature block and start the new */ @@ -1279,7 +1279,7 @@ static size_t cortexr_build_target_fpu_description(char *const buffer, size_t ma } /* - * This function creates the target description XML string for a Cortex-R part. + * This function creates the target description XML string for a Cortex-A/R part. * This is done this way to decrease string duplications and thus code size, * making it unfortunately much less readable than the string literal it is * equivilent to. @@ -1310,7 +1310,7 @@ static size_t cortexr_build_target_fpu_description(char *const buffer, size_t ma * * */ -static size_t cortexr_build_target_description(char *const buffer, size_t max_length, const bool has_fpu) +static size_t cortexar_build_target_description(char *const buffer, size_t max_length, const bool has_fpu) { size_t print_size = max_length; /* Start with the "preamble" chunks which are mostly common across targets save for 2 words. */ @@ -1342,7 +1342,7 @@ static size_t cortexr_build_target_description(char *const buffer, size_t max_le if (max_length != 0) print_size = max_length - (size_t)offset; - offset += cortexr_build_target_fpu_description(buffer + offset, print_size); + offset += cortexar_build_target_fpu_description(buffer + offset, print_size); } /* Build the XML blob's termination */ @@ -1354,13 +1354,13 @@ static size_t cortexr_build_target_description(char *const buffer, size_t max_le return (size_t)offset; } -static const char *cortexr_target_description(target_s *const target) +static const char *cortexar_target_description(target_s *const target) { const size_t description_length = - cortexr_build_target_description(NULL, 0, target->target_options & TOPT_FLAVOUR_FLOAT) + 1U; + cortexar_build_target_description(NULL, 0, target->target_options & TOPT_FLAVOUR_FLOAT) + 1U; char *const description = malloc(description_length); if (description) - (void)cortexr_build_target_description( + (void)cortexar_build_target_description( description, description_length, target->target_options & TOPT_FLAVOUR_FLOAT); return description; } From 3150b2bf3d45eacb5422e9fa9142b84ae4357e76 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sat, 14 Oct 2023 23:39:47 +0100 Subject: [PATCH 10/22] cortexar: Renamed the target attach/detach functions --- src/target/cortexar.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index ad89d0b2aeb..8be3ef37189 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -308,8 +308,8 @@ static int cortexar_breakwatch_set(target_s *target, breakwatch_s *breakwatch); static int cortexar_breakwatch_clear(target_s *target, breakwatch_s *breakwatch); static void cortexar_config_breakpoint(target_s *target, size_t slot, uint32_t mode, target_addr_t addr); -bool cortexr_attach(target_s *target); -void cortexr_detach(target_s *target); +bool cortexar_attach(target_s *target); +void cortexar_detach(target_s *target); static const char *cortexar_target_description(target_s *target); @@ -608,8 +608,8 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre DEBUG_TARGET( "%s: Core uses the %cMSA memory model\n", __func__, target->target_options & TOPT_FLAVOUR_VIRT_MEM ? 'V' : 'P'); - target->attach = cortexr_attach; - target->detach = cortexr_detach; + target->attach = cortexar_attach; + target->detach = cortexar_detach; /* Probe for FP extension. */ uint32_t cpacr = cortexar_coproc_read(target, CORTEXAR_CPACR); @@ -662,7 +662,7 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre return true; } -bool cortexr_attach(target_s *const target) +bool cortexar_attach(target_s *const target) { adiv5_access_port_s *ap = cortex_ap(target); /* Mark the DP as being in fault so error recovery will switch to this core when in multi-drop mode */ @@ -701,7 +701,7 @@ bool cortexr_attach(target_s *const target) return true; } -void cortexr_detach(target_s *const target) +void cortexar_detach(target_s *const target) { const cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; From a815ce5c89ec2d49a5a327f8b11c08bf3fa2ff49 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sat, 14 Oct 2023 23:40:31 +0100 Subject: [PATCH 11/22] cortexar: Refactored the Cortex-R probe routine to allow for a common probe routine for Cortex-A and -R parts --- src/target/cortexar.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 8be3ef37189..534f07b8323 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -529,11 +529,12 @@ static void cortexar_coproc_write(target_s *const target, const uint8_t coproc, ENCODE_CP_ACCESS(coproc & 0xfU, (op >> 8U) & 0x7U, 0U, (op >> 4U) & 0xfU, op & 0xfU, (op >> 12U) & 0x7U)); } -bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_address) +static target_s *cortexar_probe( + adiv5_access_port_s *const ap, const target_addr_t base_address, const char *const core_type) { target_s *target = target_new(); if (!target) - return false; + return NULL; adiv5_ap_ref(ap); if (ap->dp->version >= 2 && ap->dp->target_designer_code != 0) { @@ -549,10 +550,10 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre cortexar_priv_s *const priv = calloc(1, sizeof(*priv)); if (!priv) { /* calloc failed: heap exhaustion */ DEBUG_ERROR("calloc: failed in %s\n", __func__); - return false; + return NULL; } - target->driver = "ARM Cortex-R"; + target->driver = core_type; target->priv = priv; target->priv_free = cortex_priv_free; priv->base.ap = ap; @@ -653,6 +654,15 @@ bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_addre } else target_check_error(target); + return target; +} + +bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_address) +{ + target_s *const target = cortexar_probe(ap, base_address, "ARM Cortex-R"); + if (!target) + return false; + #if PC_HOSTED == 0 gdb_outf("Please report unknown device with Designer 0x%x Part ID 0x%x\n", target->designer_code, target->part_id); #else From 8fe11e8125be60eef2a026efe8cfd9f72e5215f9 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sat, 14 Oct 2023 23:45:53 +0100 Subject: [PATCH 12/22] cortexar: Built a replacement Cortex-A probe routine and dropped the old support out of the build --- src/Makefile | 1 - src/target/cortexar.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index ca67f86bb7d..646b0faa07a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -31,7 +31,6 @@ SRC = \ at32f43x.c \ command.c \ cortex.c \ - cortexa.c \ cortexm.c \ crc32.c \ efm32.c \ diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 534f07b8323..02694943996 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -657,6 +657,21 @@ static target_s *cortexar_probe( return target; } +bool cortexa_probe(adiv5_access_port_s *const ap, const target_addr_t base_address) +{ + target_s *const target = cortexar_probe(ap, base_address, "ARM Cortex-A"); + if (!target) + return false; + +#if PC_HOSTED == 0 + gdb_outf("Please report unknown device with Designer 0x%x Part ID 0x%x\n", target->designer_code, target->part_id); +#else + DEBUG_WARN( + "Please report unknown device with Designer 0x%x Part ID 0x%x\n", target->designer_code, target->part_id); +#endif + return true; +} + bool cortexr_probe(adiv5_access_port_s *const ap, const target_addr_t base_address) { target_s *const target = cortexar_probe(ap, base_address, "ARM Cortex-R"); From 2133d2c4ec7a5aee82571c363cad028b8d684e07 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Oct 2023 00:47:56 +0100 Subject: [PATCH 13/22] cortexar: Implemented address translation so breakpoints and watchpoints work properly on VMSA targets --- src/target/cortexar.c | 59 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 02694943996..d8f096cf63d 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -238,15 +238,29 @@ static const uint16_t cortexar_spsr_encodings[5] = { #define ARM_STRB_R1_R0_INSN 0xe4e01001U #define ARM_STRH_R1_R0_INSN 0xe0e010b2U +/* Instruction encodings for synchronisation barriers */ +#define ARM_ISB_INSN 0xe57ff06fU + /* Coprocessor register definitions */ -#define CORTEXAR_CPACR 15U, ENCODE_CP_REG(1U, 0U, 0U, 2U) -#define CORTEXAR_DFSR 15U, ENCODE_CP_REG(5U, 0U, 0U, 0U) -#define CORTEXAR_DFAR 15U, ENCODE_CP_REG(6U, 0U, 0U, 0U) + +/* Co-Processor Access Control Register */ +#define CORTEXAR_CPACR 15U, ENCODE_CP_REG(1U, 0U, 0U, 2U) +/* Data Fault Status Register */ +#define CORTEXAR_DFSR 15U, ENCODE_CP_REG(5U, 0U, 0U, 0U) +/* Data Fault Address Register */ +#define CORTEXAR_DFAR 15U, ENCODE_CP_REG(6U, 0U, 0U, 0U) +/* Physical Address Register */ +#define CORTEXAR_PAR32 15U, ENCODE_CP_REG(7U, 4U, 0U, 0U) +/* Instruction Cache Invalidate ALL to Unification */ #define CORTEXAR_ICIALLU 15U, ENCODE_CP_REG(7U, 5U, 0U, 0U) +/* Address Translate Stage 1 Current state PL1 Read */ +#define CORTEXAR_ATS1CPR 15U, ENCODE_CP_REG(7U, 8U, 0U, 0U) #define CORTEXAR_CPACR_CP10_FULL_ACCESS 0x00300000U #define CORTEXAR_CPACR_CP11_FULL_ACCESS 0x00c00000U +#define CORTEXAR_PAR32_FAULT 0x00000001U + #define CORTEXAR_PFR1_SEC_EXT_MASK 0x000000f0U #define CORTEXAR_PFR1_VIRT_EXT_MASK 0x0000f000U @@ -529,6 +543,41 @@ static void cortexar_coproc_write(target_s *const target, const uint8_t coproc, ENCODE_CP_ACCESS(coproc & 0xfU, (op >> 8U) & 0x7U, 0U, (op >> 4U) & 0xfU, op & 0xfU, (op >> 12U) & 0x7U)); } +/* + * Perform a virtual to physical address translation. + * NB: This requires the core to be halted! Trashes r0. + */ +static target_addr_t cortexar_virt_to_phys(target_s *const target, const target_addr_t virt_addr) +{ + /* Check if the target is PMSA and return early if it is */ + if (!(target->target_options & TOPT_FLAVOUR_VIRT_MEM)) + return virt_addr; + + /* + * Now we know the target is VMSA and so has the address translation machinary, + * start by loading r0 with the VA to translate and request its translation + */ + cortexar_core_reg_write(target, 0U, virt_addr); + cortexar_coproc_write(target, CORTEXAR_ATS1CPR, 0U); + /* + * Ensure that's complete with a sync barrier, then read the result back + * from the physical address register into r0 so we can extract the result + */ + cortexar_run_insn(target, ARM_ISB_INSN); + cortexar_coproc_read(target, CORTEXAR_PAR32); + + const uint32_t phys_addr = cortexar_core_reg_read(target, 0U); + /* Check if the MMU indicated a translation failure, marking a fault if it did */ + if (phys_addr & CORTEXAR_PAR32_FAULT) { + cortexar_priv_s *const priv = (cortexar_priv_s *)target->priv; + priv->core_status |= CORTEXAR_STATUS_MMU_FAULT; + } + + /* Convert the physical address to a virtual one using the top 20 bits of PAR and the bottom 12 of the virtual. */ + const target_addr_t address = (phys_addr & 0xfffff000U) | (virt_addr & 0x00000fffU); + return address; +} + static target_s *cortexar_probe( adiv5_access_port_s *const ap, const target_addr_t base_address, const char *const core_type) { @@ -1136,7 +1185,7 @@ static void cortexar_config_breakpoint( mode |= CORTEXAR_DBG_BCR_BYTE_SELECT_ALL; /* Configure the breakpoint slot */ - cortex_dbg_write32(target, CORTEXAR_DBG_BVR + (slot << 2U), addr & ~3U); + cortex_dbg_write32(target, CORTEXAR_DBG_BVR + (slot << 2U), cortexar_virt_to_phys(target, addr & ~3U)); cortex_dbg_write32( target, CORTEXAR_DBG_BCR + (slot << 2U), CORTEXAR_DBG_BCR_ENABLE | CORTEXAR_DBG_BCR_ALL_MODES | (mode & ~7U)); } @@ -1168,7 +1217,7 @@ static void cortexar_config_watchpoint(target_s *const target, const size_t slot const uint32_t mode = cortexar_watchpoint_mode(breakwatch->type) | CORTEXAR_DBG_WCR_BYTE_SELECT(byte_mask); /* Configure the watchpoint slot */ - cortex_dbg_write32(target, CORTEXAR_DBG_WVR + (slot << 2U), breakwatch->addr & ~3U); + cortex_dbg_write32(target, CORTEXAR_DBG_WVR + (slot << 2U), cortexar_virt_to_phys(target, breakwatch->addr & ~3U)); cortex_dbg_write32( target, CORTEXAR_DBG_WCR + (slot << 2U), CORTEXAR_DBG_WCR_ENABLE | CORTEXAR_DBG_WCR_ALL_MODES | mode); } From 2db5422165a7b26bd9fdccc8b306d18d6465ed81 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Oct 2023 14:04:24 +0100 Subject: [PATCH 14/22] cortexar: Ported over the OS lock unlock logic from the ALTracer --- src/target/cortexar.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index d8f096cf63d..6d2b587e26e 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -86,6 +86,10 @@ typedef struct cortexar_priv { #define CORTEXAR_DBG_BCR 0x140U #define CORTEXAR_DBG_WVR 0x180U #define CORTEXAR_DBG_WCR 0x1c0U +#define CORTEXAR_DBG_OSLAR 0x300U +#define CORTEXAR_DBG_OSLSR 0x304U +#define CORTEXAR_DBG_OSSSR 0x308U +#define CORTEXAR_DBG_OSDLR 0x30cU #define CORTEXAR_CPUID 0xd00U #define CORTEXAR_CTR 0xd04U @@ -139,6 +143,11 @@ typedef struct cortexar_priv { #define CORTEXAR_DBG_WCR_BYTE_SELECT(x) \ (((x) << CORTEXAR_DBG_WCR_BYTE_SELECT_OFFSET) & CORTEXAR_DBG_WCR_BYTE_SELECT_MASK) +#define CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL 0x00000009U +#define CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL_FULL 0x00000001U +#define CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL_PARTIAL 0x00000008U +#define CORTEXAR_DBG_OSLSR_LOCKED (1U << 1U) + /* * Instruction encodings for reading/writing the program counter to/from r0, * reading/writing CPSR to/from r0, and reading/writing the SPSRs to/from r0. @@ -578,6 +587,25 @@ static target_addr_t cortexar_virt_to_phys(target_s *const target, const target_ return address; } +static void cortexar_oslock_unlock(target_s *const target) +{ + const uint32_t lock_status = cortex_dbg_read32(target, CORTEXAR_DBG_OSLSR); + DEBUG_TARGET("%s: OS lock status: %08" PRIx32 "\n", __func__, lock_status); + /* Check if the lock is implemented, then if it is, if it's set */ + if (((lock_status & CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL) == CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL_FULL || + (lock_status & CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL) == CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL_PARTIAL) && + (lock_status & CORTEXAR_DBG_OSLSR_LOCKED)) { + /* Lock implemented, and set. Try to unlock */ + DEBUG_WARN("%s: OS lock set, unlocking\n", __func__); + cortex_dbg_write32(target, CORTEXAR_DBG_OSLAR, 0U); + + /* Read back to check if we succeeded */ + const bool locked = cortex_dbg_read32(target, CORTEXAR_DBG_OSLSR) & CORTEXAR_DBG_OSLSR_LOCKED; + if (locked) + DEBUG_ERROR("%s: Lock sticky. Core not powered?\n", __func__); + } +} + static target_s *cortexar_probe( adiv5_access_port_s *const ap, const target_addr_t base_address, const char *const core_type) { @@ -612,6 +640,12 @@ static target_s *cortexar_probe( target->halt_poll = cortexar_halt_poll; target->halt_resume = cortexar_halt_resume; + /* + * Clear the OSLock if set prior to halting the core - trying to do this after target_halt_request() + * does not function over JTAG and triggers the lock sticky message. + */ + cortexar_oslock_unlock(target); + /* Try to halt the target core */ target_halt_request(target); platform_timeout_s timeout; @@ -745,6 +779,8 @@ bool cortexar_attach(target_s *const target) /* Clear any pending fault condition (and switch to this core) */ target_check_error(target); + /* Ensure the OS lock is unset just in case it was re-set between probe and attach */ + cortexar_oslock_unlock(target); /* Try to halt the core */ target_halt_request(target); platform_timeout_s timeout; @@ -1092,6 +1128,8 @@ static target_halt_reason_e cortexar_halt_poll(target_s *const target, target_ad if (!(dscr & CORTEXAR_DBG_DSCR_HALTED)) return TARGET_HALT_RUNNING; + /* Ensure the OS lock is cleared as a precaution */ + cortexar_oslock_unlock(target); /* Make sure ITR is enabled and likewise halting debug (so breakpoints work) */ cortex_dbg_write32( target, CORTEXAR_DBG_DSCR, dscr | CORTEXAR_DBG_DSCR_ITR_ENABLE | CORTEXAR_DBG_DSCR_HALTING_DBG_ENABLE); From 958da46487e41d2ca526425e2ae1cd9aab82cb39 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Oct 2023 14:31:50 +0100 Subject: [PATCH 15/22] cortexar: Improved the register documentation and CPSR definitions --- src/target/cortexar.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 6d2b587e26e..6e581a4a14c 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -73,23 +73,23 @@ typedef struct cortexar_priv { uint8_t core_status; } cortexar_priv_s; -#define CORTEXAR_DBG_IDR 0x000U +#define CORTEXAR_DBG_IDR 0x000U /* ID register */ #define CORTEXAR_DBG_WFAR 0x018U -#define CORTEXAR_DBG_VCR 0x01cU +#define CORTEXAR_DBG_VCR 0x01cU /* Vector Catch register */ #define CORTEXAR_DBG_DSCCR 0x028U -#define CORTEXAR_DBG_DTRTX 0x080U -#define CORTEXAR_DBG_ITR 0x084U -#define CORTEXAR_DBG_DSCR 0x088U -#define CORTEXAR_DBG_DTRRX 0x08cU -#define CORTEXAR_DBG_DRCR 0x090U +#define CORTEXAR_DBG_DTRTX 0x080U /* DBGDTRRXext */ +#define CORTEXAR_DBG_ITR 0x084U /* Instruction register */ +#define CORTEXAR_DBG_DSCR 0x088U /* Debug Status and Control register */ +#define CORTEXAR_DBG_DTRRX 0x08cU /* DBGDTRTXext */ +#define CORTEXAR_DBG_DRCR 0x090U /* Debug Run Control register */ #define CORTEXAR_DBG_BVR 0x100U #define CORTEXAR_DBG_BCR 0x140U #define CORTEXAR_DBG_WVR 0x180U #define CORTEXAR_DBG_WCR 0x1c0U -#define CORTEXAR_DBG_OSLAR 0x300U -#define CORTEXAR_DBG_OSLSR 0x304U -#define CORTEXAR_DBG_OSSSR 0x308U -#define CORTEXAR_DBG_OSDLR 0x30cU +#define CORTEXAR_DBG_OSLAR 0x300U /* OS lock access register */ +#define CORTEXAR_DBG_OSLSR 0x304U /* OS lock status register */ +#define CORTEXAR_DBG_OSSRR 0x308U /* OS save/restore register */ +#define CORTEXAR_DBG_OSDLR 0x30cU /* OS double-lock register */ #define CORTEXAR_CPUID 0xd00U #define CORTEXAR_CTR 0xd04U @@ -160,7 +160,14 @@ typedef struct cortexar_priv { #define ARM_MSR_SPSR_R0_INSN 0xe160f200U /* CPSR register definitions */ -#define CORTEXAR_CPSR_THUMB (1U << 5U) +#define CORTEXAR_CPSR_MODE_MASK 0xffffffe0U +#define CORTEXAR_CPSR_MODE_USER 0x00000010U +#define CORTEXAR_CPSR_MODE_SVC 0x00000013U +#define CORTEXAR_CPSR_MODE_MON 0x00000016U +#define CORTEXAR_CPSR_MODE_ABRT 0x00000017U +#define CORTEXAR_CPSR_MODE_HYP 0x0000001aU +#define CORTEXAR_CPSR_MODE_SYS 0x0000001fU +#define CORTEXAR_CPSR_THUMB (1U << 5U) /* * Table of encodings for the banked SPSRs - These are encoded in the following format: From e93dee1a4f6a9308ff0ac88b2c9e29571774db51 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Oct 2023 16:04:43 +0100 Subject: [PATCH 16/22] cortex: Moved and renamed CORTEXM_TOPT_INHIBIT_NRST to CORTEX_TOPT_INHIBIT_NRST and put it in the unified Cortex header --- src/target/HACKING.md | 4 ++-- src/target/cortex.h | 2 ++ src/target/cortexm.c | 4 ++-- src/target/cortexm.h | 1 - src/target/efm32.c | 2 +- src/target/imxrt.c | 2 +- src/target/lmi.c | 8 ++++---- src/target/lpc43xx.c | 2 +- src/target/lpc546xx.c | 2 +- src/target/lpc55xx.c | 2 +- src/target/nrf51.c | 4 ++-- src/target/nrf91.c | 2 +- src/target/rp.c | 2 +- src/target/sam3x.c | 2 +- 14 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/target/HACKING.md b/src/target/HACKING.md index adb3829531d..5bfcac30f7b 100644 --- a/src/target/HACKING.md +++ b/src/target/HACKING.md @@ -30,8 +30,8 @@ In summary, the following applies: * JTAG physical reset is referred to by 'nTRST' * Software reset as in the case of JTAG-PDI is referred to by 'SRST' if shortened. -The upshot of this is that to inhibit physical reset in the ARM ADIv5/Cortex-M code, set -`CORTEXM_TOPT_INHIBIT_NRST`, which refers to inhibiting the ADIv5 spec 'SRST'. +The upshot of this is that to inhibit physical reset in the ARM ADIv5/Cortex code, set +`CORTEX_TOPT_INHIBIT_NRST`, which refers to inhibiting the ADIv5 spec 'SRST'. ## Multiple-inclusion guarding diff --git a/src/target/cortex.h b/src/target/cortex.h index ba9d89431de..41220731e00 100644 --- a/src/target/cortex.h +++ b/src/target/cortex.h @@ -80,6 +80,8 @@ #define CORTEXM_GENERAL_REG_COUNT 20U #define CORTEXAR_GENERAL_REG_COUNT 17U +#define CORTEX_TOPT_INHIBIT_NRST (1U << 0U) + adiv5_access_port_s *cortex_ap(target_s *target); #endif /* TARGET_CORTEX_H */ diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 6d9c6f764a9..ea612257086 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -953,7 +953,7 @@ static void cortexm_reset(target_s *t) /* Read DHCSR here to clear S_RESET_ST bit before reset */ target_mem_read32(t, CORTEXM_DHCSR); platform_timeout_s reset_timeout; - if ((t->target_options & CORTEXM_TOPT_INHIBIT_NRST) == 0) { + if ((t->target_options & CORTEX_TOPT_INHIBIT_NRST) == 0) { platform_nrst_set_val(true); platform_nrst_set_val(false); /* Some NRF52840 users saw invalid SWD transaction with native/firmware without this delay.*/ @@ -962,7 +962,7 @@ static void cortexm_reset(target_s *t) uint32_t dhcsr = target_mem_read32(t, CORTEXM_DHCSR); if ((dhcsr & CORTEXM_DHCSR_S_RESET_ST) == 0) { /* - * No reset seen yet, maybe as nRST is not connected, or device has CORTEXM_TOPT_INHIBIT_NRST set. + * No reset seen yet, maybe as nRST is not connected, or device has CORTEX_TOPT_INHIBIT_NRST set. * Trigger reset by AIRCR. */ target_mem_write32(t, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); diff --git a/src/target/cortexm.h b/src/target/cortexm.h index 322b0e6ebae..af722c1e478 100644 --- a/src/target/cortexm.h +++ b/src/target/cortexm.h @@ -164,7 +164,6 @@ extern unsigned cortexm_wait_timeout; #define CORTEXM_XPSR_THUMB (1U << 24U) #define CORTEXM_XPSR_EXCEPTION_MASK 0x0000001fU -#define CORTEXM_TOPT_INHIBIT_NRST (1U << 2U) #define CORTEXM_TOPT_FLAVOUR_V7MF (1U << 1U) bool cortexm_attach(target_s *t); diff --git a/src/target/efm32.c b/src/target/efm32.c index dbfcaa56c32..f5216952684 100644 --- a/src/target/efm32.c +++ b/src/target/efm32.c @@ -579,7 +579,7 @@ bool efm32_probe(target_s *t) device->name, part_number, flash_kib, device->description); /* Setup Target */ - t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + t->target_options |= CORTEX_TOPT_INHIBIT_NRST; t->driver = priv_storage->efm32_variant_string; tc_printf(t, "flash size %u page size %u\n", flash_size, flash_page_size); diff --git a/src/target/imxrt.c b/src/target/imxrt.c index eeba517c0fa..8d0e4b917c8 100644 --- a/src/target/imxrt.c +++ b/src/target/imxrt.c @@ -210,7 +210,7 @@ bool imxrt_probe(target_s *const target) return false; } target->target_storage = priv; - target->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + target->target_options |= CORTEX_TOPT_INHIBIT_NRST; if (!imxrt_ident_device(target)) return false; diff --git a/src/target/lmi.c b/src/target/lmi.c index e62d4dab9aa..1053959c828 100644 --- a/src/target/lmi.c +++ b/src/target/lmi.c @@ -158,22 +158,22 @@ bool tm4c_probe(target_s *const t, const uint16_t did1) /* On Tiva targets, asserting nRST results in the debug * logic also being reset. We can't assert nRST and must * only use the AIRCR SYSRESETREQ. */ - t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + t->target_options |= CORTEX_TOPT_INHIBIT_NRST; break; case DID1_TM4C1230C3PM: target_add_ram(t, 0x20000000, 0x6000); lmi_add_flash(t, 0x10000); - t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + t->target_options |= CORTEX_TOPT_INHIBIT_NRST; break; case DID1_TM4C1294KCPDT: target_add_ram(t, 0x20000000, 0x40000); lmi_add_flash(t, 0x80000); - t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + t->target_options |= CORTEX_TOPT_INHIBIT_NRST; break; case DID1_TM4C1294NCPDT: target_add_ram(t, 0x20000000, 0x40000); lmi_add_flash(t, 0x100000); - t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + t->target_options |= CORTEX_TOPT_INHIBIT_NRST; break; default: t->driver = driver; diff --git a/src/target/lpc43xx.c b/src/target/lpc43xx.c index fc38f80f551..02249ea4180 100644 --- a/src/target/lpc43xx.c +++ b/src/target/lpc43xx.c @@ -470,7 +470,7 @@ bool lpc43xx_probe(target_s *const t) return false; const uint32_t chip_code = (chipid & LPC43xx_CHIPID_CHIP_MASK) >> LPC43xx_CHIPID_CHIP_SHIFT; - t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + t->target_options |= CORTEX_TOPT_INHIBIT_NRST; /* If we're on the M4 core, poke the M0APP and M0SUB core resets to make them available */ if ((t->cpuid & CORTEX_CPUID_PARTNO_MASK) == CORTEX_M4) { diff --git a/src/target/lpc546xx.c b/src/target/lpc546xx.c index 694aebe9c50..36e4471a546 100644 --- a/src/target/lpc546xx.c +++ b/src/target/lpc546xx.c @@ -164,7 +164,7 @@ bool lpc546xx_probe(target_s *t) target_add_ram(t, 0x20010000, sram123_size); target_add_ram(t, 0x04000000, 0x8000U); /* SRAMX */ target_add_commands(t, lpc546xx_cmd_list, "LPC546xx"); - t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + t->target_options |= CORTEX_TOPT_INHIBIT_NRST; return true; } diff --git a/src/target/lpc55xx.c b/src/target/lpc55xx.c index 69f9d8a18ca..9b415b64bc7 100644 --- a/src/target/lpc55xx.c +++ b/src/target/lpc55xx.c @@ -561,7 +561,7 @@ bool lpc55xx_probe(target_s *const target) const uint32_t chipid = target_mem_read32(target, LPC55xx_CHIPID_ADDRESS); DEBUG_WARN("Chip ID: %08" PRIx32 "\n", chipid); - target->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + target->target_options |= CORTEX_TOPT_INHIBIT_NRST; target->driver = lpc55xx_get_device_name(chipid); switch (chipid) { diff --git a/src/target/nrf51.c b/src/target/nrf51.c index c010eeeec2b..55c0280aba7 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -143,7 +143,7 @@ bool nrf51_probe(target_s *t) if (info_part != 0xffffffffU && info_part != 0 && (info_part & 0x00ff000U) == 0x52000U) { uint32_t ram_size = target_mem_read32(t, NRF52_INFO_RAM); t->driver = "Nordic nRF52"; - t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + t->target_options |= CORTEX_TOPT_INHIBIT_NRST; target_add_ram(t, 0x20000000U, ram_size * 1024U); nrf51_add_flash(t, 0, page_size * code_size, page_size); nrf51_add_flash(t, NRF51_UICR, page_size, page_size); @@ -155,7 +155,7 @@ bool nrf51_probe(target_s *t) * IDCODE is kept as '0', as deciphering is hard and there is later no usage. */ target_add_ram(t, 0x20000000U, 0x8000U); - t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + t->target_options |= CORTEX_TOPT_INHIBIT_NRST; nrf51_add_flash(t, 0, page_size * code_size, page_size); nrf51_add_flash(t, NRF51_UICR, page_size, page_size); target_add_commands(t, nrf51_cmd_list, "nRF51"); diff --git a/src/target/nrf91.c b/src/target/nrf91.c index 04118b24081..eff0ced444c 100644 --- a/src/target/nrf91.c +++ b/src/target/nrf91.c @@ -93,7 +93,7 @@ bool nrf91_probe(target_s *target) switch (ap->dp->target_partno) { case 0x90: target->driver = "Nordic nRF9160"; - target->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + target->target_options |= CORTEX_TOPT_INHIBIT_NRST; target_add_ram(target, 0x20000000, 256U * 1024U); nrf91_add_flash(target, 0, 4096U * 256U, 4096U); break; diff --git a/src/target/rp.c b/src/target/rp.c index 744f27b5e49..9504b2c12d5 100644 --- a/src/target/rp.c +++ b/src/target/rp.c @@ -237,7 +237,7 @@ bool rp_probe(target_s *target) target->mass_erase = bmp_spi_mass_erase; target->driver = "Raspberry RP2040"; - target->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + target->target_options |= CORTEX_TOPT_INHIBIT_NRST; target->attach = rp_attach; target->enter_flash_mode = rp_flash_prepare; target->exit_flash_mode = rp_flash_resume; diff --git a/src/target/sam3x.c b/src/target/sam3x.c index acac747bd5c..c73ec472472 100644 --- a/src/target/sam3x.c +++ b/src/target/sam3x.c @@ -424,7 +424,7 @@ bool sam3x_probe(target_s *t) case CHIPID_CIDR_ARCH_SAM3XxE | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3XxG | CHIPID_CIDR_EPROC_CM3: t->driver = "Atmel SAM3X"; - t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; + t->target_options |= CORTEX_TOPT_INHIBIT_NRST; target_add_ram(t, 0x20000000, 0x200000); /* 2 Flash memories back-to-back starting at 0x80000 */ sam3_add_flash(t, SAM3X_EEFC_BASE(0), 0x80000, size / 2U); From 3cce642a5d12f1a56b5db94991746c090b252ea8 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Oct 2023 18:39:58 +0100 Subject: [PATCH 17/22] cortexar: Implemented basic reset support for both core types --- src/target/cortexar.c | 66 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 6e581a4a14c..33dfb5d5810 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -86,10 +86,12 @@ typedef struct cortexar_priv { #define CORTEXAR_DBG_BCR 0x140U #define CORTEXAR_DBG_WVR 0x180U #define CORTEXAR_DBG_WCR 0x1c0U -#define CORTEXAR_DBG_OSLAR 0x300U /* OS lock access register */ -#define CORTEXAR_DBG_OSLSR 0x304U /* OS lock status register */ -#define CORTEXAR_DBG_OSSRR 0x308U /* OS save/restore register */ -#define CORTEXAR_DBG_OSDLR 0x30cU /* OS double-lock register */ +#define CORTEXAR_DBG_OSLAR 0x300U /* OS Lock Access register */ +#define CORTEXAR_DBG_OSLSR 0x304U /* OS Lock Status register */ +#define CORTEXAR_DBG_OSSRR 0x308U /* OS Save/Restore register */ +#define CORTEXAR_DBG_OSDLR 0x30cU /* OS Double-Lock register */ +#define CORTEXAR_DBG_PRCR 0x310U /* Power and Reset Control register */ +#define CORTEXAR_DBG_PRSR 0x314U /* Power and Reset Status register */ #define CORTEXAR_CPUID 0xd00U #define CORTEXAR_CTR 0xd04U @@ -148,6 +150,19 @@ typedef struct cortexar_priv { #define CORTEXAR_DBG_OSLSR_OS_LOCK_MODEL_PARTIAL 0x00000008U #define CORTEXAR_DBG_OSLSR_LOCKED (1U << 1U) +#define CORTEXAR_DBG_PRCR_CORE_POWER_DOWN_REQ (1U << 0U) +#define CORTEXAR_DBG_PRCR_CORE_WARM_RESET_REQ (1U << 1U) +#define CORTEXAR_DBG_PRCR_HOLD_CORE_WARM_RESET (1U << 2U) +#define CORTEXAR_DBG_PRCR_CORE_POWER_UP_REQ (1U << 3U) + +#define CORTEXAR_DBG_PRSR_POWERED_UP (1U << 0U) +#define CORTEXAR_DBG_PRSR_STICKY_PD (1U << 1U) +#define CORTEXAR_DBG_PRSR_RESET_ACTIVE (1U << 2U) +#define CORTEXAR_DBG_PRSR_STICKY_RESET (1U << 3U) +#define CORTEXAR_DBG_PRSR_HALTED (1U << 4U) +#define CORTEXAR_DBG_PRSR_OS_LOCK (1U << 5U) +#define CORTEXAR_DBG_PRSR_DOUBLE_LOCK (1U << 6U) + /* * Instruction encodings for reading/writing the program counter to/from r0, * reading/writing CPSR to/from r0, and reading/writing the SPSRs to/from r0. @@ -330,6 +345,7 @@ static void cortexar_regs_write(target_s *target, const void *data); static ssize_t cortexar_reg_read(target_s *target, uint32_t reg, void *data, size_t max); static ssize_t cortexar_reg_write(target_s *target, uint32_t reg, const void *data, size_t max); +static void cortexar_reset(target_s *target); static target_halt_reason_e cortexar_halt_poll(target_s *target, target_addr_t *watch); static void cortexar_halt_request(target_s *target); static void cortexar_halt_resume(target_s *target, bool step); @@ -643,6 +659,7 @@ static target_s *cortexar_probe( priv->base.ap = ap; priv->base.base_addr = base_address; + target->reset = cortexar_reset; target->halt_request = cortexar_halt_request; target->halt_poll = cortexar_halt_poll; target->halt_resume = cortexar_halt_resume; @@ -1103,6 +1120,47 @@ static ssize_t cortexar_reg_write(target_s *const target, const uint32_t reg, co return reg_width; } +static void cortexar_reset(target_s *const target) +{ + /* Read PRSR here to clear DBG_PRSR.SR before reset */ + cortex_dbg_read32(target, CORTEXAR_DBG_PRSR); + /* If the physical reset pin is not inhibited, use it */ + if (!(target->target_options & CORTEX_TOPT_INHIBIT_NRST)) { + platform_nrst_set_val(true); + platform_nrst_set_val(false); + /* Precautionary delay as with the Cortex-M code for targets that take a hot minute to come back */ + platform_delay(10); + } + + /* Check if the reset succeeded */ + const uint32_t status = cortex_dbg_read32(target, CORTEXAR_DBG_PRSR); + if (!(status & CORTEXAR_DBG_PRSR_STICKY_RESET)) + /* No reset seen yet, or nRST is inhibited, so let's do this via PRCR */ + cortex_dbg_write32(target, CORTEXAR_DBG_PRCR, CORTEXAR_DBG_PRCR_CORE_WARM_RESET_REQ); + + /* If the targets needs to do something extra, handle that here */ + if (target->extended_reset) + target->extended_reset(target); + + /* Now wait for sticky reset to read high and reset low, indicating the reset has been completed */ + platform_timeout_s reset_timeout; + platform_timeout_set(&reset_timeout, 1000); + while ((cortex_dbg_read32(target, CORTEXAR_DBG_PRSR) & + (CORTEXAR_DBG_PRSR_STICKY_RESET | CORTEXAR_DBG_PRSR_RESET_ACTIVE)) && + !platform_timeout_is_expired(&reset_timeout)) + continue; + +#if defined(PLATFORM_HAS_DEBUG) + if (platform_timeout_is_expired(&reset_timeout)) + DEBUG_WARN("Reset seems to be stuck low!\n"); +#endif + + /* 10ms delay to ensure bootroms have had time to run */ + platform_delay(10); + /* Ignore any initial errors out of reset */ + target_check_error(target); +} + static void cortexar_halt_request(target_s *const target) { volatile exception_s error; From bf7b66b4d8bf23c8340a746a037ae76c0d7fb83f Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Oct 2023 18:40:54 +0100 Subject: [PATCH 18/22] cortexm: Cleaned up and documented cortexm_reset() some more --- src/target/cortexm.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index ea612257086..e138e3c886b 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -948,43 +948,50 @@ static void cortexm_pc_write(target_s *t, const uint32_t val) * The following three routines implement target halt/resume * using the core debug registers in the NVIC. */ -static void cortexm_reset(target_s *t) +static void cortexm_reset(target_s *const target) { /* Read DHCSR here to clear S_RESET_ST bit before reset */ - target_mem_read32(t, CORTEXM_DHCSR); - platform_timeout_s reset_timeout; - if ((t->target_options & CORTEX_TOPT_INHIBIT_NRST) == 0) { + target_mem_read32(target, CORTEXM_DHCSR); + /* If the physical reset pin is not inhibited, use it */ + if (!(target->target_options & CORTEX_TOPT_INHIBIT_NRST)) { platform_nrst_set_val(true); platform_nrst_set_val(false); - /* Some NRF52840 users saw invalid SWD transaction with native/firmware without this delay.*/ + /* Some NRF52840 users saw invalid SWD transaction with native/firmware without this delay.*/ platform_delay(10); } - uint32_t dhcsr = target_mem_read32(t, CORTEXM_DHCSR); - if ((dhcsr & CORTEXM_DHCSR_S_RESET_ST) == 0) { + + /* Check if the reset succeeded */ + const uint32_t status = target_mem_read32(target, CORTEXM_DHCSR); + if (!(status & CORTEXM_DHCSR_S_RESET_ST)) { /* * No reset seen yet, maybe as nRST is not connected, or device has CORTEX_TOPT_INHIBIT_NRST set. * Trigger reset by AIRCR. */ - target_mem_write32(t, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); + target_mem_write32(target, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); } + /* If target needs to do something extra (see Atmel SAM4L for example) */ - if (t->extended_reset != NULL) - t->extended_reset(t); + if (target->extended_reset != NULL) + target->extended_reset(target); + /* Wait for CORTEXM_DHCSR_S_RESET_ST to read 0, meaning reset released.*/ + platform_timeout_s reset_timeout; platform_timeout_set(&reset_timeout, 1000); - while ((target_mem_read32(t, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST) && + while ((target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST) && !platform_timeout_is_expired(&reset_timeout)) continue; + #if defined(PLATFORM_HAS_DEBUG) if (platform_timeout_is_expired(&reset_timeout)) DEBUG_WARN("Reset seem to be stuck low!\n"); #endif + /* 10 ms delay to ensure that things such as the STM32 HSI clock have started up fully. */ platform_delay(10); /* Reset DFSR flags */ - target_mem_write32(t, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); + target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); /* Make sure we ignore any initial DAP error */ - target_check_error(t); + target_check_error(target); } static void cortexm_halt_request(target_s *t) From a26b7dae8a19c52b516cba76384cd425e6043b6b Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Oct 2023 21:35:44 +0100 Subject: [PATCH 19/22] cortexar: Implemented insurances that the core is powered up and unlocked prior to halt in cortexar_probe() --- src/target/cortexar.c | 50 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/src/target/cortexar.c b/src/target/cortexar.c index 33dfb5d5810..3abe83cbeb2 100644 --- a/src/target/cortexar.c +++ b/src/target/cortexar.c @@ -610,7 +610,7 @@ static target_addr_t cortexar_virt_to_phys(target_s *const target, const target_ return address; } -static void cortexar_oslock_unlock(target_s *const target) +static bool cortexar_oslock_unlock(target_s *const target) { const uint32_t lock_status = cortex_dbg_read32(target, CORTEXAR_DBG_OSLSR); DEBUG_TARGET("%s: OS lock status: %08" PRIx32 "\n", __func__, lock_status); @@ -626,7 +626,48 @@ static void cortexar_oslock_unlock(target_s *const target) const bool locked = cortex_dbg_read32(target, CORTEXAR_DBG_OSLSR) & CORTEXAR_DBG_OSLSR_LOCKED; if (locked) DEBUG_ERROR("%s: Lock sticky. Core not powered?\n", __func__); + return !locked; } + return true; +} + +static bool cortexar_ensure_core_powered(target_s *const target) +{ + /* Read the power/reset status register and check if the core is up or down */ + uint8_t status = cortex_dbg_read32(target, CORTEXAR_DBG_PRSR) & 0xffU; + if (!(status & CORTEXAR_DBG_PRSR_POWERED_UP)) { + /* The core is powered down, so get it up. */ + cortex_dbg_write32( + target, CORTEXAR_DBG_PRCR, CORTEXAR_DBG_PRCR_CORE_POWER_UP_REQ | CORTEXAR_DBG_PRCR_HOLD_CORE_WARM_RESET); + /* Spin waiting for the core to come up */ + platform_timeout_s timeout; + platform_timeout_set(&timeout, 250); + while (!(cortex_dbg_read32(target, CORTEXAR_DBG_PRSR) & CORTEXAR_DBG_PRSR_POWERED_UP) && + !platform_timeout_is_expired(&timeout)) + continue; + /* + * Assume it worked, because it's implementation-defined if we can even do a power-up this way. + * Clear the PRCR back to 0 so the hold and power-up requests don't interfere further. + */ + cortex_dbg_write32(target, CORTEXAR_DBG_PRCR, 0U); + } + /* Re-read the PRSR and check if the core actually powered on */ + status = cortex_dbg_read32(target, CORTEXAR_DBG_PRSR) & 0xffU; + if (!(status & CORTEXAR_DBG_PRSR_POWERED_UP)) + return false; + + /* Check for the OS double lock */ + if (status & CORTEXAR_DBG_PRSR_DOUBLE_LOCK) + return false; + + /* + * Finally, check for the normal OS Lock and clear it if it's set prior to halting the core. + * Trying to do this after target_halt_request() does not function over JTAG and triggers + * the lock sticky message. + */ + if (status & CORTEXAR_DBG_PRSR_OS_LOCK) + return cortexar_oslock_unlock(target); + return true; } static target_s *cortexar_probe( @@ -664,11 +705,8 @@ static target_s *cortexar_probe( target->halt_poll = cortexar_halt_poll; target->halt_resume = cortexar_halt_resume; - /* - * Clear the OSLock if set prior to halting the core - trying to do this after target_halt_request() - * does not function over JTAG and triggers the lock sticky message. - */ - cortexar_oslock_unlock(target); + /* Ensure the core is powered up and we can talk to it */ + cortexar_ensure_core_powered(target); /* Try to halt the target core */ target_halt_request(target); From 974fc8d255b217051abe1ed03aa3f9f09a42b8cd Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Oct 2023 22:00:45 +0100 Subject: [PATCH 20/22] cortexm: Fixed the target parameter for cortexm_{at,de}tach(), and variable in cortexm_probe() + the `PROBE()` macro --- src/target/cortexm.c | 167 +++++++++++++++++++------------------- src/target/cortexm.h | 10 +-- src/target/target_probe.h | 8 +- 3 files changed, 93 insertions(+), 92 deletions(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index e138e3c886b..b778fc8d9f3 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -483,25 +483,25 @@ const char *cortexm_regs_description(target_s *t) bool cortexm_probe(adiv5_access_port_s *ap) { - target_s *t = target_new(); - if (!t) + target_s *target = target_new(); + if (!target) return false; adiv5_ap_ref(ap); if (ap->dp->version >= 2 && ap->dp->target_designer_code != 0) { /* Use TARGETID register to identify target */ - t->designer_code = ap->dp->target_designer_code; - t->part_id = ap->dp->target_partno; + target->designer_code = ap->dp->target_designer_code; + target->part_id = ap->dp->target_partno; } else { /* Use AP DESIGNER and AP PARTNO to identify target */ - t->designer_code = ap->designer_code; - t->part_id = ap->partno; + target->designer_code = ap->designer_code; + target->part_id = ap->partno; } /* MM32F5xxx: part designer code is Arm China, target designer code uses forbidden continuation code */ - if (t->designer_code == JEP106_MANUFACTURER_ERRATA_ARM_CHINA && + if (target->designer_code == JEP106_MANUFACTURER_ERRATA_ARM_CHINA && ap->dp->designer_code == JEP106_MANUFACTURER_ARM_CHINA) - t->designer_code = JEP106_MANUFACTURER_ARM_CHINA; + target->designer_code = JEP106_MANUFACTURER_ARM_CHINA; cortexm_priv_s *priv = calloc(1, sizeof(*priv)); if (!priv) { /* calloc failed: heap exhaustion */ @@ -509,48 +509,48 @@ bool cortexm_probe(adiv5_access_port_s *ap) return false; } - t->priv = priv; - t->priv_free = cortex_priv_free; + target->priv = priv; + target->priv_free = cortex_priv_free; priv->base.ap = ap; priv->base.base_addr = CORTEXM_SCS_BASE; - t->check_error = cortex_check_error; - t->mem_read = cortexm_mem_read; - t->mem_write = cortexm_mem_write; + target->check_error = cortex_check_error; + target->mem_read = cortexm_mem_read; + target->mem_write = cortexm_mem_write; - t->driver = "ARM Cortex-M"; + target->driver = "ARM Cortex-M"; - cortex_read_cpuid(t); + cortex_read_cpuid(target); - t->attach = cortexm_attach; - t->detach = cortexm_detach; + target->attach = cortexm_attach; + target->detach = cortexm_detach; /* Probe for FP extension. */ - uint32_t cpacr = target_mem_read32(t, CORTEXM_CPACR); + uint32_t cpacr = target_mem_read32(target, CORTEXM_CPACR); cpacr |= 0x00f00000U; /* CP10 = 0b11, CP11 = 0b11 */ - target_mem_write32(t, CORTEXM_CPACR, cpacr); - bool is_cortexmf = target_mem_read32(t, CORTEXM_CPACR) == cpacr; + target_mem_write32(target, CORTEXM_CPACR, cpacr); + bool is_cortexmf = target_mem_read32(target, CORTEXM_CPACR) == cpacr; - t->regs_description = cortexm_regs_description; - t->regs_read = cortexm_regs_read; - t->regs_write = cortexm_regs_write; - t->reg_read = cortexm_reg_read; - t->reg_write = cortexm_reg_write; + target->regs_description = cortexm_regs_description; + target->regs_read = cortexm_regs_read; + target->regs_write = cortexm_regs_write; + target->reg_read = cortexm_reg_read; + target->reg_write = cortexm_reg_write; - t->reset = cortexm_reset; - t->halt_request = cortexm_halt_request; - t->halt_poll = cortexm_halt_poll; - t->halt_resume = cortexm_halt_resume; - t->regs_size = sizeof(uint32_t) * CORTEXM_GENERAL_REG_COUNT; + target->reset = cortexm_reset; + target->halt_request = cortexm_halt_request; + target->halt_poll = cortexm_halt_poll; + target->halt_resume = cortexm_halt_resume; + target->regs_size = sizeof(uint32_t) * CORTEXM_GENERAL_REG_COUNT; - t->breakwatch_set = cortexm_breakwatch_set; - t->breakwatch_clear = cortexm_breakwatch_clear; + target->breakwatch_set = cortexm_breakwatch_set; + target->breakwatch_clear = cortexm_breakwatch_clear; - target_add_commands(t, cortexm_cmd_list, t->driver); + target_add_commands(target, cortexm_cmd_list, target->driver); if (is_cortexmf) { - t->target_options |= CORTEXM_TOPT_FLAVOUR_V7MF; - t->regs_size += sizeof(uint32_t) * CORTEX_FLOAT_REG_COUNT; + target->target_options |= CORTEXM_TOPT_FLAVOUR_V7MF; + target->regs_size += sizeof(uint32_t) * CORTEX_FLOAT_REG_COUNT; } /* Default vectors to catch */ @@ -568,15 +568,15 @@ bool cortexm_probe(adiv5_access_port_s *ap) conn_reset = true; /* Request halt when reset is de-asseted */ - target_mem_write32(t, CORTEXM_DEMCR, priv->demcr); + target_mem_write32(target, CORTEXM_DEMCR, priv->demcr); /* Force a halt */ - cortexm_halt_request(t); + cortexm_halt_request(target); /* Release reset */ platform_nrst_set_val(false); /* Poll for release from reset */ platform_timeout_s timeout; platform_timeout_set(&timeout, 1000); - while (target_mem_read32(t, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST) { + while (target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST) { if (platform_timeout_is_expired(&timeout)) { DEBUG_ERROR("Error releasing from reset\n"); /* Go on and try to detect the target anyways */ @@ -587,18 +587,18 @@ bool cortexm_probe(adiv5_access_port_s *ap) } /* Check cache type */ - const uint32_t cache_type = target_mem_read32(t, CORTEXM_CTR); + const uint32_t cache_type = target_mem_read32(target, CORTEXM_CTR); if (cache_type >> CORTEX_CTR_FORMAT_SHIFT == CORTEX_CTR_FORMAT_ARMv7) { priv->base.icache_line_length = CORTEX_CTR_ICACHE_LINE(cache_type); priv->base.dcache_line_length = CORTEX_CTR_DCACHE_LINE(cache_type); } else - target_check_error(t); + target_check_error(target); /* If we set the interrupt catch vector earlier, clear it. */ if (conn_reset) - target_mem_write32(t, CORTEXM_DEMCR, 0); + target_mem_write32(target, CORTEXM_DEMCR, 0); - switch (t->designer_code) { + switch (target->designer_code) { case JEP106_MANUFACTURER_FREESCALE: PROBE(imxrt_probe); PROBE(kinetis_probe); @@ -649,7 +649,7 @@ bool cortexm_probe(adiv5_access_port_s *ap) PROBE(renesas_probe); break; case JEP106_MANUFACTURER_NXP: - if ((t->cpuid & CORTEX_CPUID_PARTNO_MASK) == CORTEX_M33) + if ((target->cpuid & CORTEX_CPUID_PARTNO_MASK) == CORTEX_M33) PROBE(lpc55xx_probe); else DEBUG_WARN("Unhandled NXP device\n"); @@ -662,22 +662,22 @@ bool cortexm_probe(adiv5_access_port_s *ap) * All of these have braces as a brake from the standard so they're completely * consistent and easier to add new probe calls to. */ - if (t->part_id == 0x4c0U) { /* Cortex-M0+ ROM */ - PROBE(lpc11xx_probe); /* LPC8 */ - PROBE(hc32l110_probe); /* HDSC HC32L110 */ - } else if (t->part_id == 0x4c1U) { /* NXP Cortex-M0+ ROM */ - PROBE(lpc11xx_probe); /* newer LPC11U6x */ - } else if (t->part_id == 0x4c3U) { /* Cortex-M3 ROM */ + if (target->part_id == 0x4c0U) { /* Cortex-M0+ ROM */ + PROBE(lpc11xx_probe); /* LPC8 */ + PROBE(hc32l110_probe); /* HDSC HC32L110 */ + } else if (target->part_id == 0x4c1U) { /* NXP Cortex-M0+ ROM */ + PROBE(lpc11xx_probe); /* newer LPC11U6x */ + } else if (target->part_id == 0x4c3U) { /* Cortex-M3 ROM */ PROBE(lmi_probe); PROBE(ch32f1_probe); - PROBE(stm32f1_probe); /* Care for other STM32F1 clones (?) */ - PROBE(lpc15xx_probe); /* Thanks to JojoS for testing */ - PROBE(mm32f3xx_probe); /* MindMotion MM32 */ - } else if (t->part_id == 0x471U) { /* Cortex-M0 ROM */ - PROBE(lpc11xx_probe); /* LPC24C11 */ + PROBE(stm32f1_probe); /* Care for other STM32F1 clones (?) */ + PROBE(lpc15xx_probe); /* Thanks to JojoS for testing */ + PROBE(mm32f3xx_probe); /* MindMotion MM32 */ + } else if (target->part_id == 0x471U) { /* Cortex-M0 ROM */ + PROBE(lpc11xx_probe); /* LPC24C11 */ PROBE(lpc43xx_probe); - PROBE(mm32l0xx_probe); /* MindMotion MM32 */ - } else if (t->part_id == 0x4c4U) { /* Cortex-M4 ROM */ + PROBE(mm32l0xx_probe); /* MindMotion MM32 */ + } else if (target->part_id == 0x4c4U) { /* Cortex-M4 ROM */ PROBE(sam3x_probe); PROBE(lmi_probe); /* @@ -695,8 +695,8 @@ bool cortexm_probe(adiv5_access_port_s *ap) PROBE(lpc40xx_probe); PROBE(kinetis_probe); /* Older K-series */ PROBE(msp432e4_probe); - } else if (t->part_id == 0x4cbU) { /* Cortex-M23 ROM */ - PROBE(gd32f1_probe); /* GD32E23x uses GD32F1 peripherals */ + } else if (target->part_id == 0x4cbU) { /* Cortex-M23 ROM */ + PROBE(gd32f1_probe); /* GD32E23x uses GD32F1 peripherals */ } break; case ASCII_CODE_FLAG: @@ -713,61 +713,62 @@ bool cortexm_probe(adiv5_access_port_s *ap) #if PC_HOSTED == 0 gdb_outf("Please report unknown device with Designer 0x%x Part ID 0x%x\n", t->designer_code, t->part_id); #else - DEBUG_WARN("Please report unknown device with Designer 0x%x Part ID 0x%x\n", t->designer_code, t->part_id); + DEBUG_WARN( + "Please report unknown device with Designer 0x%x Part ID 0x%x\n", target->designer_code, target->part_id); #endif return true; } -bool cortexm_attach(target_s *t) +bool cortexm_attach(target_s *target) { - adiv5_access_port_s *ap = cortex_ap(t); + adiv5_access_port_s *ap = cortex_ap(target); /* Mark the DP as being in fault so error recovery will switch to this core when in multi-drop mode */ ap->dp->fault = 1; - cortexm_priv_s *priv = t->priv; + cortexm_priv_s *priv = target->priv; /* Clear any pending fault condition (and switch to this core) */ - target_check_error(t); + target_check_error(target); - target_halt_request(t); + target_halt_request(target); /* Request halt on reset */ - target_mem_write32(t, CORTEXM_DEMCR, priv->demcr); + target_mem_write32(target, CORTEXM_DEMCR, priv->demcr); /* Reset DFSR flags */ - target_mem_write32(t, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); + target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); /* size the break/watchpoint units */ priv->base.breakpoints_available = CORTEX_MAX_BREAKPOINTS; - const uint32_t flash_break_cfg = target_mem_read32(t, CORTEXM_FPB_CTRL); + const uint32_t flash_break_cfg = target_mem_read32(target, CORTEXM_FPB_CTRL); const uint32_t breakpoints = ((flash_break_cfg >> 4U) & 0xfU); if (breakpoints < priv->base.breakpoints_available) /* only look at NUM_COMP1 */ priv->base.breakpoints_available = breakpoints; priv->flash_patch_revision = flash_break_cfg >> 28U; priv->base.watchpoints_available = CORTEX_MAX_WATCHPOINTS; - const uint32_t watchpoints = target_mem_read32(t, CORTEXM_DWT_CTRL); + const uint32_t watchpoints = target_mem_read32(target, CORTEXM_DWT_CTRL); if ((watchpoints >> 28U) < priv->base.watchpoints_available) priv->base.watchpoints_available = watchpoints >> 28U; /* Clear any stale breakpoints */ priv->base.breakpoints_mask = 0; for (size_t i = 0; i < priv->base.breakpoints_available; i++) - target_mem_write32(t, CORTEXM_FPB_COMP(i), 0); + target_mem_write32(target, CORTEXM_FPB_COMP(i), 0); /* Clear any stale watchpoints */ priv->base.watchpoints_mask = 0; for (size_t i = 0; i < priv->base.watchpoints_available; i++) - target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0); + target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0); /* Flash Patch Control Register: set ENABLE */ - target_mem_write32(t, CORTEXM_FPB_CTRL, CORTEXM_FPB_CTRL_KEY | CORTEXM_FPB_CTRL_ENABLE); + target_mem_write32(target, CORTEXM_FPB_CTRL, CORTEXM_FPB_CTRL_KEY | CORTEXM_FPB_CTRL_ENABLE); - (void)target_mem_read32(t, CORTEXM_DHCSR); - if (target_mem_read32(t, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST) { + (void)target_mem_read32(target, CORTEXM_DHCSR); + if (target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST) { platform_nrst_set_val(false); platform_timeout_s timeout; platform_timeout_set(&timeout, 1000); while (1) { - const uint32_t reset_status = target_mem_read32(t, CORTEXM_DHCSR); + const uint32_t reset_status = target_mem_read32(target, CORTEXM_DHCSR); if (!(reset_status & CORTEXM_DHCSR_S_RESET_ST)) break; if (platform_timeout_is_expired(&timeout)) { @@ -779,25 +780,25 @@ bool cortexm_attach(target_s *t) return true; } -void cortexm_detach(target_s *t) +void cortexm_detach(target_s *target) { - cortexm_priv_s *priv = t->priv; + cortexm_priv_s *priv = target->priv; /* Clear any stale breakpoints */ for (size_t i = 0; i < priv->base.breakpoints_available; i++) - target_mem_write32(t, CORTEXM_FPB_COMP(i), 0); + target_mem_write32(target, CORTEXM_FPB_COMP(i), 0); /* Clear any stale watchpoints */ for (size_t i = 0; i < priv->base.watchpoints_available; i++) - target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0); + target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0); /* Restore DEMCR */ - adiv5_access_port_s *ap = cortex_ap(t); - target_mem_write32(t, CORTEXM_DEMCR, ap->ap_cortexm_demcr); + adiv5_access_port_s *ap = cortex_ap(target); + target_mem_write32(target, CORTEXM_DEMCR, ap->ap_cortexm_demcr); /* Resume target and disable debug, re-enabling interrupts in the process */ - target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN | CORTEXM_DHCSR_C_HALT); - target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN); - target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); + target_mem_write32(target, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN | CORTEXM_DHCSR_C_HALT); + target_mem_write32(target, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN); + target_mem_write32(target, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); } enum { diff --git a/src/target/cortexm.h b/src/target/cortexm.h index af722c1e478..64d78e7fcf7 100644 --- a/src/target/cortexm.h +++ b/src/target/cortexm.h @@ -166,10 +166,10 @@ extern unsigned cortexm_wait_timeout; #define CORTEXM_TOPT_FLAVOUR_V7MF (1U << 1U) -bool cortexm_attach(target_s *t); -void cortexm_detach(target_s *t); -void cortexm_halt_resume(target_s *t, bool step); -bool cortexm_run_stub(target_s *t, uint32_t loadaddr, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3); -int cortexm_mem_write_sized(target_s *t, target_addr_t dest, const void *src, size_t len, align_e align); +bool cortexm_attach(target_s *target); +void cortexm_detach(target_s *target); +void cortexm_halt_resume(target_s *target, bool step); +bool cortexm_run_stub(target_s *target, uint32_t loadaddr, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3); +int cortexm_mem_write_sized(target_s *target, target_addr_t dest, const void *src, size_t len, align_e align); #endif /* TARGET_CORTEXM_H */ diff --git a/src/target/target_probe.h b/src/target/target_probe.h index ed55729d9d1..5134f2d23fd 100644 --- a/src/target/target_probe.h +++ b/src/target/target_probe.h @@ -28,9 +28,9 @@ #define PROBE(x) \ do { \ DEBUG_TARGET("Calling " STRINGIFY(x) "\n"); \ - if ((x)(t)) \ + if ((x)(target)) \ return true; \ - target_check_error(t); \ + target_check_error(target); \ } while (0) /* @@ -38,8 +38,8 @@ * Actual functions implemented in their respective drivers. */ -bool cortexa_probe(adiv5_access_port_s *apb, target_addr_t debug_base); -bool cortexr_probe(adiv5_access_port_s *apb, target_addr_t base_address); +bool cortexa_probe(adiv5_access_port_s *ap, target_addr_t base_address); +bool cortexr_probe(adiv5_access_port_s *ap, target_addr_t base_address); bool cortexm_probe(adiv5_access_port_s *ap); bool kinetis_mdm_probe(adiv5_access_port_s *ap); From 4322304b2ba941d835b95f6365c2b1df04ec06dd Mon Sep 17 00:00:00 2001 From: dragonmux Date: Sun, 15 Oct 2023 22:18:07 +0100 Subject: [PATCH 21/22] cortexm: Fixed all target nomenclature in one big pass --- src/target/cortexm.c | 396 ++++++++++++++++++++++--------------------- 1 file changed, 200 insertions(+), 196 deletions(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index b778fc8d9f3..a944db1af66 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -71,9 +71,9 @@ #include #endif -static bool cortexm_vector_catch(target_s *t, int argc, const char **argv); +static bool cortexm_vector_catch(target_s *target, int argc, const char **argv); #if PC_HOSTED == 0 -static bool cortexm_redirect_stdout(target_s *t, int argc, const char **argv); +static bool cortexm_redirect_stdout(target_s *target, int argc, const char **argv); #endif const command_s cortexm_cmd_list[] = { @@ -87,23 +87,23 @@ const command_s cortexm_cmd_list[] = { /* target options recognised by the Cortex-M target */ #define TOPT_FLAVOUR_V6M (1U << 0U) /* if not set, target is assumed to be v7m */ -static const char *cortexm_regs_description(target_s *t); -static void cortexm_regs_read(target_s *t, void *data); -static void cortexm_regs_write(target_s *t, const void *data); -static uint32_t cortexm_pc_read(target_s *t); -static ssize_t cortexm_reg_read(target_s *t, uint32_t reg, void *data, size_t max); -static ssize_t cortexm_reg_write(target_s *t, uint32_t reg, const void *data, size_t max); +static const char *cortexm_regs_description(target_s *target); +static void cortexm_regs_read(target_s *target, void *data); +static void cortexm_regs_write(target_s *target, const void *data); +static uint32_t cortexm_pc_read(target_s *target); +static ssize_t cortexm_reg_read(target_s *target, uint32_t reg, void *data, size_t max); +static ssize_t cortexm_reg_write(target_s *target, uint32_t reg, const void *data, size_t max); -static void cortexm_reset(target_s *t); -static target_halt_reason_e cortexm_halt_poll(target_s *t, target_addr_t *watch); -static void cortexm_halt_request(target_s *t); -static int cortexm_fault_unwind(target_s *t); +static void cortexm_reset(target_s *target); +static target_halt_reason_e cortexm_halt_poll(target_s *target, target_addr_t *watch); +static void cortexm_halt_request(target_s *target); +static int cortexm_fault_unwind(target_s *target); -static int cortexm_breakwatch_set(target_s *t, breakwatch_s *bw); -static int cortexm_breakwatch_clear(target_s *t, breakwatch_s *bw); -static target_addr_t cortexm_check_watch(target_s *t); +static int cortexm_breakwatch_set(target_s *target, breakwatch_s *breakwatch); +static int cortexm_breakwatch_clear(target_s *target, breakwatch_s *breakwatch); +static target_addr_t cortexm_check_watch(target_s *target); -static int cortexm_hostio_request(target_s *t); +static int cortexm_hostio_request(target_s *target); static uint32_t time0_sec = UINT32_MAX; /* sys_clock time origin */ @@ -429,9 +429,9 @@ static size_t create_tdesc_cortex_mf(char *buffer, size_t max_len) return (size_t)total; } -static void cortexm_cache_clean(target_s *t, target_addr_t addr, size_t len, bool invalidate) +static void cortexm_cache_clean(target_s *target, target_addr_t addr, size_t len, bool invalidate) { - cortexm_priv_s *priv = t->priv; + cortexm_priv_s *priv = target->priv; if (!priv->base.dcache_line_length) return; uint32_t cache_reg = invalidate ? CORTEXM_DCCIMVAC : CORTEXM_DCCMVAC; @@ -440,7 +440,7 @@ static void cortexm_cache_clean(target_s *t, target_addr_t addr, size_t len, boo /* flush data cache for RAM regions that intersect requested region */ target_addr_t mem_end = addr + len; /* following code is NOP if wraparound */ /* requested region is [src, src_end) */ - for (target_ram_s *r = t->ram; r; r = r->next) { + for (target_ram_s *r = target->ram; r; r = r->next) { target_addr_t ram = r->start; target_addr_t ram_end = r->start + r->length; /* RAM region is [ram, ram_end) */ @@ -450,25 +450,25 @@ static void cortexm_cache_clean(target_s *t, target_addr_t addr, size_t len, boo ram_end = mem_end; /* intersection is [ram, ram_end) */ for (ram &= ~(minline - 1U); ram < ram_end; ram += minline) - adiv5_mem_write(cortex_ap(t), cache_reg, &ram, 4); + adiv5_mem_write(cortex_ap(target), cache_reg, &ram, 4); } } -static void cortexm_mem_read(target_s *t, void *dest, target_addr_t src, size_t len) +static void cortexm_mem_read(target_s *target, void *dest, target_addr_t src, size_t len) { - cortexm_cache_clean(t, src, len, false); - adiv5_mem_read(cortex_ap(t), dest, src, len); + cortexm_cache_clean(target, src, len, false); + adiv5_mem_read(cortex_ap(target), dest, src, len); } -static void cortexm_mem_write(target_s *t, target_addr_t dest, const void *src, size_t len) +static void cortexm_mem_write(target_s *target, target_addr_t dest, const void *src, size_t len) { - cortexm_cache_clean(t, dest, len, true); - adiv5_mem_write(cortex_ap(t), dest, src, len); + cortexm_cache_clean(target, dest, len, true); + adiv5_mem_write(cortex_ap(target), dest, src, len); } -const char *cortexm_regs_description(target_s *t) +const char *cortexm_regs_description(target_s *target) { - const bool is_cortexmf = t->target_options & CORTEXM_TOPT_FLAVOUR_V7MF; + const bool is_cortexmf = target->target_options & CORTEXM_TOPT_FLAVOUR_V7MF; const size_t description_length = (is_cortexmf ? create_tdesc_cortex_mf(NULL, 0) : create_tdesc_cortex_m(NULL, 0)) + 1U; char *const description = malloc(description_length); @@ -711,7 +711,7 @@ bool cortexm_probe(adiv5_access_port_s *ap) break; } #if PC_HOSTED == 0 - gdb_outf("Please report unknown device with Designer 0x%x Part ID 0x%x\n", t->designer_code, t->part_id); + gdb_outf("Please report unknown device with Designer 0x%x Part ID 0x%x\n", target->designer_code, target->part_id); #else DEBUG_WARN( "Please report unknown device with Designer 0x%x Part ID 0x%x\n", target->designer_code, target->part_id); @@ -897,52 +897,53 @@ static void cortexm_regs_write(target_s *const target, const void *const data) #endif } -int cortexm_mem_write_sized(target_s *t, target_addr_t dest, const void *src, size_t len, align_e align) +int cortexm_mem_write_sized(target_s *target, target_addr_t dest, const void *src, size_t len, align_e align) { - cortexm_cache_clean(t, dest, len, true); - adiv5_mem_write_sized(cortex_ap(t), dest, src, len, align); - return target_check_error(t); + cortexm_cache_clean(target, dest, len, true); + adiv5_mem_write_sized(cortex_ap(target), dest, src, len, align); + return target_check_error(target); } -static int dcrsr_regnum(target_s *t, uint32_t reg) +static int dcrsr_regnum(target_s *target, uint32_t reg) { if (reg < CORTEXM_GENERAL_REG_COUNT) return regnum_cortex_m[reg]; - if ((t->target_options & CORTEXM_TOPT_FLAVOUR_V7MF) && reg < CORTEXM_GENERAL_REG_COUNT + CORTEX_FLOAT_REG_COUNT) + if ((target->target_options & CORTEXM_TOPT_FLAVOUR_V7MF) && + reg < CORTEXM_GENERAL_REG_COUNT + CORTEX_FLOAT_REG_COUNT) return regnum_cortex_mf[reg - CORTEXM_GENERAL_REG_COUNT]; return -1; } -static ssize_t cortexm_reg_read(target_s *t, uint32_t reg, void *data, size_t max) +static ssize_t cortexm_reg_read(target_s *target, uint32_t reg, void *data, size_t max) { if (max < 4U) return -1; uint32_t *r = data; - target_mem_write32(t, CORTEXM_DCRSR, dcrsr_regnum(t, reg)); - *r = target_mem_read32(t, CORTEXM_DCRDR); + target_mem_write32(target, CORTEXM_DCRSR, dcrsr_regnum(target, reg)); + *r = target_mem_read32(target, CORTEXM_DCRDR); return 4U; } -static ssize_t cortexm_reg_write(target_s *t, uint32_t reg, const void *data, size_t max) +static ssize_t cortexm_reg_write(target_s *target, uint32_t reg, const void *data, size_t max) { if (max < 4U) return -1; const uint32_t *r = data; - target_mem_write32(t, CORTEXM_DCRDR, *r); - target_mem_write32(t, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | dcrsr_regnum(t, reg)); + target_mem_write32(target, CORTEXM_DCRDR, *r); + target_mem_write32(target, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | dcrsr_regnum(target, reg)); return 4U; } -static uint32_t cortexm_pc_read(target_s *t) +static uint32_t cortexm_pc_read(target_s *target) { - target_mem_write32(t, CORTEXM_DCRSR, 0x0f); - return target_mem_read32(t, CORTEXM_DCRDR); + target_mem_write32(target, CORTEXM_DCRSR, 0x0f); + return target_mem_read32(target, CORTEXM_DCRDR); } -static void cortexm_pc_write(target_s *t, const uint32_t val) +static void cortexm_pc_write(target_s *target, const uint32_t val) { - target_mem_write32(t, CORTEXM_DCRDR, val); - target_mem_write32(t, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0fU); + target_mem_write32(target, CORTEXM_DCRDR, val); + target_mem_write32(target, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0fU); } /* @@ -995,25 +996,26 @@ static void cortexm_reset(target_s *const target) target_check_error(target); } -static void cortexm_halt_request(target_s *t) +static void cortexm_halt_request(target_s *target) { volatile exception_s e; TRY_CATCH (e, EXCEPTION_TIMEOUT) { - target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN); + target_mem_write32( + target, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN); } if (e.type) - tc_printf(t, "Timeout sending interrupt, is target in WFI?\n"); + tc_printf(target, "Timeout sending interrupt, is target in WFI?\n"); } -static target_halt_reason_e cortexm_halt_poll(target_s *t, target_addr_t *watch) +static target_halt_reason_e cortexm_halt_poll(target_s *target, target_addr_t *watch) { - cortexm_priv_s *priv = t->priv; + cortexm_priv_s *priv = target->priv; volatile uint32_t dhcsr = 0; volatile exception_s e; TRY_CATCH (e, EXCEPTION_ALL) { /* If this times out because the target is in WFI then the target is still running. */ - dhcsr = target_mem_read32(t, CORTEXM_DHCSR); + dhcsr = target_mem_read32(target, CORTEXM_DHCSR); } switch (e.type) { case EXCEPTION_ERROR: @@ -1030,31 +1032,31 @@ static target_halt_reason_e cortexm_halt_poll(target_s *t, target_addr_t *watch) return TARGET_HALT_RUNNING; /* Read out the status register to determine why */ - uint32_t dfsr = target_mem_read32(t, CORTEXM_DFSR); - target_mem_write32(t, CORTEXM_DFSR, dfsr); /* write back to reset */ + uint32_t dfsr = target_mem_read32(target, CORTEXM_DFSR); + target_mem_write32(target, CORTEXM_DFSR, dfsr); /* write back to reset */ - if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(t)) + if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(target)) return TARGET_HALT_FAULT; /* Remember if we stopped on a breakpoint */ priv->on_bkpt = dfsr & CORTEXM_DFSR_BKPT; if (priv->on_bkpt) { /* If we've hit a programmed breakpoint, check for semihosting call. */ - const uint32_t program_counter = cortexm_pc_read(t); - const uint16_t instruction = target_mem_read16(t, program_counter); + const uint32_t program_counter = cortexm_pc_read(target); + const uint16_t instruction = target_mem_read16(target, program_counter); /* 0xbeab encodes the breakpoint instruction used to indicate a semihosting call */ if (instruction == 0xbeabU) { - if (cortexm_hostio_request(t)) + if (cortexm_hostio_request(target)) return TARGET_HALT_REQUEST; - target_halt_resume(t, priv->stepping); + target_halt_resume(target, priv->stepping); return TARGET_HALT_RUNNING; } } if (dfsr & CORTEXM_DFSR_DWTTRAP) { if (watch != NULL) - *watch = cortexm_check_watch(t); + *watch = cortexm_check_watch(target); return TARGET_HALT_WATCHPOINT; } if (dfsr & CORTEXM_DFSR_BKPT) @@ -1100,14 +1102,14 @@ void cortexm_halt_resume(target_s *const target, const bool step) target_mem_write32(target, CORTEXM_DHCSR, dhcsr); } -static int cortexm_fault_unwind(target_s *t) +static int cortexm_fault_unwind(target_s *target) { /* Read the fault status registers */ - uint32_t hfsr = target_mem_read32(t, CORTEXM_HFSR); - uint32_t cfsr = target_mem_read32(t, CORTEXM_CFSR); + uint32_t hfsr = target_mem_read32(target, CORTEXM_HFSR); + uint32_t cfsr = target_mem_read32(target, CORTEXM_CFSR); /* Write them back to reset them */ - target_mem_write32(t, CORTEXM_HFSR, hfsr); - target_mem_write32(t, CORTEXM_CFSR, cfsr); + target_mem_write32(target, CORTEXM_HFSR, hfsr); + target_mem_write32(target, CORTEXM_CFSR, cfsr); /* * We check for FORCED in the HardFault Status Register or * for a configurable fault to avoid catching core resets @@ -1117,15 +1119,15 @@ static int cortexm_fault_unwind(target_s *t) uint32_t regs[CORTEXM_GENERAL_REG_COUNT + CORTEX_FLOAT_REG_COUNT]; uint32_t stack[8]; /* Read registers for post-exception stack pointer */ - target_regs_read(t, regs); + target_regs_read(target, regs); /* save retcode currently in lr */ const uint32_t retcode = regs[CORTEX_REG_LR]; bool spsel = retcode & (1U << 2U); bool fpca = !(retcode & (1U << 4U)); /* Read stack for pre-exception registers */ uint32_t sp = spsel ? regs[CORTEX_REG_PSP] : regs[CORTEX_REG_MSP]; - target_mem_read(t, stack, sp, sizeof(stack)); - if (target_check_error(t)) + target_mem_read(target, stack, sp, sizeof(stack)); + if (target_check_error(target)) return 0; /* Restore LR and PC to their pre-exception states */ regs[CORTEX_REG_LR] = stack[5]; @@ -1152,17 +1154,17 @@ static int cortexm_fault_unwind(target_s *t) */ /* Reset exception state to allow resuming from restored state. */ - target_mem_write32(t, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_VECTCLRACTIVE); + target_mem_write32(target, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_VECTCLRACTIVE); /* Write pre-exception registers back to core */ - target_regs_write(t, regs); + target_regs_write(target, regs); return 1; } return 0; } -bool cortexm_run_stub(target_s *t, uint32_t loadaddr, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3) +bool cortexm_run_stub(target_s *target, uint32_t loadaddr, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3) { uint32_t regs[CORTEXM_GENERAL_REG_COUNT + CORTEX_FLOAT_REG_COUNT] = {0}; @@ -1174,33 +1176,33 @@ bool cortexm_run_stub(target_s *t, uint32_t loadaddr, uint32_t r0, uint32_t r1, regs[CORTEX_REG_XPSR] = CORTEXM_XPSR_THUMB; regs[19] = 0; - cortexm_regs_write(t, regs); + cortexm_regs_write(target, regs); - if (target_check_error(t)) + if (target_check_error(target)) return false; /* Execute the stub */ target_halt_reason_e reason = TARGET_HALT_RUNNING; #if defined(PLATFORM_HAS_DEBUG) uint32_t arm_regs_start[CORTEXM_GENERAL_REG_COUNT + CORTEX_FLOAT_REG_COUNT]; - target_regs_read(t, arm_regs_start); + target_regs_read(target, arm_regs_start); #endif - cortexm_halt_resume(t, 0); + cortexm_halt_resume(target, 0); platform_timeout_s timeout; platform_timeout_set(&timeout, 5000); while (reason == TARGET_HALT_RUNNING) { if (platform_timeout_is_expired(&timeout)) { - cortexm_halt_request(t); + cortexm_halt_request(target); #if defined(PLATFORM_HAS_DEBUG) DEBUG_WARN("Stub hung\n"); uint32_t arm_regs[CORTEXM_GENERAL_REG_COUNT + CORTEX_FLOAT_REG_COUNT]; - target_regs_read(t, arm_regs); + target_regs_read(target, arm_regs); for (uint32_t i = 0; i < 20U; ++i) DEBUG_WARN("%2" PRIu32 ": %08" PRIx32 ", %08" PRIx32 "\n", i, arm_regs_start[i], arm_regs[i]); #endif return false; } - reason = cortexm_halt_poll(t, NULL); + reason = cortexm_halt_poll(target, NULL); } if (reason == TARGET_HALT_ERROR) @@ -1211,8 +1213,8 @@ bool cortexm_run_stub(target_s *t, uint32_t loadaddr, uint32_t r0, uint32_t r1, return false; } - uint32_t pc = cortexm_pc_read(t); - uint16_t bkpt_instr = target_mem_read16(t, pc); + uint32_t pc = cortexm_pc_read(target); + uint16_t bkpt_instr = target_mem_read16(target, pc); if (bkpt_instr >> 8U != 0xbeU) return false; @@ -1230,18 +1232,18 @@ bool cortexm_run_stub(target_s *t, uint32_t loadaddr, uint32_t r0, uint32_t r1, * number of least-significant bits of the address to ignore during * match (maximum 31). */ -static uint32_t dwt_mask(size_t len) +static uint32_t cortexm_dwt_mask(size_t len) { if (len < 2) return 0; return MIN(ulog2(len - 1), 31); } -static uint32_t dwt_func(target_s *t, target_breakwatch_e type) +static uint32_t cortexm_dwt_func(target_s *target, target_breakwatch_e type) { uint32_t x = 0; - if ((t->target_options & TOPT_FLAVOUR_V6M) == 0) + if ((target->target_options & TOPT_FLAVOUR_V6M) == 0) x = CORTEXM_DWT_FUNC_DATAVSIZE_WORD; switch (type) { @@ -1256,17 +1258,17 @@ static uint32_t dwt_func(target_s *t, target_breakwatch_e type) } } -static int cortexm_breakwatch_set(target_s *t, breakwatch_s *bw) +static int cortexm_breakwatch_set(target_s *target, breakwatch_s *breakwatch) { - cortexm_priv_s *priv = t->priv; + cortexm_priv_s *priv = target->priv; size_t i; - uint32_t val = bw->addr; + uint32_t val = breakwatch->addr; - switch (bw->type) { + switch (breakwatch->type) { case TARGET_BREAK_HARD: if (priv->flash_patch_revision == 0) { val &= 0x1ffffffcU; - val |= (bw->addr & 2U) ? 0x80000000U : 0x40000000U; + val |= (breakwatch->addr & 2U) ? 0x80000000U : 0x40000000U; } val |= 1U; @@ -1280,8 +1282,8 @@ static int cortexm_breakwatch_set(target_s *t, breakwatch_s *bw) return -1; priv->base.breakpoints_mask |= 1U << i; - target_mem_write32(t, CORTEXM_FPB_COMP(i), val); - bw->reserved[0] = i; + target_mem_write32(target, CORTEXM_FPB_COMP(i), val); + breakwatch->reserved[0] = i; return 0; case TARGET_WATCH_WRITE: @@ -1298,63 +1300,63 @@ static int cortexm_breakwatch_set(target_s *t, breakwatch_s *bw) priv->base.watchpoints_mask |= 1U << i; - target_mem_write32(t, CORTEXM_DWT_COMP(i), val); - target_mem_write32(t, CORTEXM_DWT_MASK(i), dwt_mask(bw->size)); - target_mem_write32(t, CORTEXM_DWT_FUNC(i), dwt_func(t, bw->type)); + target_mem_write32(target, CORTEXM_DWT_COMP(i), val); + target_mem_write32(target, CORTEXM_DWT_MASK(i), cortexm_dwt_mask(breakwatch->size)); + target_mem_write32(target, CORTEXM_DWT_FUNC(i), cortexm_dwt_func(target, breakwatch->type)); - bw->reserved[0] = i; + breakwatch->reserved[0] = i; return 0; default: return 1; } } -static int cortexm_breakwatch_clear(target_s *t, breakwatch_s *bw) +static int cortexm_breakwatch_clear(target_s *target, breakwatch_s *breakwatch) { - cortexm_priv_s *priv = t->priv; - unsigned i = bw->reserved[0]; - switch (bw->type) { + cortexm_priv_s *priv = target->priv; + unsigned i = breakwatch->reserved[0]; + switch (breakwatch->type) { case TARGET_BREAK_HARD: priv->base.breakpoints_mask &= ~(1U << i); - target_mem_write32(t, CORTEXM_FPB_COMP(i), 0); + target_mem_write32(target, CORTEXM_FPB_COMP(i), 0); return 0; case TARGET_WATCH_WRITE: case TARGET_WATCH_READ: case TARGET_WATCH_ACCESS: priv->base.watchpoints_mask &= ~(1U << i); - target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0); + target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0); return 0; default: return 1; } } -static target_addr_t cortexm_check_watch(target_s *t) +static target_addr_t cortexm_check_watch(target_s *target) { - cortexm_priv_s *priv = t->priv; + cortexm_priv_s *priv = target->priv; unsigned i; for (i = 0; i < priv->base.watchpoints_available; i++) { /* if SET and MATCHED then break */ if ((priv->base.watchpoints_mask & (1U << i)) && - (target_mem_read32(t, CORTEXM_DWT_FUNC(i)) & CORTEXM_DWT_FUNC_MATCHED)) + (target_mem_read32(target, CORTEXM_DWT_FUNC(i)) & CORTEXM_DWT_FUNC_MATCHED)) break; } if (i == priv->base.watchpoints_available) return 0; - return target_mem_read32(t, CORTEXM_DWT_COMP(i)); + return target_mem_read32(target, CORTEXM_DWT_COMP(i)); } -static bool cortexm_vector_catch(target_s *t, int argc, const char **argv) +static bool cortexm_vector_catch(target_s *target, int argc, const char **argv) { - cortexm_priv_s *priv = t->priv; + cortexm_priv_s *priv = target->priv; static const char *const vectors[] = {"reset", NULL, NULL, NULL, "mm", "nocp", "chk", "stat", "bus", "int", "hard"}; uint32_t tmp = 0; if (argc < 3) - tc_printf(t, "usage: monitor vector_catch (enable|disable) (hard|int|bus|stat|chk|nocp|mm|reset)\n"); + tc_printf(target, "usage: monitor vector_catch (enable|disable) (hard|int|bus|stat|chk|nocp|mm|reset)\n"); else { for (int j = 0; j < argc; j++) { for (size_t i = 0; i < ARRAY_LENGTH(vectors); i++) { @@ -1370,35 +1372,36 @@ static bool cortexm_vector_catch(target_s *t, int argc, const char **argv) else priv->demcr &= ~tmp; - target_mem_write32(t, CORTEXM_DEMCR, priv->demcr); + target_mem_write32(target, CORTEXM_DEMCR, priv->demcr); } } - tc_printf(t, "Catching vectors: "); + tc_printf(target, "Catching vectors: "); for (size_t i = 0; i < ARRAY_LENGTH(vectors); i++) { if (!vectors[i]) continue; if (priv->demcr & (1U << i)) - tc_printf(t, "%s ", vectors[i]); + tc_printf(target, "%s ", vectors[i]); } - tc_printf(t, "\n"); + tc_printf(target, "\n"); return true; } #if PC_HOSTED == 0 -static bool cortexm_redirect_stdout(target_s *t, int argc, const char **argv) +static bool cortexm_redirect_stdout(target_s *target, int argc, const char **argv) { if (argc == 1) - gdb_outf("Semihosting stdout redirection: %s\n", t->stdout_redirected ? "enabled" : "disabled"); + gdb_outf("Semihosting stdout redirection: %s\n", target->stdout_redirected ? "enabled" : "disabled"); else - t->stdout_redirected = !strncmp(argv[1], "enable", strlen(argv[1])); + target->stdout_redirected = !strncmp(argv[1], "enable", strlen(argv[1])); return true; } #endif #if PC_HOSTED == 0 /* probe memory access functions */ -static void probe_mem_read(target_s *t __attribute__((unused)), void *probe_dest, target_addr_t target_src, size_t len) +static void probe_mem_read( + target_s *target __attribute__((unused)), void *probe_dest, target_addr_t target_src, size_t len) { uint8_t *dst = (uint8_t *)probe_dest; uint8_t *src = (uint8_t *)target_src; @@ -1409,7 +1412,7 @@ static void probe_mem_read(target_s *t __attribute__((unused)), void *probe_dest } static void probe_mem_write( - target_s *t __attribute__((unused)), target_addr_t target_dest, const void *probe_src, size_t len) + target_s *target __attribute__((unused)), target_addr_t target_dest, const void *probe_src, size_t len) { uint8_t *dst = (uint8_t *)target_dest; uint8_t *src = (uint8_t *)probe_src; @@ -1419,16 +1422,16 @@ static void probe_mem_write( } #endif -static int cortexm_hostio_request(target_s *t) +static int cortexm_hostio_request(target_s *target) { uint32_t arm_regs[CORTEXM_GENERAL_REG_COUNT + CORTEX_FLOAT_REG_COUNT]; uint32_t params[4] = {0}; - t->tc->interrupted = false; - target_regs_read(t, arm_regs); + target->tc->interrupted = false; + target_regs_read(target, arm_regs); uint32_t syscall = arm_regs[0]; if (syscall != SEMIHOSTING_SYS_EXIT) - target_mem_read(t, params, arm_regs[1], sizeof(params)); + target_mem_read(target, params, arm_regs[1], sizeof(params)); int32_t ret = 0; DEBUG_INFO("syscall 0" PRIx32 "%" PRIx32 " (%" PRIx32 " %" PRIx32 " %" PRIx32 " %" PRIx32 ")\n", syscall, params[0], @@ -1458,7 +1461,7 @@ static int cortexm_hostio_request(target_s *t) uint32_t pflag = flags[params[1] >> 1U]; char filename[4]; - target_mem_read(t, filename, fnam_taddr, sizeof(filename)); + target_mem_read(target, filename, fnam_taddr, sizeof(filename)); /* handle requests for console i/o */ if (!strcmp(filename, ":tt")) { if (pflag == TARGET_O_RDONLY) @@ -1474,8 +1477,8 @@ static int cortexm_hostio_request(target_s *t) char *fnam = malloc(fnam_len + 1U); if (fnam == NULL) break; - target_mem_read(t, fnam, fnam_taddr, fnam_len + 1U); - if (target_check_error(t)) { + target_mem_read(target, fnam, fnam_taddr, fnam_len + 1U); + if (target_check_error(target)) { free(fnam); break; } @@ -1507,9 +1510,9 @@ static int cortexm_hostio_request(target_s *t) ssize_t rc = read(params[0] - 1, buf, buf_len); if (rc >= 0) rc = buf_len - rc; - target_mem_write(t, buf_taddr, buf, buf_len); + target_mem_write(target, buf_taddr, buf, buf_len); free(buf); - if (target_check_error(t)) + if (target_check_error(target)) break; ret = rc; break; @@ -1528,8 +1531,8 @@ static int cortexm_hostio_request(target_s *t) uint8_t *buf = malloc(buf_len); if (buf == NULL) break; - target_mem_read(t, buf, buf_taddr, buf_len); - if (target_check_error(t)) { + target_mem_read(target, buf, buf_taddr, buf_len); + if (target_check_error(target)) { free(buf); break; } @@ -1546,8 +1549,8 @@ static int cortexm_hostio_request(target_s *t) target_addr_t ch_taddr = arm_regs[1]; if (ch_taddr == TARGET_NULL) break; - ch = target_mem_read8(t, ch_taddr); - if (target_check_error(t)) + ch = target_mem_read8(target, ch_taddr); + if (target_check_error(target)) break; fputc(ch, stderr); ret = 0; @@ -1560,8 +1563,8 @@ static int cortexm_hostio_request(target_s *t) if (str_addr == TARGET_NULL) break; while (true) { - const uint8_t str_c = target_mem_read8(t, str_addr++); - if (target_check_error(t) || str_c == 0x00) + const uint8_t str_c = target_mem_read8(target, str_addr++); + if (target_check_error(target) || str_c == 0x00) break; fputc(str_c, stderr); } @@ -1599,8 +1602,8 @@ static int cortexm_hostio_request(target_s *t) char *fnam1 = malloc(fnam1_len + 1U); if (fnam1 == NULL) break; - target_mem_read(t, fnam1, fnam1_taddr, fnam1_len + 1U); - if (target_check_error(t)) { + target_mem_read(target, fnam1, fnam1_taddr, fnam1_len + 1U); + if (target_check_error(target)) { free(fnam1); break; } @@ -1610,8 +1613,8 @@ static int cortexm_hostio_request(target_s *t) free(fnam1); break; } - target_mem_read(t, fnam2, fnam2_taddr, fnam2_len + 1U); - if (target_check_error(t)) { + target_mem_read(target, fnam2, fnam2_taddr, fnam2_len + 1U); + if (target_check_error(target)) { free(fnam1); free(fnam2); break; @@ -1634,8 +1637,8 @@ static int cortexm_hostio_request(target_s *t) char *fnam = malloc(fnam_len + 1U); if (fnam == NULL) break; - target_mem_read(t, fnam, fnam_taddr, fnam_len + 1U); - if (target_check_error(t)) { + target_mem_read(target, fnam, fnam_taddr, fnam_len + 1U); + if (target_check_error(target)) { free(fnam); break; } @@ -1656,8 +1659,8 @@ static int cortexm_hostio_request(target_s *t) char *cmd = malloc(cmd_len + 1U); if (cmd == NULL) break; - target_mem_read(t, cmd, cmd_taddr, cmd_len + 1U); - if (target_check_error(t)) { + target_mem_read(target, cmd, cmd_taddr, cmd_len + 1U); + if (target_check_error(target)) { free(cmd); break; } @@ -1725,7 +1728,7 @@ static int cortexm_hostio_request(target_s *t) uint32_t pflag = flags[params[1] >> 1U]; char filename[4]; - target_mem_read(t, filename, params[0], sizeof(filename)); + target_mem_read(target, filename, params[0], sizeof(filename)); /* handle requests for console i/o */ if (!strcmp(filename, ":tt")) { if (pflag == TARGET_O_RDONLY) @@ -1738,40 +1741,40 @@ static int cortexm_hostio_request(target_s *t) break; } - ret = tc_open(t, params[0], params[2] + 1U, pflag, 0644); + ret = tc_open(target, params[0], params[2] + 1U, pflag, 0644); if (ret != -1) ret++; break; } case SEMIHOSTING_SYS_CLOSE: /* close */ - ret = tc_close(t, params[0] - 1); + ret = tc_close(target, params[0] - 1); break; case SEMIHOSTING_SYS_READ: /* read */ - ret = tc_read(t, params[0] - 1, params[1], params[2]); + ret = tc_read(target, params[0] - 1, params[1], params[2]); if (ret >= 0) ret = params[2] - ret; break; case SEMIHOSTING_SYS_WRITE: /* write */ - ret = tc_write(t, params[0] - 1, params[1], params[2]); + ret = tc_write(target, params[0] - 1, params[1], params[2]); if (ret >= 0) ret = params[2] - ret; break; case SEMIHOSTING_SYS_WRITEC: /* writec */ - ret = tc_write(t, STDERR_FILENO, arm_regs[1], 1); + ret = tc_write(target, STDERR_FILENO, arm_regs[1], 1); break; case SEMIHOSTING_SYS_WRITE0: { /* write0 */ ret = -1; target_addr_t str_begin = arm_regs[1]; target_addr_t str_end = str_begin; - while (target_mem_read8(t, str_end) != 0) { - if (target_check_error(t)) + while (target_mem_read8(target, str_end) != 0) { + if (target_check_error(target)) break; str_end++; } int len = str_end - str_begin; if (len != 0) { - int rc = tc_write(t, STDERR_FILENO, str_begin, len); + int rc = tc_write(target, STDERR_FILENO, str_begin, len); if (rc != len) break; } @@ -1779,38 +1782,38 @@ static int cortexm_hostio_request(target_s *t) break; } case SEMIHOSTING_SYS_ISTTY: /* isatty */ - ret = tc_isatty(t, params[0] - 1); + ret = tc_isatty(target, params[0] - 1); break; case SEMIHOSTING_SYS_SEEK: /* lseek */ - if (tc_lseek(t, params[0] - 1, params[1], TARGET_SEEK_SET) == (long)params[1]) + if (tc_lseek(target, params[0] - 1, params[1], TARGET_SEEK_SET) == (long)params[1]) ret = 0; else ret = -1; break; case SEMIHOSTING_SYS_RENAME: /* rename */ - ret = tc_rename(t, params[0], params[1] + 1U, params[2], params[3] + 1U); + ret = tc_rename(target, params[0], params[1] + 1U, params[2], params[3] + 1U); break; case SEMIHOSTING_SYS_REMOVE: /* unlink */ - ret = tc_unlink(t, params[0], params[1] + 1U); + ret = tc_unlink(target, params[0], params[1] + 1U); break; case SEMIHOSTING_SYS_SYSTEM: /* system */ /* before use first enable system calls with the following gdb command: 'set remote system-call-allowed 1' */ - ret = tc_system(t, params[0], params[1] + 1U); + ret = tc_system(target, params[0], params[1] + 1U); break; case SEMIHOSTING_SYS_FLEN: { /* file length */ ret = -1; uint32_t fio_stat[16]; /* same size as fio_stat in gdb/include/gdb/fileio.h */ //DEBUG("SYS_FLEN fio_stat addr %p\n", fio_stat); - void (*saved_mem_read)(target_s *t, void *dest, target_addr_t src, size_t len); - void (*saved_mem_write)(target_s *t, target_addr_t dest, const void *src, size_t len); - saved_mem_read = t->mem_read; - saved_mem_write = t->mem_write; - t->mem_read = probe_mem_read; - t->mem_write = probe_mem_write; - int rc = tc_fstat(t, params[0] - 1, (target_addr_t)fio_stat); /* write fstat() result in fio_stat[] */ - t->mem_read = saved_mem_read; - t->mem_write = saved_mem_write; + void (*saved_mem_read)(target_s *target, void *dest, target_addr_t src, size_t len); + void (*saved_mem_write)(target_s *target, target_addr_t dest, const void *src, size_t len); + saved_mem_read = target->mem_read; + saved_mem_write = target->mem_write; + target->mem_read = probe_mem_read; + target->mem_write = probe_mem_write; + int rc = tc_fstat(target, params[0] - 1, (target_addr_t)fio_stat); /* write fstat() result in fio_stat[] */ + target->mem_read = saved_mem_read; + target->mem_write = saved_mem_write; if (rc) break; /* tc_fstat() failed */ uint32_t fst_size_msw = fio_stat[7]; /* most significant 32 bits of fst_size in fio_stat */ @@ -1834,16 +1837,16 @@ static int cortexm_hostio_request(target_s *t) } fio_timeval; //DEBUG("SYS_TIME fio_timeval addr %p\n", &fio_timeval); - void (*saved_mem_read)(target_s *t, void *dest, target_addr_t src, size_t len); - void (*saved_mem_write)(target_s *t, target_addr_t dest, const void *src, size_t len); - saved_mem_read = t->mem_read; - saved_mem_write = t->mem_write; - t->mem_read = probe_mem_read; - t->mem_write = probe_mem_write; + void (*saved_mem_read)(target_s *target, void *dest, target_addr_t src, size_t len); + void (*saved_mem_write)(target_s *target, target_addr_t dest, const void *src, size_t len); + saved_mem_read = target->mem_read; + saved_mem_write = target->mem_write; + target->mem_read = probe_mem_read; + target->mem_write = probe_mem_write; /* write gettimeofday() result in fio_timeval[] */ - int rc = tc_gettimeofday(t, (target_addr_t)&fio_timeval, (target_addr_t)NULL); - t->mem_read = saved_mem_read; - t->mem_write = saved_mem_write; + int rc = tc_gettimeofday(target, (target_addr_t)&fio_timeval, (target_addr_t)NULL); + target->mem_read = saved_mem_read; + target->mem_write = saved_mem_write; if (rc) /* tc_gettimeofday() failed */ break; /* convert from bigendian to target order */ @@ -1867,15 +1870,15 @@ static int cortexm_hostio_request(target_s *t) case SEMIHOSTING_SYS_READC: { /* readc */ uint8_t ch = '?'; //DEBUG("SYS_READC ch addr %p\n", &ch); - void (*saved_mem_read)(target_s *t, void *dest, target_addr_t src, size_t len); - void (*saved_mem_write)(target_s *t, target_addr_t dest, const void *src, size_t len); - saved_mem_read = t->mem_read; - saved_mem_write = t->mem_write; - t->mem_read = probe_mem_read; - t->mem_write = probe_mem_write; - int rc = tc_read(t, STDIN_FILENO, (target_addr_t)&ch, 1); /* read a character in ch */ - t->mem_read = saved_mem_read; - t->mem_write = saved_mem_write; + void (*saved_mem_read)(target_s *target, void *dest, target_addr_t src, size_t len); + void (*saved_mem_write)(target_s *target, target_addr_t dest, const void *src, size_t len); + saved_mem_read = target->mem_read; + saved_mem_write = target->mem_write; + target->mem_read = probe_mem_read; + target->mem_write = probe_mem_write; + int rc = tc_read(target, STDIN_FILENO, (target_addr_t)&ch, 1); /* read a character in ch */ + target->mem_read = saved_mem_read; + target->mem_write = saved_mem_write; if (rc == 1) ret = ch; else @@ -1884,18 +1887,18 @@ static int cortexm_hostio_request(target_s *t) } case SEMIHOSTING_SYS_ERRNO: /* Return last errno from GDB */ - ret = t->tc->errno_; + ret = target->tc->errno_; break; #endif case SEMIHOSTING_SYS_EXIT: /* _exit() */ - tc_printf(t, "_exit(0x%x)\n", arm_regs[1]); - target_halt_resume(t, 1); + tc_printf(target, "_exit(0x%x)\n", arm_regs[1]); + target_halt_resume(target, 1); break; - case SEMIHOSTING_SYS_EXIT_EXTENDED: /* _exit() */ - tc_printf(t, "_exit(0x%x%08x)\n", params[1], params[0]); /* exit() with 64bit exit value */ - target_halt_resume(t, 1); + case SEMIHOSTING_SYS_EXIT_EXTENDED: /* _exit() */ + tc_printf(target, "_exit(0x%x%08x)\n", params[1], params[0]); /* exit() with 64bit exit value */ + target_halt_resume(target, 1); break; case SEMIHOSTING_SYS_GET_CMDLINE: { /* get_cmdline */ @@ -1903,13 +1906,13 @@ static int cortexm_hostio_request(target_s *t) ret = -1; target_addr_t buf_ptr = params[0]; target_addr_t buf_len = params[1]; - if (strlen(t->cmdline) + 1U > buf_len) + if (strlen(target->cmdline) + 1U > buf_len) break; - if (target_mem_write(t, buf_ptr, t->cmdline, strlen(t->cmdline) + 1U)) + if (target_mem_write(target, buf_ptr, target->cmdline, strlen(target->cmdline) + 1U)) break; retval[0] = buf_ptr; - retval[1] = strlen(t->cmdline) + 1U; - if (target_mem_write(t, arm_regs[1], retval, sizeof(retval))) + retval[1] = strlen(target->cmdline) + 1U; + if (target_mem_write(target, arm_regs[1], retval, sizeof(retval))) break; ret = 0; break; @@ -1926,8 +1929,9 @@ static int cortexm_hostio_request(target_s *t) break; } - case SEMIHOSTING_SYS_HEAPINFO: /* heapinfo */ - target_mem_write(t, arm_regs[1], &t->heapinfo, sizeof(t->heapinfo)); /* See newlib/libc/sys/arm/crt0.S */ + case SEMIHOSTING_SYS_HEAPINFO: /* heapinfo */ + target_mem_write( + target, arm_regs[1], &target->heapinfo, sizeof(target->heapinfo)); /* See newlib/libc/sys/arm/crt0.S */ break; case SEMIHOSTING_SYS_TMPNAM: { /* tmpnam */ @@ -1947,7 +1951,7 @@ static int cortexm_hostio_request(target_s *t) fnam[4] = 'A' + (target_id >> 4 & 0xf); if (strlen(fnam) + 1U > (uint32_t)buf_size) break; /* target buffer too small */ - if (target_mem_write(t, buf_ptr, fnam, strlen(fnam) + 1U)) + if (target_mem_write(target, buf_ptr, fnam, strlen(fnam) + 1U)) break; /* copy filename to target */ ret = 0; break; @@ -1961,7 +1965,7 @@ static int cortexm_hostio_request(target_s *t) } arm_regs[0] = ret; - target_regs_write(t, arm_regs); + target_regs_write(target, arm_regs); - return t->tc->interrupted; + return target->tc->interrupted; } From 54566b05d6386851818ee43820ce3ff40ea35e84 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Mon, 16 Oct 2023 13:19:43 +0100 Subject: [PATCH 22/22] cortexa: Removed the old Cortex-A implementation now it has been superceeded --- src/target/cortexa.c | 1126 ------------------------------------------ 1 file changed, 1126 deletions(-) delete mode 100644 src/target/cortexa.c diff --git a/src/target/cortexa.c b/src/target/cortexa.c deleted file mode 100644 index 6268c46682b..00000000000 --- a/src/target/cortexa.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2016 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* This file implements debugging functionality specific to ARM - * the Cortex-A9 core. This should be generic to ARMv7-A as it is - * implemented according to the "ARMv7-A Architecture Reference Manual", - * ARM doc DDI0406C. - * - * Cache line length is from Cortex-A9 TRM, may differ for others. - * Janky reset code is for Zynq-7000 which disconnects the DP from the JTAG - * scan chain during reset. - */ -#include "general.h" -#include "exception.h" -#include "adiv5.h" -#include "target.h" -#include "target_internal.h" -#include "target_probe.h" -#include "cortex.h" -#include "cortex_internal.h" -#include "gdb_reg.h" - -#include -#include - -static bool cortexa_attach(target_s *t); -static void cortexa_detach(target_s *t); -static void cortexa_halt_resume(target_s *t, bool step); - -static const char *cortexa_regs_description(target_s *t); -static void cortexa_regs_read(target_s *t, void *data); -static void cortexa_regs_write(target_s *t, const void *data); -static void cortexa_regs_read_internal(target_s *t); -static void cortexa_regs_write_internal(target_s *t); -static ssize_t cortexa_reg_read(target_s *t, uint32_t reg, void *data, size_t max); -static ssize_t cortexa_reg_write(target_s *t, uint32_t reg, const void *data, size_t max); - -static void cortexa_reset(target_s *t); -static target_halt_reason_e cortexa_halt_poll(target_s *t, target_addr_t *watch); -static void cortexa_halt_request(target_s *t); - -static int cortexa_breakwatch_set(target_s *t, breakwatch_s *); -static int cortexa_breakwatch_clear(target_s *t, breakwatch_s *); -static uint32_t bp_bas(uint32_t addr, uint8_t len); - -static void write_gpreg(target_s *t, uint8_t regno, uint32_t val); -static uint32_t read_gpreg(target_s *t, uint8_t regno); - -typedef struct cortexa_priv { - /* Base core information */ - cortex_priv_s base; - - struct { - uint32_t r[16]; - uint32_t cpsr; - uint32_t fpscr; - uint64_t d[16]; - } reg_cache; - - uint32_t bcr0; - uint32_t bvr0; - bool mmu_fault; -} cortexa_priv_s; - -#define CORTEXAR_DBG_IDR 0x000U -#define CORTEXAR_DBG_DTRTX 0x080U /* DBGDTRRXext */ -#define CORTEXAR_DBG_ITR 0x084U -#define CORTEXAR_DBG_DSCR 0x088U -#define CORTEXAR_DBG_DTRRX 0x08cU /* DBGDTRTXext */ -#define CORTEXAR_DBG_DRCR 0x090U -#define CORTEXAR_DBG_BVR 0x100U -#define CORTEXAR_DBG_BCR 0x140U -#define CORTEXAR_DBG_WVR 0x180U -#define CORTEXAR_DBG_WCR 0x1c0U -#define CORTEXAR_CTR 0xd04U - -#define CORTEXAR_DBG_DSCCR 0x028U -#define CORTEXAR_DBG_DSMCR 0x02cU -#define CORTEXAR_DBG_OSLAR 0x300U -#define CORTEXAR_DBG_OSLSR 0x304U -#define CORTEXAR_DBG_LAR 0xfb0U /* Lock Access */ -#define CORTEXAR_DBG_LSR 0xfb4U /* Lock Status */ - -#define CORTEXAR_DBG_OSLSR_OSLM0 (1U << 0U) -#define CORTEXAR_DBG_OSLSR_OSLK (1U << 1U) -#define CORTEXAR_DBG_OSLSR_NTT (1U << 2U) -#define CORTEXAR_DBG_OSLSR_OSLM1 (1U << 3U) -#define CORTEXAR_DBG_OSLSR_OSLM (CORTEXAR_DBG_OSLSR_OSLM0 | CORTEXAR_DBG_OSLSR_OSLM1) - -#define CORTEXAR_DBG_IDR_BREAKPOINT_MASK 0xfU -#define CORTEXAR_DBG_IDR_BREAKPOINT_SHIFT 24U -#define CORTEXAR_DBG_IDR_WATCHPOINT_MASK 0xfU -#define CORTEXAR_DBG_IDR_WATCHPOINT_SHIFT 28U - -#define CORTEXAR_DBG_DSCR_HALTED (1U << 0U) -#define CORTEXAR_DBG_DSCR_RESTARTED (1U << 1U) -#define CORTEXAR_DBG_DSCR_MOE_MASK 0x0000003cU -#define CORTEXAR_DBG_DSCR_MOE_HALT_REQUEST 0x00000000U -#define CORTEXAR_DBG_DSCR_MOE_BREAKPOINT 0x00000004U -#define CORTEXAR_DBG_DSCR_MOE_ASYNC_WATCH 0x00000008U -#define CORTEXAR_DBG_DSCR_MOE_BKPT_INSN 0x0000000cU -#define CORTEXAR_DBG_DSCR_MOE_EXTERNAL_DBG 0x00000010U -#define CORTEXAR_DBG_DSCR_MOE_VEC_CATCH 0x00000014U -#define CORTEXAR_DBG_DSCR_MOE_SYNC_WATCH 0x00000028U -#define CORTEXAR_DBG_DSCR_ITR_ENABLE (1U << 13U) -#define CORTEXAR_DBG_DSCR_HALT_DBG_ENABLE (1U << 14U) -#define CORTEXAR_DBG_DSCR_INSN_COMPLETE (1U << 24U) -#define CORTEXAR_DBG_DSCR_DTR_READ_READY (1U << 29U) -#define CORTEXAR_DBG_DSCR_DTR_WRITE_DONE (1U << 30U) - -#define DBGDSCR_EXTDCCMODE_STALL (1U << 20U) -#define DBGDSCR_EXTDCCMODE_FAST (2U << 20U) -#define DBGDSCR_EXTDCCMODE_MASK (3U << 20U) -#define DBGDSCR_INTDIS (1U << 11U) -#define DBGDSCR_UND_I (1U << 8U) -#define DBGDSCR_SDABORT_L (1U << 6U) - -#define DBGDRCR_CSE (1U << 2U) -#define DBGDRCR_RRQ (1U << 1U) -#define DBGDRCR_HRQ (1U << 0U) - -#define DBGBCR_INST_MISMATCH (4U << 20U) -#define DBGBCR_BAS_ANY (0xfU << 5U) -#define DBGBCR_BAS_LOW_HW (0x3U << 5U) -#define DBGBCR_BAS_HIGH_HW (0xcU << 5U) -#define DBGBCR_EN (1U << 0U) -#define DBGBCR_PMC_ANY (0x3U << 1U) /* 0b11 */ - -#define DBGWCR_LSC_LOAD (0x1U << 3U) /* 0b01 */ -#define DBGWCR_LSC_STORE (0x2U << 3U) /* 0b10 */ -#define DBGWCR_LSC_ANY (0x3U << 3U) /* 0b11U */ -#define DBGWCR_BAS_BYTE (0x1U << 5U) /* 0b0001U */ -#define DBGWCR_BAS_HALFWORD (0x3U << 5U) /* 0b0011U */ -#define DBGWCR_BAS_WORD (0xfU << 5U) /* 0b1111U */ -#define DBGWCR_PAC_ANY (0x3U << 1U) /* 0b11U */ -#define DBGWCR_EN (1U << 0U) - -/* Instruction encodings for accessing the coprocessor interface */ -#define MCR 0xee000010U -#define MRC 0xee100010U -#define CPREG(coproc, opc1, rt, crn, crm, opc2) \ - (((opc1) << 21U) | ((crn) << 16U) | ((rt) << 12U) | ((coproc) << 8U) | ((opc2) << 5U) | (crm)) - -/* Debug registers CP14 */ -#define DBGDTRRXint CPREG(14U, 0U, 0U, 0U, 5U, 0U) -#define DBGDTRTXint CPREG(14U, 0U, 0U, 0U, 5U, 0U) - -/* Address translation registers CP15 */ -#define PAR CPREG(15U, 0U, 0U, 7U, 4U, 0U) -#define ATS1CPR CPREG(15U, 0U, 0U, 7U, 8U, 0U) - -/* Cache management registers CP15 */ -#define ICIALLU CPREG(15U, 0U, 0U, 7U, 5U, 0U) -#define DCCIMVAC CPREG(15U, 0U, 0U, 7U, 14U, 1U) -#define DCCMVAC CPREG(15U, 0U, 0U, 7U, 10U, 1U) - -/* Thumb mode bit in CPSR */ -#define CPSR_THUMB (1U << 5U) - -/** - * Fields for Cortex-A special purpose registers, used in the generation of GDB's target description XML. - * The general purpose registers r0-r12 and the vector floating point registers d0-d15 all follow a very - * regular format, so we only need to store fields for the special purpose registers. - * The arrays for each SPR field have the same order as each other, making each of them as pseduo - * 'associative array'. - */ - -// Strings for the names of the Cortex-A's special purpose registers. -static const char *cortex_a_spr_names[] = {"sp", "lr", "pc", "cpsr"}; - -// The "type" field for each Cortex-A special purpose register. -static const gdb_reg_type_e cortex_a_spr_types[] = { - GDB_TYPE_DATA_PTR, // sp - GDB_TYPE_CODE_PTR, // lr - GDB_TYPE_CODE_PTR, // pc - GDB_TYPE_UNSPECIFIED // cpsr -}; - -// clang-format off -static_assert(ARRAY_LENGTH(cortex_a_spr_types) == ARRAY_LENGTH(cortex_a_spr_names), - "SPR array length mixmatch! SPR type array should have the same length as SPR name array." -); - -// clang-format on - -// Creates the target description XML string for a Cortex-A. Like snprintf(), this function -// will write no more than max_len and returns the amount of bytes written. Or, if max_len is 0, -// then this function will return the amount of bytes that _would_ be necessary to create this -// string. -// -// This function is hand-optimized to decrease string duplication and thus code size, making it -// Unfortunately much less readable than the string literal it is equivalent to. -// -// The string it creates is XML-equivalent to the following: -/* - "" - "" - "" - " arm" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; -*/ -// Returns the amount of characters written to the buffer. -static size_t create_tdesc_cortex_a(char *buffer, size_t max_len) -{ - // Minor hack: technically snprintf returns an int for possibility of error, but in this case - // these functions are given static input that should not be able to fail -- and if it does, - // then there's nothing we can do about it, so we'll repatedly cast this variable to a size_t - // when calculating printsz (see below). - int total = 0; - - // We can't just repeatedly pass max_len to snprintf, because we keep changing the start - // of buffer (effectively changing its size), so we have to repeatedly compute the size - // passed to snprintf by subtracting the current total from max_len. - // ...Unless max_len is 0, in which case that subtraction will result in an (underflowed) - // negative number. So we also have to repeatedly check if max_len is 0 before performing - // that subtraction. - size_t printsz = max_len; - - // Start with the "preamble", which is generic across ARM targets, - // ...save for one word, so we'll have to do the preamble in halves, and then we'll - // follow it with the GDB ARM Core feature tag. - total += snprintf(buffer, printsz, "%s feature %sarm%s ", - gdb_xml_preamble_first, gdb_xml_preamble_second, gdb_xml_preamble_third); - - // Then the general purpose registers, which have names of r0 to r12. - for (uint8_t i = 0; i <= 12; ++i) { - if (max_len != 0) - printsz = max_len - (size_t)total; - - total += snprintf(buffer + total, printsz, "", i); - } - - // The special purpose registers are a slightly more complicated. - // Some of them have different types specified, however unlike the Cortex-M SPRs, - // all of the Cortex-A target description SPRs have the same bitsize, and none of them - // have a specified save-restore value. So we only need one "associative array" here. - // NOTE: unlike the other loops, this loop uses a size_t for its counter, as it's used to index into arrays. - for (size_t i = 0; i < ARRAY_LENGTH(cortex_a_spr_names); ++i) { - gdb_reg_type_e type = cortex_a_spr_types[i]; - - if (max_len != 0) - printsz = max_len - (size_t)total; - - total += snprintf(buffer + total, printsz, "", cortex_a_spr_names[i], - gdb_reg_type_strings[type]); - } - - if (max_len != 0) - printsz = max_len - (size_t)total; - - // Now onto the floating point registers. - // The first register is unique; the rest all follow the same format. - total += snprintf(buffer + total, printsz, - "" - "" - ""); - - // Now onto the simple ones. - for (uint8_t i = 0; i <= 15; ++i) { - if (max_len != 0) - printsz = max_len - (size_t)total; - - total += snprintf(buffer + total, printsz, "", i); - } - - if (max_len != 0) - printsz = max_len - (size_t)total; - - total += snprintf(buffer + total, printsz, ""); - - // Minor hack: technically snprintf returns an int for possibility of error, but in this case - // these functions are given static input that should not ever be able to fail -- and if it - // does, then there's nothing we can do about it, so we'll just discard the signedness - // of total when we return it. - return (size_t)total; -} - -#ifdef ENABLE_DEBUG -typedef struct bitfield_entry { - char *desc; - uint8_t bitnum; -} bitfields_lut_s; - -static const bitfields_lut_s cortexa_dbg_dscr_lut[] = { - {"HALTED", 0U}, - {"RESTARTED", 1U}, - {"SDABORT_l", 6U}, - {"ADABORT_l", 7U}, - {"UND_l", 8U}, - {"FS", 9U}, - {"ITRen", 13U}, - {"HDBGen", 14U}, - {"MDBGen", 15U}, - {"InstrCompl_l", 24U}, - {"PipeAdv", 25U}, - {"TXfull_l", 26U}, - {"RXfull_l", 27U}, - {"TXfull", 29U}, - {"RXfull", 30U}, -}; - -static void helper_print_bitfields(const uint32_t val, const bitfields_lut_s *lut, const size_t array_length) -{ - for (size_t i = 0; i < array_length; i++) { - if (val & (1U << lut[i].bitnum)) - DEBUG_TARGET("%s ", lut[i].desc); - } -} - -static void cortexa_decode_bitfields(const uint32_t reg, const uint32_t val) -{ - DEBUG_TARGET("Bits set in reg "); - switch (reg) { - case CORTEXAR_DBG_DSCR: - DEBUG_TARGET("DBGDSCR: "); - helper_print_bitfields(val, cortexa_dbg_dscr_lut, ARRAY_LENGTH(cortexa_dbg_dscr_lut)); - break; - default: - DEBUG_TARGET("unknown reg"); - break; - } - - DEBUG_TARGET("\n"); -} -#else -static void cortexa_decode_bitfields(const uint32_t reg, const uint32_t val) -{ - (void)reg; - (void)val; -} -#endif - -static void cortexar_run_insn(target_s *const target, const uint32_t insn) -{ - /* Issue the requested instruction to the core */ - cortex_dbg_write32(target, CORTEXAR_DBG_ITR, insn); - /* Poll for the instruction to complete */ - while (!(cortex_dbg_read32(target, CORTEXAR_DBG_DSCR) & CORTEXAR_DBG_DSCR_INSN_COMPLETE)) - continue; -} - -static uint32_t cortexar_run_read_insn(target_s *const target, const uint32_t insn) -{ - /* Issue the requested instruction to the core */ - cortex_dbg_write32(target, CORTEXAR_DBG_ITR, insn); - /* Poll for the instruction to complete and the data to become ready in the DTR */ - while ((cortex_dbg_read32(target, CORTEXAR_DBG_DSCR) & - (CORTEXAR_DBG_DSCR_INSN_COMPLETE | CORTEXAR_DBG_DSCR_DTR_READ_READY)) != - (CORTEXAR_DBG_DSCR_INSN_COMPLETE | CORTEXAR_DBG_DSCR_DTR_READ_READY)) - continue; - /* Read back the DTR to complete the read */ - return cortex_dbg_read32(target, CORTEXAR_DBG_DTRRX); -} - -static void cortexar_run_write_insn(target_s *const target, const uint32_t insn, const uint32_t data) -{ - /* Set up the data in the DTR for the transaction */ - cortex_dbg_write32(target, CORTEXAR_DBG_DTRTX, data); - /* Poll for the data to become ready in the DTR */ - while (!(cortex_dbg_read32(target, CORTEXAR_DBG_DSCR) & CORTEXAR_DBG_DSCR_DTR_WRITE_DONE)) - continue; - /* Issue the requested instruction to the core */ - cortex_dbg_write32(target, CORTEXAR_DBG_ITR, insn); - /* Poll for the instruction to complete and the data to be consumed from the DTR */ - while ((cortex_dbg_read32(target, CORTEXAR_DBG_DSCR) & - (CORTEXAR_DBG_DSCR_INSN_COMPLETE | CORTEXAR_DBG_DSCR_DTR_WRITE_DONE)) != CORTEXAR_DBG_DSCR_INSN_COMPLETE) - continue; -} - -static uint32_t va_to_pa(target_s *t, uint32_t va) -{ - cortexa_priv_s *priv = t->priv; - write_gpreg(t, 0, va); - cortexar_run_insn(t, MCR | ATS1CPR); - cortexar_run_insn(t, MRC | PAR); - uint32_t par = read_gpreg(t, 0); - if (par & 1U) - priv->mmu_fault = true; - uint32_t pa = (par & ~0xfffU) | (va & 0xfffU); - DEBUG_INFO("%s: VA = 0x%08" PRIx32 ", PAR = 0x%08" PRIx32 ", PA = 0x%08" PRIX32 "\n", __func__, va, par, pa); - return pa; -} - -static void cortexa_slow_mem_read(target_s *t, void *dest, target_addr_t src, size_t len) -{ - cortexa_priv_s *priv = t->priv; - unsigned words = (len + (src & 3U) + 3U) / 4U; - uint32_t dest32[words]; - - /* Set r0 to aligned src address */ - write_gpreg(t, 0, src & ~3); - - /* Switch to fast DCC mode */ - uint32_t dbgdscr = cortex_dbg_read32(t, CORTEXAR_DBG_DSCR); - dbgdscr = (dbgdscr & ~DBGDSCR_EXTDCCMODE_MASK) | DBGDSCR_EXTDCCMODE_FAST; - cortex_dbg_write32(t, CORTEXAR_DBG_DSCR, dbgdscr); - - cortex_dbg_write32(t, CORTEXAR_DBG_ITR, 0xecb05e01); /* ldc 14, cr5, [r0], #4 */ - /* - * According to the ARMv7-AR ARM, in fast mode, the first read from - * DBGDTRTXext (CORTEXAR_DBG_DTRRX) is supposed to block until the instruction - * is complete, but we see the first read returns junk, so it's read here and ignored. - */ - cortex_dbg_read32(t, CORTEXAR_DBG_DTRRX); - - for (unsigned i = 0; i < words; i++) - dest32[i] = cortex_dbg_read32(t, CORTEXAR_DBG_DTRRX); - - memcpy(dest, (uint8_t *)dest32 + (src & 3U), len); - - /* Switch back to non-blocking DCC mode */ - dbgdscr = (dbgdscr & ~DBGDSCR_EXTDCCMODE_MASK); - cortex_dbg_write32(t, CORTEXAR_DBG_DSCR, dbgdscr); - - if (cortex_dbg_read32(t, CORTEXAR_DBG_DSCR) & DBGDSCR_SDABORT_L) { - /* Memory access aborted, flag a fault */ - cortex_dbg_write32(t, CORTEXAR_DBG_DRCR, DBGDRCR_CSE); - priv->mmu_fault = true; - } else { - cortex_dbg_read32(t, CORTEXAR_DBG_DTRRX); - } -} - -static void cortexa_slow_mem_write_bytes(target_s *t, target_addr_t dest, const uint8_t *src, size_t len) -{ - cortexa_priv_s *priv = t->priv; - - /* Set r13 to dest address */ - write_gpreg(t, 13, dest); - - while (len--) { - write_gpreg(t, 0, *src++); - cortex_dbg_write32(t, CORTEXAR_DBG_ITR, 0xe4cd0001); /* strb r0, [sp], #1 */ - if (cortex_dbg_read32(t, CORTEXAR_DBG_DSCR) & DBGDSCR_SDABORT_L) { - /* Memory access aborted, flag a fault */ - cortex_dbg_write32(t, CORTEXAR_DBG_DRCR, DBGDRCR_CSE); - priv->mmu_fault = true; - return; - } - } -} - -static void cortexa_slow_mem_write(target_s *t, target_addr_t dest, const void *src, size_t len) -{ - cortexa_priv_s *priv = t->priv; - if (len == 0) - return; - - if ((dest & 3U) || (len & 3U)) { - cortexa_slow_mem_write_bytes(t, dest, src, len); - return; - } - - write_gpreg(t, 0, dest); - const uint32_t *src32 = src; - - /* Switch to fast DCC mode */ - uint32_t dbgdscr = cortex_dbg_read32(t, CORTEXAR_DBG_DSCR); - dbgdscr = (dbgdscr & ~DBGDSCR_EXTDCCMODE_MASK) | DBGDSCR_EXTDCCMODE_FAST; - cortex_dbg_write32(t, CORTEXAR_DBG_DSCR, dbgdscr); - - cortex_dbg_write32(t, CORTEXAR_DBG_ITR, 0xeca05e01); /* stc 14, cr5, [r0], #4 */ - - for (; len; len -= 4U) - cortex_dbg_write32(t, CORTEXAR_DBG_DTRTX, *src32++); - - /* Switch back to non-blocking DCC mode */ - dbgdscr &= ~DBGDSCR_EXTDCCMODE_MASK; - cortex_dbg_write32(t, CORTEXAR_DBG_DSCR, dbgdscr); - - if (cortex_dbg_read32(t, CORTEXAR_DBG_DSCR) & DBGDSCR_SDABORT_L) { - /* Memory access aborted, flag a fault */ - cortex_dbg_write32(t, CORTEXAR_DBG_DRCR, DBGDRCR_CSE); - priv->mmu_fault = true; - } -} - -static bool cortexa_check_error(target_s *target) -{ - cortexa_priv_s *priv = target->priv; - bool err = priv->mmu_fault; - priv->mmu_fault = false; - return err || cortex_check_error(target); -} - -const char *cortexa_regs_description(target_s *t) -{ - (void)t; - const size_t description_length = create_tdesc_cortex_a(NULL, 0) + 1U; - char *const description = malloc(description_length); - if (description) - create_tdesc_cortex_a(description, description_length); - return description; -} - -static void cortexa_oslock_unlock(target_s *target) -{ - uint32_t dbg_osreg = cortex_dbg_read32(target, CORTEXAR_DBG_OSLSR); - DEBUG_INFO("%s: DBGOSLSR = 0x%08" PRIx32 "\n", __func__, dbg_osreg); - /* Is OS Lock implemented? */ - if ((dbg_osreg & CORTEXAR_DBG_OSLSR_OSLM) == CORTEXAR_DBG_OSLSR_OSLM0 || - (dbg_osreg & CORTEXAR_DBG_OSLSR_OSLM) == CORTEXAR_DBG_OSLSR_OSLM1) { - /* Is OS Lock set? */ - if (dbg_osreg & CORTEXAR_DBG_OSLSR_OSLK) { - DEBUG_WARN("%s: OSLock set! Trying to unlock\n", __func__); - cortex_dbg_write32(target, CORTEXAR_DBG_OSLAR, 0U); - dbg_osreg = cortex_dbg_read32(target, CORTEXAR_DBG_OSLSR); - - if ((dbg_osreg & CORTEXAR_DBG_OSLSR_OSLK) != 0) - DEBUG_ERROR("%s: OSLock sticky, core not powered?\n", __func__); - } - } -} - -bool cortexa_probe(adiv5_access_port_s *ap, target_addr_t base_address) -{ - target_s *const target = target_new(); - if (!target) - return false; - - adiv5_ap_ref(ap); - cortexa_priv_s *const priv = calloc(1, sizeof(*priv)); - if (!priv) { /* calloc failed: heap exhaustion */ - DEBUG_ERROR("calloc: failed in %s\n", __func__); - return false; - } - - target->priv = priv; - target->priv_free = cortex_priv_free; - priv->base.ap = ap; - priv->base.base_addr = base_address; - - target->mem_read = cortexa_slow_mem_read; - target->mem_write = cortexa_slow_mem_write; - target->check_error = cortexa_check_error; - - target->driver = "ARM Cortex-A"; - - target->halt_request = cortexa_halt_request; - target->halt_poll = cortexa_halt_poll; - target->halt_resume = cortexa_halt_resume; - -#if 0 - /* Reset 0xc5acce55 lock access to deter software */ - cortex_dbg_write32(target, CORTEXAR_DBG_LAR, 0U); - /* Cache write-through */ - cortex_dbg_write32(target, CORTEXAR_DBG_DSCCR, 0U); - /* Disable TLB lookup and refill/eviction */ - cortex_dbg_write32(target, CORTEXAR_DBG_DSMCR, 0U); -#endif - - /* - * Clear the OSLock if set prior to halting the core - trying to do this after target_halt_request() - * does not function over JTAG and triggers the lock sticky message. - */ - cortexa_oslock_unlock(target); - - /* Try to halt the target core */ - target_halt_request(target); - platform_timeout_s timeout; - platform_timeout_set(&timeout, 250); - target_halt_reason_e reason = TARGET_HALT_RUNNING; - while (!platform_timeout_is_expired(&timeout) && reason == TARGET_HALT_RUNNING) - reason = target_halt_poll(target, NULL); - /* If we did not succeed, we must abort at this point. */ - if (reason == TARGET_HALT_FAULT || reason == TARGET_HALT_ERROR) - return false; - - cortex_read_cpuid(target); - /* The format of the debug identification register is described in DDI0406C §C11.11.15 pg2217 */ - const uint32_t debug_id = cortex_dbg_read32(target, CORTEXAR_DBG_IDR); - /* Reserve the last available breakpoint for our use to implement single-stepping */ - priv->base.breakpoints_available = - (debug_id >> CORTEXAR_DBG_IDR_BREAKPOINT_SHIFT) & CORTEXAR_DBG_IDR_BREAKPOINT_MASK; - priv->base.watchpoints_available = - ((debug_id >> CORTEXAR_DBG_IDR_WATCHPOINT_SHIFT) & CORTEXAR_DBG_IDR_WATCHPOINT_MASK) + 1U; - DEBUG_TARGET("%s %s core has %u breakpoint and %u watchpoint units available\n", target->driver, target->core, - priv->base.breakpoints_available + 1U, priv->base.watchpoints_available); - - target->attach = cortexa_attach; - target->detach = cortexa_detach; - - target->regs_description = cortexa_regs_description; - target->regs_read = cortexa_regs_read; - target->regs_write = cortexa_regs_write; - target->reg_read = cortexa_reg_read; - target->reg_write = cortexa_reg_write; - - target->reset = cortexa_reset; - target->regs_size = sizeof(uint32_t) * (CORTEXAR_GENERAL_REG_COUNT + CORTEX_FLOAT_REG_COUNT); - /* Check cache type */ - const uint32_t cache_type = cortex_dbg_read32(target, CORTEXAR_CTR); - if (cache_type >> CORTEX_CTR_FORMAT_SHIFT == CORTEX_CTR_FORMAT_ARMv7) { - /* If there is an ICache defined, decompress its length to a uint32_t count */ - if (cache_type & CORTEX_CTR_ICACHE_LINE_MASK) - priv->base.icache_line_length = CORTEX_CTR_ICACHE_LINE(cache_type); - /* If there is a DCache defined, decompress its length to a uint32_t count */ - if ((cache_type >> CORTEX_CTR_DCACHE_LINE_SHIFT) & CORTEX_CTR_DCACHE_LINE_MASK) - priv->base.dcache_line_length = CORTEX_CTR_DCACHE_LINE(cache_type); - - DEBUG_TARGET("%s: ICache line length = %u, DCache line length = %u\n", __func__, - priv->base.icache_line_length << 2U, priv->base.dcache_line_length << 2U); - } else - target_check_error(target); - - target->breakwatch_set = cortexa_breakwatch_set; - target->breakwatch_clear = cortexa_breakwatch_clear; - - return true; -} - -bool cortexa_attach(target_s *target) -{ - cortexa_priv_s *priv = target->priv; - - /* Clear any pending fault condition */ - target_check_error(target); - - /* Make sure the OSLock is cleared prior to halting the core in case it got re-set between probe and attach. */ - cortexa_oslock_unlock(target); - target_halt_request(target); - size_t tries = 10; - while (!platform_nrst_get_val() && !target_halt_poll(target, NULL) && --tries) - platform_delay(200); - if (!tries) - return false; - - /* Clear any stale breakpoints */ - priv->base.breakpoints_mask = 0U; - for (size_t i = 0; i <= priv->base.breakpoints_available; ++i) { - cortex_dbg_write32(target, CORTEXAR_DBG_BVR + (i << 2U), 0U); - cortex_dbg_write32(target, CORTEXAR_DBG_BCR + (i << 2U), 0U); - } - priv->bcr0 = 0; - - platform_nrst_set_val(false); - - return true; -} - -void cortexa_detach(target_s *target) -{ - cortexa_priv_s *priv = target->priv; - - /* Clear any stale breakpoints */ - for (size_t i = 0; i <= priv->base.breakpoints_available; ++i) { - cortex_dbg_write32(target, CORTEXAR_DBG_BVR + (i << 2U), 0U); - cortex_dbg_write32(target, CORTEXAR_DBG_BCR + (i << 2U), 0U); - } - - /* Restore any clobbered registers */ - cortexa_regs_write_internal(target); - /* Invalidate cache */ - cortexar_run_insn(target, MCR | ICIALLU); - - /* Disable halting debug mode */ - uint32_t dbgdscr = cortex_dbg_read32(target, CORTEXAR_DBG_DSCR); - dbgdscr &= ~(CORTEXAR_DBG_DSCR_HALT_DBG_ENABLE | CORTEXAR_DBG_DSCR_ITR_ENABLE); - cortex_dbg_write32(target, CORTEXAR_DBG_DSCR, dbgdscr); - /* Clear sticky error and resume */ - cortex_dbg_write32(target, CORTEXAR_DBG_DRCR, DBGDRCR_CSE | DBGDRCR_RRQ); -} - -static inline uint32_t read_gpreg(target_s *t, uint8_t regno) -{ - return cortexar_run_read_insn(t, MCR | DBGDTRTXint | ((regno & 0xfU) << 12U)); -} - -static inline void write_gpreg(target_s *t, uint8_t regno, uint32_t val) -{ - cortexar_run_write_insn(t, MRC | DBGDTRRXint | ((regno & 0xfU) << 12U), val); -} - -static void cortexa_regs_read(target_s *t, void *data) -{ - cortexa_priv_s *priv = (cortexa_priv_s *)t->priv; - memcpy(data, &priv->reg_cache, t->regs_size); -} - -static void cortexa_regs_write(target_s *t, const void *data) -{ - cortexa_priv_s *priv = (cortexa_priv_s *)t->priv; - memcpy(&priv->reg_cache, data, t->regs_size); -} - -static ssize_t ptr_for_reg(target_s *t, uint32_t reg, void **r) -{ - cortexa_priv_s *priv = (cortexa_priv_s *)t->priv; - if (reg <= 15U) { /* 0 .. 15 */ - *r = &priv->reg_cache.r[reg]; - return 4U; - } else if (reg == 16U) { /* 16 */ - *r = &priv->reg_cache.cpsr; - return 4U; - } else if (reg == 17U) { /* 17 */ - *r = &priv->reg_cache.fpscr; - return 4U; - } else if (reg <= 33U) { /* 18 .. 33 */ - *r = &priv->reg_cache.d[reg - 18U]; - return 8U; - } - return -1; -} - -static ssize_t cortexa_reg_read(target_s *t, uint32_t reg, void *data, size_t max) -{ - void *r = NULL; - size_t s = ptr_for_reg(t, reg, &r); - if (s > max) - return -1; - memcpy(data, r, s); - return s; -} - -static ssize_t cortexa_reg_write(target_s *t, uint32_t reg, const void *data, size_t max) -{ - void *r = NULL; - size_t s = ptr_for_reg(t, reg, &r); - if (s > max) - return -1; - memcpy(r, data, s); - return s; -} - -static void cortexa_regs_read_internal(target_s *t) -{ - cortexa_priv_s *priv = (cortexa_priv_s *)t->priv; - /* Read general purpose registers */ - for (size_t i = 0; i < 15U; i++) - priv->reg_cache.r[i] = read_gpreg(t, i); - - /* Read PC, via r0. MCR is UNPREDICTABLE for Rt = r15. */ - cortexar_run_insn(t, 0xe1a0000f); /* mov r0, pc */ - priv->reg_cache.r[15] = read_gpreg(t, 0); - /* Read CPSR */ - cortexar_run_insn(t, 0xe10f0000); /* mrs r0, CPSR */ - priv->reg_cache.cpsr = read_gpreg(t, 0); - /* Read FPSCR */ - cortexar_run_insn(t, 0xeef10a10); /* vmrs r0, fpscr */ - priv->reg_cache.fpscr = read_gpreg(t, 0); - /* Read out VFP registers */ - for (size_t i = 0; i < 16U; i++) { - /* Read D[i] to R0/R1 */ - cortexar_run_insn(t, 0xec510b10 | i); /* vmov r0, r1, d0 */ - priv->reg_cache.d[i] = ((uint64_t)read_gpreg(t, 1) << 32U) | read_gpreg(t, 0); - } - priv->reg_cache.r[15] -= (priv->reg_cache.cpsr & CPSR_THUMB) ? 4 : 8; -} - -static void cortexa_regs_write_internal(target_s *t) -{ - cortexa_priv_s *priv = (cortexa_priv_s *)t->priv; - /* First write back floats */ - for (size_t i = 0; i < 16U; i++) { - write_gpreg(t, 1, priv->reg_cache.d[i] >> 32U); - write_gpreg(t, 0, priv->reg_cache.d[i]); - cortexar_run_insn(t, 0xec410b10U | i); /* vmov d[i], r0, r1 */ - } - /* Write back FPSCR */ - write_gpreg(t, 0, priv->reg_cache.fpscr); - cortexar_run_insn(t, 0xeee10a10); /* vmsr fpscr, r0 */ - /* Write back the CPSR */ - write_gpreg(t, 0, priv->reg_cache.cpsr); - cortexar_run_insn(t, 0xe12ff000); /* msr CPSR_fsxc, r0 */ - /* Write back PC, via r0. MRC clobbers CPSR instead */ - write_gpreg(t, 0, priv->reg_cache.r[15] | ((priv->reg_cache.cpsr & CPSR_THUMB) ? 1 : 0)); - cortexar_run_insn(t, 0xe1a0f000); /* mov pc, r0 */ - /* Finally the GP registers now that we're done using them */ - for (size_t i = 0; i < 15U; i++) - write_gpreg(t, i, priv->reg_cache.r[i]); -} - -static void cortexa_reset(target_s *target) -{ - /* This mess is Xilinx Zynq specific - * See Zynq-7000 TRM, Xilinx doc UG585 - */ -#define ZYNQ_SLCR_UNLOCK 0xf8000008U -#define ZYNQ_SLCR_UNLOCK_KEY 0xdf0dU -#define ZYNQ_SLCR_PSS_RST_CTRL 0xf8000200U - target_mem_write32(target, ZYNQ_SLCR_UNLOCK, ZYNQ_SLCR_UNLOCK_KEY); - target_mem_write32(target, ZYNQ_SLCR_PSS_RST_CTRL, 1); - - /* Try hard reset too */ - platform_nrst_set_val(true); - platform_nrst_set_val(false); - - /* Spin until Xilinx reconnects us */ - platform_timeout_s timeout; - platform_timeout_set(&timeout, 1000); - volatile exception_s e; - do { - TRY_CATCH (e, EXCEPTION_ALL) { - cortex_dbg_read32(target, CORTEXAR_DBG_IDR); - } - } while (!platform_timeout_is_expired(&timeout) && e.type == EXCEPTION_ERROR); - if (e.type == EXCEPTION_ERROR) - raise_exception(e.type, e.msg); - - platform_delay(100); - - cortexa_attach(target); -} - -static void cortexa_halt_request(target_s *t) -{ - volatile exception_s e; - TRY_CATCH (e, EXCEPTION_TIMEOUT) { - cortex_dbg_write32(t, CORTEXAR_DBG_DRCR, DBGDRCR_HRQ); - } - if (e.type) { - tc_printf(t, "Timeout sending interrupt, is target in WFI?\n"); - } -} - -static target_halt_reason_e cortexa_halt_poll(target_s *t, target_addr_t *watch) -{ - volatile uint32_t dbgdscr = 0; - volatile exception_s e; - TRY_CATCH (e, EXCEPTION_ALL) { - /* If this times out because the target is in WFI then - * the target is still running. */ - dbgdscr = cortex_dbg_read32(t, CORTEXAR_DBG_DSCR); - } - switch (e.type) { - case EXCEPTION_ERROR: - /* Oh crap, there's no recovery from this... */ - target_list_free(); - return TARGET_HALT_ERROR; - case EXCEPTION_TIMEOUT: - /* Timeout isn't a problem, target could be in WFI */ - return TARGET_HALT_RUNNING; - } - - if (!(dbgdscr & CORTEXAR_DBG_DSCR_HALTED)) /* Not halted */ - return TARGET_HALT_RUNNING; - - cortexa_oslock_unlock(t); - - DEBUG_INFO("%s: DBGDSCR = 0x%08" PRIx32 "\n", __func__, dbgdscr); - cortexa_decode_bitfields(CORTEXAR_DBG_DSCR, dbgdscr); - - /* Enable halting debug mode */ - dbgdscr |= CORTEXAR_DBG_DSCR_HALT_DBG_ENABLE | CORTEXAR_DBG_DSCR_ITR_ENABLE; - dbgdscr &= ~DBGDSCR_EXTDCCMODE_MASK; - cortex_dbg_write32(t, CORTEXAR_DBG_DSCR, dbgdscr); - - dbgdscr = cortex_dbg_read32(t, CORTEXAR_DBG_DSCR); - DEBUG_INFO("%s: DBGDSCR = 0x%08" PRIx32 "\n", __func__, dbgdscr); - cortexa_decode_bitfields(CORTEXAR_DBG_DSCR, dbgdscr); - - /* Find out why we halted */ - target_halt_reason_e reason = TARGET_HALT_BREAKPOINT; - switch (dbgdscr & CORTEXAR_DBG_DSCR_MOE_MASK) { - case CORTEXAR_DBG_DSCR_MOE_HALT_REQUEST: - reason = TARGET_HALT_REQUEST; - break; - case CORTEXAR_DBG_DSCR_MOE_ASYNC_WATCH: - case CORTEXAR_DBG_DSCR_MOE_SYNC_WATCH: - /* How do we know which watchpoint was hit? */ - /* If there is only one set, it's that */ - for (breakwatch_s *bw = t->bw_list; bw; bw = bw->next) { - if ((bw->type != TARGET_WATCH_READ) && (bw->type != TARGET_WATCH_WRITE) && - (bw->type != TARGET_WATCH_ACCESS)) - continue; - if (reason == TARGET_HALT_WATCHPOINT) { - /* More than one watchpoint set, - * we can't tell which triggered. */ - reason = TARGET_HALT_BREAKPOINT; - break; - } - *watch = bw->addr; - reason = TARGET_HALT_WATCHPOINT; - } - break; - default: - reason = TARGET_HALT_BREAKPOINT; - } - - cortexa_regs_read_internal(t); - - return reason; -} - -void cortexa_halt_resume(target_s *t, bool step) -{ - cortexa_priv_s *priv = t->priv; - /* Set breakpoint comparator for single stepping if needed */ - if (step) { - uint32_t addr = priv->reg_cache.r[15]; - uint32_t bas = bp_bas(addr, (priv->reg_cache.cpsr & CPSR_THUMB) ? 2 : 4); - DEBUG_INFO("step 0x%08" PRIx32 " %" PRIx32 "\n", addr, bas); - /* Set match any breakpoint */ - cortex_dbg_write32(t, CORTEXAR_DBG_BVR + 0, priv->reg_cache.r[15] & ~3); - cortex_dbg_write32(t, CORTEXAR_DBG_BCR + 0, DBGBCR_INST_MISMATCH | bas | DBGBCR_PMC_ANY | DBGBCR_EN); - } else { - cortex_dbg_write32(t, CORTEXAR_DBG_BVR + 0, priv->bvr0); - cortex_dbg_write32(t, CORTEXAR_DBG_BCR + 0, priv->bcr0); - } - - /* Write back register cache */ - cortexa_regs_write_internal(t); - - cortexar_run_insn(t, MCR | ICIALLU); /* invalidate cache */ - - /* Disable DBGITR. Not sure why, but RRQ is ignored otherwise. */ - uint32_t dbgdscr = cortex_dbg_read32(t, CORTEXAR_DBG_DSCR); - if (step) - dbgdscr |= DBGDSCR_INTDIS; - else - dbgdscr &= ~(DBGDSCR_INTDIS | CORTEXAR_DBG_DSCR_HALT_DBG_ENABLE); - dbgdscr &= ~CORTEXAR_DBG_DSCR_ITR_ENABLE; - cortex_dbg_write32(t, CORTEXAR_DBG_DSCR, dbgdscr); - - platform_timeout_s to; - platform_timeout_set(&to, 200); - do { - cortex_dbg_write32(t, CORTEXAR_DBG_DRCR, DBGDRCR_CSE | DBGDRCR_RRQ); - dbgdscr = cortex_dbg_read32(t, CORTEXAR_DBG_DSCR); - DEBUG_INFO("%s: DBGDSCR = 0x%08" PRIx32 "\n", __func__, dbgdscr); - } while (!(dbgdscr & CORTEXAR_DBG_DSCR_RESTARTED) && !platform_timeout_is_expired(&to)); -} - -/* Breakpoints */ -static uint32_t bp_bas(uint32_t addr, uint8_t len) -{ - if (len == 4U) - return DBGBCR_BAS_ANY; - if (addr & 2U) - return DBGBCR_BAS_HIGH_HW; - return DBGBCR_BAS_LOW_HW; -} - -static int cortexa_breakwatch_set(target_s *t, breakwatch_s *bw) -{ - cortexa_priv_s *priv = t->priv; - uint32_t i; - - switch (bw->type) { - case TARGET_BREAK_SOFT: - switch (bw->size) { - case 2: - bw->reserved[0] = target_mem_read16(t, bw->addr); - target_mem_write16(t, bw->addr, 0xbe00); - return target_check_error(t); - case 4: - bw->reserved[0] = target_mem_read32(t, bw->addr); - target_mem_write32(t, bw->addr, 0xe1200070); - return target_check_error(t); - default: - return -1; - } - case TARGET_BREAK_HARD: - if ((bw->size != 4) && (bw->size != 2)) - return -1; - - /* Find the first available breakpoint slot */ - for (i = 0; i < priv->base.breakpoints_available; i++) { - if (!(priv->base.breakpoints_mask & (1U << i))) - break; - } - - if (i == priv->base.breakpoints_available) - return -1; - - bw->reserved[0] = i; - priv->base.breakpoints_mask |= 1U << i; - - uint32_t addr = va_to_pa(t, bw->addr); - uint32_t bcr = bp_bas(addr, bw->size) | DBGBCR_PMC_ANY | DBGBCR_EN; - cortex_dbg_write32(t, CORTEXAR_DBG_BVR + (i << 2U), addr & ~3); - cortex_dbg_write32(t, CORTEXAR_DBG_BCR + (i << 2U), bcr); - if (i == 0) { - priv->bcr0 = bcr; - priv->bvr0 = addr & ~3; - } - - return 0; - - case TARGET_WATCH_WRITE: - case TARGET_WATCH_READ: - case TARGET_WATCH_ACCESS: - /* Find the first available watchpoint slot */ - for (i = 0; i < priv->base.watchpoints_available; i++) { - if (!(priv->base.watchpoints_mask & (1U << i))) - break; - } - - if (i == priv->base.watchpoints_available) - return -1; - - bw->reserved[0] = i; - priv->base.watchpoints_mask |= 1U << i; - - { - uint32_t wcr = DBGWCR_PAC_ANY | DBGWCR_EN; - uint32_t bas = 0; - switch (bw->size) { /* Convert bytes size to BAS bits */ - case 1U: - bas = DBGWCR_BAS_BYTE; - break; - case 2U: - bas = DBGWCR_BAS_HALFWORD; - break; - case 4U: - bas = DBGWCR_BAS_WORD; - break; - default: - return -1; - } - /* Apply shift based on address LSBs */ - wcr |= bas << (bw->addr & 3U); - - switch (bw->type) { /* Convert gdb type */ - case TARGET_WATCH_WRITE: - wcr |= DBGWCR_LSC_STORE; - break; - case TARGET_WATCH_READ: - wcr |= DBGWCR_LSC_LOAD; - break; - case TARGET_WATCH_ACCESS: - wcr |= DBGWCR_LSC_ANY; - break; - default: - return -1; - } - - cortex_dbg_write32(t, CORTEXAR_DBG_WVR + (i << 2U), wcr); - cortex_dbg_write32(t, CORTEXAR_DBG_WCR + (i << 2U), bw->addr & ~3U); - DEBUG_INFO("Watchpoint set WCR = 0x%08" PRIx32 ", WVR = %08" PRIx32 "\n", - cortex_dbg_read32(t, CORTEXAR_DBG_WVR + (i << 2U)), cortex_dbg_read32(t, CORTEXAR_DBG_WCR + (i << 2U))); - } - return 0; - - default: - return 1; - } -} - -static int cortexa_breakwatch_clear(target_s *t, breakwatch_s *bw) -{ - cortexa_priv_s *priv = t->priv; - uint32_t i = bw->reserved[0]; - switch (bw->type) { - case TARGET_BREAK_SOFT: - switch (bw->size) { - case 2: - target_mem_write16(t, bw->addr, i); - return target_check_error(t); - case 4: - target_mem_write32(t, bw->addr, i); - return target_check_error(t); - default: - return -1; - } - case TARGET_BREAK_HARD: - priv->base.breakpoints_mask &= ~(1U << i); - cortex_dbg_write32(t, CORTEXAR_DBG_BCR + (i << 2U), 0); - if (i == 0) - priv->bcr0 = 0; - return 0; - case TARGET_WATCH_WRITE: - case TARGET_WATCH_READ: - case TARGET_WATCH_ACCESS: - priv->base.watchpoints_mask &= ~(1U << i); - cortex_dbg_write32(t, CORTEXAR_DBG_WCR + (i << 2U), 0); - return 0; - default: - return 1; - } -}