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"
@@ -173,6 +174,94 @@ static int examine_vlenb(struct target *target)
173174 return ERROR_OK ;
174175}
175176
177+ enum misa_mxl {
178+ MISA_MXL_INVALID = 0 ,
179+ MISA_MXL_32 = 1 ,
180+ MISA_MXL_64 = 2 ,
181+ MISA_MXL_128 = 3
182+ };
183+
184+ unsigned int mxl_to_xlen (enum misa_mxl mxl )
185+ {
186+ switch (mxl ) {
187+ case MISA_MXL_32 :
188+ return 32 ;
189+ case MISA_MXL_64 :
190+ return 64 ;
191+ case MISA_MXL_128 :
192+ return 128 ;
193+ case MISA_MXL_INVALID :
194+ assert (0 );
195+ }
196+ return 0 ;
197+ }
198+
199+ static int check_misa_mxl (const struct target * target )
200+ {
201+ RISCV_INFO (r );
202+
203+ if (r -> misa == 0 ) {
204+ LOG_TARGET_WARNING (target , "'misa' register is read as zero."
205+ "OpenOCD will not be able to determine some hart's capabilities." );
206+ return ERROR_OK ;
207+ }
208+ const unsigned int dxlen = riscv_xlen (target );
209+ assert (dxlen <= sizeof (riscv_reg_t ) * CHAR_BIT );
210+ assert (dxlen >= 2 );
211+ const riscv_reg_t misa_mxl_mask = (riscv_reg_t )0x3 << (dxlen - 2 );
212+ const unsigned int mxl = get_field (r -> misa , misa_mxl_mask );
213+ if (mxl == MISA_MXL_INVALID ) {
214+ /* This is not an error!
215+ * Imagine the platform that:
216+ * - Has no abstract access to CSRs, so that CSRs are read
217+ * through Program Buffer via "csrr" instruction.
218+ * - Complies to v1.10 of the Priveleged Spec, so that misa.mxl
219+ * is WARL and MXLEN may be chainged.
220+ * https://github.com/riscv/riscv-isa-manual/commit/9a7dd2fe29011587954560b5dcf1875477b27ad8
221+ * - DXLEN == MXLEN on reset == 64.
222+ * In a following scenario:
223+ * - misa.mxl was written, so that MXLEN is 32.
224+ * - Debugger connects to the target.
225+ * - Debugger observes DXLEN == 64.
226+ * - Debugger reads misa:
227+ * - Abstract access fails with "cmderr == not supported".
228+ * - Access via Program Buffer involves reading "misa" to an
229+ * "xreg" via "csrr", so that the "xreg" is filled with
230+ * zero-extended value of "misa" (since "misa" is
231+ * MXLEN-wide).
232+ * - Debugger derives "misa.mxl" assumig "misa" is DXLEN-bit
233+ * wide (64) while MXLEN is 32 and therefore erroneously
234+ * assumes "misa.mxl" to be zero (invalid).
235+ */
236+ LOG_TARGET_WARNING (target , "Detected DXLEN (%u) does not match "
237+ "MXLEN: misa.mxl == 0, misa == 0x%" PRIx64 "." ,
238+ dxlen , r -> misa );
239+ return ERROR_OK ;
240+ }
241+ const unsigned int mxlen = mxl_to_xlen (mxl );
242+ if (dxlen < mxlen ) {
243+ LOG_TARGET_ERROR (target ,
244+ "MXLEN (%u) reported in misa.mxl field exceeds "
245+ "the detected DXLEN (%u)" ,
246+ mxlen , dxlen );
247+ return ERROR_FAIL ;
248+ }
249+ /* NOTE:
250+ * The value of "misa.mxl" may stil not coincide with "xlen".
251+ * "misa[26:XLEN-3]" bits are marked as WIRI in at least version 1.10
252+ * of RISC-V Priveleged Spec. Therefore, if "xlen" is erroneously
253+ * assumed to be 32 when it actually is 64, "mxl" will be read from
254+ * this WIRI field and may be equal to "MISA_MXL_32" by coincidence.
255+ * This is not an issue though from the version 1.11 onward, since
256+ * "misa[26:XLEN-3]" became WARL and equal to 0.
257+ */
258+
259+ /* Display this as early as possible to help people who are using
260+ * really slow simulators. */
261+ LOG_TARGET_DEBUG (target , " XLEN=%d, misa=0x%" PRIx64 , riscv_xlen (target ), r -> misa );
262+ return ERROR_OK ;
263+ }
264+
176265static int examine_misa (struct target * target )
177266{
178267 RISCV_INFO (r );
@@ -184,8 +273,7 @@ static int examine_misa(struct target *target)
184273 res = riscv_reg_get (target , & r -> misa , GDB_REGNO_MISA );
185274 if (res != ERROR_OK )
186275 return res ;
187-
188- return ERROR_OK ;
276+ return check_misa_mxl (target );
189277}
190278
191279static int examine_mtopi (struct target * target )
@@ -226,8 +314,6 @@ static int examine_mtopi(struct target *target)
226314 */
227315int riscv013_reg_examine_all (struct target * target )
228316{
229- RISCV_INFO (r );
230-
231317 int res = riscv_reg_impl_init_cache (target );
232318 if (res != ERROR_OK )
233319 return res ;
@@ -253,10 +339,6 @@ int riscv013_reg_examine_all(struct target *target)
253339 if (res != ERROR_OK )
254340 return res ;
255341
256- /* Display this as early as possible to help people who are using
257- * really slow simulators. */
258- LOG_TARGET_DEBUG (target , " XLEN=%d, misa=0x%" PRIx64 , riscv_xlen (target ), r -> misa );
259-
260342 res = examine_vlenb (target );
261343 if (res != ERROR_OK )
262344 return res ;
0 commit comments