diff options
author | Ian Thompson <ianst@cadence.com> | 2022-06-24 22:27:32 -0700 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2022-08-20 15:38:41 +0000 |
commit | ce5ca9f7ba782ea9fba8ecd5fc1cb9407fd27949 (patch) | |
tree | 4bffcfcf737def7c23ccc7b1b53c8a56e0a63ee9 /src/target/xtensa/xtensa.h | |
parent | be2e5c6c35f77fecb4df2a19cec05cceac500ca9 (diff) | |
download | riscv-openocd-ce5ca9f7ba782ea9fba8ecd5fc1cb9407fd27949.zip riscv-openocd-ce5ca9f7ba782ea9fba8ecd5fc1cb9407fd27949.tar.gz riscv-openocd-ce5ca9f7ba782ea9fba8ecd5fc1cb9407fd27949.tar.bz2 |
target: add generic Xtensa LX support
Generic Xtensa LX support extends the original Espressif/Xtensa
patch-set to support arbitrary Xtensa configurations, as defined in
a core-specific .cfg file. Not yet fully-featured. Additional
functionality to be added:
- Xtensa NX support
- DAP/SWD support
- File-IO support
- Generic Xtensa multi-core support
Valgrind-clean, no new Clang analyzer warnings
Signed-off-by: Ian Thompson <ianst@cadence.com>
Change-Id: I08e7bf8fa57c25b5d0cb75a1aa7a2ac13a380c52
Reviewed-on: https://review.openocd.org/c/openocd/+/7055
Tested-by: jenkins
Reviewed-by: Erhan Kurubas <erhan.kurubas@espressif.com>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Diffstat (limited to 'src/target/xtensa/xtensa.h')
-rw-r--r-- | src/target/xtensa/xtensa.h | 211 |
1 files changed, 142 insertions, 69 deletions
diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index d6000d8..fd03f07 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -2,6 +2,7 @@ /*************************************************************************** * Generic Xtensa target * + * Copyright (C) 2020-2022 Cadence Design Systems, Inc. * * Copyright (C) 2019 Espressif Systems Ltd. * ***************************************************************************/ @@ -19,41 +20,77 @@ * Holds the interface to Xtensa cores. */ -#define XT_ISNS_SZ_MAX 3 +/* Big-endian vs. little-endian detection */ +#define XT_ISBE(X) ((X)->target->endianness == TARGET_BIG_ENDIAN) -#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) +/* 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)) -#define XT_LOCAL_MEM_REGIONS_NUM_MAX 8 +/* 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_AREGS_NUM_MAX 64 -#define XT_USER_REGS_NUM_MAX 256 +#define XT_ISNS_SZ_MAX 3 -#define XT_MEM_ACCESS_NONE 0x0 -#define XT_MEM_ACCESS_READ 0x1 -#define XT_MEM_ACCESS_WRITE 0x2 +#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) -enum xtensa_mem_err_detect { - XT_MEM_ERR_DETECT_NONE, - XT_MEM_ERR_DETECT_PARITY, - XT_MEM_ERR_DETECT_ECC, +#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, +}; + +/* 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 +}; + +struct xtensa_keyval_info_s { + char *chrval; + int intval; +}; + +enum xtensa_type { + XT_UNDEF = 0, + XT_LX, }; 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; }; @@ -66,13 +103,14 @@ struct xtensa_mmu_config { 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 { @@ -82,8 +120,8 @@ 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 { @@ -91,7 +129,7 @@ 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 { @@ -100,48 +138,26 @@ 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; @@ -175,13 +191,26 @@ struct xtensa_sw_breakpoint { */ 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; @@ -192,11 +221,18 @@ struct xtensa { 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; + struct xtensa_keyval_info_s scratch_ars[XT_AR_SCRATCH_NUM]; bool regs_fetched; /* true after first register fetch completed successfully */ }; @@ -210,7 +246,6 @@ static inline struct xtensa *target_to_xtensa(struct target *target) 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); @@ -233,11 +268,41 @@ static inline bool xtensa_data_addr_valid(struct target *target, uint32_t addr) 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, unsigned int reg, uint8_t *data) +{ + struct xtensa_debug_module *dm = &xtensa->dbg_mod; + + if (!xtensa->core_config->trace.enabled && + (reg <= NARADR_MEMADDREND || (reg >= NARADR_PMG && reg <= NARADR_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, unsigned int reg, uint32_t data) +{ + struct xtensa_debug_module *dm = &xtensa->dbg_mod; + + if (!xtensa->core_config->trace.enabled && + (reg <= NARADR_MEMADDREND || (reg >= NARADR_PMG && reg <= NARADR_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); @@ -248,11 +313,15 @@ int xtensa_smpbreak_write(struct xtensa *xtensa, uint32_t set); 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); @@ -281,16 +350,22 @@ int xtensa_write_buffer(struct target *target, target_addr_t address, uint32_t c 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); 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); - - +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); @@ -300,8 +375,6 @@ 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 */ |