OpenOCD
riscv-013_reg.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 
7 #include "riscv-013_reg.h"
8 #include "field_helpers.h"
9 
10 #include "riscv_reg.h"
11 #include "riscv_reg_impl.h"
12 #include "riscv-013.h"
13 #include "debug_defines.h"
14 #include <helper/time_support.h>
15 
16 static int riscv013_reg_get(struct reg *reg)
17 {
19 
20  /* TODO: Hack to deal with gdb that thinks these registers still exist. */
23  buf_set_u64(reg->value, 0, reg->size, 0);
24  return ERROR_OK;
25  }
26 
27  if (reg->number >= GDB_REGNO_V0 && reg->number <= GDB_REGNO_V31) {
29  return ERROR_FAIL;
30 
31  reg->valid = riscv_reg_impl_gdb_regno_cacheable(reg->number, /* is write? */ false);
32  } else {
33  uint64_t value;
34  int result = riscv_reg_get(target, &value, reg->number);
35  if (result != ERROR_OK)
36  return result;
37  buf_set_u64(reg->value, 0, reg->size, value);
38  }
39  char *str = buf_to_hex_str(reg->value, reg->size);
40  LOG_TARGET_DEBUG(target, "Read 0x%s from %s (valid=%d).", str, reg->name,
41  reg->valid);
42  free(str);
43  return ERROR_OK;
44 }
45 
46 static int riscv013_reg_set(struct reg *reg, uint8_t *buf)
47 {
49 
50  char *str = buf_to_hex_str(buf, reg->size);
51  LOG_TARGET_DEBUG(target, "Write 0x%s to %s (valid=%d).", str, reg->name,
52  reg->valid);
53  free(str);
54 
55  /* TODO: Hack to deal with gdb that thinks these registers still exist. */
58  buf_get_u64(buf, 0, reg->size) == 0)
59  return ERROR_OK;
60 
61  if (reg->number >= GDB_REGNO_V0 && reg->number <= GDB_REGNO_V31) {
63  return ERROR_FAIL;
64 
65  memcpy(reg->value, buf, DIV_ROUND_UP(reg->size, 8));
66  reg->valid = riscv_reg_impl_gdb_regno_cacheable(reg->number, /* is write? */ true);
67  } else {
68  const riscv_reg_t value = buf_get_u64(buf, 0, reg->size);
69  if (riscv_reg_set(target, reg->number, value) != ERROR_OK)
70  return ERROR_FAIL;
71  }
72 
73  return ERROR_OK;
74 }
75 
76 static const struct reg_arch_type *riscv013_gdb_regno_reg_type(uint32_t regno)
77 {
78  static const struct reg_arch_type riscv013_reg_type = {
80  .set = riscv013_reg_set
81  };
82  return &riscv013_reg_type;
83 }
84 
85 static int init_cache_entry(struct target *target, uint32_t regno)
86 {
87  struct reg * const reg = riscv_reg_impl_cache_entry(target, regno);
89  return ERROR_OK;
93 }
94 
101 static int assume_reg_exist(struct target *target, uint32_t regno)
102 {
104  /* exist */ true, riscv013_gdb_regno_reg_type(regno));
105 }
106 
107 static int examine_xlen(struct target *target)
108 {
109  RISCV_INFO(r);
110  unsigned int cmderr;
111 
113  GDB_REGNO_S0, /* size */ 64, AC_ACCESS_REGISTER_TRANSFER);
114  int res = riscv013_execute_abstract_command(target, command, &cmderr);
115  if (res == ERROR_OK) {
116  r->xlen = 64;
117  return ERROR_OK;
118  }
119  if (res == ERROR_TIMEOUT_REACHED)
120  return ERROR_FAIL;
121  r->xlen = 32;
122 
123  return ERROR_OK;
124 }
125 
126 static int examine_vlenb(struct target *target)
127 {
128  RISCV_INFO(r);
129 
130  /* Reading "vlenb" requires "mstatus.vs" to be set, so "mstatus" should
131  * be accessible.*/
133  if (res != ERROR_OK)
134  return res;
135 
137  if (res != ERROR_OK)
138  return res;
139 
140  riscv_reg_t vlenb_val;
141  if (riscv_reg_get(target, &vlenb_val, GDB_REGNO_VLENB) != ERROR_OK) {
143  LOG_TARGET_WARNING(target, "Couldn't read vlenb; vector register access won't work.");
144  r->vlenb = 0;
146  }
147  /* As defined by RISC-V V extension specification:
148  * https://github.com/riscv/riscv-v-spec/blob/2f68ef7256d6ec53e4d2bd7cb12862f406d64e34/v-spec.adoc?plain=1#L67-L72 */
149  const unsigned int vlen_max = 65536;
150  const unsigned int vlenb_max = vlen_max / 8;
151  if (vlenb_val > vlenb_max) {
152  LOG_TARGET_WARNING(target, "'vlenb == %" PRIu64
153  "' is greater than maximum allowed by specification (%u); vector register access won't work.",
154  vlenb_val, vlenb_max);
155  r->vlenb = 0;
156  return ERROR_OK;
157  }
158  assert(vlenb_max <= UINT_MAX);
159  r->vlenb = (unsigned int)vlenb_val;
160 
161  LOG_TARGET_INFO(target, "Vector support with vlenb=%u", r->vlenb);
162  return ERROR_OK;
163 }
164 
165 enum misa_mxl {
169  MISA_MXL_128 = 3
170 };
171 
172 unsigned int mxl_to_xlen(enum misa_mxl mxl)
173 {
174  switch (mxl) {
175  case MISA_MXL_32:
176  return 32;
177  case MISA_MXL_64:
178  return 64;
179  case MISA_MXL_128:
180  return 128;
181  case MISA_MXL_INVALID:
182  assert(0);
183  }
184  return 0;
185 }
186 
187 static int check_misa_mxl(const struct target *target)
188 {
189  RISCV_INFO(r);
190 
191  if (r->misa == 0) {
192  LOG_TARGET_WARNING(target, "'misa' register is read as zero."
193  "OpenOCD will not be able to determine some hart's capabilities.");
194  return ERROR_OK;
195  }
196  const unsigned int dxlen = riscv_xlen(target);
197  assert(dxlen <= sizeof(riscv_reg_t) * CHAR_BIT);
198  assert(dxlen >= 2);
199  const riscv_reg_t misa_mxl_mask = (riscv_reg_t)0x3 << (dxlen - 2);
200  const unsigned int mxl = get_field(r->misa, misa_mxl_mask);
201  if (mxl == MISA_MXL_INVALID) {
202  /* This is not an error!
203  * Imagine the platform that:
204  * - Has no abstract access to CSRs, so that CSRs are read
205  * through Program Buffer via "csrr" instruction.
206  * - Complies to v1.10 of the Priveleged Spec, so that misa.mxl
207  * is WARL and MXLEN may be chainged.
208  * https://github.com/riscv/riscv-isa-manual/commit/9a7dd2fe29011587954560b5dcf1875477b27ad8
209  * - DXLEN == MXLEN on reset == 64.
210  * In a following scenario:
211  * - misa.mxl was written, so that MXLEN is 32.
212  * - Debugger connects to the target.
213  * - Debugger observes DXLEN == 64.
214  * - Debugger reads misa:
215  * - Abstract access fails with "cmderr == not supported".
216  * - Access via Program Buffer involves reading "misa" to an
217  * "xreg" via "csrr", so that the "xreg" is filled with
218  * zero-extended value of "misa" (since "misa" is
219  * MXLEN-wide).
220  * - Debugger derives "misa.mxl" assumig "misa" is DXLEN-bit
221  * wide (64) while MXLEN is 32 and therefore erroneously
222  * assumes "misa.mxl" to be zero (invalid).
223  */
224  LOG_TARGET_WARNING(target, "Detected DXLEN (%u) does not match "
225  "MXLEN: misa.mxl == 0, misa == 0x%" PRIx64 ".",
226  dxlen, r->misa);
227  return ERROR_OK;
228  }
229  const unsigned int mxlen = mxl_to_xlen(mxl);
230  if (dxlen < mxlen) {
232  "MXLEN (%u) reported in misa.mxl field exceeds "
233  "the detected DXLEN (%u)",
234  mxlen, dxlen);
235  return ERROR_FAIL;
236  }
237  /* NOTE:
238  * The value of "misa.mxl" may stil not coincide with "xlen".
239  * "misa[26:XLEN-3]" bits are marked as WIRI in at least version 1.10
240  * of RISC-V Priveleged Spec. Therefore, if "xlen" is erroneously
241  * assumed to be 32 when it actually is 64, "mxl" will be read from
242  * this WIRI field and may be equal to "MISA_MXL_32" by coincidence.
243  * This is not an issue though from the version 1.11 onward, since
244  * "misa[26:XLEN-3]" became WARL and equal to 0.
245  */
246 
247  /* Display this as early as possible to help people who are using
248  * really slow simulators. */
249  LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, riscv_xlen(target), r->misa);
250  return ERROR_OK;
251 }
252 
253 static int examine_misa(struct target *target)
254 {
255  RISCV_INFO(r);
256 
258  if (res != ERROR_OK)
259  return res;
260 
261  res = riscv_reg_get(target, &r->misa, GDB_REGNO_MISA);
262  if (res != ERROR_OK)
263  return res;
264  return check_misa_mxl(target);
265 }
266 
267 static int examine_mtopi(struct target *target)
268 {
269  /* Assume the registers exist */
271  if (res != ERROR_OK)
272  return res;
274  if (res != ERROR_OK)
275  return res;
276 
280  if (res != ERROR_OK)
281  return res;
283  }
285  LOG_TARGET_INFO(target, "S?aia detected without IMSIC");
287  }
288  LOG_TARGET_INFO(target, "S?aia detected with IMSIC");
289  return ERROR_OK;
290 }
291 
297 {
299  if (res != ERROR_OK)
300  return res;
301 
303 
304  assert(target->state == TARGET_HALTED);
305 
306  res = examine_xlen(target);
307  if (res != ERROR_OK)
308  return res;
309 
310  /* Reading CSRs may clobber "s0", "s1", so it should be possible to
311  * save them in cache. */
313  if (res != ERROR_OK)
314  return res;
316  if (res != ERROR_OK)
317  return res;
318 
319  res = examine_misa(target);
320  if (res != ERROR_OK)
321  return res;
322 
323  res = examine_vlenb(target);
324  if (res != ERROR_OK)
325  return res;
326 
328 
329  res = examine_mtopi(target);
330  if (res != ERROR_OK)
331  return res;
332 
333  for (uint32_t regno = 0; regno < target->reg_cache->num_regs; ++regno) {
334  res = init_cache_entry(target, regno);
335  if (res != ERROR_OK)
336  return res;
337  }
338 
340  if (res != ERROR_OK)
341  return res;
342 
344 
345  return ERROR_OK;
346 }
347 
352 int riscv013_reg_save(struct target *target, enum gdb_regno regid)
353 {
354  if (target->state != TARGET_HALTED) {
355  LOG_TARGET_ERROR(target, "Can't save register %s on a hart that is not halted.",
357  return ERROR_FAIL;
358  }
359  assert(riscv_reg_impl_gdb_regno_cacheable(regid, /* is write? */ false) &&
360  "Only cacheable registers can be saved.");
361 
362  RISCV_INFO(r);
364  if (!target->reg_cache) {
365  assert(!target_was_examined(target));
366  /* To create register cache it is needed to examine the target first,
367  * therefore during examine, any changed register needs to be saved
368  * and restored manually.
369  */
370  return ERROR_OK;
371  }
372 
373  struct reg *reg = riscv_reg_impl_cache_entry(target, regid);
374 
375  LOG_TARGET_DEBUG(target, "Saving %s", reg->name);
376  if (riscv_reg_get(target, &value, regid) != ERROR_OK)
377  return ERROR_FAIL;
378 
379  assert(reg->valid &&
380  "The register is cacheable, so the cache entry must be valid now.");
381  /* Mark the register dirty. We assume that this function is called
382  * because the caller is about to mess with the underlying value of the
383  * register. */
384  reg->dirty = true;
385 
386  r->last_activity = timeval_ms();
387 
388  return ERROR_OK;
389 }
char * buf_to_hex_str(const void *_buf, unsigned int buf_len)
Definition: binarybuffer.c:178
static uint64_t buf_get_u64(const uint8_t *_buffer, unsigned int first, unsigned int num)
Retrieves num bits from _buffer, starting at the first bit, returning the bits in a 64-bit word.
Definition: binarybuffer.h:134
static void buf_set_u64(uint8_t *_buffer, unsigned int first, unsigned int num, uint64_t value)
Sets num bits in _buffer, starting at the first bit, using the bits in value.
Definition: binarybuffer.h:65
#define AC_ACCESS_REGISTER_TRANSFER
static uint64_t get_field(uint64_t reg, uint64_t mask)
Definition: field_helpers.h:9
gdb_regno
Definition: gdb_regs.h:10
@ GDB_REGNO_MTOPI
Definition: gdb_regs.h:109
@ GDB_REGNO_MSTATUS
Definition: gdb_regs.h:102
@ GDB_REGNO_MTOPEI
Definition: gdb_regs.h:110
@ GDB_REGNO_S1
Definition: gdb_regs.h:21
@ GDB_REGNO_XPR15
Definition: gdb_regs.h:28
@ GDB_REGNO_V0
Definition: gdb_regs.h:117
@ GDB_REGNO_XPR31
Definition: gdb_regs.h:45
@ GDB_REGNO_S0
Definition: gdb_regs.h:19
@ GDB_REGNO_VLENB
Definition: gdb_regs.h:90
@ GDB_REGNO_V31
Definition: gdb_regs.h:124
@ GDB_REGNO_MISA
Definition: gdb_regs.h:98
#define LOG_TARGET_INFO(target, fmt_str,...)
Definition: log.h:154
#define LOG_TARGET_WARNING(target, fmt_str,...)
Definition: log.h:160
#define ERROR_FAIL
Definition: log.h:175
#define LOG_TARGET_ERROR(target, fmt_str,...)
Definition: log.h:163
#define LOG_TARGET_DEBUG(target, fmt_str,...)
Definition: log.h:151
#define ERROR_TIMEOUT_REACHED
Definition: log.h:178
#define ERROR_OK
Definition: log.h:169
int riscv013_set_register_buf(struct target *target, enum gdb_regno regno, const uint8_t *value)
Definition: riscv-013.c:2419
uint32_t riscv013_access_register_command(struct target *target, uint32_t number, unsigned int size, uint32_t flags)
Definition: riscv-013.c:879
int riscv013_get_register_buf(struct target *target, uint8_t *value, enum gdb_regno regno)
Definition: riscv-013.c:2364
int riscv013_execute_abstract_command(struct target *target, uint32_t command, uint32_t *cmderr)
Definition: riscv-013.c:740
static int assume_reg_exist(struct target *target, uint32_t regno)
Some registers are optional (e.g.
static int check_misa_mxl(const struct target *target)
unsigned int mxl_to_xlen(enum misa_mxl mxl)
int riscv013_reg_examine_all(struct target *target)
This function assumes target's DM to be initialized (target is able to access DMs registers,...
static int examine_xlen(struct target *target)
static int riscv013_reg_get(struct reg *reg)
Definition: riscv-013_reg.c:16
int riscv013_reg_save(struct target *target, enum gdb_regno regid)
This function is used to save the value of a register in cache.
static int examine_vlenb(struct target *target)
static int examine_mtopi(struct target *target)
static int examine_misa(struct target *target)
static int init_cache_entry(struct target *target, uint32_t regno)
Definition: riscv-013_reg.c:85
misa_mxl
@ MISA_MXL_INVALID
@ MISA_MXL_128
@ MISA_MXL_32
@ MISA_MXL_64
static int riscv013_reg_set(struct reg *reg, uint8_t *buf)
Definition: riscv-013_reg.c:46
static const struct reg_arch_type * riscv013_gdb_regno_reg_type(uint32_t regno)
Definition: riscv-013_reg.c:76
unsigned int riscv_xlen(const struct target *target)
Definition: riscv.c:6060
bool riscv_supports_extension(const struct target *target, char letter)
Definition: riscv.c:6047
#define RISCV_INFO(R)
Definition: riscv.h:426
uint64_t riscv_reg_t
Definition: riscv.h:46
int riscv_reg_impl_set_exist(const struct target *target, uint32_t regno, bool exist)
Mark register as existing or not.
Definition: riscv_reg.c:601
void riscv_reg_impl_hide_csrs(const struct target *target)
Hide additional CSRs, as specified by riscv_info_t::hide_csr list.
Definition: riscv_reg.c:736
bool riscv_reg_impl_gdb_regno_exist(const struct target *target, uint32_t regno)
For most registers, returns whether they exist or not.
Definition: riscv_reg.c:368
struct target * riscv_reg_impl_get_target(const struct reg *reg)
Return the target that owns the cache entry.
Definition: riscv_reg.c:207
int riscv_reg_set(struct target *target, enum gdb_regno regid, riscv_reg_t value)
This function is used to change the value of a register.
Definition: riscv_reg.c:918
const char * riscv_reg_gdb_regno_name(const struct target *target, enum gdb_regno regno)
This file describes the register cache interface available to the RISC-V target.
Definition: riscv_reg.c:171
int riscv_reg_impl_expose_csrs(const struct target *target)
Expose additional CSRs, as specified by riscv_info_t::expose_csr list.
Definition: riscv_reg.c:709
int riscv_reg_impl_init_cache_entry(struct target *target, uint32_t regno, bool exist, const struct reg_arch_type *reg_type)
Initialize register.
Definition: riscv_reg.c:608
int riscv_reg_impl_init_cache(struct target *target)
Initialize register cache.
Definition: riscv_reg.c:678
int riscv_reg_get(struct target *target, riscv_reg_t *value, enum gdb_regno regid)
This function is used to get the value of a register.
Definition: riscv_reg.c:952
struct reg * riscv_reg_impl_cache_entry(const struct target *target, uint32_t number)
Return the entry in the register cache of the target.
Definition: riscv_reg.c:571
static bool riscv_reg_impl_is_initialized(const struct reg *reg)
This file describes the helpers to use during register cache initialization of a RISC-V target.
static void init_shared_reg_info(struct target *target)
static void riscv_reg_impl_init_vector_reg_type(const struct target *target)
TODO: vector register type description can be moved into riscv013_info_t, since 0....
static bool riscv_reg_impl_gdb_regno_cacheable(enum gdb_regno regno, bool is_write)
If write is true: return true iff we are guaranteed that the register will contain exactly the value ...
int(* get)(struct reg *reg)
Definition: register.h:152
unsigned int num_regs
Definition: register.h:148
Definition: register.h:111
bool valid
Definition: register.h:126
uint32_t size
Definition: register.h:132
uint8_t * value
Definition: register.h:122
uint32_t number
Definition: register.h:115
bool dirty
Definition: register.h:124
const char * name
Definition: register.h:113
Definition: target.h:119
enum target_state state
Definition: target.h:160
struct reg_cache * reg_cache
Definition: target.h:161
static bool target_was_examined(const struct target *target)
Definition: target.h:432
@ TARGET_HALTED
Definition: target.h:58
int64_t timeval_ms(void)
#define DIV_ROUND_UP(m, n)
Rounds m up to the nearest multiple of n using division.
Definition: types.h:79