Upstream a whole host of RISC-V changes.
Made no attempt to separate this out into reviewable chunks, since this is all RISC-V-specific code developed at https://github.com/riscv/riscv-openocd Memory sample and repeat read functionality was left out of this change since it requires some target-independent changes that I'll upstream some other time. Change-Id: I92917c86d549c232cbf36ffbfefc93331c05accd Signed-off-by: Tim Newsome <tim@sifive.com> Reviewed-on: https://review.openocd.org/c/openocd/+/6529 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
committed by
Antonio Borneo
parent
f4612e06c6
commit
615709d140
@@ -10,6 +10,7 @@ struct riscv_program;
|
||||
#include "gdb_regs.h"
|
||||
#include "jtag/jtag.h"
|
||||
#include "target/register.h"
|
||||
#include <helper/command.h>
|
||||
|
||||
/* The register cache is statically allocated. */
|
||||
#define RISCV_MAX_HARTS 1024
|
||||
@@ -26,6 +27,8 @@ struct riscv_program;
|
||||
|
||||
# define PG_MAX_LEVEL 4
|
||||
|
||||
#define RISCV_NUM_MEM_ACCESS_METHODS 3
|
||||
|
||||
extern struct target_type riscv011_target;
|
||||
extern struct target_type riscv013_target;
|
||||
|
||||
@@ -36,6 +39,13 @@ typedef uint64_t riscv_reg_t;
|
||||
typedef uint32_t riscv_insn_t;
|
||||
typedef uint64_t riscv_addr_t;
|
||||
|
||||
enum riscv_mem_access_method {
|
||||
RISCV_MEM_ACCESS_UNSPECIFIED,
|
||||
RISCV_MEM_ACCESS_PROGBUF,
|
||||
RISCV_MEM_ACCESS_SYSBUS,
|
||||
RISCV_MEM_ACCESS_ABSTRACT
|
||||
};
|
||||
|
||||
enum riscv_halt_reason {
|
||||
RISCV_HALT_INTERRUPT,
|
||||
RISCV_HALT_BREAKPOINT,
|
||||
@@ -51,15 +61,35 @@ typedef struct {
|
||||
unsigned 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;
|
||||
|
||||
typedef struct {
|
||||
unsigned dtm_version;
|
||||
|
||||
struct command_context *cmd_ctx;
|
||||
void *version_specific;
|
||||
|
||||
/* The hart that the RTOS thinks is currently being debugged. */
|
||||
int rtos_hartid;
|
||||
|
||||
/* The hart that is currently being debugged. Note that this is
|
||||
* different than the hartid that the RTOS is expected to use. This
|
||||
* one will change all the time, it's more of a global argument to
|
||||
@@ -76,13 +106,13 @@ typedef struct {
|
||||
char *reg_names;
|
||||
|
||||
/* It's possible that each core has a different supported ISA set. */
|
||||
int xlen[RISCV_MAX_HARTS];
|
||||
riscv_reg_t misa[RISCV_MAX_HARTS];
|
||||
int xlen;
|
||||
riscv_reg_t misa;
|
||||
/* Cached value of vlenb. 0 if vlenb is not readable for some reason. */
|
||||
unsigned vlenb[RISCV_MAX_HARTS];
|
||||
unsigned int vlenb;
|
||||
|
||||
/* The number of triggers per hart. */
|
||||
unsigned trigger_count[RISCV_MAX_HARTS];
|
||||
unsigned int trigger_count;
|
||||
|
||||
/* For each physical trigger, contains -1 if the hwbp is available, or the
|
||||
* unique_id of the breakpoint/watchpoint that is using it.
|
||||
@@ -91,7 +121,7 @@ typedef struct {
|
||||
int trigger_unique_id[RISCV_MAX_HWBPS];
|
||||
|
||||
/* The number of entries in the debug buffer. */
|
||||
int debug_buffer_size[RISCV_MAX_HARTS];
|
||||
int debug_buffer_size;
|
||||
|
||||
/* This avoids invalidating the register cache too often. */
|
||||
bool registers_initialized;
|
||||
@@ -112,10 +142,8 @@ typedef struct {
|
||||
|
||||
/* Helper functions that target the various RISC-V debug spec
|
||||
* implementations. */
|
||||
int (*get_register)(struct target *target,
|
||||
riscv_reg_t *value, int hid, int rid);
|
||||
int (*set_register)(struct target *target, int hartid, int regid,
|
||||
uint64_t value);
|
||||
int (*get_register)(struct target *target, riscv_reg_t *value, int regid);
|
||||
int (*set_register)(struct target *target, int regid, uint64_t value);
|
||||
int (*get_register_buf)(struct target *target, uint8_t *buf, int regno);
|
||||
int (*set_register_buf)(struct target *target, int regno,
|
||||
const uint8_t *buf);
|
||||
@@ -143,8 +171,8 @@ typedef struct {
|
||||
void (*fill_dmi_read_u64)(struct target *target, char *buf, int a);
|
||||
void (*fill_dmi_nop_u64)(struct target *target, char *buf);
|
||||
|
||||
int (*authdata_read)(struct target *target, uint32_t *value);
|
||||
int (*authdata_write)(struct target *target, uint32_t value);
|
||||
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);
|
||||
@@ -152,7 +180,10 @@ typedef struct {
|
||||
int (*test_sba_config_reg)(struct target *target, target_addr_t legal_address,
|
||||
uint32_t num_words, target_addr_t illegal_address, bool run_sbbusyerror_test);
|
||||
|
||||
int (*test_compliance)(struct target *target);
|
||||
int (*sample_memory)(struct target *target,
|
||||
struct riscv_sample_buf *buf,
|
||||
riscv_sample_config_t *config,
|
||||
int64_t until_ms);
|
||||
|
||||
int (*read_memory)(struct target *target, target_addr_t address,
|
||||
uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment);
|
||||
@@ -161,6 +192,8 @@ typedef struct {
|
||||
int (*hart_count)(struct target *target);
|
||||
unsigned (*data_bits)(struct target *target);
|
||||
|
||||
COMMAND_HELPER((*print_info), struct target *target);
|
||||
|
||||
/* Storage for vector register types. */
|
||||
struct reg_data_type_vector vector_uint8;
|
||||
struct reg_data_type_vector vector_uint16;
|
||||
@@ -179,8 +212,31 @@ typedef struct {
|
||||
/* Set when trigger registers are changed by the user. This indicates we eed
|
||||
* to beware that we may hit a trigger that we didn't realize had been set. */
|
||||
bool manual_hwbp_set;
|
||||
|
||||
/* Memory access methods to use, ordered by priority, highest to lowest. */
|
||||
int mem_access_methods[RISCV_NUM_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_progbuf_warn;
|
||||
bool mem_access_sysbus_warn;
|
||||
bool mem_access_abstract_warn;
|
||||
|
||||
/* 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;
|
||||
|
||||
riscv_sample_config_t sample_config;
|
||||
struct riscv_sample_buf sample_buf;
|
||||
} riscv_info_t;
|
||||
|
||||
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];
|
||||
@@ -205,8 +261,6 @@ extern int riscv_command_timeout_sec;
|
||||
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
|
||||
extern int riscv_reset_timeout_sec;
|
||||
|
||||
extern bool riscv_prefer_sba;
|
||||
|
||||
extern bool riscv_enable_virtual;
|
||||
extern bool riscv_ebreakm;
|
||||
extern bool riscv_ebreaks;
|
||||
@@ -216,7 +270,10 @@ extern bool riscv_ebreaku;
|
||||
* that provides that. */
|
||||
static inline riscv_info_t *riscv_info(const struct target *target) __attribute__((unused));
|
||||
static inline riscv_info_t *riscv_info(const struct target *target)
|
||||
{ return target->arch_info; }
|
||||
{
|
||||
assert(target->arch_info);
|
||||
return target->arch_info;
|
||||
}
|
||||
#define RISCV_INFO(R) riscv_info_t *R = riscv_info(target);
|
||||
|
||||
extern uint8_t ir_dtmcontrol[4];
|
||||
@@ -269,44 +326,30 @@ void riscv_info_init(struct target *target, riscv_info_t *r);
|
||||
* then the only hart. */
|
||||
int riscv_step_rtos_hart(struct target *target);
|
||||
|
||||
bool riscv_supports_extension(struct target *target, int hartid, char letter);
|
||||
bool riscv_supports_extension(struct target *target, char letter);
|
||||
|
||||
/* Returns XLEN for the given (or current) hart. */
|
||||
unsigned riscv_xlen(const struct target *target);
|
||||
int riscv_xlen_of_hart(const struct target *target, int hartid);
|
||||
|
||||
bool riscv_rtos_enabled(const struct target *target);
|
||||
int riscv_xlen_of_hart(const struct target *target);
|
||||
|
||||
/* Sets the current hart, which is the hart that will actually be used when
|
||||
* issuing debug commands. */
|
||||
int riscv_set_current_hartid(struct target *target, int hartid);
|
||||
int riscv_select_current_hart(struct target *target);
|
||||
int riscv_current_hartid(const struct target *target);
|
||||
|
||||
/*** Support functions for the RISC-V 'RTOS', which provides multihart support
|
||||
* without requiring multiple targets. */
|
||||
|
||||
/* When using the RTOS to debug, this selects the hart that is currently being
|
||||
* debugged. This doesn't propagate to the hardware. */
|
||||
void riscv_set_all_rtos_harts(struct target *target);
|
||||
void riscv_set_rtos_hartid(struct target *target, int hartid);
|
||||
|
||||
/* Lists the number of harts in the system, which are assumed to be
|
||||
* consecutive and start with mhartid=0. */
|
||||
int riscv_count_harts(struct target *target);
|
||||
|
||||
/* Returns TRUE if the target has the given register on the given hart. */
|
||||
bool riscv_has_register(struct target *target, int hartid, int regid);
|
||||
|
||||
/** Set register, updating the cache. */
|
||||
int riscv_set_register(struct target *target, enum gdb_regno i, riscv_reg_t v);
|
||||
/** Set register, updating the cache. */
|
||||
int riscv_set_register_on_hart(struct target *target, int hid, enum gdb_regno rid, uint64_t v);
|
||||
/** Get register, from the cache if it's in there. */
|
||||
int riscv_get_register(struct target *target, riscv_reg_t *value,
|
||||
enum gdb_regno r);
|
||||
/** Get register, from the cache if it's in there. */
|
||||
int riscv_get_register_on_hart(struct target *target, riscv_reg_t *value,
|
||||
int hartid, enum gdb_regno regid);
|
||||
|
||||
/* Checks the state of the current hart -- "is_halted" checks the actual
|
||||
* on-device register. */
|
||||
@@ -329,9 +372,6 @@ int riscv_dmi_write_u64_bits(struct target *target);
|
||||
/* Invalidates the register cache. */
|
||||
void riscv_invalidate_register_cache(struct target *target);
|
||||
|
||||
/* Returns TRUE when a hart is enabled in this target. */
|
||||
bool riscv_hart_enabled(struct target *target, int hartid);
|
||||
|
||||
int riscv_enumerate_triggers(struct target *target);
|
||||
|
||||
int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint);
|
||||
@@ -356,4 +396,7 @@ semihosting_result_t riscv_semihosting(struct target *target, int *retval);
|
||||
void riscv_add_bscan_tunneled_scan(struct target *target, 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
|
||||
|
||||
Reference in New Issue
Block a user