Browse Source

arm_adi_v5: fix access to 64-bit MEM-AP

Commit ac22cdc573 ("target/adiv5: Large Physical Address
Extension") reads the register MEM_AP_REG_CFG and keeps it in a
new field of struct adiv5_ap. The test on LE bit (Large Extension)
is used to identify if mem_ap addresses are 32 or 64 bits.
But the register MEM_AP_REG_CFG is only read during mem_ap_init(),
that is called only when the AP is used as a target debug AP or if
a target mem_ap is attached to that AP.

The openocd commands '<dapname> baseaddr', '<dapname> info' and
'dap info' can be executed on AP that has not been associated yet
to a target, thus executed without any knowledge of MEM_AP_REG_CFG
value. The initialization to ADI_BAD_CFG causes openocd to always
use 32 bit mode on un-associated APs.

Verify if MEM_AP_REG_CFG has not been read and eventually read it.
In case of 32 bits mode AP, MEM_AP_REG_BASE64 is defined as 'RES0'
(reserved, but readable); the code can queue both the read of
MEM_AP_REG_CFG and MEM_AP_REG_BASE64, before knowing if the former
is required. This speeds-up the operation.
Rename ADI_BAD_CFG as MEM_AP_REG_CFG_INVALID.

Change-Id: If3bbd792b56a483022c37ccc2ce82b5ba5c36caa
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Fixes: ac22cdc573 ("target/adiv5: Large Physical Address Extension")
Reviewed-on: http://openocd.zylin.com/6412
Tested-by: jenkins
Reviewed-by: Daniel Goehring <dgoehrin@os.amperecomputing.com>
jim
Antonio Borneo 2 years ago
parent
commit
020e46d186
3 changed files with 27 additions and 17 deletions
  1. +22
    -11
      src/target/arm_adi_v5.c
  2. +4
    -3
      src/target/arm_adi_v5.h
  3. +1
    -3
      src/target/arm_dap.c

+ 22
- 11
src/target/arm_adi_v5.c View File

@@ -946,25 +946,30 @@ int dap_get_debugbase(struct adiv5_ap *ap,
int retval; int retval;
uint32_t baseptr_upper, baseptr_lower; uint32_t baseptr_upper, baseptr_lower;


baseptr_upper = 0;

if (is_64bit_ap(ap)) {
/* Read higher order 32-bits of base address */
retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE64, &baseptr_upper);
if (ap->cfg_reg == MEM_AP_REG_CFG_INVALID) {
retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG, &ap->cfg_reg);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
} }

retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseptr_lower); retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseptr_lower);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
retval = dap_queue_ap_read(ap, AP_REG_IDR, apid); retval = dap_queue_ap_read(ap, AP_REG_IDR, apid);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
/* MEM_AP_REG_BASE64 is defined as 'RES0'; can be read and then ignored on 32 bits AP */
if (ap->cfg_reg == MEM_AP_REG_CFG_INVALID || is_64bit_ap(ap)) {
retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE64, &baseptr_upper);
if (retval != ERROR_OK)
return retval;
}

retval = dap_run(dap); retval = dap_run(dap);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;


if (!is_64bit_ap(ap))
baseptr_upper = 0;
*dbgbase = (((target_addr_t)baseptr_upper) << 32) | baseptr_lower; *dbgbase = (((target_addr_t)baseptr_upper) << 32) | baseptr_lower;


return ERROR_OK; return ERROR_OK;
@@ -1768,20 +1773,26 @@ COMMAND_HANDLER(dap_baseaddr_command)
ap = dap_ap(dap, apsel); ap = dap_ap(dap, apsel);
retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseaddr_lower); retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseaddr_lower);


if (is_64bit_ap(ap) && retval == ERROR_OK)
if (retval == ERROR_OK && ap->cfg_reg == MEM_AP_REG_CFG_INVALID)
retval = dap_queue_ap_read(ap, MEM_AP_REG_CFG, &ap->cfg_reg);

if (retval == ERROR_OK && (ap->cfg_reg == MEM_AP_REG_CFG_INVALID || is_64bit_ap(ap))) {
/* MEM_AP_REG_BASE64 is defined as 'RES0'; can be read and then ignored on 32 bits AP */
retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE64, &baseaddr_upper); retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE64, &baseaddr_upper);
}

if (retval == ERROR_OK)
retval = dap_run(dap);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
retval = dap_run(dap);
if (retval != ERROR_OK)
return retval;

if (is_64bit_ap(ap)) { if (is_64bit_ap(ap)) {
baseaddr = (((target_addr_t)baseaddr_upper) << 32) | baseaddr_lower; baseaddr = (((target_addr_t)baseaddr_upper) << 32) | baseaddr_lower;
command_print(CMD, "0x%016" PRIx64, baseaddr); command_print(CMD, "0x%016" PRIx64, baseaddr);
} else } else
command_print(CMD, "0x%08" PRIx32, baseaddr_lower); command_print(CMD, "0x%08" PRIx32, baseaddr_lower);


return retval;
return ERROR_OK;
} }


COMMAND_HANDLER(dap_memaccess_command) COMMAND_HANDLER(dap_memaccess_command)


+ 4
- 3
src/target/arm_adi_v5.h View File

@@ -151,9 +151,10 @@
#define CSW_APB_DEFAULT (CSW_DBGSWENABLE) #define CSW_APB_DEFAULT (CSW_DBGSWENABLE)


/* Fields of the MEM-AP's CFG register */ /* Fields of the MEM-AP's CFG register */
#define MEM_AP_REG_CFG_BE BIT(0)
#define MEM_AP_REG_CFG_LA BIT(1)
#define MEM_AP_REG_CFG_LD BIT(2)
#define MEM_AP_REG_CFG_BE BIT(0)
#define MEM_AP_REG_CFG_LA BIT(1)
#define MEM_AP_REG_CFG_LD BIT(2)
#define MEM_AP_REG_CFG_INVALID 0xFFFFFFF8


/* Fields of the MEM-AP's IDR register */ /* Fields of the MEM-AP's IDR register */
#define IDR_REV (0xFUL << 28) #define IDR_REV (0xFUL << 28)


+ 1
- 3
src/target/arm_dap.c View File

@@ -36,8 +36,6 @@ extern const struct dap_ops swd_dap_ops;
extern const struct dap_ops jtag_dp_ops; extern const struct dap_ops jtag_dp_ops;
extern struct adapter_driver *adapter_driver; extern struct adapter_driver *adapter_driver;


#define ADI_BAD_CFG 0xBAD00000

/* DAP command support */ /* DAP command support */
struct arm_dap_object { struct arm_dap_object {
struct list_head lh; struct list_head lh;
@@ -59,7 +57,7 @@ static void dap_instance_init(struct adiv5_dap *dap)
dap->ap[i].tar_autoincr_block = (1<<10); dap->ap[i].tar_autoincr_block = (1<<10);
/* default CSW value */ /* default CSW value */
dap->ap[i].csw_default = CSW_AHB_DEFAULT; dap->ap[i].csw_default = CSW_AHB_DEFAULT;
dap->ap[i].cfg_reg = ADI_BAD_CFG; /* mem_ap configuration reg (large physical addr, etc.) */
dap->ap[i].cfg_reg = MEM_AP_REG_CFG_INVALID; /* mem_ap configuration reg (large physical addr, etc.) */
} }
INIT_LIST_HEAD(&dap->cmd_journal); INIT_LIST_HEAD(&dap->cmd_journal);
INIT_LIST_HEAD(&dap->cmd_pool); INIT_LIST_HEAD(&dap->cmd_pool);


Loading…
Cancel
Save