jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / aarch64.c
index d11fd943bd1b9354acb5cd2c880093a205f552b2..2e4d0b5c034f4c9d7f4249da109165e1d2aaa033 100644 (file)
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 /***************************************************************************
  *   Copyright (C) 2015 by David Ung                                       *
  *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (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, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *                                                                         *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -33,6 +21,7 @@
 #include "arm_semihosting.h"
 #include "jtag/interface.h"
 #include "smp.h"
+#include <helper/nvp.h>
 #include <helper/time_support.h>
 
 enum restart_mode {
@@ -104,6 +93,7 @@ static int aarch64_restore_system_control_reg(struct target *target)
                case ARM_MODE_HYP:
                case ARM_MODE_UND:
                case ARM_MODE_SYS:
+               case ARM_MODE_MON:
                        instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0);
                        break;
 
@@ -116,7 +106,7 @@ static int aarch64_restore_system_control_reg(struct target *target)
                if (target_mode != ARM_MODE_ANY)
                        armv8_dpm_modeswitch(&armv8->dpm, target_mode);
 
-               retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr, aarch64->system_control_reg);
+               retval = armv8->dpm.instr_write_data_r0_64(&armv8->dpm, instr, aarch64->system_control_reg);
                if (retval != ERROR_OK)
                        return retval;
 
@@ -183,6 +173,7 @@ static int aarch64_mmu_modify(struct target *target, int enable)
        case ARM_MODE_HYP:
        case ARM_MODE_UND:
        case ARM_MODE_SYS:
+       case ARM_MODE_MON:
                instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0);
                break;
 
@@ -193,7 +184,7 @@ static int aarch64_mmu_modify(struct target *target, int enable)
        if (target_mode != ARM_MODE_ANY)
                armv8_dpm_modeswitch(&armv8->dpm, target_mode);
 
-       retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr,
+       retval = armv8->dpm.instr_write_data_r0_64(&armv8->dpm, instr,
                                aarch64->system_control_reg_curr);
 
        if (target_mode != ARM_MODE_ANY)
@@ -333,15 +324,14 @@ static int aarch64_wait_halt_one(struct target *target)
 static int aarch64_prepare_halt_smp(struct target *target, bool exc_target, struct target **p_first)
 {
        int retval = ERROR_OK;
-       struct target_list *head = target->head;
+       struct target_list *head;
        struct target *first = NULL;
 
        LOG_DEBUG("target %s exc %i", target_name(target), exc_target);
 
-       while (head) {
+       foreach_smp_target(head, target->smp_targets) {
                struct target *curr = head->target;
                struct armv8_common *armv8 = target_to_armv8(curr);
-               head = head->next;
 
                if (exc_target && curr == target)
                        continue;
@@ -430,7 +420,7 @@ static int aarch64_halt_smp(struct target *target, bool exc_target)
                struct target_list *head;
                struct target *curr;
 
-               foreach_smp_target(head, target->head) {
+               foreach_smp_target(head, target->smp_targets) {
                        int halted;
 
                        curr = head->target;
@@ -480,7 +470,7 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug
        }
 
        /* poll all targets in the group, but skip the target that serves GDB */
-       foreach_smp_target(head, target->head) {
+       foreach_smp_target(head, target->smp_targets) {
                curr = head->target;
                /* skip calling context */
                if (curr == target)
@@ -601,7 +591,7 @@ static int aarch64_restore_one(struct target *target, int current,
                        resume_pc &= 0xFFFFFFFC;
                        break;
                case ARM_STATE_AARCH64:
-                       resume_pc &= 0xFFFFFFFFFFFFFFFC;
+                       resume_pc &= 0xFFFFFFFFFFFFFFFCULL;
                        break;
                case ARM_STATE_THUMB:
                case ARM_STATE_THUMB_EE:
@@ -745,7 +735,7 @@ static int aarch64_prep_restart_smp(struct target *target, int handle_breakpoint
        struct target *first = NULL;
        uint64_t address;
 
-       foreach_smp_target(head, target->head) {
+       foreach_smp_target(head, target->smp_targets) {
                struct target *curr = head->target;
 
                /* skip calling target */
@@ -800,7 +790,7 @@ static int aarch64_step_restart_smp(struct target *target)
                struct target *curr = target;
                bool all_resumed = true;
 
-               foreach_smp_target(head, target->head) {
+               foreach_smp_target(head, target->smp_targets) {
                        uint32_t prsr;
                        int resumed;
 
@@ -858,8 +848,10 @@ static int aarch64_resume(struct target *target, int current,
        struct armv8_common *armv8 = target_to_armv8(target);
        armv8->last_run_control_op = ARMV8_RUNCONTROL_RESUME;
 
-       if (target->state != TARGET_HALTED)
+       if (target->state != TARGET_HALTED) {
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
+       }
 
        /*
         * If this target is part of a SMP group, prepare the others
@@ -888,7 +880,7 @@ static int aarch64_resume(struct target *target, int current,
                        struct target_list *head;
                        bool all_resumed = true;
 
-                       foreach_smp_target(head, target->head) {
+                       foreach_smp_target(head, target->smp_targets) {
                                uint32_t prsr;
                                int resumed;
 
@@ -1053,6 +1045,7 @@ static int aarch64_post_debug_entry(struct target *target)
        case ARM_MODE_HYP:
        case ARM_MODE_UND:
        case ARM_MODE_SYS:
+       case ARM_MODE_MON:
                instr = ARMV4_5_MRC(15, 0, 0, 1, 0, 0);
                break;
 
@@ -1065,23 +1058,26 @@ static int aarch64_post_debug_entry(struct target *target)
        if (target_mode != ARM_MODE_ANY)
                armv8_dpm_modeswitch(&armv8->dpm, target_mode);
 
-       retval = armv8->dpm.instr_read_data_r0(&armv8->dpm, instr, &aarch64->system_control_reg);
+       retval = armv8->dpm.instr_read_data_r0_64(&armv8->dpm, instr, &aarch64->system_control_reg);
        if (retval != ERROR_OK)
                return retval;
 
        if (target_mode != ARM_MODE_ANY)
                armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY);
 
-       LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg);
+       LOG_DEBUG("System_register: %8.8" PRIx64, aarch64->system_control_reg);
        aarch64->system_control_reg_curr = aarch64->system_control_reg;
 
        if (armv8->armv8_mmu.armv8_cache.info == -1) {
                armv8_identify_cache(armv8);
                armv8_read_mpidr(armv8);
        }
-
-       armv8->armv8_mmu.mmu_enabled =
+       if (armv8->is_armv8r) {
+               armv8->armv8_mmu.mmu_enabled = 0;
+       } else {
+               armv8->armv8_mmu.mmu_enabled =
                        (aarch64->system_control_reg & 0x1U) ? 1 : 0;
+       }
        armv8->armv8_mmu.armv8_cache.d_u_cache_enabled =
                (aarch64->system_control_reg & 0x4U) ? 1 : 0;
        armv8->armv8_mmu.armv8_cache.i_cache_enabled =
@@ -1098,13 +1094,14 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
        struct armv8_common *armv8 = target_to_armv8(target);
        struct aarch64_common *aarch64 = target_to_aarch64(target);
        int saved_retval = ERROR_OK;
+       int poll_retval;
        int retval;
        uint32_t edecr;
 
        armv8->last_run_control_op = ARMV8_RUNCONTROL_STEP;
 
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target not halted");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -1180,6 +1177,8 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
        if (retval == ERROR_TARGET_TIMEOUT)
                saved_retval = aarch64_halt_one(target, HALT_SYNC);
 
+       poll_retval = aarch64_poll(target);
+
        /* restore EDECR */
        retval = mem_ap_write_atomic_u32(armv8->debug_ap,
                        armv8->debug_base + CPUV8_DBG_EDECR, edecr);
@@ -1196,6 +1195,9 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
        if (saved_retval != ERROR_OK)
                return saved_retval;
 
+       if (poll_retval != ERROR_OK)
+               return poll_retval;
+
        return ERROR_OK;
 }
 
@@ -1237,7 +1239,7 @@ static int aarch64_set_breakpoint(struct target *target,
        struct armv8_common *armv8 = &aarch64->armv8_common;
        struct aarch64_brp *brp_list = aarch64->brp_list;
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                LOG_WARNING("breakpoint already set");
                return ERROR_OK;
        }
@@ -1250,7 +1252,7 @@ static int aarch64_set_breakpoint(struct target *target,
                        LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
-               breakpoint->set = brp_i + 1;
+               breakpoint_hw_set(breakpoint, brp_i);
                if (breakpoint->length == 2)
                        byte_addr_select = (3 << (breakpoint->address & 0x02));
                control = ((matchmode & 0x7) << 20)
@@ -1258,7 +1260,7 @@ static int aarch64_set_breakpoint(struct target *target,
                        | (byte_addr_select << 5)
                        | (3 << 1) | 1;
                brp_list[brp_i].used = 1;
-               brp_list[brp_i].value = breakpoint->address & 0xFFFFFFFFFFFFFFFC;
+               brp_list[brp_i].value = breakpoint->address & 0xFFFFFFFFFFFFFFFCULL;
                brp_list[brp_i].control = control;
                bpt_value = brp_list[brp_i].value;
 
@@ -1310,31 +1312,31 @@ static int aarch64_set_breakpoint(struct target *target,
                buf_set_u32(code, 0, 32, opcode);
 
                retval = target_read_memory(target,
-                               breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+                               breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
                                breakpoint->length, 1,
                                breakpoint->orig_instr);
                if (retval != ERROR_OK)
                        return retval;
 
                armv8_cache_d_inner_flush_virt(armv8,
-                               breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+                               breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
                                breakpoint->length);
 
                retval = target_write_memory(target,
-                               breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+                               breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
                                breakpoint->length, 1, code);
                if (retval != ERROR_OK)
                        return retval;
 
                armv8_cache_d_inner_flush_virt(armv8,
-                               breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+                               breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
                                breakpoint->length);
 
                armv8_cache_i_inner_inval_virt(armv8,
-                               breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+                               breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
                                breakpoint->length);
 
-               breakpoint->set = 0x11; /* Any nice value but 0 */
+               breakpoint->is_set = true;
        }
 
        /* Ensure that halting debug mode is enable */
@@ -1358,7 +1360,7 @@ static int aarch64_set_context_breakpoint(struct target *target,
        struct armv8_common *armv8 = &aarch64->armv8_common;
        struct aarch64_brp *brp_list = aarch64->brp_list;
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                LOG_WARNING("breakpoint already set");
                return retval;
        }
@@ -1372,7 +1374,7 @@ static int aarch64_set_context_breakpoint(struct target *target,
                return ERROR_FAIL;
        }
 
-       breakpoint->set = brp_i + 1;
+       breakpoint_hw_set(breakpoint, brp_i);
        control = ((matchmode & 0x7) << 20)
                | (1 << 13)
                | (byte_addr_select << 5)
@@ -1411,7 +1413,7 @@ static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoin
        struct armv8_common *armv8 = &aarch64->armv8_common;
        struct aarch64_brp *brp_list = aarch64->brp_list;
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                LOG_WARNING("breakpoint already set");
                return retval;
        }
@@ -1436,7 +1438,7 @@ static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoin
                return ERROR_FAIL;
        }
 
-       breakpoint->set = brp_1 + 1;
+       breakpoint_hw_set(breakpoint, brp_1);
        breakpoint->linked_brp = brp_2;
        control_ctx = ((ctx_machmode & 0x7) << 20)
                | (brp_2 << 16)
@@ -1463,7 +1465,7 @@ static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoin
                | (iva_byte_addr_select << 5)
                | (3 << 1) | 1;
        brp_list[brp_2].used = 1;
-       brp_list[brp_2].value = breakpoint->address & 0xFFFFFFFFFFFFFFFC;
+       brp_list[brp_2].value = breakpoint->address & 0xFFFFFFFFFFFFFFFCULL;
        brp_list[brp_2].control = control_iva;
        retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base
                        + CPUV8_DBG_BVR_BASE + 16 * brp_list[brp_2].brpn,
@@ -1491,16 +1493,16 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br
        struct armv8_common *armv8 = &aarch64->armv8_common;
        struct aarch64_brp *brp_list = aarch64->brp_list;
 
-       if (!breakpoint->set) {
+       if (!breakpoint->is_set) {
                LOG_WARNING("breakpoint not set");
                return ERROR_OK;
        }
 
        if (breakpoint->type == BKPT_HARD) {
                if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
-                       int brp_i = breakpoint->set - 1;
+                       int brp_i = breakpoint->number;
                        int brp_j = breakpoint->linked_brp;
-                       if ((brp_i < 0) || (brp_i >= aarch64->brp_num)) {
+                       if (brp_i >= aarch64->brp_num) {
                                LOG_DEBUG("Invalid BRP number in breakpoint");
                                return ERROR_OK;
                        }
@@ -1550,12 +1552,12 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br
                                return retval;
 
                        breakpoint->linked_brp = 0;
-                       breakpoint->set = 0;
+                       breakpoint->is_set = false;
                        return ERROR_OK;
 
                } else {
-                       int brp_i = breakpoint->set - 1;
-                       if ((brp_i < 0) || (brp_i >= aarch64->brp_num)) {
+                       int brp_i = breakpoint->number;
+                       if (brp_i >= aarch64->brp_num) {
                                LOG_DEBUG("Invalid BRP number in breakpoint");
                                return ERROR_OK;
                        }
@@ -1580,39 +1582,39 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br
                                        (uint32_t)brp_list[brp_i].value);
                        if (retval != ERROR_OK)
                                return retval;
-                       breakpoint->set = 0;
+                       breakpoint->is_set = false;
                        return ERROR_OK;
                }
        } else {
                /* restore original instruction (kept in target endianness) */
 
                armv8_cache_d_inner_flush_virt(armv8,
-                               breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+                               breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
                                breakpoint->length);
 
                if (breakpoint->length == 4) {
                        retval = target_write_memory(target,
-                                       breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+                                       breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
                                        4, 1, breakpoint->orig_instr);
                        if (retval != ERROR_OK)
                                return retval;
                } else {
                        retval = target_write_memory(target,
-                                       breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+                                       breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
                                        2, 1, breakpoint->orig_instr);
                        if (retval != ERROR_OK)
                                return retval;
                }
 
                armv8_cache_d_inner_flush_virt(armv8,
-                               breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+                               breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
                                breakpoint->length);
 
                armv8_cache_i_inner_inval_virt(armv8,
-                               breakpoint->address & 0xFFFFFFFFFFFFFFFE,
+                               breakpoint->address & 0xFFFFFFFFFFFFFFFEULL,
                                breakpoint->length);
        }
-       breakpoint->set = 0;
+       breakpoint->is_set = false;
 
        return ERROR_OK;
 }
@@ -1677,7 +1679,7 @@ static int aarch64_remove_breakpoint(struct target *target, struct breakpoint *b
        }
 #endif
 
-       if (breakpoint->set) {
+       if (breakpoint->is_set) {
                aarch64_unset_breakpoint(target, breakpoint);
                if (breakpoint->type == BKPT_HARD)
                        aarch64->brp_num_available++;
@@ -1697,7 +1699,7 @@ static int aarch64_set_watchpoint(struct target *target,
        struct armv8_common *armv8 = &aarch64->armv8_common;
        struct aarch64_brp *wp_list = aarch64->wp_list;
 
-       if (watchpoint->set) {
+       if (watchpoint->is_set) {
                LOG_WARNING("watchpoint already set");
                return ERROR_OK;
        }
@@ -1765,7 +1767,7 @@ static int aarch64_set_watchpoint(struct target *target,
        }
 
        wp_list[wp_i].used = 1;
-       watchpoint->set = wp_i + 1;
+       watchpoint_set(watchpoint, wp_i);
 
        return ERROR_OK;
 }
@@ -1774,18 +1776,18 @@ static int aarch64_set_watchpoint(struct target *target,
 static int aarch64_unset_watchpoint(struct target *target,
        struct watchpoint *watchpoint)
 {
-       int retval, wp_i;
+       int retval;
        struct aarch64_common *aarch64 = target_to_aarch64(target);
        struct armv8_common *armv8 = &aarch64->armv8_common;
        struct aarch64_brp *wp_list = aarch64->wp_list;
 
-       if (!watchpoint->set) {
+       if (!watchpoint->is_set) {
                LOG_WARNING("watchpoint not set");
                return ERROR_OK;
        }
 
-       wp_i = watchpoint->set - 1;
-       if ((wp_i < 0) || (wp_i >= aarch64->wp_num)) {
+       int wp_i = watchpoint->number;
+       if (wp_i >= aarch64->wp_num) {
                LOG_DEBUG("Invalid WP number in watchpoint");
                return ERROR_OK;
        }
@@ -1810,7 +1812,7 @@ static int aarch64_unset_watchpoint(struct target *target,
                        (uint32_t)wp_list[wp_i].value);
        if (retval != ERROR_OK)
                return retval;
-       watchpoint->set = 0;
+       watchpoint->is_set = false;
 
        return ERROR_OK;
 }
@@ -1838,7 +1840,7 @@ static int aarch64_remove_watchpoint(struct target *target,
 {
        struct aarch64_common *aarch64 = target_to_aarch64(target);
 
-       if (watchpoint->set) {
+       if (watchpoint->is_set) {
                aarch64_unset_watchpoint(target, watchpoint);
                aarch64->wp_num_available++;
        }
@@ -1850,7 +1852,7 @@ static int aarch64_remove_watchpoint(struct target *target,
  * find out which watchpoint hits
  * get exception address and compare the address to watchpoints
  */
-int aarch64_hit_watchpoint(struct target *target,
+static int aarch64_hit_watchpoint(struct target *target,
        struct watchpoint **hit_watchpoint)
 {
        if (target->debug_reason != DBG_REASON_WATCHPOINT)
@@ -1943,7 +1945,7 @@ static int aarch64_assert_reset(struct target *target)
        else if (reset_config & RESET_HAS_SRST) {
                bool srst_asserted = false;
 
-               if (target->reset_halt) {
+               if (target->reset_halt && !(reset_config & RESET_SRST_PULLS_TRST)) {
                        if (target_was_examined(target)) {
 
                                if (reset_config & RESET_SRST_NO_GATING) {
@@ -1953,12 +1955,12 @@ static int aarch64_assert_reset(struct target *target)
                                         */
                                        adapter_assert_reset();
                                        srst_asserted = true;
-
-                                       /* make sure to clear all sticky errors */
-                                       mem_ap_write_atomic_u32(armv8->debug_ap,
-                                                       armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE);
                                }
 
+                               /* make sure to clear all sticky errors */
+                               mem_ap_write_atomic_u32(armv8->debug_ap,
+                                               armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE);
+
                                /* set up Reset Catch debug event to halt the CPU after reset */
                                retval = aarch64_enable_reset_catch(target, true);
                                if (retval != ERROR_OK)
@@ -2027,9 +2029,13 @@ static int aarch64_deassert_reset(struct target *target)
                if (target->state != TARGET_HALTED) {
                        LOG_WARNING("%s: ran after reset and before halt ...",
                                target_name(target));
-                       retval = target_halt(target);
-                       if (retval != ERROR_OK)
-                               return retval;
+                       if (target_was_examined(target)) {
+                               retval = aarch64_halt_one(target, HALT_LAZY);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       } else {
+                               target->state = TARGET_UNKNOWN;
+                       }
                }
        }
 
@@ -2044,6 +2050,11 @@ static int aarch64_write_cpu_memory_slow(struct target *target,
        struct arm *arm = &armv8->arm;
        int retval;
 
+       if (size > 4 && arm->core_state != ARM_STATE_AARCH64) {
+               LOG_ERROR("memory write sizes greater than 4 bytes is only supported for AArch64 state");
+               return ERROR_FAIL;
+       }
+
        armv8_reg_current(arm, 1)->dirty = true;
 
        /* change DCC to normal mode if necessary */
@@ -2056,22 +2067,32 @@ static int aarch64_write_cpu_memory_slow(struct target *target,
        }
 
        while (count) {
-               uint32_t data, opcode;
+               uint32_t opcode;
+               uint64_t data;
 
-               /* write the data to store into DTRRX */
+               /* write the data to store into DTRRX (and DTRTX for 64-bit) */
                if (size == 1)
                        data = *buffer;
                else if (size == 2)
                        data = target_buffer_get_u16(target, buffer);
-               else
+               else if (size == 4)
                        data = target_buffer_get_u32(target, buffer);
+               else
+                       data = target_buffer_get_u64(target, buffer);
+
                retval = mem_ap_write_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DTRRX, data);
+                               armv8->debug_base + CPUV8_DBG_DTRRX, (uint32_t)data);
+               if (retval == ERROR_OK && size > 4)
+                       retval = mem_ap_write_atomic_u32(armv8->debug_ap,
+                                       armv8->debug_base + CPUV8_DBG_DTRTX, (uint32_t)(data >> 32));
                if (retval != ERROR_OK)
                        return retval;
 
                if (arm->core_state == ARM_STATE_AARCH64)
-                       retval = dpm->instr_execute(dpm, ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0, 1));
+                       if (size <= 4)
+                               retval = dpm->instr_execute(dpm, ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0, 1));
+                       else
+                               retval = dpm->instr_execute(dpm, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 1));
                else
                        retval = dpm->instr_execute(dpm, ARMV4_5_MRC(14, 0, 1, 0, 5, 0));
                if (retval != ERROR_OK)
@@ -2081,8 +2102,11 @@ static int aarch64_write_cpu_memory_slow(struct target *target,
                        opcode = armv8_opcode(armv8, ARMV8_OPC_STRB_IP);
                else if (size == 2)
                        opcode = armv8_opcode(armv8, ARMV8_OPC_STRH_IP);
-               else
+               else if (size == 4)
                        opcode = armv8_opcode(armv8, ARMV8_OPC_STRW_IP);
+               else
+                       opcode = armv8_opcode(armv8, ARMV8_OPC_STRD_IP);
+
                retval = dpm->instr_execute(dpm, opcode);
                if (retval != ERROR_OK)
                        return retval;
@@ -2140,7 +2164,7 @@ static int aarch64_write_cpu_memory(struct target *target,
        uint32_t dscr;
 
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target not halted");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -2223,6 +2247,11 @@ static int aarch64_read_cpu_memory_slow(struct target *target,
        struct arm *arm = &armv8->arm;
        int retval;
 
+       if (size > 4 && arm->core_state != ARM_STATE_AARCH64) {
+               LOG_ERROR("memory read sizes greater than 4 bytes is only supported for AArch64 state");
+               return ERROR_FAIL;
+       }
+
        armv8_reg_current(arm, 1)->dirty = true;
 
        /* change DCC to normal mode (if necessary) */
@@ -2235,36 +2264,56 @@ static int aarch64_read_cpu_memory_slow(struct target *target,
        }
 
        while (count) {
-               uint32_t opcode, data;
+               uint32_t opcode;
+               uint32_t lower;
+               uint32_t higher;
+               uint64_t data;
 
                if (size == 1)
                        opcode = armv8_opcode(armv8, ARMV8_OPC_LDRB_IP);
                else if (size == 2)
                        opcode = armv8_opcode(armv8, ARMV8_OPC_LDRH_IP);
-               else
+               else if (size == 4)
                        opcode = armv8_opcode(armv8, ARMV8_OPC_LDRW_IP);
+               else
+                       opcode = armv8_opcode(armv8, ARMV8_OPC_LDRD_IP);
+
                retval = dpm->instr_execute(dpm, opcode);
                if (retval != ERROR_OK)
                        return retval;
 
                if (arm->core_state == ARM_STATE_AARCH64)
-                       retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 1));
+                       if (size <= 4)
+                               retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 1));
+                       else
+                               retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 1));
                else
                        retval = dpm->instr_execute(dpm, ARMV4_5_MCR(14, 0, 1, 0, 5, 0));
                if (retval != ERROR_OK)
                        return retval;
 
                retval = mem_ap_read_atomic_u32(armv8->debug_ap,
-                               armv8->debug_base + CPUV8_DBG_DTRTX, &data);
+                               armv8->debug_base + CPUV8_DBG_DTRTX, &lower);
+               if (retval == ERROR_OK) {
+                       if (size > 4)
+                               retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+                                               armv8->debug_base + CPUV8_DBG_DTRRX, &higher);
+                       else
+                               higher = 0;
+               }
                if (retval != ERROR_OK)
                        return retval;
 
+               data = (uint64_t)lower | (uint64_t)higher << 32;
+
                if (size == 1)
                        *buffer = (uint8_t)data;
                else if (size == 2)
                        target_buffer_set_u16(target, buffer, (uint16_t)data);
+               else if (size == 4)
+                       target_buffer_set_u32(target, buffer, (uint32_t)data);
                else
-                       target_buffer_set_u32(target, buffer, data);
+                       target_buffer_set_u64(target, buffer, data);
 
                /* Advance */
                buffer += size;
@@ -2358,7 +2407,7 @@ static int aarch64_read_cpu_memory(struct target *target,
                        address, size, count);
 
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target not halted");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -2555,15 +2604,21 @@ static int aarch64_examine_first(struct target *target)
        if (!pc)
                return ERROR_FAIL;
 
-       if (pc->adiv5_config.ap_num == DP_APSEL_INVALID) {
-               /* Search for the APB-AB */
-               retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv8->debug_ap);
-               if (retval != ERROR_OK) {
-                       LOG_ERROR("Could not find APB-AP for debug access");
-                       return retval;
+       if (!armv8->debug_ap) {
+               if (pc->adiv5_config.ap_num == DP_APSEL_INVALID) {
+                       /* Search for the APB-AB */
+                       retval = dap_find_get_ap(swjdp, AP_TYPE_APB_AP, &armv8->debug_ap);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("Could not find APB-AP for debug access");
+                               return retval;
+                       }
+               } else {
+                       armv8->debug_ap = dap_get_ap(swjdp, pc->adiv5_config.ap_num);
+                       if (!armv8->debug_ap) {
+                               LOG_ERROR("Cannot get AP");
+                               return ERROR_FAIL;
+                       }
                }
-       } else {
-               armv8->debug_ap = dap_ap(swjdp, pc->adiv5_config.ap_num);
        }
 
        retval = mem_ap_init(armv8->debug_ap);
@@ -2575,20 +2630,13 @@ static int aarch64_examine_first(struct target *target)
        armv8->debug_ap->memaccess_tck = 10;
 
        if (!target->dbgbase_set) {
-               target_addr_t dbgbase;
-               /* Get ROM Table base */
-               uint32_t apid;
-               int32_t coreidx = target->coreid;
-               retval = dap_get_debugbase(armv8->debug_ap, &dbgbase, &apid);
-               if (retval != ERROR_OK)
-                       return retval;
                /* Lookup Processor DAP */
-               retval = dap_lookup_cs_component(armv8->debug_ap, dbgbase, ARM_CS_C9_DEVTYPE_CORE_DEBUG,
-                               &armv8->debug_base, &coreidx);
+               retval = dap_lookup_cs_component(armv8->debug_ap, ARM_CS_C9_DEVTYPE_CORE_DEBUG,
+                               &armv8->debug_base, target->coreid);
                if (retval != ERROR_OK)
                        return retval;
-               LOG_DEBUG("Detected core %" PRId32 " dbgbase: " TARGET_ADDR_FMT
-                               " apid: %08" PRIx32, coreidx, armv8->debug_base, apid);
+               LOG_DEBUG("Detected core %" PRId32 " dbgbase: " TARGET_ADDR_FMT,
+                               target->coreid, armv8->debug_base);
        } else
                armv8->debug_base = target->dbgbase;
 
@@ -2699,6 +2747,9 @@ static int aarch64_examine(struct target *target)
        if (retval == ERROR_OK)
                retval = aarch64_init_debug_access(target);
 
+       if (retval == ERROR_OK)
+               retval = aarch64_poll(target);
+
        return retval;
 }
 
@@ -2736,6 +2787,25 @@ static int aarch64_init_arch_info(struct target *target,
        return ERROR_OK;
 }
 
+static int armv8r_target_create(struct target *target, Jim_Interp *interp)
+{
+       struct aarch64_private_config *pc = target->private_config;
+       struct aarch64_common *aarch64;
+
+       if (adiv5_verify_config(&pc->adiv5_config) != ERROR_OK)
+               return ERROR_FAIL;
+
+       aarch64 = calloc(1, sizeof(struct aarch64_common));
+       if (!aarch64) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+
+       aarch64->armv8_common.is_armv8r = true;
+
+       return aarch64_init_arch_info(target, aarch64, pc->adiv5_config.dap);
+}
+
 static int aarch64_target_create(struct target *target, Jim_Interp *interp)
 {
        struct aarch64_private_config *pc = target->private_config;
@@ -2750,6 +2820,8 @@ static int aarch64_target_create(struct target *target, Jim_Interp *interp)
                return ERROR_FAIL;
        }
 
+       aarch64->armv8_common.is_armv8r = false;
+
        return aarch64_init_arch_info(target, aarch64, pc->adiv5_config.dap);
 }
 
@@ -2759,6 +2831,9 @@ static void aarch64_deinit_target(struct target *target)
        struct armv8_common *armv8 = &aarch64->armv8_common;
        struct arm_dpm *dpm = &armv8->dpm;
 
+       if (armv8->debug_ap)
+               dap_put_ap(armv8->debug_ap);
+
        armv8_free_reg_cache(target);
        free(aarch64->brp_list);
        free(dpm->dbp);
@@ -2769,12 +2844,16 @@ static void aarch64_deinit_target(struct target *target)
 
 static int aarch64_mmu(struct target *target, int *enabled)
 {
+       struct aarch64_common *aarch64 = target_to_aarch64(target);
+       struct armv8_common *armv8 = &aarch64->armv8_common;
        if (target->state != TARGET_HALTED) {
-               LOG_ERROR("%s: target %s not halted", __func__, target_name(target));
-               return ERROR_TARGET_INVALID;
+               LOG_TARGET_ERROR(target, "not halted");
+               return ERROR_TARGET_NOT_HALTED;
        }
-
-       *enabled = target_to_aarch64(target)->armv8_common.armv8_mmu.mmu_enabled;
+       if (armv8->is_armv8r)
+               *enabled = 0;
+       else
+               *enabled = target_to_aarch64(target)->armv8_common.armv8_mmu.mmu_enabled;
        return ERROR_OK;
 }
 
@@ -2815,13 +2894,8 @@ static int aarch64_jim_configure(struct target *target, struct jim_getopt_info *
         * options, JIM_OK if it correctly parsed the topmost option
         * and JIM_ERR if an error occurred during parameter evaluation.
         * For JIM_CONTINUE, we check our own params.
-        *
-        * adiv5_jim_configure() assumes 'private_config' to point to
-        * 'struct adiv5_private_config'. Override 'private_config'!
         */
-       target->private_config = &pc->adiv5_config;
-       e = adiv5_jim_configure(target, goi);
-       target->private_config = pc;
+       e = adiv5_jim_configure_ext(target, goi, &pc->adiv5_config, ADI_CONFIGURE_DAP_COMPULSORY);
        if (e != JIM_CONTINUE)
                return e;
 
@@ -2936,15 +3010,15 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command)
        struct target *target = get_current_target(CMD_CTX);
        struct aarch64_common *aarch64 = target_to_aarch64(target);
 
-       static const struct jim_nvp nvp_maskisr_modes[] = {
+       static const struct nvp nvp_maskisr_modes[] = {
                { .name = "off", .value = AARCH64_ISRMASK_OFF },
                { .name = "on", .value = AARCH64_ISRMASK_ON },
                { .name = NULL, .value = -1 },
        };
-       const struct jim_nvp *n;
+       const struct nvp *n;
 
        if (CMD_ARGC > 0) {
-               n = jim_nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
+               n = nvp_name2value(nvp_maskisr_modes, CMD_ARGV[0]);
                if (!n->name) {
                        LOG_ERROR("Unknown parameter: %s - should be off or on", CMD_ARGV[0]);
                        return ERROR_COMMAND_SYNTAX_ERROR;
@@ -2953,59 +3027,49 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command)
                aarch64->isrmasking_mode = n->value;
        }
 
-       n = jim_nvp_value2name_simple(nvp_maskisr_modes, aarch64->isrmasking_mode);
+       n = nvp_value2name(nvp_maskisr_modes, aarch64->isrmasking_mode);
        command_print(CMD, "aarch64 interrupt mask %s", n->name);
 
        return ERROR_OK;
 }
 
-static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+COMMAND_HANDLER(aarch64_mcrmrc_command)
 {
-       struct command *c = jim_to_command(interp);
-       struct command_context *context;
-       struct target *target;
-       struct arm *arm;
-       int retval;
        bool is_mcr = false;
-       int arg_cnt = 0;
+       unsigned int arg_cnt = 5;
 
-       if (!strcmp(c->name, "mcr")) {
+       if (!strcmp(CMD_NAME, "mcr")) {
                is_mcr = true;
-               arg_cnt = 7;
-       } else {
                arg_cnt = 6;
        }
 
-       context = current_command_context(interp);
-       assert(context);
+       if (arg_cnt != CMD_ARGC)
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-       target = get_current_target(context);
+       struct target *target = get_current_target(CMD_CTX);
        if (!target) {
-               LOG_ERROR("%s: no current target", __func__);
-               return JIM_ERR;
+               command_print(CMD, "no current target");
+               return ERROR_FAIL;
        }
        if (!target_was_examined(target)) {
-               LOG_ERROR("%s: not yet examined", target_name(target));
-               return JIM_ERR;
+               command_print(CMD, "%s: not yet examined", target_name(target));
+               return ERROR_TARGET_NOT_EXAMINED;
        }
 
-       arm = target_to_arm(target);
+       struct arm *arm = target_to_arm(target);
        if (!is_arm(arm)) {
-               LOG_ERROR("%s: not an ARM", target_name(target));
-               return JIM_ERR;
+               command_print(CMD, "%s: not an ARM", target_name(target));
+               return ERROR_FAIL;
        }
 
-       if (target->state != TARGET_HALTED)
+       if (target->state != TARGET_HALTED) {
+               command_print(CMD, "Error: [%s] not halted", target_name(target));
                return ERROR_TARGET_NOT_HALTED;
-
-       if (arm->core_state == ARM_STATE_AARCH64) {
-               LOG_ERROR("%s: not 32-bit arm target", target_name(target));
-               return JIM_ERR;
        }
 
-       if (argc != arg_cnt) {
-               LOG_ERROR("%s: wrong number of arguments", __func__);
-               return JIM_ERR;
+       if (arm->core_state == ARM_STATE_AARCH64) {
+               command_print(CMD, "%s: not 32-bit arm target", target_name(target));
+               return ERROR_FAIL;
        }
 
        int cpnum;
@@ -3014,87 +3078,62 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
        uint32_t crn;
        uint32_t crm;
        uint32_t value;
-       long l;
 
        /* NOTE:  parameter sequence matches ARM instruction set usage:
         *      MCR     pNUM, op1, rX, CRn, CRm, op2    ; write CP from rX
         *      MRC     pNUM, op1, rX, CRn, CRm, op2    ; read CP into rX
         * The "rX" is necessarily omitted; it uses Tcl mechanisms.
         */
-       retval = Jim_GetLong(interp, argv[1], &l);
-       if (retval != JIM_OK)
-               return retval;
-       if (l & ~0xf) {
-               LOG_ERROR("%s: %s %d out of range", __func__,
-                       "coprocessor", (int) l);
-               return JIM_ERR;
+       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cpnum);
+       if (cpnum & ~0xf) {
+               command_print(CMD, "coprocessor %d out of range", cpnum);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
-       cpnum = l;
 
-       retval = Jim_GetLong(interp, argv[2], &l);
-       if (retval != JIM_OK)
-               return retval;
-       if (l & ~0x7) {
-               LOG_ERROR("%s: %s %d out of range", __func__,
-                       "op1", (int) l);
-               return JIM_ERR;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], op1);
+       if (op1 & ~0x7) {
+               command_print(CMD, "op1 %d out of range", op1);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
-       op1 = l;
 
-       retval = Jim_GetLong(interp, argv[3], &l);
-       if (retval != JIM_OK)
-               return retval;
-       if (l & ~0xf) {
-               LOG_ERROR("%s: %s %d out of range", __func__,
-                       "CRn", (int) l);
-               return JIM_ERR;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], crn);
+       if (crn & ~0xf) {
+               command_print(CMD, "CRn %d out of range", crn);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
-       crn = l;
 
-       retval = Jim_GetLong(interp, argv[4], &l);
-       if (retval != JIM_OK)
-               return retval;
-       if (l & ~0xf) {
-               LOG_ERROR("%s: %s %d out of range", __func__,
-                       "CRm", (int) l);
-               return JIM_ERR;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], crm);
+       if (crm & ~0xf) {
+               command_print(CMD, "CRm %d out of range", crm);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
-       crm = l;
 
-       retval = Jim_GetLong(interp, argv[5], &l);
-       if (retval != JIM_OK)
-               return retval;
-       if (l & ~0x7) {
-               LOG_ERROR("%s: %s %d out of range", __func__,
-                       "op2", (int) l);
-               return JIM_ERR;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], op2);
+       if (op2 & ~0x7) {
+               command_print(CMD, "op2 %d out of range", op2);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
-       op2 = l;
-
-       value = 0;
 
-       if (is_mcr == true) {
-               retval = Jim_GetLong(interp, argv[6], &l);
-               if (retval != JIM_OK)
-                       return retval;
-               value = l;
+       if (is_mcr) {
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[5], value);
 
                /* NOTE: parameters reordered! */
                /* ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2) */
-               retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value);
+               int retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value);
                if (retval != ERROR_OK)
-                       return JIM_ERR;
+                       return retval;
        } else {
+               value = 0;
                /* NOTE: parameters reordered! */
                /* ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2) */
-               retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value);
+               int retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value);
                if (retval != ERROR_OK)
-                       return JIM_ERR;
+                       return retval;
 
-               Jim_SetResult(interp, Jim_NewIntObj(interp, value));
+               command_print(CMD, "0x%" PRIx32, value);
        }
 
-       return JIM_OK;
+       return ERROR_OK;
 }
 
 static const struct command_registration aarch64_exec_command_handlers[] = {
@@ -3129,14 +3168,14 @@ static const struct command_registration aarch64_exec_command_handlers[] = {
        {
                .name = "mcr",
                .mode = COMMAND_EXEC,
-               .jim_handler = jim_mcrmrc,
+               .handler = aarch64_mcrmrc_command,
                .help = "write coprocessor register",
                .usage = "cpnum op1 CRn CRm op2 value",
        },
        {
                .name = "mrc",
                .mode = COMMAND_EXEC,
-               .jim_handler = jim_mcrmrc,
+               .handler = aarch64_mcrmrc_command,
                .help = "read coprocessor register",
                .usage = "cpnum op1 CRn CRm op2",
        },
@@ -3148,8 +3187,6 @@ static const struct command_registration aarch64_exec_command_handlers[] = {
        COMMAND_REGISTRATION_DONE
 };
 
-extern const struct command_registration semihosting_common_handlers[];
-
 static const struct command_registration aarch64_command_handlers[] = {
        {
                .name = "arm",
@@ -3211,3 +3248,39 @@ struct target_type aarch64_target = {
        .mmu = aarch64_mmu,
        .virt2phys = aarch64_virt2phys,
 };
+
+struct target_type armv8r_target = {
+       .name = "armv8r",
+
+       .poll = aarch64_poll,
+       .arch_state = armv8_arch_state,
+
+       .halt = aarch64_halt,
+       .resume = aarch64_resume,
+       .step = aarch64_step,
+
+       .assert_reset = aarch64_assert_reset,
+       .deassert_reset = aarch64_deassert_reset,
+
+       /* REVISIT allow exporting VFP3 registers ... */
+       .get_gdb_arch = armv8_get_gdb_arch,
+       .get_gdb_reg_list = armv8_get_gdb_reg_list,
+
+       .read_memory = aarch64_read_phys_memory,
+       .write_memory = aarch64_write_phys_memory,
+
+       .add_breakpoint = aarch64_add_breakpoint,
+       .add_context_breakpoint = aarch64_add_context_breakpoint,
+       .add_hybrid_breakpoint = aarch64_add_hybrid_breakpoint,
+       .remove_breakpoint = aarch64_remove_breakpoint,
+       .add_watchpoint = aarch64_add_watchpoint,
+       .remove_watchpoint = aarch64_remove_watchpoint,
+       .hit_watchpoint = aarch64_hit_watchpoint,
+
+       .commands = aarch64_command_handlers,
+       .target_create = armv8r_target_create,
+       .target_jim_configure = aarch64_jim_configure,
+       .init_target = aarch64_init_target,
+       .deinit_target = aarch64_deinit_target,
+       .examine = aarch64_examine,
+};

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)