Skip to content

Commit 3cd99c0

Browse files
authored
Merge pull request #1112 from en-sc/en-sc/misa-xlen
target/riscv: check `misa` value before reporting
2 parents d58c656 + 6c021da commit 3cd99c0

File tree

1 file changed

+90
-8
lines changed

1 file changed

+90
-8
lines changed

src/target/riscv/riscv-013_reg.c

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#endif
66

77
#include "riscv-013_reg.h"
8+
#include "field_helpers.h"
89

910
#include "riscv_reg.h"
1011
#include "riscv_reg_impl.h"
@@ -161,6 +162,94 @@ static int examine_vlenb(struct target *target)
161162
return ERROR_OK;
162163
}
163164

165+
enum misa_mxl {
166+
MISA_MXL_INVALID = 0,
167+
MISA_MXL_32 = 1,
168+
MISA_MXL_64 = 2,
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) {
231+
LOG_TARGET_ERROR(target,
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+
164253
static int examine_misa(struct target *target)
165254
{
166255
RISCV_INFO(r);
@@ -172,8 +261,7 @@ static int examine_misa(struct target *target)
172261
res = riscv_reg_get(target, &r->misa, GDB_REGNO_MISA);
173262
if (res != ERROR_OK)
174263
return res;
175-
176-
return ERROR_OK;
264+
return check_misa_mxl(target);
177265
}
178266

179267
static int examine_mtopi(struct target *target)
@@ -214,8 +302,6 @@ static int examine_mtopi(struct target *target)
214302
*/
215303
int riscv013_reg_examine_all(struct target *target)
216304
{
217-
RISCV_INFO(r);
218-
219305
int res = riscv_reg_impl_init_cache(target);
220306
if (res != ERROR_OK)
221307
return res;
@@ -241,10 +327,6 @@ int riscv013_reg_examine_all(struct target *target)
241327
if (res != ERROR_OK)
242328
return res;
243329

244-
/* Display this as early as possible to help people who are using
245-
* really slow simulators. */
246-
LOG_TARGET_DEBUG(target, " XLEN=%d, misa=0x%" PRIx64, riscv_xlen(target), r->misa);
247-
248330
res = examine_vlenb(target);
249331
if (res != ERROR_OK)
250332
return res;

0 commit comments

Comments
 (0)