diff options
-rw-r--r-- | fesvr/htif.h | 8 | ||||
-rw-r--r-- | riscv/common.h | 2 | ||||
-rw-r--r-- | riscv/csrs.cc | 32 | ||||
-rw-r--r-- | riscv/csrs.h | 2 | ||||
-rw-r--r-- | riscv/isa_parser.cc | 2 | ||||
-rw-r--r-- | riscv/isa_parser.h | 1 | ||||
-rw-r--r-- | riscv/mmu.h | 27 | ||||
-rw-r--r-- | riscv/processor.cc | 42 | ||||
-rw-r--r-- | riscv/sim.cc | 4 |
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) |