Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/iss/arch/riscv_hart_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,11 @@ template <typename WORD_TYPE> struct priv_if {
};

template <typename BASE = logging::disass> struct riscv_hart_common : public BASE, public mem::memory_elem {
// Extension status bits (SD needs to be set when writing FS / VS / XS):
// TODO implement XS
static constexpr uint32_t extension_status_mask =
(traits<BASE>::FP_REGS_SIZE ? (0b11u << 13) : 0u) | (traits<BASE>::V_REGS_SIZE ? (0b11u << 9) : 0u);

const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
const std::array<const char*, 16> trap_str = {{""
"Instruction address misaligned", // 0
Expand Down
87 changes: 53 additions & 34 deletions src/iss/arch/riscv_hart_m_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,46 +63,65 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_m_p : pub
using reg_t = typename core::reg_t;
using phys_addr_t = typename core::phys_addr_t;

// Notation for differing fields is: 32 bits / 64 bits
static constexpr uint32_t lower_half = 0b00000000000000000001100010001000;
// ||||||||||||||||/|/|/|/|||||||||
// |||||||||||||||| | | | ||||||||+-- UIE
// |||||||||||||||| | | | |||||||+--- SIE
// |||||||||||||||| | | | ||||||+---- WPRI
// |||||||||||||||| | | | |||||+----- MIE
// |||||||||||||||| | | | ||||+------ UPIE
// |||||||||||||||| | | | |||+------- SPIE
// |||||||||||||||| | | | ||+-------- UBE
// |||||||||||||||| | | | |+--------- MPIE
// |||||||||||||||| | | | +---------- SPP
// |||||||||||||||| | | +------------ VS
// |||||||||||||||| | +-------------- MPP
// |||||||||||||||| +---------------- FS
// |||||||||||||||+------------------ XS
// ||||||||||||||+------------------- MPRV
// |||||||||||||+-------------------- SUM
// ||||||||||||+--------------------- MXR
// |||||||||||+---------------------- TVM
// ||||||||||+----------------------- TW
// |||||||||+------------------------ TSR
// ||||||||+------------------------- SPELP
// |||||||+-------------------------- SDT
// ||||||+--------------------------- WPRI
// +--------------------------------- SD / WPRI

// upper half corresponds to mstatush bit meanings
static constexpr uint32_t upper_half = 0b00000000000000000000000000000000;
// |||||||||||||||||||||||||||||/|/
// ||||||||||||||||||||||||||||| +--- WPRI / UXL
// ||||||||||||||||||||||||||||+----- WPRI / SXL
// |||||||||||||||||||||||||||+------ SBE
// |||||||||||||||||||||||||+-------- MBE
// ||||||||||||||||||||||||+--------- GVA
// |||||||||||||||||||||||+---------- MPV
// ||||||||||||||||||||||+----------- WPRI
// |||||||||||||||||||||+------------ MPELP
// ||||||||||||||||||||+------------- MDT
// +--------------------------------- WPRI / SD

static constexpr reg_t get_mstatus_mask() {
if(sizeof(reg_t) == 4)
// return 0x807ff988UL; // 0b1000 0000 0111 1111 1111 1000 1000 1000 // only machine mode is supported
// +-SD
// | +-TSR
// | |+-TW
// | ||+-TVM
// | |||+-MXR
// | ||||+-SUM
// | |||||+-MPRV
// | |||||| +-XS
// | |||||| | +-FS
// | |||||| | | +-MPP
// | |||||| | | | +-SPP
// | |||||| | | | |+-MPIE
// | ||||||/|/|/| || +-MIE
return 0b00000000000000000001100010001000;
else if(sizeof(reg_t) == 8)
// return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
//
// +-TSR
// |+-TW
// ||+-TVM
// |||+-MXR
// ||||+-SUM
// |||||+-MPRV
// |||||| +-XS
// |||||| | +-FS
// |||||| | | +-MPP
// |||||| | | | +-SPP
// |||||| | | | |+-MPIE
// ||||||/|/|/| || +-MIE
return 0b00000000000000000001100010001000;
if constexpr(sizeof(reg_t) == 4)
return lower_half | riscv_hart_common<BASE>::extension_status_mask;
else if constexpr(sizeof(reg_t) == 8)
return static_cast<reg_t>(upper_half) << 32 | lower_half | riscv_hart_common<BASE>::extension_status_mask;
else
assert(false && "Unsupported XLEN value");
static_assert("Unsupported XLEN value");
}

void write_mstatus(reg_t val) {
auto mask = get_mstatus_mask() & 0xff; // MPP is hardcoded as 0x3
constexpr auto mask = get_mstatus_mask();
auto new_val = (this->state.mstatus() & ~mask) | (val & mask);
if constexpr(riscv_hart_common<BASE>::extension_status_mask)
// set SD bit if any of FS or VS are dirty
// FIXME: this wont work if XS is 01 and FS is 10
if(reg_t masked = new_val & riscv_hart_common<BASE>::extension_status_mask; masked & (masked >> 1))
new_val |= reg_t(1) << (sizeof(reg_t) * 8 - 1);

this->state.mstatus = new_val;
}

Expand Down
61 changes: 36 additions & 25 deletions src/iss/arch/riscv_hart_msu_vp.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#ifndef _RISCV_HART_MSU_VP_H
#define _RISCV_HART_MSU_VP_H

#include "iss/arch/riscv_hart_mu_p.h"
#include "iss/arch/traits.h"
#include "iss/vm_if.h"
#include "iss/vm_types.h"
Expand Down Expand Up @@ -66,32 +67,33 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_msu_vp :
using this_class = riscv_hart_msu_vp<BASE>;
using reg_t = typename core::reg_t;
using phys_addr_t = typename core::phys_addr_t;

static constexpr uint32_t s_mask_lower = 0b00000000011111100000000100100010;
// ||||||||||||||||/|/|/|/|||||||||
// |||||||||||||||| | | | ||||||||+-- UIE
// |||||||||||||||| | | | |||||||+--- SIE
// |||||||||||||||| | | | ||||||+---- WPRI
// |||||||||||||||| | | | |||||+----- MIE
// |||||||||||||||| | | | ||||+------ UPIE
// |||||||||||||||| | | | |||+------- SPIE
// |||||||||||||||| | | | ||+-------- UBE
// |||||||||||||||| | | | |+--------- MPIE
// |||||||||||||||| | | | +---------- SPP
// |||||||||||||||| | | +------------ VS
// |||||||||||||||| | +-------------- MPP
// |||||||||||||||| +---------------- FS
// |||||||||||||||+------------------ XS
// ||||||||||||||+------------------- MPRV
// |||||||||||||+-------------------- SUM
// ||||||||||||+--------------------- MXR
// |||||||||||+---------------------- TVM
// ||||||||||+----------------------- TW
// |||||||||+------------------------ TSR
// ||||||||+------------------------- SPELP
// |||||||+-------------------------- SDT
// ||||||+--------------------------- WPRI
// +--------------------------------- SD / WPRI
static constexpr reg_t get_mstatus_mask(unsigned priv_lvl) {
if(sizeof(reg_t) == 4) {
#if __cplusplus < 201402L
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
#else
switch(priv_lvl) {
case PRIV_U:
return 0x80000000UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
case PRIV_S:
return 0x800de762UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011
default:
return 0x801fffeaUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011
}
#endif
} else if(sizeof(reg_t) == 8) {
switch(priv_lvl) {
case PRIV_U:
return 0x8000000f00000000ULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
case PRIV_S:
return 0x80000003000de762ULL; // 0b1...0 0011 0000 0000 0000 1101 1110 0111 0110 0010
default:
return 0x80000030001fffeaULL; // 0b1...0 0000 0000 0000 0001 1111 1111 1111 1110 1010
}
} else
assert(false && "Unsupported XLEN value");
return riscv_hart_mu_p<BASE>::get_mstatus_mask(priv_lvl) | ((priv_lvl >= PRIV_S) ? s_mask_lower : 0);
}
static constexpr reg_t get_mstatus_rd_mask(unsigned priv_lvl) {
if(sizeof(reg_t) == 4) {
Expand All @@ -115,6 +117,11 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_msu_vp :
reg_t old_val = this->state.mstatus;
auto mask = get_mstatus_mask(priv_lvl);
auto new_val = (old_val & ~mask) | (val & mask);
if constexpr(riscv_hart_common<BASE>::extension_status_mask)
// set SD bit if any of FS or VS are dirty
// FIXME: this wont work if XS is 01 and FS is 10
if(reg_t masked = new_val & riscv_hart_common<BASE>::extension_status_mask && masked & (masked >> 1))
new_val |= reg_t(1) << (sizeof(reg_t) * 8 - 1);
this->state.mstatus = new_val;
}

Expand All @@ -129,6 +136,10 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_msu_vp :
if((new_val & this->state.mstatus.UXL.Mask) == 0) {
new_val |= old_val & this->state.mstatus.UXL.Mask;
}
if constexpr(riscv_hart_common<BASE>::extension_status_mask)
if(new_val && riscv_hart_common<BASE>::extension_status_mask)
// set SD bit if any of FS, VS and XS are set
new_val |= reg_t(1) << (sizeof(reg_t) * 8 - 1);
this->state.mstatus = new_val;
}

Expand Down
86 changes: 33 additions & 53 deletions src/iss/arch/riscv_hart_mu_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@
#ifndef _RISCV_HART_MU_P_H
#define _RISCV_HART_MU_P_H

#include "iss/arch/riscv_hart_m_p.h"
#include "iss/arch/traits.h"
#include "iss/vm_if.h"
#include "iss/vm_types.h"
#include "riscv_hart_common.h"
#include "util/logging.h"
#include <algorithm>
#include <array>
#include <cassert>
#include <cstdint>
#include <elfio/elf_types.hpp>
#include <elfio/elfio.hpp>
Expand All @@ -64,65 +66,43 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_mu_p : pu
using reg_t = typename core::reg_t;
using phys_addr_t = typename core::phys_addr_t;

static constexpr uint32_t u_mask_lower = 0b00000000000000000000000000010001;
// ||||||||||||||||/|/|/|/|||||||||
// |||||||||||||||| | | | ||||||||+-- UIE
// |||||||||||||||| | | | |||||||+--- SIE
// |||||||||||||||| | | | ||||||+---- WPRI
// |||||||||||||||| | | | |||||+----- MIE
// |||||||||||||||| | | | ||||+------ UPIE
// |||||||||||||||| | | | |||+------- SPIE
// |||||||||||||||| | | | ||+-------- UBE
// |||||||||||||||| | | | |+--------- MPIE
// |||||||||||||||| | | | +---------- SPP
// |||||||||||||||| | | +------------ VS
// |||||||||||||||| | +-------------- MPP
// |||||||||||||||| +---------------- FS
// |||||||||||||||+------------------ XS
// ||||||||||||||+------------------- MPRV
// |||||||||||||+-------------------- SUM
// ||||||||||||+--------------------- MXR
// |||||||||||+---------------------- TVM
// ||||||||||+----------------------- TW
// |||||||||+------------------------ TSR
// ||||||||+------------------------- SPELP
// |||||||+-------------------------- SDT
// ||||||+--------------------------- WPRI
// +--------------------------------- SD / WPRI
static constexpr reg_t get_mstatus_mask(unsigned priv_lvl) {
if(sizeof(reg_t) == 4) {
#if __cplusplus < 201402L
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
#else
switch(priv_lvl) {
case PRIV_U:
return FEAT & features_e::FEAT_EXT_N ? 0x00000011UL : 0UL; // 0b1...0 0001 0001
default:
// +-SD
// | +-TSR
// | |+-TW
// | ||+-TVM
// | |||+-MXR
// | ||||+-SUM
// | |||||+-MPRV
// | |||||| +-XS
// | |||||| | +-FS
// | |||||| | | +-MPP
// | |||||| | | | +-SPP
// | |||||| | | | |+-MPIE
// | |||||| | | | || +-UPIE
// | ||||||/|/|/| || |+-MIE
// | ||||||/|/|/| || || +-UIE
return 0b10000000001000000001100010011001;
}
#endif
} else if(sizeof(reg_t) == 8) {
#if __cplusplus < 201402L
return priv_lvl == PRIV_U ? 0x011ULL : priv_lvl == PRIV_S ? 0x000de133ULL : 0x007ff9ddULL;
#else
switch(priv_lvl) {
case PRIV_U:
return FEAT & features_e::FEAT_EXT_N ? 0x8000000000000011ULL : 0ULL; // 0b1...0 0001 0001
default:
// +-TSR
// |+-TW
// ||+-TVM
// |||+-MXR
// ||||+-SUM
// |||||+-MPRV
// |||||| +-XS
// |||||| | +-FS
// |||||| | | +-MPP
// |||||| | | | +-SPP
// |||||| | | | |+-MPIE
// |||||| | | | || +-UPIE
// ||||||/|/|/| || |+-MIE
// ||||||/|/|/| || || +-UIE
return 0b00000000001000000001100010011001 | 0x8000000000000000ULL;
}
#endif
} else
assert(false && "Unsupported XLEN value");
return u_mask_lower | (priv_lvl >= PRIV_M ? riscv_hart_m_p<BASE>::get_mstatus_mask() : 0);
}

void write_mstatus(reg_t val, unsigned priv_lvl) {
auto mask = get_mstatus_mask(priv_lvl);
auto new_val = (this->state.mstatus() & ~mask) | (val & mask);
if constexpr(riscv_hart_common<BASE>::extension_status_mask)
// set SD bit if any of FS or VS are dirty
// FIXME: this wont work if XS is 01 and FS is 10
if(reg_t masked = new_val & riscv_hart_common<BASE>::extension_status_mask && masked & (masked >> 1))
new_val |= reg_t(1) << (sizeof(reg_t) * 8 - 1);
this->state.mstatus = new_val;
}

Expand Down