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+
164253static 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
179267static int examine_mtopi (struct target * target )
@@ -214,8 +302,6 @@ static int examine_mtopi(struct target *target)
214302 */
215303int 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