Browse Source

Fix VSSTATUS bits updation (#568)

This patch fixes VSSTATUS bits updations as follows:
1. set_csr() should not allow writs to VSSTATUS.SD bit instead
   VSSTATUS.SD bit should be derived again after VSSTATUS is updated
2. set_virt() should copy FS, VS and XS bits when transitioning
   from virt=on (VS/VU-mode) to virt=off (HS/M-mode)

Signed-off-by: Anup Patel <anup.patel@wdc.com>
pull/603/head
Anup Patel 6 years ago
committed by GitHub
parent
commit
8be5c086bd
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      riscv/encoding.h
  2. 34
      riscv/processor.cc

2
riscv/encoding.h

@ -50,7 +50,7 @@
#define SSTATUS64_SD 0x8000000000000000
#define SSTATUS_VS_MASK (SSTATUS_SIE | SSTATUS_SPIE | \
SSTATUS_SPP | SSTATUS_SUM | \
SSTATUS_SPP | SSTATUS_FS | SSTATUS_SUM | \
SSTATUS_MXR | SSTATUS_UXL)
#define HSTATUS_VSXL 0x300000000

34
riscv/processor.cc

@ -630,21 +630,22 @@ void processor_t::set_virt(bool virt)
* we should sync Guest/VM FS, VS, and XS state with Host FS,
* VS, and XS state.
*/
if ((state.mstatus & SSTATUS_FS) == SSTATUS_FS) {
state.vsstatus |= SSTATUS_FS;
state.vsstatus |= (xlen == 64 ? SSTATUS64_SD : SSTATUS32_SD);
}
if ((state.mstatus & SSTATUS_VS) == SSTATUS_VS) {
state.vsstatus |= SSTATUS_VS;
state.vsstatus |= (xlen == 64 ? SSTATUS64_SD : SSTATUS32_SD);
}
if ((state.mstatus & SSTATUS_XS) == SSTATUS_XS) {
state.vsstatus |= SSTATUS_XS;
state.vsstatus &= ~SSTATUS_FS;
state.vsstatus |= (state.mstatus & SSTATUS_FS);
if (supports_extension('V')) {
state.vsstatus &= ~SSTATUS_VS;
state.vsstatus |= (state.mstatus & SSTATUS_VS);
}
state.vsstatus &= ~SSTATUS_XS;
state.vsstatus |= (state.mstatus & SSTATUS_XS);
state.vsstatus &= (xlen == 64 ? ~SSTATUS64_SD : ~SSTATUS32_SD);
if (((state.mstatus & SSTATUS_FS) == SSTATUS_FS) ||
((state.vsstatus & SSTATUS_VS) == SSTATUS_VS) ||
((state.vsstatus & SSTATUS_XS) == SSTATUS_XS)) {
state.vsstatus |= (xlen == 64 ? SSTATUS64_SD : SSTATUS32_SD);
}
}
}
mask = SSTATUS_VS_MASK;
mask |= (supports_extension('F') ? SSTATUS_FS : 0);
mask |= (supports_extension('V') ? SSTATUS_VS : 0);
mask |= (xlen == 64 ? SSTATUS64_SD : SSTATUS32_SD);
tmp = state.mstatus & mask;
@ -1171,10 +1172,14 @@ void processor_t::set_csr(int which, reg_t val)
}
case CSR_VSSTATUS: {
reg_t mask = SSTATUS_VS_MASK;
mask |= (supports_extension('F') ? SSTATUS_FS : 0);
mask |= (supports_extension('V') ? SSTATUS_VS : 0);
mask |= (xlen == 64 ? SSTATUS64_SD : SSTATUS32_SD);
state.vsstatus = (state.vsstatus & ~mask) | (val & mask);
state.vsstatus &= (xlen == 64 ? ~SSTATUS64_SD : ~SSTATUS32_SD);
if (((state.mstatus & SSTATUS_FS) == SSTATUS_FS) ||
((state.vsstatus & SSTATUS_VS) == SSTATUS_VS) ||
((state.vsstatus & SSTATUS_XS) == SSTATUS_XS)) {
state.vsstatus |= (xlen == 64 ? SSTATUS64_SD : SSTATUS32_SD);
}
break;
}
case CSR_VSIE: {
@ -1585,7 +1590,6 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek)
case CSR_HGEIP: ret(0);
case CSR_VSSTATUS: {
reg_t mask = SSTATUS_VS_MASK;
mask |= (supports_extension('F') ? SSTATUS_FS : 0);
mask |= (supports_extension('V') ? SSTATUS_VS : 0);
mask |= (xlen == 64 ? SSTATUS64_SD : SSTATUS32_SD);
ret(state.vsstatus & mask);

Loading…
Cancel
Save