From 88c443cfc931986a2cc18a4b9076433cb0bbd62c Mon Sep 17 00:00:00 2001
From: YenHaoChen <howard25336284@gmail.com>
Date: Thu, 11 Apr 2024 14:25:18 +0800
Subject: [PATCH] Smstateen: Implement *stateen0[59] controlling RV32-only CSRs
 (v)siph, (v)sieh, hidelegh, and hviph

---
 riscv/csrs.cc      | 16 ++++++++++++++++
 riscv/csrs.h       |  6 ++++++
 riscv/processor.cc | 12 ++++++------
 3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/riscv/csrs.cc b/riscv/csrs.cc
index 0a65e189ff..732fb23c14 100644
--- a/riscv/csrs.cc
+++ b/riscv/csrs.cc
@@ -592,6 +592,22 @@ reg_t rv32_high_csr_t::written_value() const noexcept {
   return (orig->written_value() >> 32) & 0xffffffffU;
 }
 
+aia_rv32_high_csr_t::aia_rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig):
+  rv32_high_csr_t(proc, addr, orig) {
+}
+
+void aia_rv32_high_csr_t::verify_permissions(insn_t insn, bool write) const {
+  if (proc->extension_enabled(EXT_SMSTATEEN)) {
+    if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_AIA))
+      throw trap_illegal_instruction(insn.bits());
+
+    if (state->v && !(state->hstateen[0]->read() & HSTATEEN0_AIA))
+      throw trap_virtual_instruction(insn.bits());
+  }
+
+  aia_rv32_high_csr_t::verify_permissions(insn, write);
+}
+
 // implement class sstatus_csr_t
 sstatus_csr_t::sstatus_csr_t(processor_t* const proc, sstatus_proxy_csr_t_p orig, vsstatus_csr_t_p virt):
   virtualized_csr_t(proc, orig, virt),
diff --git a/riscv/csrs.h b/riscv/csrs.h
index 5a44f5762e..1e9bbb3c4c 100644
--- a/riscv/csrs.h
+++ b/riscv/csrs.h
@@ -300,6 +300,12 @@ class rv32_high_csr_t: public csr_t {
   csr_t_p orig;
 };
 
+class aia_rv32_high_csr_t: public rv32_high_csr_t {
+ public:
+  aia_rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig);
+  virtual void verify_permissions(insn_t insn, bool write) const override;
+};
+
 class sstatus_proxy_csr_t final: public base_status_csr_t {
  public:
   sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus);
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 9be18e51ae..d94444af54 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -353,9 +353,9 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
   auto sip = std::make_shared<virtualized_stimecmp_csr_t>(proc, nonvirtual_sip, vsip);
   if (xlen == 32 && proc->extension_enabled_const(EXT_SSAIA)) {
     csrmap[CSR_VSIP] = std::make_shared<rv32_low_csr_t>(proc, CSR_VSIP, vsip);
-    csrmap[CSR_VSIPH] = std::make_shared<rv32_high_csr_t>(proc, CSR_VSIPH, vsip);
+    csrmap[CSR_VSIPH] = std::make_shared<aia_rv32_high_csr_t>(proc, CSR_VSIPH, vsip);
     csrmap[CSR_SIP] = std::make_shared<rv32_low_csr_t>(proc, CSR_SIP, sip);
-    csrmap[CSR_SIPH] = std::make_shared<rv32_high_csr_t>(proc, CSR_SIPH, sip);
+    csrmap[CSR_SIPH] = std::make_shared<aia_rv32_high_csr_t>(proc, CSR_SIPH, sip);
   } else {
     csrmap[CSR_VSIP] = vsip;
     csrmap[CSR_SIP] = sip;
@@ -364,7 +364,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
   hvip = std::make_shared<hvip_csr_t>(proc, CSR_HVIP, 0);
   if (xlen == 32 && proc->extension_enabled_const(EXT_SSAIA)) {
     csrmap[CSR_HVIP] = std::make_shared<rv32_low_csr_t>(proc, CSR_HVIP, hvip);
-    csrmap[CSR_HVIPH] = std::make_shared<rv32_high_csr_t>(proc, CSR_HVIPH, hvip);
+    csrmap[CSR_HVIPH] = std::make_shared<aia_rv32_high_csr_t>(proc, CSR_HVIPH, hvip);
   } else {
     csrmap[CSR_HVIP] = hvip;
   }
@@ -374,9 +374,9 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
   auto sie = std::make_shared<virtualized_stimecmp_csr_t>(proc, nonvirtual_sie, vsie);
   if (xlen == 32 && proc->extension_enabled_const(EXT_SSAIA)) {
     csrmap[CSR_VSIE] = std::make_shared<rv32_low_csr_t>(proc, CSR_VSIE, vsie);
-    csrmap[CSR_VSIEH] = std::make_shared<rv32_high_csr_t>(proc, CSR_VSIEH, vsie);
+    csrmap[CSR_VSIEH] = std::make_shared<aia_rv32_high_csr_t>(proc, CSR_VSIEH, vsie);
     csrmap[CSR_SIE] = std::make_shared<rv32_low_csr_t>(proc, CSR_SIE, sie);
-    csrmap[CSR_SIEH] = std::make_shared<rv32_high_csr_t>(proc, CSR_SIEH, sie);
+    csrmap[CSR_SIEH] = std::make_shared<aia_rv32_high_csr_t>(proc, CSR_SIEH, sie);
   } else {
     csrmap[CSR_VSIE] = vsie;
     csrmap[CSR_SIE] = sie;
@@ -427,7 +427,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
   hideleg = std::make_shared<hideleg_csr_t>(proc, CSR_HIDELEG, mideleg);
   if (xlen == 32 && proc->extension_enabled_const(EXT_SSAIA)) {
     csrmap[CSR_HIDELEG] = std::make_shared<rv32_low_csr_t>(proc, CSR_HIDELEG, hideleg);
-    csrmap[CSR_HIDELEGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_HIDELEGH, hideleg);
+    csrmap[CSR_HIDELEGH] = std::make_shared<aia_rv32_high_csr_t>(proc, CSR_HIDELEGH, hideleg);
   } else {
     csrmap[CSR_HIDELEG] = hideleg;
   }