aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fesvr/htif.h8
-rw-r--r--riscv/common.h2
-rw-r--r--riscv/csrs.cc32
-rw-r--r--riscv/csrs.h2
-rw-r--r--riscv/isa_parser.cc2
-rw-r--r--riscv/isa_parser.h1
-rw-r--r--riscv/mmu.h27
-rw-r--r--riscv/processor.cc42
-rw-r--r--riscv/sim.cc4
9 files changed, 77 insertions, 43 deletions
diff --git a/fesvr/htif.h b/fesvr/htif.h
index 3cee25f..ca5b362 100644
--- a/fesvr/htif.h
+++ b/fesvr/htif.h
@@ -31,26 +31,18 @@ class htif_t : public chunked_memif_t
template<typename T> inline T from_target(target_endian<T> n) const
{
-#ifdef RISCV_ENABLE_DUAL_ENDIAN
memif_endianness_t endianness = get_target_endianness();
assert(endianness == memif_endianness_little || endianness == memif_endianness_big);
return endianness == memif_endianness_big? n.from_be() : n.from_le();
-#else
- return n.from_le();
-#endif
}
template<typename T> inline target_endian<T> to_target(T n) const
{
-#ifdef RISCV_ENABLE_DUAL_ENDIAN
memif_endianness_t endianness = get_target_endianness();
assert(endianness == memif_endianness_little || endianness == memif_endianness_big);
return endianness == memif_endianness_big? target_endian<T>::to_be(n) : target_endian<T>::to_le(n);
-#else
- return target_endian<T>::to_le(n);
-#endif
}
protected:
diff --git a/riscv/common.h b/riscv/common.h
index 002a83f..7d37001 100644
--- a/riscv/common.h
+++ b/riscv/common.h
@@ -8,11 +8,13 @@
# define unlikely(x) __builtin_expect(x, 0)
# define NOINLINE __attribute__ ((noinline))
# define NORETURN __attribute__ ((noreturn))
+# define ALWAYS_INLINE __attribute__ ((always_inline))
#else
# define likely(x) (x)
# define unlikely(x) (x)
# define NOINLINE
# define NORETURN
+# define ALWAYS_INLINE
#endif
#endif
diff --git a/riscv/csrs.cc b/riscv/csrs.cc
index 27bef5e..3cb6af2 100644
--- a/riscv/csrs.cc
+++ b/riscv/csrs.cc
@@ -272,6 +272,12 @@ mseccfg_csr_t::mseccfg_csr_t(processor_t* const proc, const reg_t addr):
basic_csr_t(proc, addr, 0) {
}
+void mseccfg_csr_t::verify_permissions(insn_t insn, bool write) const {
+ basic_csr_t::verify_permissions(insn, write);
+ if (!proc->extension_enabled(EXT_SMEPMP))
+ throw trap_illegal_instruction(insn.bits());
+}
+
bool mseccfg_csr_t::get_mml() const noexcept {
return (read() & MSECCFG_MML);
}
@@ -466,15 +472,7 @@ bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
// implement class mstatus_csr_t
mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr):
base_status_csr_t(proc, addr),
- val(0
- | (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
- | (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
-
-#ifdef RISCV_ENABLE_DUAL_ENDIAN
- | (proc->get_mmu()->is_target_big_endian() ? MSTATUS_UBE | MSTATUS_SBE | MSTATUS_MBE : 0)
-#endif
- | 0 // initial value for mstatus
- ) {
+ val(compute_mstatus_initial_value()) {
}
bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
@@ -482,7 +480,8 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
const bool has_gva = has_mpv;
const reg_t mask = sstatus_write_mask
- | MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPRV
+ | MSTATUS_MIE | MSTATUS_MPIE
+ | (proc->extension_enabled('U') ? MSTATUS_MPRV : 0)
| MSTATUS_MPP | MSTATUS_TW
| (proc->extension_enabled('S') ? MSTATUS_TSR : 0)
| (has_page ? MSTATUS_TVM : 0)
@@ -497,6 +496,17 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
return true;
}
+reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept {
+ const reg_t big_endian_bits = (proc->extension_enabled_const('U') ? MSTATUS_UBE : 0)
+ | (proc->extension_enabled_const('S') ? MSTATUS_SBE : 0)
+ | MSTATUS_MBE;
+ return 0
+ | (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
+ | (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
+ | (proc->get_mmu()->is_target_big_endian() ? big_endian_bits : 0)
+ | 0; // initial value for mstatus
+}
+
// implement class rv32_low_csr_t
rv32_low_csr_t::rv32_low_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig):
csr_t(proc, addr),
@@ -889,7 +899,7 @@ satp_csr_t::satp_csr_t(processor_t* const proc, const reg_t addr):
void satp_csr_t::verify_permissions(insn_t insn, bool write) const {
base_atp_csr_t::verify_permissions(insn, write);
if (get_field(state->mstatus->read(), MSTATUS_TVM))
- require(state->prv >= PRV_M);
+ require(state->prv == PRV_M);
}
virtualized_satp_csr_t::virtualized_satp_csr_t(processor_t* const proc, satp_csr_t_p orig, csr_t_p virt):
diff --git a/riscv/csrs.h b/riscv/csrs.h
index 34bc9d0..c979942 100644
--- a/riscv/csrs.h
+++ b/riscv/csrs.h
@@ -132,6 +132,7 @@ class pmpcfg_csr_t: public csr_t {
class mseccfg_csr_t: public basic_csr_t {
public:
mseccfg_csr_t(processor_t* const proc, const reg_t addr);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
bool get_mml() const noexcept;
bool get_mmwp() const noexcept;
bool get_rlb() const noexcept;
@@ -246,6 +247,7 @@ class mstatus_csr_t final: public base_status_csr_t {
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
private:
+ reg_t compute_mstatus_initial_value() const noexcept;
reg_t val;
};
diff --git a/riscv/isa_parser.cc b/riscv/isa_parser.cc
index 720f373..81b770c 100644
--- a/riscv/isa_parser.cc
+++ b/riscv/isa_parser.cc
@@ -164,6 +164,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
} else if (ext_str == "zkr") {
extension_table[EXT_ZKR] = true;
} else if (ext_str == "zkt") {
+ } else if (ext_str == "smepmp") {
+ extension_table[EXT_SMEPMP] = true;
} else if (ext_str == "smstateen") {
extension_table[EXT_SMSTATEEN] = true;
} else if (ext_str == "svnapot") {
diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h
index 8debf5d..6065dbc 100644
--- a/riscv/isa_parser.h
+++ b/riscv/isa_parser.h
@@ -31,6 +31,7 @@ typedef enum {
EXT_ZBPBO,
EXT_ZPN,
EXT_ZPSFOPERAND,
+ EXT_SMEPMP,
EXT_SMSTATEEN,
EXT_SVNAPOT,
EXT_SVPBMT,
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 5e776a9..6f24ec7 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -56,8 +56,15 @@ public:
{
#ifdef RISCV_ENABLE_MISALIGNED
reg_t res = 0;
- for (size_t i = 0; i < size; i++)
- res += (reg_t)load_uint8(addr + (target_big_endian? size-1-i : i)) << (i * 8);
+ for (size_t i = 0; i < size; i++) {
+ const reg_t byteaddr = addr + (target_big_endian? size-1-i : i);
+ const reg_t bytedata
+ = (RISCV_XLATE_VIRT_HLVX & xlate_flags) ? guest_load_x_uint8(byteaddr)
+ : (RISCV_XLATE_VIRT & xlate_flags) ? guest_load_uint8(byteaddr)
+ : load_uint8(byteaddr)
+ ;
+ res += bytedata << (i * 8);
+ }
return res;
#else
bool gva = ((proc) ? proc->state.v : false) || (RISCV_XLATE_VIRT & xlate_flags);
@@ -68,8 +75,15 @@ public:
inline void misaligned_store(reg_t addr, reg_t data, size_t size, uint32_t xlate_flags, bool actually_store=true)
{
#ifdef RISCV_ENABLE_MISALIGNED
- for (size_t i = 0; i < size; i++)
- store_uint8(addr + (target_big_endian? size-1-i : i), data >> (i * 8), actually_store);
+ for (size_t i = 0; i < size; i++) {
+ const reg_t byteaddr = addr + (target_big_endian? size-1-i : i);
+ const reg_t bytedata = data >> (i * 8);
+ if (RISCV_XLATE_VIRT & xlate_flags) {
+ guest_store_uint8(byteaddr, bytedata, actually_store);
+ } else {
+ store_uint8(byteaddr, bytedata, actually_store);
+ }
+ }
#else
bool gva = ((proc) ? proc->state.v : false) || (RISCV_XLATE_VIRT & xlate_flags);
throw trap_store_address_misaligned(gva, addr, 0, 0);
@@ -85,7 +99,7 @@ public:
// template for functions that load an aligned value from memory
#define load_func(type, prefix, xlate_flags) \
- inline type##_t prefix##_##type(reg_t addr, bool require_alignment = false) { \
+ type##_t ALWAYS_INLINE prefix##_##type(reg_t addr, bool require_alignment = false) { \
if (unlikely(addr & (sizeof(type##_t)-1))) { \
if (require_alignment) load_reserved_address_misaligned(addr); \
else return misaligned_load(addr, sizeof(type##_t), xlate_flags); \
@@ -123,6 +137,7 @@ public:
load_func(uint16, guest_load, RISCV_XLATE_VIRT)
load_func(uint32, guest_load, RISCV_XLATE_VIRT)
load_func(uint64, guest_load, RISCV_XLATE_VIRT)
+ load_func(uint8, guest_load_x, RISCV_XLATE_VIRT|RISCV_XLATE_VIRT_HLVX) // only for use by misaligned HLVX
load_func(uint16, guest_load_x, RISCV_XLATE_VIRT|RISCV_XLATE_VIRT_HLVX)
load_func(uint32, guest_load_x, RISCV_XLATE_VIRT|RISCV_XLATE_VIRT_HLVX)
@@ -147,7 +162,7 @@ public:
// template for functions that store an aligned value to memory
#define store_func(type, prefix, xlate_flags) \
- void prefix##_##type(reg_t addr, type##_t val, bool actually_store=true, bool require_alignment=false) { \
+ void ALWAYS_INLINE prefix##_##type(reg_t addr, type##_t val, bool actually_store=true, bool require_alignment=false) { \
if (unlikely(addr & (sizeof(type##_t)-1))) { \
if (require_alignment) store_conditional_address_misaligned(addr); \
else return misaligned_store(addr, val, sizeof(type##_t), xlate_flags, actually_store); \
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 642f1fb..6d0d349 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -401,20 +401,34 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
csrmap[CSR_MIMPID] = std::make_shared<const_csr_t>(proc, CSR_MIMPID, 0);
csrmap[CSR_MVENDORID] = std::make_shared<const_csr_t>(proc, CSR_MVENDORID, 0);
csrmap[CSR_MHARTID] = std::make_shared<const_csr_t>(proc, CSR_MHARTID, proc->get_id());
- const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) |
- (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) |
- (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0);
- const reg_t menvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0);
- csrmap[CSR_MENVCFG] = menvcfg = std::make_shared<masked_csr_t>(proc, CSR_MENVCFG, menvcfg_mask, menvcfg_init);
- const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) |
- (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0);
- csrmap[CSR_SENVCFG] = senvcfg = std::make_shared<senvcfg_csr_t>(proc, CSR_SENVCFG, senvcfg_mask, 0);
- const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) |
- (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) |
- (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0);
- const reg_t henvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0);
- csrmap[CSR_HENVCFG] = henvcfg = std::make_shared<henvcfg_csr_t>(proc, CSR_HENVCFG, henvcfg_mask, henvcfg_init, menvcfg);
-
+ csrmap[CSR_MCONFIGPTR] = std::make_shared<const_csr_t>(proc, CSR_MCONFIGPTR, 0);
+ if (proc->extension_enabled_const('U')) {
+ const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) |
+ (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) |
+ (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0);
+ const reg_t menvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0);
+ menvcfg = std::make_shared<masked_csr_t>(proc, CSR_MENVCFG, menvcfg_mask, menvcfg_init);
+ if (xlen == 32) {
+ csrmap[CSR_MENVCFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MENVCFG, menvcfg);
+ csrmap[CSR_MENVCFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MENVCFGH, menvcfg);
+ } else {
+ csrmap[CSR_MENVCFG] = menvcfg;
+ }
+ const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) |
+ (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0);
+ csrmap[CSR_SENVCFG] = senvcfg = std::make_shared<senvcfg_csr_t>(proc, CSR_SENVCFG, senvcfg_mask, 0);
+ const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) |
+ (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) |
+ (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0);
+ const reg_t henvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0);
+ henvcfg = std::make_shared<henvcfg_csr_t>(proc, CSR_HENVCFG, henvcfg_mask, henvcfg_init, menvcfg);
+ if (xlen == 32) {
+ csrmap[CSR_HENVCFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_HENVCFG, henvcfg);
+ csrmap[CSR_HENVCFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_HENVCFGH, henvcfg);
+ } else {
+ csrmap[CSR_HENVCFG] = henvcfg;
+ }
+ }
if (proc->extension_enabled_const(EXT_SMSTATEEN)) {
const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) | SSTATEEN0_CS;
const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN;
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 069e1b5..0000537 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -425,11 +425,7 @@ void sim_t::set_target_endianness(memif_endianness_t endianness)
memif_endianness_t sim_t::get_target_endianness() const
{
-#ifdef RISCV_ENABLE_DUAL_ENDIAN
return debug_mmu->is_target_big_endian()? memif_endianness_big : memif_endianness_little;
-#else
- return memif_endianness_little;
-#endif
}
void sim_t::proc_reset(unsigned id)