diff --git a/src/target/riscv/gdb_regs.h b/src/target/riscv/gdb_regs.h index 3a4657743..08926b5a7 100644 --- a/src/target/riscv/gdb_regs.h +++ b/src/target/riscv/gdb_regs.h @@ -98,6 +98,8 @@ enum gdb_regno { GDB_REGNO_MEPC = CSR_MEPC + GDB_REGNO_CSR0, GDB_REGNO_MCAUSE = CSR_MCAUSE + GDB_REGNO_CSR0, GDB_REGNO_SATP = CSR_SATP + GDB_REGNO_CSR0, + GDB_REGNO_MTOPI = CSR_MTOPI + GDB_REGNO_CSR0, + GDB_REGNO_MTOPEI = CSR_MTOPEI + GDB_REGNO_CSR0, GDB_REGNO_CSR4095 = GDB_REGNO_CSR0 + 4095, GDB_REGNO_PRIV = 4161, /* It's still undecided what register numbers GDB will actually use for diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 3043b0614..e15384ad7 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1725,16 +1725,30 @@ static int examine(struct target *target) return ERROR_FAIL; } - uint64_t vlenb; - if (register_read_direct(target, &vlenb, GDB_REGNO_VLENB) != ERROR_OK) { + uint64_t value; + if (register_read_direct(target, &value, GDB_REGNO_VLENB) != ERROR_OK) { if (riscv_supports_extension(target, 'V')) LOG_TARGET_WARNING(target, "Couldn't read vlenb; vector register access won't work."); r->vlenb = 0; } else { - r->vlenb = vlenb; + r->vlenb = value; LOG_TARGET_INFO(target, "Vector support with vlenb=%d", r->vlenb); } + if (register_read_direct(target, &value, GDB_REGNO_MTOPI) == ERROR_OK) { + r->mtopi_readable = true; + + if (register_read_direct(target, &value, GDB_REGNO_MTOPEI) == ERROR_OK) { + LOG_TARGET_INFO(target, "S?aia detected with IMSIC"); + r->mtopei_readable = true; + } else { + r->mtopei_readable = false; + LOG_TARGET_INFO(target, "S?aia detected without IMSIC"); + } + } else { + r->mtopi_readable = false; + } + /* Now init registers based on what we discovered. */ if (riscv_init_registers(target) != ERROR_OK) return ERROR_FAIL; diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 5f6c2dbb1..3e7daafef 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -5400,6 +5400,72 @@ int riscv_init_registers(struct target *target) case CSR_MCOUNTEREN: r->exist = riscv_supports_extension(target, 'U'); break; + + /* Interrupts M-Mode CSRs. */ + case CSR_MISELECT: + case CSR_MIREG: + case CSR_MTOPI: + case CSR_MVIEN: + case CSR_MVIP: + r->exist = info->mtopi_readable; + break; + case CSR_MTOPEI: + r->exist = info->mtopei_readable; + break; + case CSR_MIDELEGH: + case CSR_MVIENH: + case CSR_MVIPH: + r->exist = info->mtopi_readable && + riscv_xlen(target) == 32 && + riscv_supports_extension(target, 'S'); + break; + case CSR_MIEH: + case CSR_MIPH: + r->exist = info->mtopi_readable; + break; + /* Interrupts S-Mode CSRs. */ + case CSR_SISELECT: + case CSR_SIREG: + case CSR_STOPI: + r->exist = info->mtopi_readable && + riscv_supports_extension(target, 'S'); + break; + case CSR_STOPEI: + r->exist = info->mtopei_readable && + riscv_supports_extension(target, 'S'); + break; + case CSR_SIEH: + case CSR_SIPH: + r->exist = info->mtopi_readable && + riscv_xlen(target) == 32 && + riscv_supports_extension(target, 'S'); + break; + /* Interrupts Hypervisor and VS CSRs. */ + case CSR_HVIEN: + case CSR_HVICTL: + case CSR_HVIPRIO1: + case CSR_HVIPRIO2: + case CSR_VSISELECT: + case CSR_VSIREG: + case CSR_VSTOPI: + r->exist = info->mtopi_readable && + riscv_supports_extension(target, 'V'); + break; + case CSR_VSTOPEI: + r->exist = info->mtopei_readable && + riscv_supports_extension(target, 'V'); + break; + case CSR_HIDELEGH: + case CSR_HVIENH: + case CSR_HVIPH: + case CSR_HVIPRIO1H: + case CSR_HVIPRIO2H: + case CSR_VSIEH: + case CSR_VSIPH: + r->exist = info->mtopi_readable && + riscv_xlen(target) == 32 && + riscv_supports_extension(target, 'V'); + break; } if (!r->exist && !list_empty(&info->expose_csr)) { diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 6b4d577c8..a6a1f93da 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -124,6 +124,9 @@ typedef struct { * Zve* extensions implement vector registers without setting misa.V. */ unsigned int vlenb; + bool mtopi_readable; + bool mtopei_readable; + /* The number of triggers per hart. */ unsigned int trigger_count;