arm_adi_v5: fix access to 64-bit MEM-AP 12/6412/2
authorAntonio Borneo <borneo.antonio@gmail.com>
Thu, 5 Aug 2021 15:08:11 +0000 (17:08 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sat, 14 Aug 2021 12:30:35 +0000 (13:30 +0100)
Commit ac22cdc57322 ("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: ac22cdc57322 ("target/adiv5: Large Physical Address Extension")
Reviewed-on: http://openocd.zylin.com/6412
Tested-by: jenkins
Reviewed-by: Daniel Goehring <dgoehrin@os.amperecomputing.com>
src/target/arm_adi_v5.c
src/target/arm_adi_v5.h
src/target/arm_dap.c

index 21788af793c53c6e07dada64440478753dd83edd..2bb11b25ec2f26b9c3807fab1982af74e3cf7f37 100644 (file)
@@ -946,25 +946,30 @@ int dap_get_debugbase(struct adiv5_ap *ap,
        int retval;
        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)
                        return retval;
        }
-
        retval = dap_queue_ap_read(ap, MEM_AP_REG_BASE, &baseptr_lower);
        if (retval != ERROR_OK)
                return retval;
        retval = dap_queue_ap_read(ap, AP_REG_IDR, apid);
        if (retval != ERROR_OK)
                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);
        if (retval != ERROR_OK)
                return retval;
 
+       if (!is_64bit_ap(ap))
+               baseptr_upper = 0;
        *dbgbase = (((target_addr_t)baseptr_upper) << 32) | baseptr_lower;
 
        return ERROR_OK;
@@ -1768,20 +1773,26 @@ COMMAND_HANDLER(dap_baseaddr_command)
        ap = dap_ap(dap, apsel);
        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);
+       }
+
+       if (retval == ERROR_OK)
+               retval = dap_run(dap);
        if (retval != ERROR_OK)
                return retval;
-       retval = dap_run(dap);
-       if (retval != ERROR_OK)
-               return retval;
+
        if (is_64bit_ap(ap)) {
                baseaddr = (((target_addr_t)baseaddr_upper) << 32) | baseaddr_lower;
                command_print(CMD, "0x%016" PRIx64, baseaddr);
        } else
                command_print(CMD, "0x%08" PRIx32, baseaddr_lower);
 
-       return retval;
+       return ERROR_OK;
 }
 
 COMMAND_HANDLER(dap_memaccess_command)
index 5d1e793781107d3700f5f7fea4ec5aadf294f133..73ceea03f0718914f0f84e302b355f1080863205 100644 (file)
 #define CSW_APB_DEFAULT         (CSW_DBGSWENABLE)
 
 /* 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 */
 #define IDR_REV     (0xFUL << 28)
index a399c51dec540396b17c6727ea6fc9616c62faa0..2f21aa170d4b125e539be8ed7ad7fdc715548f2a 100644 (file)
@@ -36,8 +36,6 @@ extern const struct dap_ops swd_dap_ops;
 extern const struct dap_ops jtag_dp_ops;
 extern struct adapter_driver *adapter_driver;
 
-#define ADI_BAD_CFG 0xBAD00000
-
 /* DAP command support */
 struct arm_dap_object {
        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);
                /* default CSW value */
                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_pool);

Linking to existing account procedure

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

SSH host keys fingerprints

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