+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
/***************************************************************************
* Generic Xtensa target *
+ * Copyright (C) 2020-2022 Cadence Design Systems, Inc. *
* Copyright (C) 2019 Espressif Systems Ltd. *
- * Author: Alexey Gerenkov <alexey@espressif.com> *
- * *
- * 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, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_TARGET_XTENSA_H
* Holds the interface to Xtensa cores.
*/
-#define XT_ISNS_SZ_MAX 3
-
-#define XT_PS_RING(_v_) ((uint32_t)((_v_) & 0x3) << 6)
-#define XT_PS_RING_MSK (0x3 << 6)
-#define XT_PS_RING_GET(_v_) (((_v_) >> 6) & 0x3)
-#define XT_PS_CALLINC_MSK (0x3 << 16)
-#define XT_PS_OWB_MSK (0xF << 8)
-
-#define XT_LOCAL_MEM_REGIONS_NUM_MAX 8
+/* Big-endian vs. little-endian detection */
+#define XT_ISBE(X) ((X)->target->endianness == TARGET_BIG_ENDIAN)
+
+/* 24-bit break; BE version field-swapped then byte-swapped for use in memory R/W fns */
+#define XT_INS_BREAK_LE(S, T) (0x004000 | (((S) & 0xF) << 8) | (((T) & 0xF) << 4))
+#define XT_INS_BREAK_BE(S, T) (0x000400 | (((S) & 0xF) << 12) | ((T) & 0xF))
+#define XT_INS_BREAK(X, S, T) (XT_ISBE(X) ? XT_INS_BREAK_BE(S, T) : XT_INS_BREAK_LE(S, T))
+
+/* 16-bit break; BE version field-swapped then byte-swapped for use in memory R/W fns */
+#define XT_INS_BREAKN_LE(IMM4) (0xF02D | (((IMM4) & 0xF) << 8))
+#define XT_INS_BREAKN_BE(IMM4) (0x0FD2 | (((IMM4) & 0xF) << 12))
+#define XT_INS_BREAKN(X, IMM4) (XT_ISBE(X) ? XT_INS_BREAKN_BE(IMM4) : XT_INS_BREAKN_LE(IMM4))
+
+#define XT_ISNS_SZ_MAX 3
+
+/* PS register bits (LX) */
+#define XT_PS_RING(_v_) ((uint32_t)((_v_) & 0x3) << 6)
+#define XT_PS_RING_MSK (0x3 << 6)
+#define XT_PS_RING_GET(_v_) (((_v_) >> 6) & 0x3)
+#define XT_PS_CALLINC_MSK (0x3 << 16)
+#define XT_PS_OWB_MSK (0xF << 8)
+#define XT_PS_WOE_MSK BIT(18)
+
+/* PS register bits (NX) */
+#define XT_PS_DIEXC_MSK BIT(2)
+
+/* MS register bits (NX) */
+#define XT_MS_DE_MSK BIT(5)
+#define XT_MS_DISPST_MSK (0x1f)
+#define XT_MS_DISPST_DBG (0x10)
+
+/* WB register bits (NX) */
+#define XT_WB_P_SHIFT (0)
+#define XT_WB_P_MSK (0x7U << XT_WB_P_SHIFT)
+#define XT_WB_C_SHIFT (4)
+#define XT_WB_C_MSK (0x7U << XT_WB_C_SHIFT)
+#define XT_WB_N_SHIFT (8)
+#define XT_WB_N_MSK (0x7U << XT_WB_N_SHIFT)
+#define XT_WB_S_SHIFT (30)
+#define XT_WB_S_MSK (0x3U << XT_WB_S_SHIFT)
+
+/* IBREAKC register bits (NX) */
+#define XT_IBREAKC_FB (0x80000000)
+
+/* Definitions for imprecise exception registers (NX) */
+#define XT_IMPR_EXC_MSK (0x00000013)
+#define XT_MESRCLR_IMPR_EXC_MSK (0x00000090)
+
+#define XT_LOCAL_MEM_REGIONS_NUM_MAX 8
+
+#define XT_AREGS_NUM_MAX 64
+#define XT_USER_REGS_NUM_MAX 256
+
+#define XT_MEM_ACCESS_NONE 0x0
+#define XT_MEM_ACCESS_READ 0x1
+#define XT_MEM_ACCESS_WRITE 0x2
+
+#define XT_MAX_TIE_REG_WIDTH (512) /* TIE register file max 4096 bits */
+#define XT_QUERYPKT_RESP_MAX (XT_MAX_TIE_REG_WIDTH * 2 + 1)
+
+enum xtensa_qerr_e {
+ XT_QERR_INTERNAL = 0,
+ XT_QERR_FAIL,
+ XT_QERR_INVAL,
+ XT_QERR_MEM,
+ XT_QERR_NUM,
+};
-#define XT_AREGS_NUM_MAX 64
-#define XT_USER_REGS_NUM_MAX 256
+/* An and ARn registers potentially used as scratch regs */
+enum xtensa_ar_scratch_set_e {
+ XT_AR_SCRATCH_A3 = 0,
+ XT_AR_SCRATCH_AR3,
+ XT_AR_SCRATCH_A4,
+ XT_AR_SCRATCH_AR4,
+ XT_AR_SCRATCH_NUM
+};
-#define XT_MEM_ACCESS_NONE 0x0
-#define XT_MEM_ACCESS_READ 0x1
-#define XT_MEM_ACCESS_WRITE 0x2
+struct xtensa_keyval_info_s {
+ char *chrval;
+ int intval;
+};
-enum xtensa_mem_err_detect {
- XT_MEM_ERR_DETECT_NONE,
- XT_MEM_ERR_DETECT_PARITY,
- XT_MEM_ERR_DETECT_ECC,
+enum xtensa_type {
+ XT_UNDEF = 0,
+ XT_LX,
+ XT_NX,
};
struct xtensa_cache_config {
uint8_t way_count;
- uint8_t line_size;
- uint16_t size;
- bool writeback;
- enum xtensa_mem_err_detect mem_err_check;
+ uint32_t line_size;
+ uint32_t size;
+ int writeback;
};
struct xtensa_local_mem_region_config {
target_addr_t base;
uint32_t size;
- enum xtensa_mem_err_detect mem_err_check;
int access;
};
bool enabled;
uint8_t itlb_entries_count;
uint8_t dtlb_entries_count;
- bool ivarway56;
- bool dvarway56;
};
-struct xtensa_exception_config {
+struct xtensa_mpu_config {
bool enabled;
- uint8_t depc_num;
+ uint8_t nfgseg;
+ uint32_t minsegsize;
+ bool lockable;
+ bool execonly;
};
struct xtensa_irq_config {
struct xtensa_high_prio_irq_config {
bool enabled;
+ uint8_t level_num;
uint8_t excm_level;
- uint8_t nmi_num;
};
struct xtensa_debug_config {
uint8_t irq_level;
uint8_t ibreaks_num;
uint8_t dbreaks_num;
- uint8_t icount_sz;
+ uint8_t perfcount_num;
};
struct xtensa_tracing_config {
bool reversed_mem_access;
};
-struct xtensa_timer_irq_config {
- bool enabled;
- uint8_t comp_num;
-};
-
struct xtensa_config {
- bool density;
+ enum xtensa_type core_type;
uint8_t aregs_num;
bool windowed;
bool coproc;
- bool fp_coproc;
- bool loop;
- uint8_t miscregs_num;
- bool threadptr;
- bool boolean;
- bool cond_store;
- bool ext_l32r;
- bool mac16;
- bool reloc_vec;
- bool proc_id;
- bool mem_err_check;
- uint16_t user_regs_num;
- const struct xtensa_user_reg_desc *user_regs;
- int (*fetch_user_regs)(struct target *target);
- int (*queue_write_dirty_user_regs)(struct target *target);
+ bool exceptions;
+ struct xtensa_irq_config irq;
+ struct xtensa_high_prio_irq_config high_irq;
+ struct xtensa_mmu_config mmu;
+ struct xtensa_mpu_config mpu;
+ struct xtensa_debug_config debug;
+ struct xtensa_tracing_config trace;
struct xtensa_cache_config icache;
struct xtensa_cache_config dcache;
struct xtensa_local_mem_config irom;
struct xtensa_local_mem_config iram;
struct xtensa_local_mem_config drom;
struct xtensa_local_mem_config dram;
- struct xtensa_local_mem_config uram;
- struct xtensa_local_mem_config xlmi;
- struct xtensa_mmu_config mmu;
- struct xtensa_exception_config exc;
- struct xtensa_irq_config irq;
- struct xtensa_high_prio_irq_config high_irq;
- struct xtensa_timer_irq_config tim_irq;
- struct xtensa_debug_config debug;
- struct xtensa_tracing_config trace;
- unsigned int gdb_general_regs_num;
- const unsigned int *gdb_regs_mapping;
+ struct xtensa_local_mem_config sram;
+ struct xtensa_local_mem_config srom;
};
typedef uint32_t xtensa_insn_t;
XT_STEPPING_ISR_ON, /* interrupts are enabled during stepping */
};
+enum xtensa_nx_reg_idx {
+ XT_NX_REG_IDX_IBREAKC0 = 0,
+ XT_NX_REG_IDX_WB,
+ XT_NX_REG_IDX_MS,
+ XT_NX_REG_IDX_IEVEC, /* IEVEC, IEEXTERN, and MESR must be contiguous */
+ XT_NX_REG_IDX_IEEXTERN,
+ XT_NX_REG_IDX_MESR,
+ XT_NX_REG_IDX_MESRCLR,
+ XT_NX_REG_IDX_NUM
+};
+
/* Only supported in cores with in-CPU MMU. None of Espressif chips as of now. */
enum xtensa_mode {
XT_MODE_RING0,
uint8_t insn_sz; /* 2 or 3 bytes */
};
+/**
+ * Xtensa algorithm data.
+ */
+struct xtensa_algorithm {
+ /** User can set this to specify which core mode algorithm should be run in. */
+ enum xtensa_mode core_mode;
+ /** Used internally to backup and restore core state. */
+ enum target_debug_reason ctx_debug_reason;
+ xtensa_reg_val_t ctx_ps;
+};
+
#define XTENSA_COMMON_MAGIC 0x54E4E555U
/**
*/
struct xtensa {
unsigned int common_magic;
- const struct xtensa_config *core_config;
+ struct xtensa_chip_common *xtensa_chip;
+ struct xtensa_config *core_config;
struct xtensa_debug_module dbg_mod;
struct reg_cache *core_cache;
- unsigned int regs_num;
+ unsigned int total_regs_num;
+ unsigned int core_regs_num;
+ bool regmap_contiguous;
+ unsigned int genpkt_regs_num;
+ struct xtensa_reg_desc **contiguous_regs_desc;
+ struct reg **contiguous_regs_list;
+ /* Per-config Xtensa registers as specified via "xtreg" in xtensa-core*.cfg */
+ struct xtensa_reg_desc *optregs;
+ unsigned int num_optregs;
+ struct reg *empty_regs;
+ char qpkt_resp[XT_QUERYPKT_RESP_MAX];
/* An array of pointers to buffers to backup registers' values while algo is run on target.
* Size is 'regs_num'. */
void **algo_context_backup;
+ unsigned int eps_dbglevel_idx;
+ unsigned int dbregs_num;
struct target *target;
bool reset_asserted;
enum xtensa_stepping_isr_mode stepping_isr_mode;
bool permissive_mode; /* bypass memory checks */
bool suppress_dsr_errors;
uint32_t smp_break;
+ uint32_t spill_loc;
+ unsigned int spill_bytes;
+ uint8_t *spill_buf;
+ int8_t probe_lsddr32p;
/* Sometimes debug module's 'powered' bit is cleared after reset, but get set after some
* time.This is the number of polling periods after which core is considered to be powered
* off (marked as unexamined) if the bit retains to be cleared (e.g. if core is disabled by
* SW running on target).*/
uint8_t come_online_probes_num;
+ bool proc_syscall;
+ bool halt_request;
+ uint32_t nx_stop_cause;
+ uint32_t nx_reg_idx[XT_NX_REG_IDX_NUM];
+ struct xtensa_keyval_info_s scratch_ars[XT_AR_SCRATCH_NUM];
bool regs_fetched; /* true after first register fetch completed successfully */
};
int xtensa_init_arch_info(struct target *target,
struct xtensa *xtensa,
- const struct xtensa_config *cfg,
const struct xtensa_debug_module_config *dm_cfg);
int xtensa_target_init(struct command_context *cmd_ctx, struct target *target);
void xtensa_target_deinit(struct target *target);
return true;
if (xtensa_addr_in_mem(&xtensa->core_config->dram, addr))
return true;
- if (xtensa_addr_in_mem(&xtensa->core_config->uram, addr))
+ if (xtensa_addr_in_mem(&xtensa->core_config->sram, addr))
return true;
return false;
}
+static inline int xtensa_queue_dbg_reg_read(struct xtensa *xtensa, enum xtensa_dm_reg reg, uint8_t *data)
+{
+ struct xtensa_debug_module *dm = &xtensa->dbg_mod;
+
+ if (!xtensa->core_config->trace.enabled &&
+ (reg <= XDMREG_MEMADDREND || (reg >= XDMREG_PMG && reg <= XDMREG_PMSTAT7))) {
+ LOG_ERROR("Can not access %u reg when Trace Port option disabled!", reg);
+ return ERROR_FAIL;
+ }
+ return dm->dbg_ops->queue_reg_read(dm, reg, data);
+}
+
+static inline int xtensa_queue_dbg_reg_write(struct xtensa *xtensa, enum xtensa_dm_reg reg, uint32_t data)
+{
+ struct xtensa_debug_module *dm = &xtensa->dbg_mod;
+
+ if (!xtensa->core_config->trace.enabled &&
+ (reg <= XDMREG_MEMADDREND || (reg >= XDMREG_PMG && reg <= XDMREG_PMSTAT7))) {
+ LOG_ERROR("Can not access %u reg when Trace Port option disabled!", reg);
+ return ERROR_FAIL;
+ }
+ return dm->dbg_ops->queue_reg_write(dm, reg, data);
+}
+
+static inline int xtensa_core_status_clear(struct target *target, uint32_t bits)
+{
+ struct xtensa *xtensa = target_to_xtensa(target);
+ return xtensa_dm_core_status_clear(&xtensa->dbg_mod, bits);
+}
+
int xtensa_core_status_check(struct target *target);
int xtensa_examine(struct target *target);
int xtensa_smpbreak_read(struct xtensa *xtensa, uint32_t *val);
xtensa_reg_val_t xtensa_reg_get(struct target *target, enum xtensa_reg_id reg_id);
void xtensa_reg_set(struct target *target, enum xtensa_reg_id reg_id, xtensa_reg_val_t value);
+void xtensa_reg_set_deep_relgen(struct target *target, enum xtensa_reg_id a_idx, xtensa_reg_val_t value);
int xtensa_fetch_all_regs(struct target *target);
int xtensa_get_gdb_reg_list(struct target *target,
struct reg **reg_list[],
int *reg_list_size,
enum target_register_class reg_class);
+uint32_t xtensa_cause_get(struct target *target);
+void xtensa_cause_clear(struct target *target);
+void xtensa_cause_reset(struct target *target);
int xtensa_poll(struct target *target);
void xtensa_on_poll(struct target *target);
int xtensa_halt(struct target *target);
int xtensa_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum);
int xtensa_assert_reset(struct target *target);
int xtensa_deassert_reset(struct target *target);
+int xtensa_soft_reset_halt(struct target *target);
int xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint);
int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint);
int xtensa_watchpoint_add(struct target *target, struct watchpoint *watchpoint);
int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoint);
+int xtensa_start_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ target_addr_t entry_point, target_addr_t exit_point,
+ void *arch_info);
+int xtensa_wait_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ target_addr_t exit_point, unsigned int timeout_ms,
+ void *arch_info);
+int xtensa_run_algorithm(struct target *target,
+ int num_mem_params, struct mem_param *mem_params,
+ int num_reg_params, struct reg_param *reg_params,
+ target_addr_t entry_point, target_addr_t exit_point,
+ unsigned int timeout_ms, void *arch_info);
void xtensa_set_permissive_mode(struct target *target, bool state);
-int xtensa_fetch_user_regs_u32(struct target *target);
-int xtensa_queue_write_dirty_user_regs_u32(struct target *target);
-const char *xtensa_get_gdb_arch(struct target *target);
+const char *xtensa_get_gdb_arch(const struct target *target);
+int xtensa_gdb_query_custom(struct target *target, const char *packet, char **response_p);
+
+COMMAND_HELPER(xtensa_cmd_xtdef_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtopt_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtmem_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtmpu_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtmmu_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtregfmt_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_permissive_mode_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_mask_interrupts_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_smpbreak_do, struct target *target);
+COMMAND_HELPER(xtensa_cmd_perfmon_dump_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_perfmon_enable_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_tracestart_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_tracestop_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_tracedump_do, struct xtensa *xtensa, const char *fname);
-extern const struct reg_arch_type xtensa_user_reg_u32_type;
-extern const struct reg_arch_type xtensa_user_reg_u128_type;
extern const struct command_registration xtensa_command_handlers[];
#endif /* OPENOCD_TARGET_XTENSA_H */