-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Hypervisor extension #41
base: main
Are you sure you want to change the base?
Conversation
enabled_ints = ~a.read_mideleg(); | ||
} | ||
break; | ||
auto mstatus = a.read_mstatus(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I miss the comments explaining what was going on that you added and were lost here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I'll do this after we settle on the final decision regarding this discussion
src/interpret.cpp
Outdated
static inline uint32_t get_enabled_irq_mask_HS(STATE_ACCESS &a, uint64_t sie, uint8_t priv) { | ||
uint32_t deleg = a.read_mideleg() & ~a.read_hideleg(); | ||
uint32_t enabled_HS = is_virtual_mode(a) || priv < PRV_HS || (priv == PRV_HS && sie); | ||
return (deleg & -enabled_HS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't you do an & sie
in the final return? Checking just if sie
has any bit set feels odd for me, actually it should check if the corresponding deleg
and sie
is bits are enabled. Same apply for other get_enabled_irq_mask_*
functions. I think these functions may need some rewriting considering this and the previous comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is done at the end of the get_pending_irq_mask
method here. maybe the naming of those methods is misleading, do you have any ideas what would be a better naming here?
src/riscv-constants.h
Outdated
PRV_HS = 2, ///< Hypervisor-extended supervisor mode | ||
PRV_M = 3 ///< Machine mode | ||
PRV_U = 0, ///< User mode | ||
PRV_HS = 1, ///< Supervisor mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading the spec and the code, I feel that PRV_HS
should be renamed back to PRV_S
. Because when VRT is 1, we are in VS mode, and the checks have HS in them, so it is misleading.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I commented on things that may have to be improved after reading the spec. Despite having some issues this is already working well, most issues commented are edge cases or minor details. Great work @alexmikhalevich !
src/interpret.cpp
Outdated
|
||
template <typename STATE_ACCESS> | ||
static execute_status write_csr_vsstatus(STATE_ACCESS &a, uint64_t val) { | ||
a.write_vsstatus(val); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A write filter is missing here, we should not allow to writes to WPRI fields of vsstatus
to preserve backward compability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FS
and SD
fields are not being handled here, they should be handled is similar way to mstatus
. While it was handled in write_csr_sstatus
, I think you should move the vsstatus
related logic from write_csr_sstatus
to here and call this function.
When doing this, FS
field should always mark state as dirty, like is done in write_csr_mstatus
and according to the spec for both mstatus
and vsstatus
:
Modifying the floating-point state when V=1 causes both fields to be set to 3 (Dirty).
Meaning if vsstatus.FS
is set as dirty, then mstatus.FS
will also be set as dirty, and both vsstatus.SD
and mstatus.SD
must also be set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/interpret.cpp
Outdated
if (is_virtual_mode(a)) { | ||
uint64_t vsstatus = a.read_vsstatus() & VSSTATUS_R_MASK; | ||
vsstatus = (vsstatus & ~VSSTATUS_W_MASK) | (val & VSSTATUS_W_MASK); | ||
if ((vsstatus & MSTATUS_FS_MASK) == MSTATUS_FS_MASK) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Despite MSTATUS_FS_MASK
being set, it's not ever read. You will find multiple of the following checks in the code:
// If FS is OFF, attempts to read or write the float state will cause an illegal instruction exception.
if (unlikely((mstatus & MSTATUS_FS_MASK) == MSTATUS_FS_OFF)) {
return execute_status::failure;
}
They all should be extended taking this in consideration:
When V=1, both vsstatus.FS and the HS-level sstatus.FS are in effect. Attempts to execute a
floating-point instruction when either field is 0 (Off) raise an illegal-instruction exception.
This mean a exception should be raised if either mstatus.FS
is OFF, or vsstatus.FS
is Off while in virtual mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/interpret.cpp
Outdated
return execute_HSV_H(a, pc, mcycle, insn); | ||
case insn_privileged_funct7::HSV_W: | ||
return execute_HSV_W(a, pc, mcycle, insn); | ||
// case insn_privileged_funct7::HLV_WU: // TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The case still commented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, that's because this insn is processed in another switch
. I removed this comment.
e49b5a3
to
3b25b67
Compare
9b9d7cd
to
ac02322
Compare
// hgatp can only be changed when virtual mode is off, and when virtual mode is off | ||
// the address translation function will not use it. Enabling virtual mode will trigger | ||
// a TLB shootdown. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing:
When mstatus.TVM=1, attempts to read or write hgatp while executing
in HS-mode will raise an illegal instruction exception.
Setting TVM=1 prevents HS-mode from accessing hgatp or executing HFENCE.GVMA or HIN-
VAL.GVMA
The above is also missing in read_csr_hgatp
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/interpret.cpp
Outdated
// a TLB shootdown. | ||
|
||
auto mode = val >> 60; | ||
if (mode == 0 || (mode >= 8 && mode <= 10)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use the enums SATP_MODE_BARE
, SATP_MODE_SV39
and SATP_MODE_SV57
instead of these constants here.
And SATP_MODE_SHIFT
for the 60 above.
I also think a switch makes the code more clear, like in write_csr_satp
. Same applies to write_csr_vsatp
, it could have used a switch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/interpret.cpp
Outdated
@@ -1975,7 +2687,10 @@ static NO_INLINE execute_status write_csr_satp(STATE_ACCESS &a, uint64_t val) { | |||
} | |||
|
|||
uint64_t old_satp = a.read_satp(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an extra unnecessary read of satp
here when read_iflags_VRT
is true, you could move this read in the else of the bellow if.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/interpret.cpp
Outdated
@@ -1975,7 +2687,10 @@ static NO_INLINE execute_status write_csr_satp(STATE_ACCESS &a, uint64_t val) { | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TSR and TVM fields of mstatus affect execution only in HS-mode, not in VS-mode. The TW
field affects execution in all modes except M-mode.
This is not respected here, TVM is affecting VS-mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/interpret.cpp
Outdated
auto mode = current_mode(a); | ||
auto priv = (mode & ACCESS_MODE_PRV_MASK) >> ACCESS_MODE_PRV_SHIFT; | ||
uint64_t mstatus = a.read_mstatus(); | ||
if (unlikely(priv == PRV_U || (priv == PRV_S && (mstatus & MSTATUS_TVM_MASK)))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TSR and TVM fields of mstatus affect execution only in HS-mode, not in VS-mode.
setting TVM=1 does not cause traps for accesses to vsatp or instructions
HFENCE.VVMA or HINVAL.VVMA, or for any actions taken in VS-mode
This is not respected here, TVM is affecting VS-mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/interpret.cpp
Outdated
uint64_t old_vsstatus = a.read_vsstatus() & VSSTATUS_R_MASK; | ||
uint64_t vsstatus = (old_vsstatus & ~VSSTATUS_W_MASK) | (val & VSSTATUS_W_MASK); | ||
auto mstatus = a.read_mstatus(); | ||
if ((vsstatus & MSTATUS_FS_MASK) == MSTATUS_FS_MASK) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this if should have been (vsstatus & MSTATUS_FS_MASK) != MSTATUS_FS_OFF
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/interpret.cpp
Outdated
vsstatus |= MSTATUS_FS_DIRTY; | ||
vsstatus |= MSTATUS_SD_MASK; | ||
} else { | ||
mstatus &= ~MSTATUS_SD_MASK; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MSTATUS_FS_MASK
could still be dirty, and SD
cannot be cleared in this case. So I think this line should be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@@ -2198,6 +2924,12 @@ static inline execute_status write_csr_fflags(STATE_ACCESS &a, uint64_t val) { | |||
if (unlikely((mstatus & MSTATUS_FS_MASK) == MSTATUS_FS_OFF)) { | |||
return execute_status::failure; | |||
} | |||
if (a.read_iflags_VRT()) { | |||
auto vsstatus = a.read_vsstatus(); | |||
if (unlikely((vsstatus & MSTATUS_FS_MASK) == MSTATUS_FS_OFF)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is correct, however there are other places missing the same check, such as:
- read_csr_fflags
- read_csr_frm
- read_csr_fcsr
- the two switches in execute_insn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/interpret.cpp
Outdated
@@ -5407,17 +6608,22 @@ template <typename STATE_ACCESS> | |||
static FORCE_INLINE fetch_status fetch_translate_pc_slow(STATE_ACCESS &a, uint64_t &pc, uint64_t vaddr, | |||
unsigned char **phptr) { | |||
uint64_t paddr{}; | |||
MODE_constants access_mode = get_current_memory_access_mode(a); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When MPRV=1, load
and store memory addresses are translated and protected, and endianness is applied, as though
the current privilege mode were set to MPP. Instruction address-translation and protection are
unaffected by the setting of MPRV.
get_current_memory_access_mode
will always consider MRPV, but for fetch MRPV should be ignored.
Our old code respected this, with this (in translate_virtual_address):
// When MPRV is set, data loads and stores use privilege in MPP
// instead of the current privilege level (code access is unaffected)
if (xwr_shift != PTE_XWR_X_SHIFT && (mstatus & MSTATUS_MPRV_MASK)) {
priv = (mstatus & MSTATUS_MPP_MASK) >> MSTATUS_MPP_SHIFT;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
src/translate-virtual-address.h
Outdated
} | ||
|
||
// when checking the U bit for G translation, the current privilege mode is always taken to be U-mode | ||
if constexpr (TRANSLATION_MODE == TRANSLATION_G) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After making all G translations to use priv=PRV_U
, this if could just be removed to simplify this code. The else branch already has the same logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
23c19c1
to
e08cc68
Compare
e08cc68
to
ef476ff
Compare
4c72df3
to
f3cd606
Compare
2f9548f
to
aeef15b
Compare
aeef15b
to
c287764
Compare
48d0559
to
9e21789
Compare
Hypervisor extension implementation.