Skip to content

Commit 4b854a5

Browse files
committed
reworks mstatus handling,
this introduces a hierarchical approach to the masking of the lower priv level status views
1 parent b4284ff commit 4b854a5

4 files changed

Lines changed: 127 additions & 112 deletions

File tree

src/iss/arch/riscv_hart_common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,11 @@ template <typename WORD_TYPE> struct priv_if {
308308
};
309309

310310
template <typename BASE = logging::disass> struct riscv_hart_common : public BASE, public mem::memory_elem {
311+
// Extension status bits (SD needs to be set when writing FS / VS / XS):
312+
// TODO implement XS
313+
static constexpr uint32_t extension_status_mask =
314+
(traits<BASE>::FP_REGS_SIZE ? (0b11u << 13) : 0u) | (traits<BASE>::V_REGS_SIZE ? (0b11u << 9) : 0u);
315+
311316
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
312317
const std::array<const char*, 16> trap_str = {{""
313318
"Instruction address misaligned", // 0

src/iss/arch/riscv_hart_m_p.h

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -63,46 +63,65 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_m_p : pub
6363
using reg_t = typename core::reg_t;
6464
using phys_addr_t = typename core::phys_addr_t;
6565

66+
// Notation for differing fields is: 32 bits / 64 bits
67+
static constexpr uint32_t lower_half = 0b00000000000000000001100010001000;
68+
// ||||||||||||||||/|/|/|/|||||||||
69+
// |||||||||||||||| | | | ||||||||+-- UIE
70+
// |||||||||||||||| | | | |||||||+--- SIE
71+
// |||||||||||||||| | | | ||||||+---- WPRI
72+
// |||||||||||||||| | | | |||||+----- MIE
73+
// |||||||||||||||| | | | ||||+------ UPIE
74+
// |||||||||||||||| | | | |||+------- SPIE
75+
// |||||||||||||||| | | | ||+-------- UBE
76+
// |||||||||||||||| | | | |+--------- MPIE
77+
// |||||||||||||||| | | | +---------- SPP
78+
// |||||||||||||||| | | +------------ VS
79+
// |||||||||||||||| | +-------------- MPP
80+
// |||||||||||||||| +---------------- FS
81+
// |||||||||||||||+------------------ XS
82+
// ||||||||||||||+------------------- MPRV
83+
// |||||||||||||+-------------------- SUM
84+
// ||||||||||||+--------------------- MXR
85+
// |||||||||||+---------------------- TVM
86+
// ||||||||||+----------------------- TW
87+
// |||||||||+------------------------ TSR
88+
// ||||||||+------------------------- SPELP
89+
// |||||||+-------------------------- SDT
90+
// ||||||+--------------------------- WPRI
91+
// +--------------------------------- SD / WPRI
92+
93+
// upper half corresponds to mstatush bit meanings
94+
static constexpr uint32_t upper_half = 0b00000000000000000000000000000000;
95+
// |||||||||||||||||||||||||||||/|/
96+
// ||||||||||||||||||||||||||||| +--- WPRI / UXL
97+
// ||||||||||||||||||||||||||||+----- WPRI / SXL
98+
// |||||||||||||||||||||||||||+------ SBE
99+
// |||||||||||||||||||||||||+-------- MBE
100+
// ||||||||||||||||||||||||+--------- GVA
101+
// |||||||||||||||||||||||+---------- MPV
102+
// ||||||||||||||||||||||+----------- WPRI
103+
// |||||||||||||||||||||+------------ MPELP
104+
// ||||||||||||||||||||+------------- MDT
105+
// +--------------------------------- WPRI / SD
106+
66107
static constexpr reg_t get_mstatus_mask() {
67-
if(sizeof(reg_t) == 4)
68-
// return 0x807ff988UL; // 0b1000 0000 0111 1111 1111 1000 1000 1000 // only machine mode is supported
69-
// +-SD
70-
// | +-TSR
71-
// | |+-TW
72-
// | ||+-TVM
73-
// | |||+-MXR
74-
// | ||||+-SUM
75-
// | |||||+-MPRV
76-
// | |||||| +-XS
77-
// | |||||| | +-FS
78-
// | |||||| | | +-MPP
79-
// | |||||| | | | +-SPP
80-
// | |||||| | | | |+-MPIE
81-
// | ||||||/|/|/| || +-MIE
82-
return 0b00000000000000000001100010001000;
83-
else if(sizeof(reg_t) == 8)
84-
// return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
85-
//
86-
// +-TSR
87-
// |+-TW
88-
// ||+-TVM
89-
// |||+-MXR
90-
// ||||+-SUM
91-
// |||||+-MPRV
92-
// |||||| +-XS
93-
// |||||| | +-FS
94-
// |||||| | | +-MPP
95-
// |||||| | | | +-SPP
96-
// |||||| | | | |+-MPIE
97-
// ||||||/|/|/| || +-MIE
98-
return 0b00000000000000000001100010001000;
108+
if constexpr(sizeof(reg_t) == 4)
109+
return lower_half | riscv_hart_common<BASE>::extension_status_mask;
110+
else if constexpr(sizeof(reg_t) == 8)
111+
return static_cast<reg_t>(upper_half) << 32 | lower_half | riscv_hart_common<BASE>::extension_status_mask;
99112
else
100-
assert(false && "Unsupported XLEN value");
113+
static_assert("Unsupported XLEN value");
101114
}
102115

103116
void write_mstatus(reg_t val) {
104-
auto mask = get_mstatus_mask() & 0xff; // MPP is hardcoded as 0x3
117+
constexpr auto mask = get_mstatus_mask();
105118
auto new_val = (this->state.mstatus() & ~mask) | (val & mask);
119+
if constexpr(riscv_hart_common<BASE>::extension_status_mask)
120+
// set SD bit if any of FS or VS are dirty
121+
// FIXME: this wont work if XS is 01 and FS is 10
122+
if(reg_t masked = new_val & riscv_hart_common<BASE>::extension_status_mask; masked & (masked >> 1))
123+
new_val |= reg_t(1) << (sizeof(reg_t) * 8 - 1);
124+
106125
this->state.mstatus = new_val;
107126
}
108127

src/iss/arch/riscv_hart_msu_vp.h

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#ifndef _RISCV_HART_MSU_VP_H
3636
#define _RISCV_HART_MSU_VP_H
3737

38+
#include "iss/arch/riscv_hart_mu_p.h"
3839
#include "iss/arch/traits.h"
3940
#include "iss/vm_if.h"
4041
#include "iss/vm_types.h"
@@ -66,32 +67,33 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_msu_vp :
6667
using this_class = riscv_hart_msu_vp<BASE>;
6768
using reg_t = typename core::reg_t;
6869
using phys_addr_t = typename core::phys_addr_t;
69-
70+
static constexpr uint32_t s_mask_lower = 0b00000000011111100000000100100010;
71+
// ||||||||||||||||/|/|/|/|||||||||
72+
// |||||||||||||||| | | | ||||||||+-- UIE
73+
// |||||||||||||||| | | | |||||||+--- SIE
74+
// |||||||||||||||| | | | ||||||+---- WPRI
75+
// |||||||||||||||| | | | |||||+----- MIE
76+
// |||||||||||||||| | | | ||||+------ UPIE
77+
// |||||||||||||||| | | | |||+------- SPIE
78+
// |||||||||||||||| | | | ||+-------- UBE
79+
// |||||||||||||||| | | | |+--------- MPIE
80+
// |||||||||||||||| | | | +---------- SPP
81+
// |||||||||||||||| | | +------------ VS
82+
// |||||||||||||||| | +-------------- MPP
83+
// |||||||||||||||| +---------------- FS
84+
// |||||||||||||||+------------------ XS
85+
// ||||||||||||||+------------------- MPRV
86+
// |||||||||||||+-------------------- SUM
87+
// ||||||||||||+--------------------- MXR
88+
// |||||||||||+---------------------- TVM
89+
// ||||||||||+----------------------- TW
90+
// |||||||||+------------------------ TSR
91+
// ||||||||+------------------------- SPELP
92+
// |||||||+-------------------------- SDT
93+
// ||||||+--------------------------- WPRI
94+
// +--------------------------------- SD / WPRI
7095
static constexpr reg_t get_mstatus_mask(unsigned priv_lvl) {
71-
if(sizeof(reg_t) == 4) {
72-
#if __cplusplus < 201402L
73-
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
74-
#else
75-
switch(priv_lvl) {
76-
case PRIV_U:
77-
return 0x80000000UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
78-
case PRIV_S:
79-
return 0x800de762UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011
80-
default:
81-
return 0x801fffeaUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011
82-
}
83-
#endif
84-
} else if(sizeof(reg_t) == 8) {
85-
switch(priv_lvl) {
86-
case PRIV_U:
87-
return 0x8000000f00000000ULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
88-
case PRIV_S:
89-
return 0x80000003000de762ULL; // 0b1...0 0011 0000 0000 0000 1101 1110 0111 0110 0010
90-
default:
91-
return 0x80000030001fffeaULL; // 0b1...0 0000 0000 0000 0001 1111 1111 1111 1110 1010
92-
}
93-
} else
94-
assert(false && "Unsupported XLEN value");
96+
return riscv_hart_mu_p<BASE>::get_mstatus_mask(priv_lvl) | ((priv_lvl >= PRIV_S) ? s_mask_lower : 0);
9597
}
9698
static constexpr reg_t get_mstatus_rd_mask(unsigned priv_lvl) {
9799
if(sizeof(reg_t) == 4) {
@@ -115,6 +117,11 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_msu_vp :
115117
reg_t old_val = this->state.mstatus;
116118
auto mask = get_mstatus_mask(priv_lvl);
117119
auto new_val = (old_val & ~mask) | (val & mask);
120+
if constexpr(riscv_hart_common<BASE>::extension_status_mask)
121+
// set SD bit if any of FS or VS are dirty
122+
// FIXME: this wont work if XS is 01 and FS is 10
123+
if(reg_t masked = new_val & riscv_hart_common<BASE>::extension_status_mask && masked & (masked >> 1))
124+
new_val |= reg_t(1) << (sizeof(reg_t) * 8 - 1);
118125
this->state.mstatus = new_val;
119126
}
120127

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

src/iss/arch/riscv_hart_mu_p.h

Lines changed: 33 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,15 @@
3535
#ifndef _RISCV_HART_MU_P_H
3636
#define _RISCV_HART_MU_P_H
3737

38+
#include "iss/arch/riscv_hart_m_p.h"
3839
#include "iss/arch/traits.h"
3940
#include "iss/vm_if.h"
4041
#include "iss/vm_types.h"
4142
#include "riscv_hart_common.h"
4243
#include "util/logging.h"
4344
#include <algorithm>
4445
#include <array>
46+
#include <cassert>
4547
#include <cstdint>
4648
#include <elfio/elf_types.hpp>
4749
#include <elfio/elfio.hpp>
@@ -64,65 +66,43 @@ template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_mu_p : pu
6466
using reg_t = typename core::reg_t;
6567
using phys_addr_t = typename core::phys_addr_t;
6668

69+
static constexpr uint32_t u_mask_lower = 0b00000000000000000000000000010001;
70+
// ||||||||||||||||/|/|/|/|||||||||
71+
// |||||||||||||||| | | | ||||||||+-- UIE
72+
// |||||||||||||||| | | | |||||||+--- SIE
73+
// |||||||||||||||| | | | ||||||+---- WPRI
74+
// |||||||||||||||| | | | |||||+----- MIE
75+
// |||||||||||||||| | | | ||||+------ UPIE
76+
// |||||||||||||||| | | | |||+------- SPIE
77+
// |||||||||||||||| | | | ||+-------- UBE
78+
// |||||||||||||||| | | | |+--------- MPIE
79+
// |||||||||||||||| | | | +---------- SPP
80+
// |||||||||||||||| | | +------------ VS
81+
// |||||||||||||||| | +-------------- MPP
82+
// |||||||||||||||| +---------------- FS
83+
// |||||||||||||||+------------------ XS
84+
// ||||||||||||||+------------------- MPRV
85+
// |||||||||||||+-------------------- SUM
86+
// ||||||||||||+--------------------- MXR
87+
// |||||||||||+---------------------- TVM
88+
// ||||||||||+----------------------- TW
89+
// |||||||||+------------------------ TSR
90+
// ||||||||+------------------------- SPELP
91+
// |||||||+-------------------------- SDT
92+
// ||||||+--------------------------- WPRI
93+
// +--------------------------------- SD / WPRI
6794
static constexpr reg_t get_mstatus_mask(unsigned priv_lvl) {
68-
if(sizeof(reg_t) == 4) {
69-
#if __cplusplus < 201402L
70-
return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL;
71-
#else
72-
switch(priv_lvl) {
73-
case PRIV_U:
74-
return FEAT & features_e::FEAT_EXT_N ? 0x00000011UL : 0UL; // 0b1...0 0001 0001
75-
default:
76-
// +-SD
77-
// | +-TSR
78-
// | |+-TW
79-
// | ||+-TVM
80-
// | |||+-MXR
81-
// | ||||+-SUM
82-
// | |||||+-MPRV
83-
// | |||||| +-XS
84-
// | |||||| | +-FS
85-
// | |||||| | | +-MPP
86-
// | |||||| | | | +-SPP
87-
// | |||||| | | | |+-MPIE
88-
// | |||||| | | | || +-UPIE
89-
// | ||||||/|/|/| || |+-MIE
90-
// | ||||||/|/|/| || || +-UIE
91-
return 0b10000000001000000001100010011001;
92-
}
93-
#endif
94-
} else if(sizeof(reg_t) == 8) {
95-
#if __cplusplus < 201402L
96-
return priv_lvl == PRIV_U ? 0x011ULL : priv_lvl == PRIV_S ? 0x000de133ULL : 0x007ff9ddULL;
97-
#else
98-
switch(priv_lvl) {
99-
case PRIV_U:
100-
return FEAT & features_e::FEAT_EXT_N ? 0x8000000000000011ULL : 0ULL; // 0b1...0 0001 0001
101-
default:
102-
// +-TSR
103-
// |+-TW
104-
// ||+-TVM
105-
// |||+-MXR
106-
// ||||+-SUM
107-
// |||||+-MPRV
108-
// |||||| +-XS
109-
// |||||| | +-FS
110-
// |||||| | | +-MPP
111-
// |||||| | | | +-SPP
112-
// |||||| | | | |+-MPIE
113-
// |||||| | | | || +-UPIE
114-
// ||||||/|/|/| || |+-MIE
115-
// ||||||/|/|/| || || +-UIE
116-
return 0b00000000001000000001100010011001 | 0x8000000000000000ULL;
117-
}
118-
#endif
119-
} else
120-
assert(false && "Unsupported XLEN value");
95+
return u_mask_lower | (priv_lvl >= PRIV_M ? riscv_hart_m_p<BASE>::get_mstatus_mask() : 0);
12196
}
12297

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

0 commit comments

Comments
 (0)