/* SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef OPENOCD_TARGET_RISCV_RISCV_H #define OPENOCD_TARGET_RISCV_RISCV_H struct riscv_program; #include #include "opcodes.h" #include "gdb_regs.h" #include "jtag/jtag.h" #include "target/semihosting_common.h" #include "target/target.h" #include "target/register.h" #include #include #define RISCV_COMMON_MAGIC 0x52495356U #define RISCV_MAX_HARTS ((int)BIT(20)) #define RISCV_MAX_TRIGGERS 32 #define RISCV_MAX_HWBPS 16 #define RISCV_MAX_DMS 100 #define DEFAULT_COMMAND_TIMEOUT_SEC 5 #define RISCV_SATP_MODE(xlen) ((xlen) == 32 ? SATP32_MODE : SATP64_MODE) #define RISCV_SATP_PPN(xlen) ((xlen) == 32 ? SATP32_PPN : SATP64_PPN) #define RISCV_HGATP_MODE(xlen) ((xlen) == 32 ? HGATP32_MODE : HGATP64_MODE) #define RISCV_HGATP_PPN(xlen) ((xlen) == 32 ? HGATP32_PPN : HGATP64_PPN) #define RISCV_PGSHIFT 12 #define RISCV_PGSIZE BIT(RISCV_PGSHIFT) #define RISCV_PGBASE(addr) ((addr) & ~(RISCV_PGSIZE - 1)) #define RISCV_PGOFFSET(addr) ((addr) & (RISCV_PGSIZE - 1)) #define PG_MAX_LEVEL 5 #define RISCV_BATCH_ALLOC_SIZE 128 extern struct target_type riscv011_target; extern struct target_type riscv013_target; /* * Definitions shared by code supporting all RISC-V versions. */ typedef uint64_t riscv_reg_t; typedef uint32_t riscv_insn_t; typedef uint64_t riscv_addr_t; enum yes_no_maybe { YNM_MAYBE, YNM_YES, YNM_NO }; enum riscv_mem_access_method { RISCV_MEM_ACCESS_PROGBUF, RISCV_MEM_ACCESS_SYSBUS, RISCV_MEM_ACCESS_ABSTRACT, RISCV_MEM_ACCESS_MAX_METHODS_NUM }; enum riscv_virt2phys_mode { RISCV_VIRT2PHYS_MODE_HW, RISCV_VIRT2PHYS_MODE_SW, RISCV_VIRT2PHYS_MODE_OFF }; const char *riscv_virt2phys_mode_to_str(enum riscv_virt2phys_mode mode); enum riscv_halt_reason { RISCV_HALT_INTERRUPT, RISCV_HALT_EBREAK, RISCV_HALT_SINGLESTEP, RISCV_HALT_TRIGGER, RISCV_HALT_UNKNOWN, RISCV_HALT_GROUP, RISCV_HALT_ERROR }; enum riscv_isrmasking_mode { /* RISCV_ISRMASK_AUTO, */ /* not supported yet */ RISCV_ISRMASK_OFF, /* RISCV_ISRMASK_ON, */ /* not supported yet */ RISCV_ISRMASK_STEPONLY, }; enum riscv_hart_state { RISCV_STATE_NON_EXISTENT, RISCV_STATE_RUNNING, RISCV_STATE_HALTED, RISCV_STATE_UNAVAILABLE }; /* RISC-V-specific data assigned to a register. */ typedef struct { struct target *target; /* Abstract command's regno for a custom register. */ unsigned int custom_number; } riscv_reg_info_t; #define RISCV_SAMPLE_BUF_TIMESTAMP_BEFORE 0x80 #define RISCV_SAMPLE_BUF_TIMESTAMP_AFTER 0x81 struct riscv_sample_buf { uint8_t *buf; unsigned int used; unsigned int size; }; typedef struct { bool enabled; struct { bool enabled; target_addr_t address; uint32_t size_bytes; } bucket[16]; } riscv_sample_config_t; typedef struct { struct list_head list; uint16_t low, high; char *name; } range_list_t; #define DTM_DTMCS_VERSION_UNKNOWN ((unsigned int)-1) #define RISCV_TINFO_VERSION_UNKNOWN (-1) #define RISCV013_DTMCS_ABITS_MIN 7 #define RISCV013_DTMCS_ABITS_MAX 32 struct reg_name_table { unsigned int num_entries; char **reg_names; }; struct riscv_mem_access_args { target_addr_t address; const uint8_t *write_buffer; uint8_t *read_buffer; uint32_t size; uint32_t count; uint32_t increment; }; static inline bool riscv_mem_access_is_valid(const struct riscv_mem_access_args args) { return !args.read_buffer != !args.write_buffer; } static inline bool riscv_mem_access_is_read(const struct riscv_mem_access_args args) { assert(riscv_mem_access_is_valid(args)); return !args.write_buffer && args.read_buffer; } static inline bool riscv_mem_access_is_write(const struct riscv_mem_access_args args) { assert(riscv_mem_access_is_valid(args)); return !args.read_buffer && args.write_buffer; } struct riscv_info { unsigned int common_magic; unsigned int dtm_version; struct command_context *cmd_ctx; void *version_specific; struct reg_name_table custom_register_names; char **reg_names; /* It's possible that each core has a different supported ISA set. */ int xlen; /* TODO: use the value from the register cache instead. */ riscv_reg_t misa; /* TODO: use the value from the register cache instead. * Cached value of vlenb. 0 indicates there is no vector support. * Note that you can have vector support without misa.V set, because * Zve* extensions implement vector registers without setting misa.V. */ unsigned int vlenb; /* The number of triggers per hart. */ unsigned int trigger_count; /* Data structure to record known unsupported tdata1+tdata2 trigger CSR values. * This is to avoid repetitive attempts to set trigger configurations that are already * known to be unsupported in the HW. * A separate data structure is created for each trigger. */ struct list_head *wp_triggers_negative_cache; /* record the tinfo of each trigger */ unsigned int trigger_tinfo[RISCV_MAX_TRIGGERS]; /* Version of the implemented Sdtrig extension */ int tinfo_version; /* Record if single-step is needed prior to resuming * from a software breakpoint or trigger. * Single-step is needed if the instruction that * caused the halt was not retired. That is, * when we halted "before" that instruction. */ bool need_single_step; /* For each physical trigger contains: * -1: the hwbp is available * -4: The trigger is used by the itrigger command * -5: The trigger is used by the etrigger command * >= 0: unique_id of the breakpoint/watchpoint that is using it. * Note that in RTOS mode the triggers are the same across all harts the * target controls, while otherwise only a single hart is controlled. */ int64_t trigger_unique_id[RISCV_MAX_HWBPS]; /* The unique id of the trigger that caused the most recent halt. If the * most recent halt was not caused by a trigger, then this is -1. */ int64_t trigger_hit; /* The configured approach to translate virtual addresses to physical */ enum riscv_virt2phys_mode virt2phys_mode; bool triggers_enumerated; /* Decremented every scan, and when it reaches 0 we clear the learned * delays, causing them to be relearned. Used for testing. */ int reset_delays_wait; /* This target has been prepped and is ready to step/resume. */ bool prepped; /* This target was selected using hasel. */ bool selected; /* Used by riscv_openocd_poll(). */ bool halted_needs_event_callback; enum target_event halted_callback_event; unsigned int halt_group_repoll_count; enum riscv_isrmasking_mode isrmask_mode; /* Helper functions that target the various RISC-V debug spec * implementations. */ int (*select_target)(struct target *target); int (*get_hart_state)(struct target *target, enum riscv_hart_state *state); /* Resume this target, as well as every other prepped target that can be * resumed near-simultaneously. Clear the prepped flag on any target that * was resumed. */ int (*resume_go)(struct target *target); int (*step_current_hart)(struct target *target); /* These get called from riscv_poll_hart(), which is a house of cards * together with openocd_poll(), so be careful not to upset things too * much. */ int (*handle_became_halted)(struct target *target, enum riscv_hart_state previous_riscv_state); int (*handle_became_running)(struct target *target, enum riscv_hart_state previous_riscv_state); int (*handle_became_unavailable)(struct target *target, enum riscv_hart_state previous_riscv_state); /* Called periodically (no guarantees about frequency), while there's * nothing else going on. */ int (*tick)(struct target *target); /* Get this target as ready as possible to resume, without actually * resuming. */ int (*resume_prep)(struct target *target); int (*halt_prep)(struct target *target); int (*halt_go)(struct target *target); int (*on_step)(struct target *target); enum riscv_halt_reason (*halt_reason)(struct target *target); int (*write_progbuf)(struct target *target, unsigned int index, riscv_insn_t d); riscv_insn_t (*read_progbuf)(struct target *target, unsigned int index); int (*execute_progbuf)(struct target *target, uint32_t *cmderr); int (*invalidate_cached_progbuf)(struct target *target); unsigned int (*get_dmi_address_bits)(const struct target *target); void (*fill_dmi_write)(const struct target *target, uint8_t *buf, uint32_t a, uint32_t d); void (*fill_dmi_read)(const struct target *target, uint8_t *buf, uint32_t a); void (*fill_dm_nop)(const struct target *target, uint8_t *buf); int (*authdata_read)(struct target *target, uint32_t *value, unsigned int index); int (*authdata_write)(struct target *target, uint32_t value, unsigned int index); int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address); int (*dmi_write)(struct target *target, uint32_t address, uint32_t value); bool (*get_impebreak)(const struct target *target); unsigned int (*get_progbufsize)(const struct target *target); /* Get the DMI address of target's DM's register. * The function should return the passed address * if the target is not assigned a DM yet. */ uint32_t (*get_dmi_address)(const struct target *target, uint32_t dm_address); int (*sample_memory)(struct target *target, struct riscv_sample_buf *buf, riscv_sample_config_t *config, int64_t until_ms); int (*access_memory)(struct target *target, const struct riscv_mem_access_args args); unsigned int (*data_bits)(struct target *target); COMMAND_HELPER((*print_info), struct target *target); /* Storage for arch_info of non-custom registers. */ riscv_reg_info_t shared_reg_info; /* Storage for vector register types. */ struct reg_data_type_vector vector_uint8; struct reg_data_type_vector vector_uint16; struct reg_data_type_vector vector_uint32; struct reg_data_type_vector vector_uint64; struct reg_data_type_vector vector_uint128; struct reg_data_type type_uint8_vector; struct reg_data_type type_uint16_vector; struct reg_data_type type_uint32_vector; struct reg_data_type type_uint64_vector; struct reg_data_type type_uint128_vector; struct reg_data_type_union_field vector_fields[5]; struct reg_data_type_union vector_union; struct reg_data_type type_vector; bool *reserved_triggers; /* Memory access methods to use, ordered by priority, highest to lowest. */ enum riscv_mem_access_method mem_access_methods[RISCV_MEM_ACCESS_MAX_METHODS_NUM]; unsigned int num_enabled_mem_access_methods; /* Different memory regions may need different methods but single configuration is applied * for all. Following flags are used to warn only once about failing memory access method. */ bool mem_access_warn[RISCV_MEM_ACCESS_MAX_METHODS_NUM]; /* In addition to the ones in the standard spec, we'll also expose additional * CSRs in this list. */ struct list_head expose_csr; /* Same, but for custom registers. * Custom registers are for non-standard extensions and use abstract register numbers * from range 0xc000 ... 0xffff. */ struct list_head expose_custom; /* The list of registers to mark as "hidden". Hidden registers are available * but do not appear in gdb targets description or reg command output. */ struct list_head hide_csr; riscv_sample_config_t sample_config; struct riscv_sample_buf sample_buf; /* Track when we were last asked to do something substantial. */ int64_t last_activity; enum yes_no_maybe vsew64_supported; bool range_trigger_fallback_encountered; bool wp_allow_equality_match_trigger; bool wp_allow_napot_trigger; bool wp_allow_ge_lt_trigger; bool autofence; }; enum riscv_priv_mode { RISCV_MODE_M, RISCV_MODE_S, RISCV_MODE_U, RISCV_MODE_VS, RISCV_MODE_VU, N_RISCV_MODE }; struct riscv_private_config { bool dcsr_ebreak_fields[N_RISCV_MODE]; }; static inline struct riscv_private_config *riscv_private_config(const struct target *target) { assert(target->private_config); return target->private_config; } COMMAND_HELPER(riscv_print_info_line, const char *section, const char *key, unsigned int value); typedef struct { uint8_t tunneled_dr_width; struct scan_field tunneled_dr[4]; } riscv_bscan_tunneled_scan_context_t; typedef struct { const char *name; int level; unsigned int va_bits; /* log2(PTESIZE) */ unsigned int pte_shift; unsigned int vpn_shift[PG_MAX_LEVEL]; unsigned int vpn_mask[PG_MAX_LEVEL]; unsigned int pte_ppn_shift[PG_MAX_LEVEL]; unsigned int pte_ppn_mask[PG_MAX_LEVEL]; unsigned int pa_ppn_shift[PG_MAX_LEVEL]; unsigned int pa_ppn_mask[PG_MAX_LEVEL]; } virt2phys_info_t; bool riscv_virt2phys_mode_is_hw(const struct target *target); bool riscv_virt2phys_mode_is_sw(const struct target *target); /* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/ int riscv_get_command_timeout_sec(void); /* Everything needs the RISC-V specific info structure, so here's a nice macro * that provides that. */ static inline struct riscv_info *riscv_info(const struct target *target) __attribute__((unused)); static inline struct riscv_info *riscv_info(const struct target *target) { assert(target->arch_info); return target->arch_info; } #define RISCV_INFO(R) struct riscv_info *R = riscv_info(target); static inline bool is_riscv(const struct riscv_info *riscv_info) { return riscv_info->common_magic == RISCV_COMMON_MAGIC; } extern struct scan_field select_dtmcontrol; extern struct scan_field select_dbus; extern struct scan_field select_idcode; int dtmcs_scan(struct jtag_tap *tap, uint32_t out, uint32_t *in_ptr); extern struct scan_field *bscan_tunneled_select_dmi; extern uint32_t bscan_tunneled_select_dmi_num_fields; typedef enum { BSCAN_TUNNEL_NESTED_TAP, BSCAN_TUNNEL_DATA_REGISTER } bscan_tunnel_type_t; extern uint8_t bscan_tunnel_ir_width; void select_dmi_via_bscan(struct jtag_tap *tap); /*** OpenOCD Interface */ int riscv_openocd_poll(struct target *target); int riscv_halt(struct target *target); int riscv_openocd_step( struct target *target, bool current, target_addr_t address, bool handle_breakpoints ); /*** RISC-V Interface ***/ bool riscv_supports_extension(const struct target *target, char letter); /* Returns XLEN for the given (or current) hart. */ unsigned int riscv_xlen(const struct target *target); /* Returns VLENB for the given (or current) hart. */ unsigned int riscv_vlenb(const struct target *target); /*** Support functions for the RISC-V 'RTOS', which provides multihart support * without requiring multiple targets. */ /* Checks the state of the current hart -- "is_halted" checks the actual * on-device register. */ int riscv_get_hart_state(struct target *target, enum riscv_hart_state *state); /* These helper functions let the generic program interface get target-specific * information. */ unsigned int riscv_progbuf_size(struct target *target); riscv_insn_t riscv_read_progbuf(struct target *target, int index); int riscv_write_progbuf(struct target *target, unsigned int index, riscv_insn_t insn); int riscv_execute_progbuf(struct target *target, uint32_t *cmderr); void riscv_fill_dm_nop(const struct target *target, uint8_t *buf); void riscv_fill_dmi_write(const struct target *target, uint8_t *buf, uint32_t a, uint32_t d); void riscv_fill_dmi_read(const struct target *target, uint8_t *buf, uint32_t a); unsigned int riscv_get_dmi_address_bits(const struct target *target); uint32_t riscv_get_dmi_address(const struct target *target, uint32_t dm_address); int riscv_enumerate_triggers(struct target *target); int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint); int riscv_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); void riscv_semihosting_init(struct target *target); enum semihosting_result riscv_semihosting(struct target *target, int *retval); void riscv_add_bscan_tunneled_scan(struct jtag_tap *tap, const struct scan_field *field, riscv_bscan_tunneled_scan_context_t *ctxt); int riscv_read_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer); int riscv_write_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer); #endif /* OPENOCD_TARGET_RISCV_RISCV_H */