xtensa: introduce support for GDB stub

This adds basic support for GDB stub on Xtensa. Note that
this only provides the common bits on the architecture side.
SoC support is also required to fully enable GDB stub on
each Xtensa SoC.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2021-10-26 12:58:21 -07:00 committed by Anas Nashif
commit dc34f6c84d
7 changed files with 1199 additions and 0 deletions

View file

@ -27,6 +27,7 @@
#include <arch/xtensa/irq.h>
#include <xtensa/config/core.h>
#include <arch/common/addr_types.h>
#include <arch/xtensa/gdbstub.h>
#ifdef CONFIG_KERNEL_COHERENCE
#define ARCH_STACK_PTR_ALIGN XCHAL_DCACHE_LINESIZE

View file

@ -0,0 +1,168 @@
/*
* Copyright (c) 2021 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <inttypes.h>
#ifndef ZEPHYR_INCLUDE_ARCH_XTENSA_GDBSTUB_SYS_H_
#define ZEPHYR_INCLUDE_ARCH_XTENSA_GDBSTUB_SYS_H_
#ifdef CONFIG_GDBSTUB
#define XTREG_GRP_MASK 0x0F00
#define XTREG_GRP_GENERAL 0x0000
#define XTREG_GRP_ADDR 0x0100
#define XTREG_GRP_SPECIAL 0x0200
#define XTREG_GRP_USER 0x0300
/*
* Register description fot GDB stub.
*
* Values are based on gdb/gdb/xtensa-config.c in the Xtensa overlay,
* where registers are defined using XTREG() macro:
* XTREG(index,ofs,bsz,sz,al,tnum,flg,cp,ty,gr,name,fet,sto,mas,ct,x,y)
*
* Translation:
* idx : index
* regno : tnum
* 0x00xx : General Registers (A0 - A15, PC)
* 0x01xx : Address Registers (AR0 - AR31/AR63)
* 0x02xx : Special Registers (access via RSR/WSR)
* 0x03xx : User Registers (access via RUR/WUR)
* byte_size : sz
* gpkt_offset : ofs
*/
struct xtensa_register {
/* Register value */
uint32_t val;
/* GDB register index (for p/P packets) */
uint8_t idx;
/* Size of register */
uint8_t byte_size;
/* Xtensa register number */
uint16_t regno;
/* Offset of this register in GDB G-packet.
* -1 if register is not in G-packet.
*/
int16_t gpkt_offset;
/* Offset of saved register in stack frame.
* 0 if not saved in stack frame.
*/
int8_t stack_offset;
/* Sequence number */
uint8_t seqno;
/* Set 1 to if register should not be written
* to during debugging.
*/
uint8_t is_read_only:1;
};
/* Due to Xtensa SoCs being highly configurable,
* the register files between SoCs are not identical.
*
* This means generic registers can, sometimes, have
* different offsets from start of register files
* needed to communicate with GDB.
*
* Therefore, it is better to defer to the SoC layer
* for proper support for GDB.
*/
#include <gdbstub/soc.h>
struct gdb_ctx {
/* Exception reason */
unsigned int exception;
/* Register descriptions */
struct xtensa_register *regs;
/* Number of registers */
uint8_t num_regs;
/* Sequence number */
uint8_t seqno;
/* Index in register descriptions of A0 register */
uint8_t a0_idx;
/* Index in register descriptions of AR0 register */
uint8_t ar_idx;
/* Index in register descriptions of WINDOWBASE register */
uint8_t wb_idx;
};
/**
* Test if the register is a logical address register (A0 - A15).
*
* @retval true if register is A0 - A15
* @retval false if register is not A0 - A15
*/
static inline bool gdb_xtensa_is_logical_addr_reg(struct xtensa_register *reg)
{
if (reg->regno < 16) {
return true;
} else {
return false;
}
}
/**
* Test if the register is a address register (AR0 - AR31/AR63).
*
* @retval true if register is AR0 - AR31/AR63
* @retval false if not
*/
static inline bool gdb_xtensa_is_address_reg(struct xtensa_register *reg)
{
if ((reg->regno & XTREG_GRP_MASK) == XTREG_GRP_ADDR) {
return true;
} else {
return false;
}
}
/**
* Test if the register is a special register that needs to be
* accessed via RSR/WSR.
*
* @retval true if special register
* @retval false if not
*/
static inline bool gdb_xtensa_is_special_reg(struct xtensa_register *reg)
{
if ((reg->regno & XTREG_GRP_MASK) == XTREG_GRP_SPECIAL) {
return true;
} else {
return false;
}
}
/**
* Test if the register is a user register that needs to be
* accessed via RUR/WUR.
*
* @retval true if user register
* @retval false if not
*/
static inline bool gdb_xtensa_is_user_reg(struct xtensa_register *reg)
{
if ((reg->regno & XTREG_GRP_MASK) == XTREG_GRP_USER) {
return true;
} else {
return false;
}
}
#endif /* CONFIG_GDBSTUB */
#endif /* ZEPHYR_INCLUDE_ARCH_XTENSA_GDBSTUB_SYS_H_ */