Merge pull request #1142 from en-sc/en-sc/from_upstream

Merge up to 1173473f66 from upstream
This commit is contained in:
Evgeniy Naydanov 2024-10-08 14:17:57 +03:00 committed by GitHub
commit a4020f1a02
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 233 additions and 158 deletions

View File

@ -2227,7 +2227,7 @@ the port @var{number} defaults to 6666.
When specified as "disabled", this service is not activated. When specified as "disabled", this service is not activated.
@end deffn @end deffn
@deffn {Config Command} {telnet_port} [number] @deffn {Config Command} {telnet port} [number]
Specify or query the Specify or query the
port on which to listen for incoming telnet connections. port on which to listen for incoming telnet connections.
This port is intended for interaction with one human through TCL commands. This port is intended for interaction with one human through TCL commands.

View File

@ -85,6 +85,9 @@
#define SAME_SERIES_51 0x01 #define SAME_SERIES_51 0x01
#define SAME_SERIES_53 0x03 #define SAME_SERIES_53 0x03
#define SAME_SERIES_54 0x04 #define SAME_SERIES_54 0x04
#define PIC32CXSG_SERIES_41 0x07
#define PIC32CXSG_SERIES_60 0x00
#define PIC32CXSG_SERIES_61 0x02
/* Device ID macros */ /* Device ID macros */
#define SAMD_GET_PROCESSOR(id) (id >> 28) #define SAMD_GET_PROCESSOR(id) (id >> 28)
@ -148,6 +151,27 @@ static const struct samd_part same54_parts[] = {
{ 0x03, "SAME54N19A", 512, 192 }, { 0x03, "SAME54N19A", 512, 192 },
}; };
/* See PIC32CX SG41/SG60/SG61 Family Silicon Errata and Datasheet Clarifications
* DS80000985G */
/* Known PIC32CX-SG41 parts. */
static const struct samd_part pic32cxsg41_parts[] = {
{ 0x00, "PIC32CX1025SG41128", 1024, 256 },
{ 0x01, "PIC32CX1025SG41100", 1024, 256 },
{ 0x02, "PIC32CX1025SG41064", 1024, 256 },
};
/* Known PIC32CX-SG60 parts. */
static const struct samd_part pic32cxsg60_parts[] = {
{ 0x00, "PIC32CX1025SG60128", 1024, 256 },
{ 0x01, "PIC32CX1025SG60100", 1024, 256 },
};
/* Known PIC32CX-SG61 parts. */
static const struct samd_part pic32cxsg61_parts[] = {
{ 0x00, "PIC32CX1025SG61128", 1024, 256 },
{ 0x01, "PIC32CX1025SG61100", 1024, 256 },
};
/* Each family of parts contains a parts table in the DEVSEL field of DID. The /* Each family of parts contains a parts table in the DEVSEL field of DID. The
* processor ID, family ID, and series ID are used to determine which exact * processor ID, family ID, and series ID are used to determine which exact
* family this is and then we can use the corresponding table. */ * family this is and then we can use the corresponding table. */
@ -169,6 +193,12 @@ static const struct samd_family samd_families[] = {
same53_parts, ARRAY_SIZE(same53_parts) }, same53_parts, ARRAY_SIZE(same53_parts) },
{ SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_54, { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_54,
same54_parts, ARRAY_SIZE(same54_parts) }, same54_parts, ARRAY_SIZE(same54_parts) },
{ SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_41,
pic32cxsg41_parts, ARRAY_SIZE(pic32cxsg41_parts) },
{ SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_60,
pic32cxsg60_parts, ARRAY_SIZE(pic32cxsg60_parts) },
{ SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_61,
pic32cxsg61_parts, ARRAY_SIZE(pic32cxsg61_parts) },
}; };
struct samd_info { struct samd_info {

View File

@ -57,49 +57,49 @@ void *buf_cpy(const void *from, void *_to, unsigned size)
return _to; return _to;
} }
static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m) static bool buf_eq_masked(uint8_t a, uint8_t b, uint8_t m)
{ {
return (a & m) != (b & m); return (a & m) == (b & m);
} }
static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing) static bool buf_eq_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing)
{ {
uint8_t mask = (1 << trailing) - 1; uint8_t mask = (1 << trailing) - 1;
return buf_cmp_masked(a, b, mask & m); return buf_eq_masked(a, b, mask & m);
} }
bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size) bool buf_eq(const void *_buf1, const void *_buf2, unsigned size)
{ {
if (!_buf1 || !_buf2) if (!_buf1 || !_buf2)
return _buf1 != _buf2; return _buf1 == _buf2;
unsigned last = size / 8; unsigned last = size / 8;
if (memcmp(_buf1, _buf2, last) != 0) if (memcmp(_buf1, _buf2, last) != 0)
return true; return false;
unsigned trailing = size % 8; unsigned trailing = size % 8;
if (!trailing) if (!trailing)
return false; return true;
const uint8_t *buf1 = _buf1, *buf2 = _buf2; const uint8_t *buf1 = _buf1, *buf2 = _buf2;
return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing); return buf_eq_trailing(buf1[last], buf2[last], 0xff, trailing);
} }
bool buf_cmp_mask(const void *_buf1, const void *_buf2, bool buf_eq_mask(const void *_buf1, const void *_buf2,
const void *_mask, unsigned size) const void *_mask, unsigned size)
{ {
if (!_buf1 || !_buf2) if (!_buf1 || !_buf2)
return _buf1 != _buf2 || _buf1 != _mask; return _buf1 == _buf2 && _buf1 == _mask;
const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask; const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask;
unsigned last = size / 8; unsigned last = size / 8;
for (unsigned i = 0; i < last; i++) { for (unsigned i = 0; i < last; i++) {
if (buf_cmp_masked(buf1[i], buf2[i], mask[i])) if (!buf_eq_masked(buf1[i], buf2[i], mask[i]))
return true; return false;
} }
unsigned trailing = size % 8; unsigned trailing = size % 8;
if (!trailing) if (!trailing)
return false; return true;
return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing); return buf_eq_trailing(buf1[last], buf2[last], mask[last], trailing);
} }
void *buf_set_ones(void *_buf, unsigned size) void *buf_set_ones(void *_buf, unsigned size)

View File

@ -172,8 +172,8 @@ static inline uint64_t buf_get_u64(const uint8_t *_buffer,
*/ */
uint32_t flip_u32(uint32_t value, unsigned width); uint32_t flip_u32(uint32_t value, unsigned width);
bool buf_cmp(const void *buf1, const void *buf2, unsigned size); bool buf_eq(const void *buf1, const void *buf2, unsigned size);
bool buf_cmp_mask(const void *buf1, const void *buf2, bool buf_eq_mask(const void *buf1, const void *buf2,
const void *mask, unsigned size); const void *mask, unsigned size);
/** /**

View File

@ -881,9 +881,9 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
int compare_failed; int compare_failed;
if (in_check_mask) if (in_check_mask)
compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits); compare_failed = !buf_eq_mask(captured, in_check_value, in_check_mask, num_bits);
else else
compare_failed = buf_cmp(captured, in_check_value, num_bits); compare_failed = !buf_eq(captured, in_check_value, num_bits);
if (compare_failed) { if (compare_failed) {
char *captured_str, *in_check_value_str; char *captured_str, *in_check_value_str;

View File

@ -32,7 +32,6 @@
struct nuttx_params { struct nuttx_params {
const char *target_name; const char *target_name;
const struct rtos_register_stacking *stacking; const struct rtos_register_stacking *stacking;
const struct rtos_register_stacking *(*select_stackinfo)(struct target *target);
}; };
/* /*
@ -56,19 +55,12 @@ struct symbols {
bool optional; bool optional;
}; };
/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */
enum nuttx_symbol_vals {
NX_SYM_READYTORUN = 0,
NX_SYM_PIDHASH,
NX_SYM_NPIDHASH,
NX_SYM_TCB_INFO,
};
static const struct symbols nuttx_symbol_list[] = { static const struct symbols nuttx_symbol_list[] = {
{ "g_readytorun", false }, { "g_readytorun", false },
{ "g_pidhash", false }, { "g_pidhash", false },
{ "g_npidhash", false }, { "g_npidhash", false },
{ "g_tcbinfo", false }, { "g_tcbinfo", false },
{ "g_reg_offs", false},
{ NULL, false } { NULL, false }
}; };
@ -86,18 +78,14 @@ static char *task_state_str[] = {
"STOPPED", "STOPPED",
}; };
static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target);
static const struct nuttx_params nuttx_params_list[] = { static const struct nuttx_params nuttx_params_list[] = {
{ {
.target_name = "cortex_m", .target_name = "cortex_m",
.stacking = NULL, .stacking = &nuttx_stacking_cortex_m,
.select_stackinfo = cortexm_select_stackinfo,
}, },
{ {
.target_name = "hla_target", .target_name = "hla_target",
.stacking = NULL, .stacking = &nuttx_stacking_cortex_m,
.select_stackinfo = cortexm_select_stackinfo,
}, },
{ {
.target_name = "esp32", .target_name = "esp32",
@ -117,28 +105,6 @@ static const struct nuttx_params nuttx_params_list[] = {
}, },
}; };
static bool cortexm_hasfpu(struct target *target)
{
uint32_t cpacr;
struct armv7m_common *armv7m_target = target_to_armv7m(target);
if (!is_armv7m(armv7m_target) || armv7m_target->fp_feature == FP_NONE)
return false;
int retval = target_read_u32(target, FPU_CPACR, &cpacr);
if (retval != ERROR_OK) {
LOG_ERROR("Could not read CPACR register to check FPU state");
return false;
}
return cpacr & 0x00F00000;
}
static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target)
{
return cortexm_hasfpu(target) ? &nuttx_stacking_cortex_m_fpu : &nuttx_stacking_cortex_m;
}
static bool nuttx_detect_rtos(struct target *target) static bool nuttx_detect_rtos(struct target *target)
{ {
if (target->rtos->symbols && if (target->rtos->symbols &&
@ -371,29 +337,25 @@ static int nuttx_getreg_current_thread(struct rtos *rtos,
static int nuttx_getregs_fromstack(struct rtos *rtos, int64_t thread_id, static int nuttx_getregs_fromstack(struct rtos *rtos, int64_t thread_id,
struct rtos_reg **reg_list, int *num_regs) struct rtos_reg **reg_list, int *num_regs)
{ {
uint16_t xcpreg_off; uint16_t regs_off;
uint32_t regsaddr; uint32_t regsaddr;
const struct nuttx_params *priv = rtos->rtos_specific_params; const struct nuttx_params *priv = rtos->rtos_specific_params;
const struct rtos_register_stacking *stacking = priv->stacking; const struct rtos_register_stacking *stacking = priv->stacking;
if (!stacking) { if (!stacking) {
if (priv->select_stackinfo) { LOG_ERROR("Can't find a way to get stacking info");
stacking = priv->select_stackinfo(rtos->target); return ERROR_FAIL;
} else {
LOG_ERROR("Can't find a way to get stacking info");
return ERROR_FAIL;
}
} }
int ret = target_read_u16(rtos->target, int ret = target_read_u16(rtos->target,
rtos->symbols[NX_SYM_TCB_INFO].address + offsetof(struct tcbinfo, regs_off), rtos->symbols[NX_SYM_TCB_INFO].address + offsetof(struct tcbinfo, regs_off),
&xcpreg_off); &regs_off);
if (ret != ERROR_OK) { if (ret != ERROR_OK) {
LOG_ERROR("Failed to read registers' offset: ret = %d", ret); LOG_ERROR("Failed to read registers' offset: ret = %d", ret);
return ERROR_FAIL; return ERROR_FAIL;
} }
ret = target_read_u32(rtos->target, thread_id + xcpreg_off, &regsaddr); ret = target_read_u32(rtos->target, thread_id + regs_off, &regsaddr);
if (ret != ERROR_OK) { if (ret != ERROR_OK) {
LOG_ERROR("Failed to read registers' address: ret = %d", ret); LOG_ERROR("Failed to read registers' address: ret = %d", ret);
return ERROR_FAIL; return ERROR_FAIL;

View File

@ -9,62 +9,102 @@
#include "rtos_nuttx_stackings.h" #include "rtos_nuttx_stackings.h"
#include "rtos_standard_stackings.h" #include "rtos_standard_stackings.h"
#include <target/riscv/riscv.h> #include <target/riscv/riscv.h>
#include <helper/bits.h>
/* see arch/arm/include/armv7-m/irq_cmnvector.h */ /* The cortex_m target uses nuttx_tcbinfo_stack_read which uses a symbol
* provided by Nuttx to read the registers from memory and place them directly
* in the order we need. This is because the register offsets change with
* different versions of Nuttx, FPU vs non-FPU and ARMv7 vs ARMv8.
* This allows a single function to work with many versions.
*/
static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = { static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = {
{ ARMV7M_R0, 0x28, 32 }, /* r0 */ { ARMV7M_R0, 0, 32 }, /* r0 */
{ ARMV7M_R1, 0x2c, 32 }, /* r1 */ { ARMV7M_R1, 4, 32 }, /* r1 */
{ ARMV7M_R2, 0x30, 32 }, /* r2 */ { ARMV7M_R2, 8, 32 }, /* r2 */
{ ARMV7M_R3, 0x34, 32 }, /* r3 */ { ARMV7M_R3, 12, 32 }, /* r3 */
{ ARMV7M_R4, 0x08, 32 }, /* r4 */ { ARMV7M_R4, 16, 32 }, /* r4 */
{ ARMV7M_R5, 0x0c, 32 }, /* r5 */ { ARMV7M_R5, 20, 32 }, /* r5 */
{ ARMV7M_R6, 0x10, 32 }, /* r6 */ { ARMV7M_R6, 24, 32 }, /* r6 */
{ ARMV7M_R7, 0x14, 32 }, /* r7 */ { ARMV7M_R7, 28, 32 }, /* r7 */
{ ARMV7M_R8, 0x18, 32 }, /* r8 */ { ARMV7M_R8, 32, 32 }, /* r8 */
{ ARMV7M_R9, 0x1c, 32 }, /* r9 */ { ARMV7M_R9, 36, 32 }, /* r9 */
{ ARMV7M_R10, 0x20, 32 }, /* r10 */ { ARMV7M_R10, 40, 32 }, /* r10 */
{ ARMV7M_R11, 0x24, 32 }, /* r11 */ { ARMV7M_R11, 44, 32 }, /* r11 */
{ ARMV7M_R12, 0x38, 32 }, /* r12 */ { ARMV7M_R12, 48, 32 }, /* r12 */
{ ARMV7M_R13, 0, 32 }, /* sp */ { ARMV7M_R13, 52, 32 }, /* sp */
{ ARMV7M_R14, 0x3c, 32 }, /* lr */ { ARMV7M_R14, 56, 32 }, /* lr */
{ ARMV7M_PC, 0x40, 32 }, /* pc */ { ARMV7M_PC, 60, 32 }, /* pc */
{ ARMV7M_XPSR, 0x44, 32 }, /* xPSR */ { ARMV7M_XPSR, 64, 32 }, /* xPSR */
}; };
/* The Nuttx stack frame for most architectures has some registers placed
* by hardware and some by software. The hardware register order and number does not change
* but the software registers may change with different versions of Nuttx.
* For example with ARMv7, nuttx-12.3.0 added a new register which changed all
* the offsets. We can either create separate offset tables for each version of Nuttx
* which will break again in the future, or read the offsets from the TCB info.
* Nuttx provides a symbol (g_reg_offs) which holds all the offsets for each stored register.
* This offset table is stored in GDB org.gnu.gdb.xxx feature order.
* The same order we need.
* Please refer:
* https://sourceware.org/gdb/current/onlinedocs/gdb/ARM-Features.html
* https://sourceware.org/gdb/current/onlinedocs/gdb/RISC_002dV-Features.html
*/
static int nuttx_cortex_m_tcbinfo_stack_read(struct target *target,
int64_t stack_ptr, const struct rtos_register_stacking *stacking,
uint8_t *stack_data)
{
struct rtos *rtos = target->rtos;
target_addr_t xcpreg_off = rtos->symbols[NX_SYM_REG_OFFSETS].address;
for (int i = 0; i < stacking->num_output_registers; ++i) {
uint16_t stack_reg_offset;
int ret = target_read_u16(rtos->target, xcpreg_off + 2 * i, &stack_reg_offset);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to read stack_reg_offset: ret = %d", ret);
return ret;
}
if (stack_reg_offset != UINT16_MAX && stacking->register_offsets[i].offset >= 0) {
ret = target_read_buffer(target,
stack_ptr + stack_reg_offset,
stacking->register_offsets[i].width_bits / 8,
&stack_data[stacking->register_offsets[i].offset]);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to read register: ret = %d", ret);
return ret;
}
}
}
/* Offset match nuttx_stack_offsets_cortex_m */
const int XPSR_OFFSET = 64;
const int SP_OFFSET = 52;
/* Nuttx stack frames (produced in exception_common) store the SP of the ISR minus
* the hardware stack frame size. This SP may include an additional 4 byte alignment
* depending in xPSR[9]. The Nuttx stack frame stores post alignment since the
* hardware will add/remove automatically on both enter/exit.
* We need to adjust the SP to get the real SP of the stack.
* See Arm Reference manual "Stack alignment on exception entry"
*/
uint32_t xpsr = target_buffer_get_u32(target, &stack_data[XPSR_OFFSET]);
if (xpsr & BIT(9)) {
uint32_t sp = target_buffer_get_u32(target, &stack_data[SP_OFFSET]);
target_buffer_set_u32(target, &stack_data[SP_OFFSET], sp - 4 * stacking->stack_growth_direction);
}
return ERROR_OK;
}
const struct rtos_register_stacking nuttx_stacking_cortex_m = { const struct rtos_register_stacking nuttx_stacking_cortex_m = {
.stack_registers_size = 0x48, /* nuttx_tcbinfo_stack_read transforms the stack into just output registers */
.stack_registers_size = ARRAY_SIZE(nuttx_stack_offsets_cortex_m) * 4,
.stack_growth_direction = -1, .stack_growth_direction = -1,
.num_output_registers = 17, .num_output_registers = ARRAY_SIZE(nuttx_stack_offsets_cortex_m),
.read_stack = nuttx_cortex_m_tcbinfo_stack_read,
.calculate_process_stack = NULL, /* Stack alignment done in nuttx_cortex_m_tcbinfo_stack_read */
.register_offsets = nuttx_stack_offsets_cortex_m, .register_offsets = nuttx_stack_offsets_cortex_m,
}; };
static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = {
{ ARMV7M_R0, 0x6c, 32 }, /* r0 */
{ ARMV7M_R1, 0x70, 32 }, /* r1 */
{ ARMV7M_R2, 0x74, 32 }, /* r2 */
{ ARMV7M_R3, 0x78, 32 }, /* r3 */
{ ARMV7M_R4, 0x08, 32 }, /* r4 */
{ ARMV7M_R5, 0x0c, 32 }, /* r5 */
{ ARMV7M_R6, 0x10, 32 }, /* r6 */
{ ARMV7M_R7, 0x14, 32 }, /* r7 */
{ ARMV7M_R8, 0x18, 32 }, /* r8 */
{ ARMV7M_R9, 0x1c, 32 }, /* r9 */
{ ARMV7M_R10, 0x20, 32 }, /* r10 */
{ ARMV7M_R11, 0x24, 32 }, /* r11 */
{ ARMV7M_R12, 0x7c, 32 }, /* r12 */
{ ARMV7M_R13, 0, 32 }, /* sp */
{ ARMV7M_R14, 0x80, 32 }, /* lr */
{ ARMV7M_PC, 0x84, 32 }, /* pc */
{ ARMV7M_XPSR, 0x88, 32 }, /* xPSR */
};
const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = {
.stack_registers_size = 0x8c,
.stack_growth_direction = -1,
.num_output_registers = 17,
.register_offsets = nuttx_stack_offsets_cortex_m_fpu,
};
static const struct stack_register_offset nuttx_stack_offsets_riscv[] = { static const struct stack_register_offset nuttx_stack_offsets_riscv[] = {
{ GDB_REGNO_ZERO, -1, 32 }, { GDB_REGNO_ZERO, -1, 32 },
{ GDB_REGNO_RA, 0x04, 32 }, { GDB_REGNO_RA, 0x04, 32 },

View File

@ -5,6 +5,15 @@
#include "rtos.h" #include "rtos.h"
/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */
enum nuttx_symbol_vals {
NX_SYM_READYTORUN = 0,
NX_SYM_PIDHASH,
NX_SYM_NPIDHASH,
NX_SYM_TCB_INFO,
NX_SYM_REG_OFFSETS,
};
extern const struct rtos_register_stacking nuttx_stacking_cortex_m; extern const struct rtos_register_stacking nuttx_stacking_cortex_m;
extern const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu; extern const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu;
extern const struct rtos_register_stacking nuttx_riscv_stacking; extern const struct rtos_register_stacking nuttx_riscv_stacking;

View File

@ -1838,18 +1838,9 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
return ERROR_FAIL; return ERROR_FAIL;
} }
retval = breakpoint_add(target, address, size, bp_type); retval = breakpoint_add(target, address, size, bp_type);
if (retval == ERROR_NOT_IMPLEMENTED) {
/* Send empty reply to report that breakpoints of this type are not supported */
gdb_put_packet(connection, "", 0);
} else if (retval != ERROR_OK) {
retval = gdb_error(connection, retval);
if (retval != ERROR_OK)
return retval;
} else
gdb_put_packet(connection, "OK", 2);
} else { } else {
breakpoint_remove(target, address); assert(packet[0] == 'z');
gdb_put_packet(connection, "OK", 2); retval = breakpoint_remove(target, address);
} }
break; break;
case 2: case 2:
@ -1858,26 +1849,26 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
{ {
if (packet[0] == 'Z') { if (packet[0] == 'Z') {
retval = watchpoint_add(target, address, size, wp_type, 0, WATCHPOINT_IGNORE_DATA_VALUE_MASK); retval = watchpoint_add(target, address, size, wp_type, 0, WATCHPOINT_IGNORE_DATA_VALUE_MASK);
if (retval == ERROR_NOT_IMPLEMENTED) {
/* Send empty reply to report that watchpoints of this type are not supported */
gdb_put_packet(connection, "", 0);
} else if (retval != ERROR_OK) {
retval = gdb_error(connection, retval);
if (retval != ERROR_OK)
return retval;
} else
gdb_put_packet(connection, "OK", 2);
} else { } else {
watchpoint_remove(target, address); assert(packet[0] == 'z');
gdb_put_packet(connection, "OK", 2); retval = watchpoint_remove(target, address);
} }
break; break;
} }
default: default:
{
retval = ERROR_NOT_IMPLEMENTED;
break; break;
}
} }
return ERROR_OK; if (retval == ERROR_NOT_IMPLEMENTED) {
/* Send empty reply to report that watchpoints of this type are not supported */
return gdb_put_packet(connection, "", 0);
}
if (retval != ERROR_OK)
return gdb_error(connection, retval);
return gdb_put_packet(connection, "OK", 2);
} }
/* print out a string and allocate more space as needed, /* print out a string and allocate more space as needed,

View File

@ -113,3 +113,9 @@ proc "tcl_trace" {state} {
echo "DEPRECATED! use 'tcl trace' not 'tcl_trace'" echo "DEPRECATED! use 'tcl trace' not 'tcl_trace'"
eval tcl trace $state eval tcl trace $state
} }
lappend _telnet_autocomplete_skip "telnet_port"
proc "telnet_port" {args} {
echo "DEPRECATED! use 'telnet port', not 'telnet_port'"
eval telnet port $args
}

View File

@ -967,7 +967,6 @@ int telnet_init(char *banner)
return ERROR_OK; return ERROR_OK;
} }
/* daemon configuration command telnet_port */
COMMAND_HANDLER(handle_telnet_port_command) COMMAND_HANDLER(handle_telnet_port_command)
{ {
return CALL_COMMAND_HANDLER(server_pipe_command, &telnet_port); return CALL_COMMAND_HANDLER(server_pipe_command, &telnet_port);
@ -978,6 +977,19 @@ COMMAND_HANDLER(handle_exit_command)
return ERROR_COMMAND_CLOSE_CONNECTION; return ERROR_COMMAND_CLOSE_CONNECTION;
} }
static const struct command_registration telnet_subcommand_handlers[] = {
{
.name = "port",
.handler = handle_telnet_port_command,
.mode = COMMAND_CONFIG,
.help = "Specify port on which to listen "
"for incoming telnet connections. "
"Read help on 'gdb port'.",
.usage = "[port_num]",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration telnet_command_handlers[] = { static const struct command_registration telnet_command_handlers[] = {
{ {
.name = "exit", .name = "exit",
@ -987,13 +999,11 @@ static const struct command_registration telnet_command_handlers[] = {
.help = "exit telnet session", .help = "exit telnet session",
}, },
{ {
.name = "telnet_port", .name = "telnet",
.handler = handle_telnet_port_command, .chain = telnet_subcommand_handlers,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "Specify port on which to listen " .help = "telnet commands",
"for incoming telnet connections. " .usage = "",
"Read help on 'gdb port'.",
.usage = "[port_num]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@ -932,7 +932,7 @@ static int svf_check_tdo(void)
index_var = svf_check_tdo_para[i].buffer_offset; index_var = svf_check_tdo_para[i].buffer_offset;
len = svf_check_tdo_para[i].bit_len; len = svf_check_tdo_para[i].bit_len;
if ((svf_check_tdo_para[i].enabled) if ((svf_check_tdo_para[i].enabled)
&& buf_cmp_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], && !buf_eq_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var],
&svf_mask_buffer[index_var], len)) { &svf_mask_buffer[index_var], len)) {
LOG_ERROR("tdo check error at line %d", LOG_ERROR("tdo check error at line %d",
svf_check_tdo_para[i].line_num); svf_check_tdo_para[i].line_num);

View File

@ -193,6 +193,20 @@ static int aarch64_mmu_modify(struct target *target, int enable)
return retval; return retval;
} }
static int aarch64_read_prsr(struct target *target, uint32_t *prsr)
{
struct armv8_common *armv8 = target_to_armv8(target);
int retval;
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
armv8->debug_base + CPUV8_DBG_PRSR, prsr);
if (retval != ERROR_OK)
return retval;
armv8->sticky_reset |= *prsr & PRSR_SR;
return ERROR_OK;
}
/* /*
* Basic debug access, very low level assumes state is saved * Basic debug access, very low level assumes state is saved
*/ */
@ -213,8 +227,7 @@ static int aarch64_init_debug_access(struct target *target)
/* Clear Sticky Power Down status Bit in PRSR to enable access to /* Clear Sticky Power Down status Bit in PRSR to enable access to
the registers in the Core Power Domain */ the registers in the Core Power Domain */
retval = mem_ap_read_atomic_u32(armv8->debug_ap, retval = aarch64_read_prsr(target, &dummy);
armv8->debug_base + CPUV8_DBG_PRSR, &dummy);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -281,12 +294,10 @@ static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask,
static int aarch64_check_state_one(struct target *target, static int aarch64_check_state_one(struct target *target,
uint32_t mask, uint32_t val, int *p_result, uint32_t *p_prsr) uint32_t mask, uint32_t val, int *p_result, uint32_t *p_prsr)
{ {
struct armv8_common *armv8 = target_to_armv8(target);
uint32_t prsr; uint32_t prsr;
int retval; int retval;
retval = mem_ap_read_atomic_u32(armv8->debug_ap, retval = aarch64_read_prsr(target, &prsr);
armv8->debug_base + CPUV8_DBG_PRSR, &prsr);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
@ -506,16 +517,28 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug
static int aarch64_poll(struct target *target) static int aarch64_poll(struct target *target)
{ {
struct armv8_common *armv8 = target_to_armv8(target);
enum target_state prev_target_state; enum target_state prev_target_state;
int retval = ERROR_OK; int retval = ERROR_OK;
int halted; uint32_t prsr;
retval = aarch64_check_state_one(target, retval = aarch64_read_prsr(target, &prsr);
PRSR_HALT, PRSR_HALT, &halted, NULL);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
if (halted) { if (armv8->sticky_reset) {
armv8->sticky_reset = false;
if (target->state != TARGET_RESET) {
target->state = TARGET_RESET;
LOG_TARGET_INFO(target, "external reset detected");
if (armv8->arm.core_cache) {
register_cache_invalidate(armv8->arm.core_cache);
register_cache_invalidate(armv8->arm.core_cache->next);
}
}
}
if (prsr & PRSR_HALT) {
prev_target_state = target->state; prev_target_state = target->state;
if (prev_target_state != TARGET_HALTED) { if (prev_target_state != TARGET_HALTED) {
enum target_debug_reason debug_reason = target->debug_reason; enum target_debug_reason debug_reason = target->debug_reason;
@ -546,8 +569,11 @@ static int aarch64_poll(struct target *target)
break; break;
} }
} }
} else } else if (prsr & PRSR_RESET) {
target->state = TARGET_RESET;
} else {
target->state = TARGET_RUNNING; target->state = TARGET_RUNNING;
}
return retval; return retval;
} }
@ -663,8 +689,7 @@ static int aarch64_prepare_restart_one(struct target *target)
if (retval == ERROR_OK) { if (retval == ERROR_OK) {
/* clear sticky bits in PRSR, SDR is now 0 */ /* clear sticky bits in PRSR, SDR is now 0 */
retval = mem_ap_read_atomic_u32(armv8->debug_ap, retval = aarch64_read_prsr(target, &tmp);
armv8->debug_base + CPUV8_DBG_PRSR, &tmp);
} }
return retval; return retval;

View File

@ -213,6 +213,8 @@ struct armv8_common {
/* True if OpenOCD provides pointer auth related info to GDB */ /* True if OpenOCD provides pointer auth related info to GDB */
bool enable_pauth; bool enable_pauth;
bool sticky_reset;
/* last run-control command issued to this target (resume, halt, step) */ /* last run-control command issued to this target (resume, halt, step) */
enum run_control_op last_run_control_op; enum run_control_op last_run_control_op;

View File

@ -357,8 +357,8 @@ static void select_dmi(struct target *target)
select_dmi_via_bscan(target); select_dmi_via_bscan(target);
return; return;
} }
if (buf_cmp(target->tap->cur_instr, select_dbus.out_value, if (buf_eq(target->tap->cur_instr, select_dbus.out_value,
target->tap->ir_length) == 0) target->tap->ir_length))
return; return;
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
} }