From 924e633d225879b7adb392bb6097f495d5a2c03d Mon Sep 17 00:00:00 2001 From: Felix Puscasu Date: Wed, 7 Aug 2024 16:52:37 +0100 Subject: [PATCH 1/6] RISC-V: Add EffectCell --- src/riscv/lib/src/state_backend.rs | 3 ++ src/riscv/lib/src/state_backend/effects.rs | 56 ++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/riscv/lib/src/state_backend/effects.rs diff --git a/src/riscv/lib/src/state_backend.rs b/src/riscv/lib/src/state_backend.rs index 0695054ad623..6b13d9b737b7 100644 --- a/src/riscv/lib/src/state_backend.rs +++ b/src/riscv/lib/src/state_backend.rs @@ -72,6 +72,9 @@ pub use enums::*; mod elems; pub use elems::*; +mod effects; +pub use effects::*; + /// Manager of the state backend storage pub trait ManagerBase { /// Region that has been allocated in the state storage diff --git a/src/riscv/lib/src/state_backend/effects.rs b/src/riscv/lib/src/state_backend/effects.rs new file mode 100644 index 000000000000..7acd4f8a4828 --- /dev/null +++ b/src/riscv/lib/src/state_backend/effects.rs @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2024 TriliTech +// +// SPDX-License-Identifier: MIT + +use std::marker::PhantomData; + +use super::{ + AllocatedOf, Atom, Cell, Elem, ManagerBase, ManagerRead, ManagerReadWrite, ManagerWrite, +}; + +/// XXX: Workaround trait for not having enum variants as const-generics +pub trait EffectGetter { + /// Effect type returned + type Effect; + + /// Effect on write/replace operations. + const EFFECT: Self::Effect; +} + +pub type EffectCellLayout = Atom; + +pub struct EffectCell { + inner: Cell, + _pd: PhantomData, +} + +impl EffectCell { + pub fn bind(space: AllocatedOf, M>) -> Self { + Self { + inner: space, + _pd: PhantomData, + } + } + + pub fn read(&self) -> T + where + M: ManagerRead, + { + self.inner.read() + } + + pub fn write(&mut self, value: T) -> EG::Effect + where + M: ManagerWrite, + { + self.inner.write(value); + EG::EFFECT + } + + pub fn replace(&mut self, value: T) -> (T, EG::Effect) + where + M: ManagerReadWrite, + { + (self.inner.replace(value), EG::EFFECT) + } +} -- GitLab From 2cfe645e0512c9f12fb8e5ed22ba4a20a4c52510 Mon Sep 17 00:00:00 2001 From: Felix Puscasu Date: Wed, 7 Aug 2024 16:52:37 +0100 Subject: [PATCH 2/6] RISC-V: Add CSREffects enum --- .../lib/src/machine_state/csregisters.rs | 1 + .../src/machine_state/csregisters/effects.rs | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/riscv/lib/src/machine_state/csregisters/effects.rs diff --git a/src/riscv/lib/src/machine_state/csregisters.rs b/src/riscv/lib/src/machine_state/csregisters.rs index 9cbef9752a84..c715cb207726 100644 --- a/src/riscv/lib/src/machine_state/csregisters.rs +++ b/src/riscv/lib/src/machine_state/csregisters.rs @@ -5,6 +5,7 @@ #![allow(non_upper_case_globals)] pub mod bits; +pub mod effects; mod root; pub mod satp; pub mod values; diff --git a/src/riscv/lib/src/machine_state/csregisters/effects.rs b/src/riscv/lib/src/machine_state/csregisters/effects.rs new file mode 100644 index 000000000000..3f943585180a --- /dev/null +++ b/src/riscv/lib/src/machine_state/csregisters/effects.rs @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2024 TriliTech +// +// SPDX-License-Identifier: MIT + +use super::CSRegisters; +use crate::state_backend::ManagerBase; + +/// Type representing CSR side effects. (on read/write/replace) +/// Effects to be handled by function [`handle_csr_effect`]. +#[derive(PartialEq, Debug, Copy, Clone)] +pub enum CSREffect { + InvalidateTranslationCacheXIE, + InvalidateTranslationCacheXIP, + None, +} + +#[inline(always)] +pub fn handle_csr_effect(state: &mut CSRegisters, effect: CSREffect) { + match effect { + CSREffect::InvalidateTranslationCacheXIE => state.interrupt_cache.invalidate(), + CSREffect::InvalidateTranslationCacheXIP => state.interrupt_cache.invalidate_by_mip(), + CSREffect::None => (), + } +} -- GitLab From 5b82ed265c5b4c4e1674f04df9578701e8552d59 Mon Sep 17 00:00:00 2001 From: Felix Puscasu Date: Wed, 7 Aug 2024 16:52:37 +0100 Subject: [PATCH 3/6] RISC-V: Aggregate mstatus from sub-fields --- .../src/machine_state/csregisters/values.rs | 2 + .../csregisters/values/mstatus.rs | 319 ++++++++++++++++++ src/riscv/lib/src/state_backend/layout.rs | 10 +- 3 files changed, 325 insertions(+), 6 deletions(-) create mode 100644 src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs diff --git a/src/riscv/lib/src/machine_state/csregisters/values.rs b/src/riscv/lib/src/machine_state/csregisters/values.rs index d8f4c6e862f4..3ad43eed60f7 100644 --- a/src/riscv/lib/src/machine_state/csregisters/values.rs +++ b/src/riscv/lib/src/machine_state/csregisters/values.rs @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: MIT +mod mstatus; + use super::root::RootCSRegister; use crate::struct_layout; use crate::{ diff --git a/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs b/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs new file mode 100644 index 000000000000..f9b6f0fe5774 --- /dev/null +++ b/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs @@ -0,0 +1,319 @@ +// SPDX-FileCopyrightText: 2024 TriliTech +// +// SPDX-License-Identifier: MIT + +use super::CSRRepr; +use crate::{ + bits::{Bits64, ConstantBits}, + machine_state::csregisters::{ + effects::CSREffect, + xstatus::{ExtensionValue, MPPValue, MStatus, SPPValue, XLenValue}, + }, + state_backend::{ + AllocatedOf, Atom, Cell, EnumCell, EnumCellLayout, ManagerBase, ManagerRead, + ManagerReadWrite, ManagerWrite, + }, + struct_layout, +}; + +/// RISCV CSRegister.mstatus register state. +/// Accounts for CSR rules like WPRI, WARL, WLRL. +/// Contains only real fields (no shadows) hence it is a public field in [`super::CSRegisterValues`] +pub struct MStatusValue { + // Individual fields can be public since they are well typed and respect the WPRI, WARL, WLRL rules. + // Except for fields which have side-effects. These ones have custom read/write/replace methods + // to return side-effects to be accounted for + sie: Cell, + mie: Cell, + pub spie: Cell, + pub ube: Cell, + pub mpie: Cell, + pub spp: EnumCell, + pub mpp: EnumCell, + pub fs: EnumCell, + pub xs: EnumCell, + // vs is always OFF as we do not support the virtualisation extension + pub mprv: Cell, + pub sum: Cell, + pub mxr: Cell, + pub tvm: Cell, + pub tw: Cell, + pub tsr: Cell, + pub uxl: EnumCell, + pub sxl: EnumCell, + pub sbe: Cell, + pub mbe: Cell, +} + +impl MStatusValue { + pub fn bind(space: AllocatedOf) -> Self { + Self { + sie: space.sie, + mie: space.mie, + spie: space.spie, + ube: space.ube, + mpie: space.mpie, + spp: EnumCell::bind(space.spp), + mpp: EnumCell::bind(space.mpp), + fs: EnumCell::bind(space.fs), + xs: EnumCell::bind(space.xs), + mprv: space.mprv, + sum: space.sum, + mxr: space.mxr, + tvm: space.tvm, + tw: space.tw, + tsr: space.tsr, + uxl: EnumCell::bind(space.uxl), + sxl: EnumCell::bind(space.sxl), + sbe: space.sbe, + mbe: space.mbe, + } + } +} + +struct_layout!( + pub struct MStatusLayout { + sie: Atom, + mie: Atom, + spie: Atom, + ube: Atom, + mpie: Atom, + spp: EnumCellLayout, + mpp: EnumCellLayout, + fs: EnumCellLayout, + xs: EnumCellLayout, + mprv: Atom, + sum: Atom, + mxr: Atom, + tvm: Atom, + tw: Atom, + tsr: Atom, + uxl: EnumCellLayout, + sxl: EnumCellLayout, + sbe: Atom, + mbe: Atom, + } +); + +// Impl block for mie & sie fields. +// Required to return side-effects which should be handled with [`super::effects::handle_csr_effect`] +impl MStatusValue { + #[inline(always)] + pub fn mie_read(&self) -> bool + where + M: ManagerRead, + { + self.mie.read() + } + + #[inline(always)] + pub fn mie_write(&mut self, value: bool) -> CSREffect + where + M: ManagerWrite, + { + self.mie.write(value); + CSREffect::InvalidateTranslationCacheXIE + } + + #[inline(always)] + pub fn mie_replace(&mut self, value: bool) -> (bool, CSREffect) + where + M: ManagerReadWrite, + { + let old_value = self.mie.replace(value); + (old_value, CSREffect::InvalidateTranslationCacheXIE) + } + + #[inline(always)] + pub fn sie_read(&self) -> bool + where + M: ManagerRead, + { + self.sie.read() + } + + #[inline(always)] + pub fn sie_write(&mut self, value: bool) -> CSREffect + where + M: ManagerWrite, + { + self.sie.write(value); + CSREffect::InvalidateTranslationCacheXIE + } + + #[inline(always)] + pub fn sie_replace(&mut self, value: bool) -> (bool, CSREffect) + where + M: ManagerReadWrite, + { + let old_value = self.sie.replace(value); + (old_value, CSREffect::InvalidateTranslationCacheXIE) + } +} + +#[inline(always)] +fn compute_sd(fs: ExtensionValue, xs: ExtensionValue) -> bool { + fs == ExtensionValue::Dirty || xs == ExtensionValue::Dirty +} + +// Impl block for fields which are derived from other values or do not need to be stored in the backend. +impl MStatusValue { + /// Read mstatus.fs field + #[inline(always)] + pub fn read_sd(&self) -> bool + where + M: ManagerRead, + { + compute_sd(self.fs.read(), self.xs.read()) + } + + /// Read `mstatus.vs` field. For our implementation, this is a constant. + #[inline(always)] + pub const fn read_vs(&self) -> ExtensionValue { + ExtensionValue::Off + } +} + +// This impl block is here for compatibility with the bits api. +impl MStatusValue { + /// Read mstatus as in its 64 bit representation + #[inline] + pub fn read(&self) -> CSRRepr + where + M: ManagerRead, + { + let mstatus = &self; + let fs = mstatus.fs.read(); + let xs = mstatus.xs.read(); + MStatus::new( + ConstantBits, + mstatus.sie.read(), + ConstantBits, + mstatus.mie.read(), + ConstantBits, + mstatus.spie.read(), + mstatus.ube.read(), + mstatus.mpie.read(), + mstatus.spp.read(), + ConstantBits, + mstatus.mpp.read(), + fs, + xs, + mstatus.mprv.read(), + mstatus.sum.read(), + mstatus.mxr.read(), + mstatus.tvm.read(), + mstatus.tw.read(), + mstatus.tsr.read(), + ConstantBits, + mstatus.uxl.read(), + mstatus.sxl.read(), + mstatus.sbe.read(), + mstatus.mbe.read(), + ConstantBits, + compute_sd(xs, fs), + ) + .to_bits() + } + + /// Write to mstatus the `value` given in 64 bit representation + #[inline] + pub fn write(&mut self, value: CSRRepr) -> CSREffect + where + M: ManagerWrite, + { + let value = MStatus::from_bits(value); + let mstatus = self; + + let effect_sie = mstatus.sie_write(value.sie()); + let effect_mie = mstatus.mie_write(value.mie()); + debug_assert_eq!(effect_sie, CSREffect::InvalidateTranslationCacheXIE); + debug_assert_eq!(effect_mie, CSREffect::InvalidateTranslationCacheXIE); + + mstatus.spie.write(value.spie()); + mstatus.ube.write(value.ube()); + mstatus.mpie.write(value.mpie()); + mstatus.spp.write(value.spp()); + mstatus.mpp.write(value.mpp()); + mstatus.fs.write(value.fs()); + mstatus.xs.write(value.xs()); + mstatus.mprv.write(value.mprv()); + mstatus.sum.write(value.sum()); + mstatus.mxr.write(value.mxr()); + mstatus.tvm.write(value.tvm()); + mstatus.tw.write(value.tw()); + mstatus.tsr.write(value.tsr()); + mstatus.uxl.write(value.uxl()); + mstatus.sxl.write(value.sxl()); + mstatus.sbe.write(value.sbe()); + mstatus.mbe.write(value.mbe()); + + CSREffect::InvalidateTranslationCacheXIE + } + + /// Replace mstatus with `value` given in 64 bit representation + #[inline] + pub fn replace(&mut self, value: CSRRepr) -> (CSRRepr, CSREffect) + where + M: ManagerReadWrite, + { + let value = MStatus::from_bits(value); + let mstatus = self; + + let (sie, effect_sie) = mstatus.sie_replace(value.sie()); + let (mie, effect_mie) = mstatus.mie_replace(value.mie()); + debug_assert_eq!(effect_sie, CSREffect::InvalidateTranslationCacheXIE); + debug_assert_eq!(effect_mie, CSREffect::InvalidateTranslationCacheXIE); + + let spie = mstatus.spie.replace(value.spie()); + let ube = mstatus.ube.replace(value.ube()); + let mpie = mstatus.mpie.replace(value.mpie()); + let spp = mstatus.spp.replace(value.spp()); + let mpp = mstatus.mpp.replace(value.mpp()); + let fs = mstatus.fs.replace(value.fs()); + let xs = mstatus.xs.replace(value.xs()); + let mprv = mstatus.mprv.replace(value.mprv()); + let sum = mstatus.sum.replace(value.sum()); + let mxr = mstatus.mxr.replace(value.mxr()); + let tvm = mstatus.tvm.replace(value.tvm()); + let tw = mstatus.tw.replace(value.tw()); + let tsr = mstatus.tsr.replace(value.tsr()); + let uxl = mstatus.uxl.replace(value.uxl()); + let sxl = mstatus.sxl.replace(value.sxl()); + let sbe = mstatus.sbe.replace(value.sbe()); + let mbe = mstatus.mbe.replace(value.mbe()); + let sd = compute_sd(fs, xs); + + let old_value = MStatus::new( + ConstantBits::from_bits(0), + sie, + ConstantBits::from_bits(0), + mie, + ConstantBits::from_bits(0), + spie, + ube, + mpie, + spp, + ConstantBits::from_bits(0), + mpp, + fs, + xs, + mprv, + sum, + mxr, + tvm, + tw, + tsr, + ConstantBits::from_bits(0), + uxl, + sxl, + sbe, + mbe, + ConstantBits::from_bits(0), + sd, + ) + .to_bits(); + + (old_value, CSREffect::InvalidateTranslationCacheXIE) + } +} diff --git a/src/riscv/lib/src/state_backend/layout.rs b/src/riscv/lib/src/state_backend/layout.rs index f6a6f903a524..01c14efda735 100644 --- a/src/riscv/lib/src/state_backend/layout.rs +++ b/src/riscv/lib/src/state_backend/layout.rs @@ -89,10 +89,8 @@ impl Layout for Array { /// Usage: Provide a struct with each field holding a layout. /// /// ``` -/// use octez_riscv::*; /// use octez_riscv::state_backend::*; /// use octez_riscv::machine_state::csregisters::CSRRepr; -/// use octez_riscv::machine_state::mode::Mode; /// use octez_riscv::struct_layout; /// /// struct_layout!( @@ -115,19 +113,19 @@ macro_rules! struct_layout { } pub struct [<$layout_t Placed>] { - $( $field_name: PlacedOf<$cell_repr> ),+ + $( $field_name: $crate::state_backend::PlacedOf<$cell_repr> ),+ } pub struct [<$layout_t Allocated>] { $( $field_name: AllocatedOf<$cell_repr, M> ),+ } - impl Layout for $layout_t { + impl $crate::state_backend::Layout for $layout_t { type Placed = [<$layout_t Placed>]; type Allocated = [<$layout_t Allocated>]; - fn place_with(alloc: &mut Choreographer) -> Self::Placed { + fn place_with(alloc: &mut $crate::state_backend::Choreographer) -> Self::Placed { [<$layout_t Placed>] { $($field_name: alloc.alloc()),+ } @@ -138,7 +136,7 @@ macro_rules! struct_layout { placed: Self::Placed ) -> Self::Allocated { Self::Allocated { - $($field_name: <$cell_repr as Layout>::allocate( + $($field_name: <$cell_repr as $crate::state_backend::Layout>::allocate( backend, placed.$field_name )),+ } -- GitLab From dfccc6707b00bd4b64d40c31451ce8756b0fd61a Mon Sep 17 00:00:00 2001 From: Felix Puscasu Date: Wed, 7 Aug 2024 16:52:37 +0100 Subject: [PATCH 4/6] RISC-V: Update CSRegisters --- .../lib/src/machine_state/csregisters.rs | 56 +- .../src/machine_state/csregisters/effects.rs | 27 +- .../src/machine_state/csregisters/values.rs | 1039 ++++++++--------- .../csregisters/values/mstatus.rs | 32 +- src/riscv/lib/src/state_backend/effects.rs | 6 +- src/riscv/lib/src/state_backend/layout.rs | 2 +- 6 files changed, 577 insertions(+), 585 deletions(-) diff --git a/src/riscv/lib/src/machine_state/csregisters.rs b/src/riscv/lib/src/machine_state/csregisters.rs index c715cb207726..d7e81741f66f 100644 --- a/src/riscv/lib/src/machine_state/csregisters.rs +++ b/src/riscv/lib/src/machine_state/csregisters.rs @@ -31,7 +31,7 @@ use crate::{ use num_enum::TryFromPrimitive; use root::RootCSRegister; use strum::IntoEnumIterator; -use values::{CSRegisterValues, CSRegisterValuesLayout}; +use values::{CSRegisterValues, CSRegisterValuesLayout, MStatusValue}; /// Privilege required to access a CSR #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] @@ -1070,6 +1070,16 @@ pub struct CSRegisters { } impl CSRegisters { + #[inline(always)] + pub const fn mstatus(&self) -> &MStatusValue { + &self.registers.mstatus + } + + #[inline(always)] + pub fn mstatus_mut(&mut self) -> &mut MStatusValue { + &mut self.registers.mstatus + } + /// Transform the write operation to account for shadow registers. /// (e.g. `sstatus` register) /// @@ -1086,32 +1096,32 @@ impl CSRegisters { // Note: This works because currently there are no shadowed WLRL registers match reg { CSRegister::sstatus => { - let mstatus = self.registers.read_mstatus(); + let mstatus = self.registers.mstatus.read(); let mstatus = MStatus::from_bits(mstatus); let sstatus = SStatus::from_bits(value); let mstatus = sstatus.to_mstatus(mstatus); mstatus.to_bits() } CSRegister::sip => { - let mip = self.registers.read_mip(); + let mip = self.registers.mip.read(); let sip_only = value & CSRegister::WARL_MASK_SIP_SIE; let mip_only = mip & !CSRegister::WARL_MASK_SIP_SIE; sip_only | mip_only } CSRegister::sie => { - let mie = self.registers.read_mie(); + let mie = self.registers.mie.read(); let sie_only = value & CSRegister::WARL_MASK_SIP_SIE; let mie_only = mie & !CSRegister::WARL_MASK_SIP_SIE; sie_only | mie_only } CSRegister::fcsr => value & CSRegister::FCSR_MASK, CSRegister::frm => { - let fcsr = self.registers.read_fcsr(); + let fcsr = self.registers.fcsr.read(); let fcsr = fcsr & !CSRegister::FRM_MASK; ((value << CSRegister::FRM_SHIFT) & CSRegister::FRM_MASK) | fcsr } CSRegister::fflags => { - let fcsr = self.registers.read_fcsr(); + let fcsr = self.registers.fcsr.read(); let fcsr = fcsr & !CSRegister::FFLAGS_MASK; (value & CSRegister::FFLAGS_MASK) | fcsr } @@ -1135,7 +1145,7 @@ impl CSRegisters { { let source_reg_value = source_reg_value.unwrap_or_else(|| { // If reg is a shadow, obtain the underlying ground truth for that register - self.registers.general_raw_read(reg.into()) + self.general_raw_read(reg.into()) }); // modify the value according to the shadowing rules of each register @@ -1159,19 +1169,7 @@ impl CSRegisters { if let Some(value) = reg.make_value_writable(value.to_bits()) { let value = self.transform_write(reg, value); let source_reg: RootCSRegister = reg.into(); - self.registers.general_raw_write(source_reg, value); - - // TODO: RV-159. after !14177 - // invalidation will be incorporated into `csregisters_boilerplate!` - match source_reg { - RootCSRegister::mstatus => { - self.interrupt_cache.invalidate(); - } - RootCSRegister::mip => { - self.interrupt_cache.invalidate_by_mip(); - } - _ => {} - } + self.general_raw_write(source_reg, value); } } @@ -1196,20 +1194,7 @@ impl CSRegisters { if let Some(value) = reg.make_value_writable(value.to_bits()) { let value = self.transform_write(reg, value); let source_reg: RootCSRegister = reg.into(); - let old_value = self.registers.general_raw_replace(source_reg, value); - - // TODO: RV-159. after !14177 - // invalidation will be incorporated into `csregisters_boilerplate!` - match source_reg { - RootCSRegister::mstatus => { - self.interrupt_cache.invalidate(); - } - RootCSRegister::mip => { - self.interrupt_cache.invalidate_by_mip(); - } - _ => {} - }; - + let old_value = self.general_raw_replace(source_reg, value); let old_value = self.transform_read(reg, Some(old_value)); V::from_bits(old_value) } else { @@ -1369,8 +1354,7 @@ impl CSRegisters { { // Try to reset known CSRs to known default values. for reg in CSRegister::iter() { - self.registers - .general_raw_write(reg.into(), reg.default_value()); + self.general_raw_write(reg.into(), reg.default_value()); } } diff --git a/src/riscv/lib/src/machine_state/csregisters/effects.rs b/src/riscv/lib/src/machine_state/csregisters/effects.rs index 3f943585180a..727cc6d35aa1 100644 --- a/src/riscv/lib/src/machine_state/csregisters/effects.rs +++ b/src/riscv/lib/src/machine_state/csregisters/effects.rs @@ -11,14 +11,29 @@ use crate::state_backend::ManagerBase; pub enum CSREffect { InvalidateTranslationCacheXIE, InvalidateTranslationCacheXIP, - None, } +macro_rules! create_effect_getter { + ($struct_name:ident, $effect:expr) => { + pub struct $struct_name; + + impl $crate::state_backend::EffectGetter for $struct_name { + type Effect = CSREffect; + + const EFFECT: Option = $effect; + } + }; +} + +create_effect_getter!(NoEffect, None); +create_effect_getter!(MipEffect, Some(CSREffect::InvalidateTranslationCacheXIP)); + #[inline(always)] -pub fn handle_csr_effect(state: &mut CSRegisters, effect: CSREffect) { - match effect { - CSREffect::InvalidateTranslationCacheXIE => state.interrupt_cache.invalidate(), - CSREffect::InvalidateTranslationCacheXIP => state.interrupt_cache.invalidate_by_mip(), - CSREffect::None => (), +pub fn handle_csr_effect(state: &mut CSRegisters, effect: Option) { + if let Some(effect) = effect { + match effect { + CSREffect::InvalidateTranslationCacheXIE => state.interrupt_cache.invalidate(), + CSREffect::InvalidateTranslationCacheXIP => state.interrupt_cache.invalidate_by_mip(), + } } } diff --git a/src/riscv/lib/src/machine_state/csregisters/values.rs b/src/riscv/lib/src/machine_state/csregisters/values.rs index 3ad43eed60f7..5447df463c63 100644 --- a/src/riscv/lib/src/machine_state/csregisters/values.rs +++ b/src/riscv/lib/src/machine_state/csregisters/values.rs @@ -4,12 +4,19 @@ mod mstatus; -use super::root::RootCSRegister; -use crate::struct_layout; +use super::{ + effects::{handle_csr_effect, CSREffect, MipEffect, NoEffect}, + root::RootCSRegister, + CSRegisters, +}; use crate::{ bits::Bits64, - state_backend::{AllocatedOf, Atom, Cell, Choreographer, Layout, PlacedOf}, + state_backend::EffectGetter, + state_backend::{AllocatedOf, EffectCell, EffectCellLayout}, + struct_layout, }; +use mstatus::MStatusLayout; +pub(super) use mstatus::MStatusValue; /// Representation of a value in a CSR pub type CSRRepr = u64; @@ -51,564 +58,550 @@ impl Bits64 for CSRValue { macro_rules! csregisters_boilerplate { ( - $struct_v:vis struct $struct_t:ident with layout $layout_t:ty { - $($name:ident: $cell_repr:ty),+ + $struct_v:vis struct $struct_t:ident where layout $layout_t:ty { + $($vis:vis $name:ident: $cell_repr:ty),+ $( , )? } - ) => { paste::paste! { - $struct_v struct $struct_t { - $($name: Cell<$cell_repr, M>,)+ + ) => { + $struct_v struct $struct_t + where + M: $crate::state_backend::ManagerBase, + { + // pub mstatus: MStatusValue, + // pub mip: MipValue, + $($vis $name: $cell_repr,)+ } impl $struct_t { pub fn bind(space: AllocatedOf<$layout_t, M>) -> Self { Self { - $($name: space.$name,)* + $($name: <$cell_repr>::bind(space.$name),)+ } } + } - // The raw read / write / replace methods on the underlying "full" CSRs (so no sub-fields) - // These are allowed to be used only by CSRegisters module since they do not account for - // CSR rules like side-effects, shadowing, WLRL, WARL, WPRI. - $( - #[inline(always)] - pub(super) fn [](&self) -> $cell_repr - where - M: $crate::state_backend::ManagerRead - { - self.$name.read() - } - - #[inline(always)] - pub(super) fn [](&mut self, value: $cell_repr) - where - M: $crate::state_backend::ManagerWrite - { - self.$name.write(value) - } - - #[inline(always)] - pub(super) fn [](&mut self, value: $cell_repr) -> $cell_repr - where - M: $crate::state_backend::ManagerReadWrite - { - - self.$name.replace(value) - } - )* - - // These methods are needed in the case the access to a CSR - // is not known statically / at compile time, - // hence they need to go through a match statement. - // e.g. the CSRRW / CSRRC etc instructions + impl CSRegisters { + // Methods for operating on a generic CSRegister (used by csrrw/csrrci etc) + // Not public since they are used only as an abstraction by [CSRegisters] #[inline(always)] pub(super) fn general_raw_read(&self, csr: RootCSRegister) -> CSRRepr where - M: $crate::state_backend::ManagerRead + M: $crate::state_backend::ManagerRead, { match csr { - $( RootCSRegister::$name => self.[]() ),* + $( RootCSRegister::$name => self.registers.$name.read() ),+ } } #[inline(always)] pub(super) fn general_raw_write(&mut self, csr: RootCSRegister, value: CSRRepr) where - M: $crate::state_backend::ManagerWrite + M: $crate::state_backend::ManagerWrite, { - match csr { - $( RootCSRegister::$name => self.[](value) ),* - } + let effect = match csr { + $( RootCSRegister::$name => self.registers.$name.write(value) ),+ + }; + + handle_csr_effect(self, effect); } #[inline(always)] pub(super) fn general_raw_replace(&mut self, csr: RootCSRegister, value: CSRRepr) -> CSRRepr where - M: $crate::state_backend::ManagerReadWrite + M: $crate::state_backend::ManagerReadWrite, { + let (old_value, effect) = match csr { + $( RootCSRegister::$name => self.registers.$name.replace(value) ),+ + }; - match csr { - $( RootCSRegister::$name => self.[](value) ),* - } + handle_csr_effect(self, effect); + old_value } } - } }; + }; } +type NoEffectCSR = EffectCell; +type MipEffectCSR = EffectCell; + +type EffectCSRLayout = EffectCellLayout; + csregisters_boilerplate!( - pub(super) struct CSRegisterValues with layout CSRegisterValuesLayout { - mnscratch: CSRRepr, - mnepc: CSRRepr, - mncause: CSRRepr, - mnstatus: CSRRepr, - cycle: CSRRepr, - time: CSRRepr, - instret: CSRRepr, - mcycle: CSRRepr, - minstret: CSRRepr, - hpmcounter3: CSRRepr, - hpmcounter4: CSRRepr, - hpmcounter5: CSRRepr, - hpmcounter6: CSRRepr, - hpmcounter7: CSRRepr, - hpmcounter8: CSRRepr, - hpmcounter9: CSRRepr, - hpmcounter10: CSRRepr, - hpmcounter11: CSRRepr, - hpmcounter12: CSRRepr, - hpmcounter13: CSRRepr, - hpmcounter14: CSRRepr, - hpmcounter15: CSRRepr, - hpmcounter16: CSRRepr, - hpmcounter17: CSRRepr, - hpmcounter18: CSRRepr, - hpmcounter19: CSRRepr, - hpmcounter20: CSRRepr, - hpmcounter21: CSRRepr, - hpmcounter22: CSRRepr, - hpmcounter23: CSRRepr, - hpmcounter24: CSRRepr, - hpmcounter25: CSRRepr, - hpmcounter26: CSRRepr, - hpmcounter27: CSRRepr, - hpmcounter28: CSRRepr, - hpmcounter29: CSRRepr, - hpmcounter30: CSRRepr, - hpmcounter31: CSRRepr, - mhpmcounter3: CSRRepr, - mhpmcounter4: CSRRepr, - mhpmcounter5: CSRRepr, - mhpmcounter6: CSRRepr, - mhpmcounter7: CSRRepr, - mhpmcounter8: CSRRepr, - mhpmcounter9: CSRRepr, - mhpmcounter10: CSRRepr, - mhpmcounter11: CSRRepr, - mhpmcounter12: CSRRepr, - mhpmcounter13: CSRRepr, - mhpmcounter14: CSRRepr, - mhpmcounter15: CSRRepr, - mhpmcounter16: CSRRepr, - mhpmcounter17: CSRRepr, - mhpmcounter18: CSRRepr, - mhpmcounter19: CSRRepr, - mhpmcounter20: CSRRepr, - mhpmcounter21: CSRRepr, - mhpmcounter22: CSRRepr, - mhpmcounter23: CSRRepr, - mhpmcounter24: CSRRepr, - mhpmcounter25: CSRRepr, - mhpmcounter26: CSRRepr, - mhpmcounter27: CSRRepr, - mhpmcounter28: CSRRepr, - mhpmcounter29: CSRRepr, - mhpmcounter30: CSRRepr, - mhpmcounter31: CSRRepr, - mhpmevent3: CSRRepr, - mhpmevent4: CSRRepr, - mhpmevent5: CSRRepr, - mhpmevent6: CSRRepr, - mhpmevent7: CSRRepr, - mhpmevent8: CSRRepr, - mhpmevent9: CSRRepr, - mhpmevent10: CSRRepr, - mhpmevent11: CSRRepr, - mhpmevent12: CSRRepr, - mhpmevent13: CSRRepr, - mhpmevent14: CSRRepr, - mhpmevent15: CSRRepr, - mhpmevent16: CSRRepr, - mhpmevent17: CSRRepr, - mhpmevent18: CSRRepr, - mhpmevent19: CSRRepr, - mhpmevent20: CSRRepr, - mhpmevent21: CSRRepr, - mhpmevent22: CSRRepr, - mhpmevent23: CSRRepr, - mhpmevent24: CSRRepr, - mhpmevent25: CSRRepr, - mhpmevent26: CSRRepr, - mhpmevent27: CSRRepr, - mhpmevent28: CSRRepr, - mhpmevent29: CSRRepr, - mhpmevent30: CSRRepr, - mhpmevent31: CSRRepr, - mcountinhibit: CSRRepr, - scounteren: CSRRepr, - mcounteren: CSRRepr, - fcsr: CSRRepr, - pmpcfg0: CSRRepr, - pmpcfg2: CSRRepr, - pmpcfg4: CSRRepr, - pmpcfg6: CSRRepr, - pmpcfg8: CSRRepr, - pmpcfg10: CSRRepr, - pmpcfg12: CSRRepr, - pmpcfg14: CSRRepr, - pmpaddr0: CSRRepr, - pmpaddr1: CSRRepr, - pmpaddr2: CSRRepr, - pmpaddr3: CSRRepr, - pmpaddr4: CSRRepr, - pmpaddr5: CSRRepr, - pmpaddr6: CSRRepr, - pmpaddr7: CSRRepr, - pmpaddr8: CSRRepr, - pmpaddr9: CSRRepr, - pmpaddr10: CSRRepr, - pmpaddr11: CSRRepr, - pmpaddr12: CSRRepr, - pmpaddr13: CSRRepr, - pmpaddr14: CSRRepr, - pmpaddr15: CSRRepr, - pmpaddr16: CSRRepr, - pmpaddr17: CSRRepr, - pmpaddr18: CSRRepr, - pmpaddr19: CSRRepr, - pmpaddr20: CSRRepr, - pmpaddr21: CSRRepr, - pmpaddr22: CSRRepr, - pmpaddr23: CSRRepr, - pmpaddr24: CSRRepr, - pmpaddr25: CSRRepr, - pmpaddr26: CSRRepr, - pmpaddr27: CSRRepr, - pmpaddr28: CSRRepr, - pmpaddr29: CSRRepr, - pmpaddr30: CSRRepr, - pmpaddr31: CSRRepr, - pmpaddr32: CSRRepr, - pmpaddr33: CSRRepr, - pmpaddr34: CSRRepr, - pmpaddr35: CSRRepr, - pmpaddr36: CSRRepr, - pmpaddr37: CSRRepr, - pmpaddr38: CSRRepr, - pmpaddr39: CSRRepr, - pmpaddr40: CSRRepr, - pmpaddr41: CSRRepr, - pmpaddr42: CSRRepr, - pmpaddr43: CSRRepr, - pmpaddr44: CSRRepr, - pmpaddr45: CSRRepr, - pmpaddr46: CSRRepr, - pmpaddr47: CSRRepr, - pmpaddr48: CSRRepr, - pmpaddr49: CSRRepr, - pmpaddr50: CSRRepr, - pmpaddr51: CSRRepr, - pmpaddr52: CSRRepr, - pmpaddr53: CSRRepr, - pmpaddr54: CSRRepr, - pmpaddr55: CSRRepr, - pmpaddr56: CSRRepr, - pmpaddr57: CSRRepr, - pmpaddr58: CSRRepr, - pmpaddr59: CSRRepr, - pmpaddr60: CSRRepr, - pmpaddr61: CSRRepr, - pmpaddr62: CSRRepr, - pmpaddr63: CSRRepr, - mhartid: CSRRepr, - mvendorid: CSRRepr, - marchid: CSRRepr, - mimpid: CSRRepr, - misa: CSRRepr, - mscratch: CSRRepr, - mstatus: CSRRepr, - sscratch: CSRRepr, - stvec: CSRRepr, - mtvec: CSRRepr, - mie: CSRRepr, - satp: CSRRepr, - scause: CSRRepr, - mcause: CSRRepr, - sepc: CSRRepr, - mepc: CSRRepr, - stval: CSRRepr, - mtval: CSRRepr, - mtval2: CSRRepr, - mip: CSRRepr, - mtinst: CSRRepr, - senvcfg: CSRRepr, - menvcfg: CSRRepr, - mconfigptr: CSRRepr, - medeleg: CSRRepr, - mideleg: CSRRepr, - mseccfg: CSRRepr, - scontext: CSRRepr, - hstatus: CSRRepr, - hedeleg: CSRRepr, - hideleg: CSRRepr, - hie: CSRRepr, - hcounteren: CSRRepr, - hgeie: CSRRepr, - htval: CSRRepr, - hip: CSRRepr, - hvip: CSRRepr, - htinst: CSRRepr, - hgeip: CSRRepr, - henvcfg: CSRRepr, - hgatp: CSRRepr, - hcontext: CSRRepr, - htimedelta: CSRRepr, - vsstatus: CSRRepr, - vsie: CSRRepr, - vstvec: CSRRepr, - vsscratch: CSRRepr, - vsepc: CSRRepr, - vscause: CSRRepr, - vstval: CSRRepr, - vsip: CSRRepr, - vsatp: CSRRepr, - tselect: CSRRepr, - tdata1: CSRRepr, - tdata2: CSRRepr, - tdata3: CSRRepr, - tcontrol: CSRRepr, - mcontext: CSRRepr, - dcsr: CSRRepr, - dpc: CSRRepr, - dscratch0: CSRRepr, - dscratch1: CSRRepr, + pub(super) struct CSRegisterValues where layout CSRegisterValuesLayout { + pub(super) mstatus: MStatusValue, + pub(super) mip: MipEffectCSR, + + mnscratch: NoEffectCSR, + mnepc: NoEffectCSR, + mncause: NoEffectCSR, + mnstatus: NoEffectCSR, + cycle: NoEffectCSR, + time: NoEffectCSR, + instret: NoEffectCSR, + mcycle: NoEffectCSR, + minstret: NoEffectCSR, + hpmcounter3: NoEffectCSR, + hpmcounter4: NoEffectCSR, + hpmcounter5: NoEffectCSR, + hpmcounter6: NoEffectCSR, + hpmcounter7: NoEffectCSR, + hpmcounter8: NoEffectCSR, + hpmcounter9: NoEffectCSR, + hpmcounter10: NoEffectCSR, + hpmcounter11: NoEffectCSR, + hpmcounter12: NoEffectCSR, + hpmcounter13: NoEffectCSR, + hpmcounter14: NoEffectCSR, + hpmcounter15: NoEffectCSR, + hpmcounter16: NoEffectCSR, + hpmcounter17: NoEffectCSR, + hpmcounter18: NoEffectCSR, + hpmcounter19: NoEffectCSR, + hpmcounter20: NoEffectCSR, + hpmcounter21: NoEffectCSR, + hpmcounter22: NoEffectCSR, + hpmcounter23: NoEffectCSR, + hpmcounter24: NoEffectCSR, + hpmcounter25: NoEffectCSR, + hpmcounter26: NoEffectCSR, + hpmcounter27: NoEffectCSR, + hpmcounter28: NoEffectCSR, + hpmcounter29: NoEffectCSR, + hpmcounter30: NoEffectCSR, + hpmcounter31: NoEffectCSR, + mhpmcounter3: NoEffectCSR, + mhpmcounter4: NoEffectCSR, + mhpmcounter5: NoEffectCSR, + mhpmcounter6: NoEffectCSR, + mhpmcounter7: NoEffectCSR, + mhpmcounter8: NoEffectCSR, + mhpmcounter9: NoEffectCSR, + mhpmcounter10: NoEffectCSR, + mhpmcounter11: NoEffectCSR, + mhpmcounter12: NoEffectCSR, + mhpmcounter13: NoEffectCSR, + mhpmcounter14: NoEffectCSR, + mhpmcounter15: NoEffectCSR, + mhpmcounter16: NoEffectCSR, + mhpmcounter17: NoEffectCSR, + mhpmcounter18: NoEffectCSR, + mhpmcounter19: NoEffectCSR, + mhpmcounter20: NoEffectCSR, + mhpmcounter21: NoEffectCSR, + mhpmcounter22: NoEffectCSR, + mhpmcounter23: NoEffectCSR, + mhpmcounter24: NoEffectCSR, + mhpmcounter25: NoEffectCSR, + mhpmcounter26: NoEffectCSR, + mhpmcounter27: NoEffectCSR, + mhpmcounter28: NoEffectCSR, + mhpmcounter29: NoEffectCSR, + mhpmcounter30: NoEffectCSR, + mhpmcounter31: NoEffectCSR, + mhpmevent3: NoEffectCSR, + mhpmevent4: NoEffectCSR, + mhpmevent5: NoEffectCSR, + mhpmevent6: NoEffectCSR, + mhpmevent7: NoEffectCSR, + mhpmevent8: NoEffectCSR, + mhpmevent9: NoEffectCSR, + mhpmevent10: NoEffectCSR, + mhpmevent11: NoEffectCSR, + mhpmevent12: NoEffectCSR, + mhpmevent13: NoEffectCSR, + mhpmevent14: NoEffectCSR, + mhpmevent15: NoEffectCSR, + mhpmevent16: NoEffectCSR, + mhpmevent17: NoEffectCSR, + mhpmevent18: NoEffectCSR, + mhpmevent19: NoEffectCSR, + mhpmevent20: NoEffectCSR, + mhpmevent21: NoEffectCSR, + mhpmevent22: NoEffectCSR, + mhpmevent23: NoEffectCSR, + mhpmevent24: NoEffectCSR, + mhpmevent25: NoEffectCSR, + mhpmevent26: NoEffectCSR, + mhpmevent27: NoEffectCSR, + mhpmevent28: NoEffectCSR, + mhpmevent29: NoEffectCSR, + mhpmevent30: NoEffectCSR, + mhpmevent31: NoEffectCSR, + mcountinhibit: NoEffectCSR, + scounteren: NoEffectCSR, + mcounteren: NoEffectCSR, + pub(super) fcsr: NoEffectCSR, + pmpcfg0: NoEffectCSR, + pmpcfg2: NoEffectCSR, + pmpcfg4: NoEffectCSR, + pmpcfg6: NoEffectCSR, + pmpcfg8: NoEffectCSR, + pmpcfg10: NoEffectCSR, + pmpcfg12: NoEffectCSR, + pmpcfg14: NoEffectCSR, + pmpaddr0: NoEffectCSR, + pmpaddr1: NoEffectCSR, + pmpaddr2: NoEffectCSR, + pmpaddr3: NoEffectCSR, + pmpaddr4: NoEffectCSR, + pmpaddr5: NoEffectCSR, + pmpaddr6: NoEffectCSR, + pmpaddr7: NoEffectCSR, + pmpaddr8: NoEffectCSR, + pmpaddr9: NoEffectCSR, + pmpaddr10: NoEffectCSR, + pmpaddr11: NoEffectCSR, + pmpaddr12: NoEffectCSR, + pmpaddr13: NoEffectCSR, + pmpaddr14: NoEffectCSR, + pmpaddr15: NoEffectCSR, + pmpaddr16: NoEffectCSR, + pmpaddr17: NoEffectCSR, + pmpaddr18: NoEffectCSR, + pmpaddr19: NoEffectCSR, + pmpaddr20: NoEffectCSR, + pmpaddr21: NoEffectCSR, + pmpaddr22: NoEffectCSR, + pmpaddr23: NoEffectCSR, + pmpaddr24: NoEffectCSR, + pmpaddr25: NoEffectCSR, + pmpaddr26: NoEffectCSR, + pmpaddr27: NoEffectCSR, + pmpaddr28: NoEffectCSR, + pmpaddr29: NoEffectCSR, + pmpaddr30: NoEffectCSR, + pmpaddr31: NoEffectCSR, + pmpaddr32: NoEffectCSR, + pmpaddr33: NoEffectCSR, + pmpaddr34: NoEffectCSR, + pmpaddr35: NoEffectCSR, + pmpaddr36: NoEffectCSR, + pmpaddr37: NoEffectCSR, + pmpaddr38: NoEffectCSR, + pmpaddr39: NoEffectCSR, + pmpaddr40: NoEffectCSR, + pmpaddr41: NoEffectCSR, + pmpaddr42: NoEffectCSR, + pmpaddr43: NoEffectCSR, + pmpaddr44: NoEffectCSR, + pmpaddr45: NoEffectCSR, + pmpaddr46: NoEffectCSR, + pmpaddr47: NoEffectCSR, + pmpaddr48: NoEffectCSR, + pmpaddr49: NoEffectCSR, + pmpaddr50: NoEffectCSR, + pmpaddr51: NoEffectCSR, + pmpaddr52: NoEffectCSR, + pmpaddr53: NoEffectCSR, + pmpaddr54: NoEffectCSR, + pmpaddr55: NoEffectCSR, + pmpaddr56: NoEffectCSR, + pmpaddr57: NoEffectCSR, + pmpaddr58: NoEffectCSR, + pmpaddr59: NoEffectCSR, + pmpaddr60: NoEffectCSR, + pmpaddr61: NoEffectCSR, + pmpaddr62: NoEffectCSR, + pmpaddr63: NoEffectCSR, + mhartid: NoEffectCSR, + mvendorid: NoEffectCSR, + marchid: NoEffectCSR, + mimpid: NoEffectCSR, + misa: NoEffectCSR, + mscratch: NoEffectCSR, + sscratch: NoEffectCSR, + stvec: NoEffectCSR, + mtvec: NoEffectCSR, + pub(super) mie: NoEffectCSR, + satp: NoEffectCSR, + scause: NoEffectCSR, + mcause: NoEffectCSR, + sepc: NoEffectCSR, + mepc: NoEffectCSR, + stval: NoEffectCSR, + mtval: NoEffectCSR, + mtval2: NoEffectCSR, + mtinst: NoEffectCSR, + senvcfg: NoEffectCSR, + menvcfg: NoEffectCSR, + mconfigptr: NoEffectCSR, + medeleg: NoEffectCSR, + mideleg: NoEffectCSR, + mseccfg: NoEffectCSR, + scontext: NoEffectCSR, + hstatus: NoEffectCSR, + hedeleg: NoEffectCSR, + hideleg: NoEffectCSR, + hie: NoEffectCSR, + hcounteren: NoEffectCSR, + hgeie: NoEffectCSR, + htval: NoEffectCSR, + hip: NoEffectCSR, + hvip: NoEffectCSR, + htinst: NoEffectCSR, + hgeip: NoEffectCSR, + henvcfg: NoEffectCSR, + hgatp: NoEffectCSR, + hcontext: NoEffectCSR, + htimedelta: NoEffectCSR, + vsstatus: NoEffectCSR, + vsie: NoEffectCSR, + vstvec: NoEffectCSR, + vsscratch: NoEffectCSR, + vsepc: NoEffectCSR, + vscause: NoEffectCSR, + vstval: NoEffectCSR, + vsip: NoEffectCSR, + vsatp: NoEffectCSR, + tselect: NoEffectCSR, + tdata1: NoEffectCSR, + tdata2: NoEffectCSR, + tdata3: NoEffectCSR, + tcontrol: NoEffectCSR, + mcontext: NoEffectCSR, + dcsr: NoEffectCSR, + dpc: NoEffectCSR, + dscratch0: NoEffectCSR, + dscratch1: NoEffectCSR, } ); struct_layout!( pub struct CSRegisterValuesLayout { - mnscratch: Atom, - mnepc: Atom, - mncause: Atom, - mnstatus: Atom, - cycle: Atom, - time: Atom, - instret: Atom, - mcycle: Atom, - minstret: Atom, - hpmcounter3: Atom, - hpmcounter4: Atom, - hpmcounter5: Atom, - hpmcounter6: Atom, - hpmcounter7: Atom, - hpmcounter8: Atom, - hpmcounter9: Atom, - hpmcounter10: Atom, - hpmcounter11: Atom, - hpmcounter12: Atom, - hpmcounter13: Atom, - hpmcounter14: Atom, - hpmcounter15: Atom, - hpmcounter16: Atom, - hpmcounter17: Atom, - hpmcounter18: Atom, - hpmcounter19: Atom, - hpmcounter20: Atom, - hpmcounter21: Atom, - hpmcounter22: Atom, - hpmcounter23: Atom, - hpmcounter24: Atom, - hpmcounter25: Atom, - hpmcounter26: Atom, - hpmcounter27: Atom, - hpmcounter28: Atom, - hpmcounter29: Atom, - hpmcounter30: Atom, - hpmcounter31: Atom, - mhpmcounter3: Atom, - mhpmcounter4: Atom, - mhpmcounter5: Atom, - mhpmcounter6: Atom, - mhpmcounter7: Atom, - mhpmcounter8: Atom, - mhpmcounter9: Atom, - mhpmcounter10: Atom, - mhpmcounter11: Atom, - mhpmcounter12: Atom, - mhpmcounter13: Atom, - mhpmcounter14: Atom, - mhpmcounter15: Atom, - mhpmcounter16: Atom, - mhpmcounter17: Atom, - mhpmcounter18: Atom, - mhpmcounter19: Atom, - mhpmcounter20: Atom, - mhpmcounter21: Atom, - mhpmcounter22: Atom, - mhpmcounter23: Atom, - mhpmcounter24: Atom, - mhpmcounter25: Atom, - mhpmcounter26: Atom, - mhpmcounter27: Atom, - mhpmcounter28: Atom, - mhpmcounter29: Atom, - mhpmcounter30: Atom, - mhpmcounter31: Atom, - mhpmevent3: Atom, - mhpmevent4: Atom, - mhpmevent5: Atom, - mhpmevent6: Atom, - mhpmevent7: Atom, - mhpmevent8: Atom, - mhpmevent9: Atom, - mhpmevent10: Atom, - mhpmevent11: Atom, - mhpmevent12: Atom, - mhpmevent13: Atom, - mhpmevent14: Atom, - mhpmevent15: Atom, - mhpmevent16: Atom, - mhpmevent17: Atom, - mhpmevent18: Atom, - mhpmevent19: Atom, - mhpmevent20: Atom, - mhpmevent21: Atom, - mhpmevent22: Atom, - mhpmevent23: Atom, - mhpmevent24: Atom, - mhpmevent25: Atom, - mhpmevent26: Atom, - mhpmevent27: Atom, - mhpmevent28: Atom, - mhpmevent29: Atom, - mhpmevent30: Atom, - mhpmevent31: Atom, - mcountinhibit: Atom, - scounteren: Atom, - mcounteren: Atom, - fcsr: Atom, - pmpcfg0: Atom, - pmpcfg2: Atom, - pmpcfg4: Atom, - pmpcfg6: Atom, - pmpcfg8: Atom, - pmpcfg10: Atom, - pmpcfg12: Atom, - pmpcfg14: Atom, - pmpaddr0: Atom, - pmpaddr1: Atom, - pmpaddr2: Atom, - pmpaddr3: Atom, - pmpaddr4: Atom, - pmpaddr5: Atom, - pmpaddr6: Atom, - pmpaddr7: Atom, - pmpaddr8: Atom, - pmpaddr9: Atom, - pmpaddr10: Atom, - pmpaddr11: Atom, - pmpaddr12: Atom, - pmpaddr13: Atom, - pmpaddr14: Atom, - pmpaddr15: Atom, - pmpaddr16: Atom, - pmpaddr17: Atom, - pmpaddr18: Atom, - pmpaddr19: Atom, - pmpaddr20: Atom, - pmpaddr21: Atom, - pmpaddr22: Atom, - pmpaddr23: Atom, - pmpaddr24: Atom, - pmpaddr25: Atom, - pmpaddr26: Atom, - pmpaddr27: Atom, - pmpaddr28: Atom, - pmpaddr29: Atom, - pmpaddr30: Atom, - pmpaddr31: Atom, - pmpaddr32: Atom, - pmpaddr33: Atom, - pmpaddr34: Atom, - pmpaddr35: Atom, - pmpaddr36: Atom, - pmpaddr37: Atom, - pmpaddr38: Atom, - pmpaddr39: Atom, - pmpaddr40: Atom, - pmpaddr41: Atom, - pmpaddr42: Atom, - pmpaddr43: Atom, - pmpaddr44: Atom, - pmpaddr45: Atom, - pmpaddr46: Atom, - pmpaddr47: Atom, - pmpaddr48: Atom, - pmpaddr49: Atom, - pmpaddr50: Atom, - pmpaddr51: Atom, - pmpaddr52: Atom, - pmpaddr53: Atom, - pmpaddr54: Atom, - pmpaddr55: Atom, - pmpaddr56: Atom, - pmpaddr57: Atom, - pmpaddr58: Atom, - pmpaddr59: Atom, - pmpaddr60: Atom, - pmpaddr61: Atom, - pmpaddr62: Atom, - pmpaddr63: Atom, - mhartid: Atom, - mvendorid: Atom, - marchid: Atom, - mimpid: Atom, - misa: Atom, - mscratch: Atom, - mstatus: Atom, - sscratch: Atom, - stvec: Atom, - mtvec: Atom, - mie: Atom, - satp: Atom, - scause: Atom, - mcause: Atom, - sepc: Atom, - mepc: Atom, - stval: Atom, - mtval: Atom, - mtval2: Atom, - mip: Atom, - mtinst: Atom, - senvcfg: Atom, - menvcfg: Atom, - mconfigptr: Atom, - medeleg: Atom, - mideleg: Atom, - mseccfg: Atom, - scontext: Atom, - hstatus: Atom, - hedeleg: Atom, - hideleg: Atom, - hie: Atom, - hcounteren: Atom, - hgeie: Atom, - htval: Atom, - hip: Atom, - hvip: Atom, - htinst: Atom, - hgeip: Atom, - henvcfg: Atom, - hgatp: Atom, - hcontext: Atom, - htimedelta: Atom, - vsstatus: Atom, - vsie: Atom, - vstvec: Atom, - vsscratch: Atom, - vsepc: Atom, - vscause: Atom, - vstval: Atom, - vsip: Atom, - vsatp: Atom, - tselect: Atom, - tdata1: Atom, - tdata2: Atom, - tdata3: Atom, - tcontrol: Atom, - mcontext: Atom, - dcsr: Atom, - dpc: Atom, - dscratch0: Atom, - dscratch1: Atom, + mstatus: MStatusLayout, + // whole CSRs + mnscratch: EffectCSRLayout, + mnepc: EffectCSRLayout, + mncause: EffectCSRLayout, + mnstatus: EffectCSRLayout, + cycle: EffectCSRLayout, + time: EffectCSRLayout, + instret: EffectCSRLayout, + mcycle: EffectCSRLayout, + minstret: EffectCSRLayout, + hpmcounter3: EffectCSRLayout, + hpmcounter4: EffectCSRLayout, + hpmcounter5: EffectCSRLayout, + hpmcounter6: EffectCSRLayout, + hpmcounter7: EffectCSRLayout, + hpmcounter8: EffectCSRLayout, + hpmcounter9: EffectCSRLayout, + hpmcounter10: EffectCSRLayout, + hpmcounter11: EffectCSRLayout, + hpmcounter12: EffectCSRLayout, + hpmcounter13: EffectCSRLayout, + hpmcounter14: EffectCSRLayout, + hpmcounter15: EffectCSRLayout, + hpmcounter16: EffectCSRLayout, + hpmcounter17: EffectCSRLayout, + hpmcounter18: EffectCSRLayout, + hpmcounter19: EffectCSRLayout, + hpmcounter20: EffectCSRLayout, + hpmcounter21: EffectCSRLayout, + hpmcounter22: EffectCSRLayout, + hpmcounter23: EffectCSRLayout, + hpmcounter24: EffectCSRLayout, + hpmcounter25: EffectCSRLayout, + hpmcounter26: EffectCSRLayout, + hpmcounter27: EffectCSRLayout, + hpmcounter28: EffectCSRLayout, + hpmcounter29: EffectCSRLayout, + hpmcounter30: EffectCSRLayout, + hpmcounter31: EffectCSRLayout, + mhpmcounter3: EffectCSRLayout, + mhpmcounter4: EffectCSRLayout, + mhpmcounter5: EffectCSRLayout, + mhpmcounter6: EffectCSRLayout, + mhpmcounter7: EffectCSRLayout, + mhpmcounter8: EffectCSRLayout, + mhpmcounter9: EffectCSRLayout, + mhpmcounter10: EffectCSRLayout, + mhpmcounter11: EffectCSRLayout, + mhpmcounter12: EffectCSRLayout, + mhpmcounter13: EffectCSRLayout, + mhpmcounter14: EffectCSRLayout, + mhpmcounter15: EffectCSRLayout, + mhpmcounter16: EffectCSRLayout, + mhpmcounter17: EffectCSRLayout, + mhpmcounter18: EffectCSRLayout, + mhpmcounter19: EffectCSRLayout, + mhpmcounter20: EffectCSRLayout, + mhpmcounter21: EffectCSRLayout, + mhpmcounter22: EffectCSRLayout, + mhpmcounter23: EffectCSRLayout, + mhpmcounter24: EffectCSRLayout, + mhpmcounter25: EffectCSRLayout, + mhpmcounter26: EffectCSRLayout, + mhpmcounter27: EffectCSRLayout, + mhpmcounter28: EffectCSRLayout, + mhpmcounter29: EffectCSRLayout, + mhpmcounter30: EffectCSRLayout, + mhpmcounter31: EffectCSRLayout, + mhpmevent3: EffectCSRLayout, + mhpmevent4: EffectCSRLayout, + mhpmevent5: EffectCSRLayout, + mhpmevent6: EffectCSRLayout, + mhpmevent7: EffectCSRLayout, + mhpmevent8: EffectCSRLayout, + mhpmevent9: EffectCSRLayout, + mhpmevent10: EffectCSRLayout, + mhpmevent11: EffectCSRLayout, + mhpmevent12: EffectCSRLayout, + mhpmevent13: EffectCSRLayout, + mhpmevent14: EffectCSRLayout, + mhpmevent15: EffectCSRLayout, + mhpmevent16: EffectCSRLayout, + mhpmevent17: EffectCSRLayout, + mhpmevent18: EffectCSRLayout, + mhpmevent19: EffectCSRLayout, + mhpmevent20: EffectCSRLayout, + mhpmevent21: EffectCSRLayout, + mhpmevent22: EffectCSRLayout, + mhpmevent23: EffectCSRLayout, + mhpmevent24: EffectCSRLayout, + mhpmevent25: EffectCSRLayout, + mhpmevent26: EffectCSRLayout, + mhpmevent27: EffectCSRLayout, + mhpmevent28: EffectCSRLayout, + mhpmevent29: EffectCSRLayout, + mhpmevent30: EffectCSRLayout, + mhpmevent31: EffectCSRLayout, + mcountinhibit: EffectCSRLayout, + scounteren: EffectCSRLayout, + mcounteren: EffectCSRLayout, + fcsr: EffectCSRLayout, + pmpcfg0: EffectCSRLayout, + pmpcfg2: EffectCSRLayout, + pmpcfg4: EffectCSRLayout, + pmpcfg6: EffectCSRLayout, + pmpcfg8: EffectCSRLayout, + pmpcfg10: EffectCSRLayout, + pmpcfg12: EffectCSRLayout, + pmpcfg14: EffectCSRLayout, + pmpaddr0: EffectCSRLayout, + pmpaddr1: EffectCSRLayout, + pmpaddr2: EffectCSRLayout, + pmpaddr3: EffectCSRLayout, + pmpaddr4: EffectCSRLayout, + pmpaddr5: EffectCSRLayout, + pmpaddr6: EffectCSRLayout, + pmpaddr7: EffectCSRLayout, + pmpaddr8: EffectCSRLayout, + pmpaddr9: EffectCSRLayout, + pmpaddr10: EffectCSRLayout, + pmpaddr11: EffectCSRLayout, + pmpaddr12: EffectCSRLayout, + pmpaddr13: EffectCSRLayout, + pmpaddr14: EffectCSRLayout, + pmpaddr15: EffectCSRLayout, + pmpaddr16: EffectCSRLayout, + pmpaddr17: EffectCSRLayout, + pmpaddr18: EffectCSRLayout, + pmpaddr19: EffectCSRLayout, + pmpaddr20: EffectCSRLayout, + pmpaddr21: EffectCSRLayout, + pmpaddr22: EffectCSRLayout, + pmpaddr23: EffectCSRLayout, + pmpaddr24: EffectCSRLayout, + pmpaddr25: EffectCSRLayout, + pmpaddr26: EffectCSRLayout, + pmpaddr27: EffectCSRLayout, + pmpaddr28: EffectCSRLayout, + pmpaddr29: EffectCSRLayout, + pmpaddr30: EffectCSRLayout, + pmpaddr31: EffectCSRLayout, + pmpaddr32: EffectCSRLayout, + pmpaddr33: EffectCSRLayout, + pmpaddr34: EffectCSRLayout, + pmpaddr35: EffectCSRLayout, + pmpaddr36: EffectCSRLayout, + pmpaddr37: EffectCSRLayout, + pmpaddr38: EffectCSRLayout, + pmpaddr39: EffectCSRLayout, + pmpaddr40: EffectCSRLayout, + pmpaddr41: EffectCSRLayout, + pmpaddr42: EffectCSRLayout, + pmpaddr43: EffectCSRLayout, + pmpaddr44: EffectCSRLayout, + pmpaddr45: EffectCSRLayout, + pmpaddr46: EffectCSRLayout, + pmpaddr47: EffectCSRLayout, + pmpaddr48: EffectCSRLayout, + pmpaddr49: EffectCSRLayout, + pmpaddr50: EffectCSRLayout, + pmpaddr51: EffectCSRLayout, + pmpaddr52: EffectCSRLayout, + pmpaddr53: EffectCSRLayout, + pmpaddr54: EffectCSRLayout, + pmpaddr55: EffectCSRLayout, + pmpaddr56: EffectCSRLayout, + pmpaddr57: EffectCSRLayout, + pmpaddr58: EffectCSRLayout, + pmpaddr59: EffectCSRLayout, + pmpaddr60: EffectCSRLayout, + pmpaddr61: EffectCSRLayout, + pmpaddr62: EffectCSRLayout, + pmpaddr63: EffectCSRLayout, + mhartid: EffectCSRLayout, + mvendorid: EffectCSRLayout, + marchid: EffectCSRLayout, + mimpid: EffectCSRLayout, + misa: EffectCSRLayout, + mscratch: EffectCSRLayout, + sscratch: EffectCSRLayout, + stvec: EffectCSRLayout, + mtvec: EffectCSRLayout, + mie: EffectCSRLayout, + satp: EffectCSRLayout, + scause: EffectCSRLayout, + mcause: EffectCSRLayout, + sepc: EffectCSRLayout, + mepc: EffectCSRLayout, + stval: EffectCSRLayout, + mtval: EffectCSRLayout, + mtval2: EffectCSRLayout, + mip: EffectCSRLayout, + mtinst: EffectCSRLayout, + senvcfg: EffectCSRLayout, + menvcfg: EffectCSRLayout, + mconfigptr: EffectCSRLayout, + medeleg: EffectCSRLayout, + mideleg: EffectCSRLayout, + mseccfg: EffectCSRLayout, + scontext: EffectCSRLayout, + hstatus: EffectCSRLayout, + hedeleg: EffectCSRLayout, + hideleg: EffectCSRLayout, + hie: EffectCSRLayout, + hcounteren: EffectCSRLayout, + hgeie: EffectCSRLayout, + htval: EffectCSRLayout, + hip: EffectCSRLayout, + hvip: EffectCSRLayout, + htinst: EffectCSRLayout, + hgeip: EffectCSRLayout, + henvcfg: EffectCSRLayout, + hgatp: EffectCSRLayout, + hcontext: EffectCSRLayout, + htimedelta: EffectCSRLayout, + vsstatus: EffectCSRLayout, + vsie: EffectCSRLayout, + vstvec: EffectCSRLayout, + vsscratch: EffectCSRLayout, + vsepc: EffectCSRLayout, + vscause: EffectCSRLayout, + vstval: EffectCSRLayout, + vsip: EffectCSRLayout, + vsatp: EffectCSRLayout, + tselect: EffectCSRLayout, + tdata1: EffectCSRLayout, + tdata2: EffectCSRLayout, + tdata3: EffectCSRLayout, + tcontrol: EffectCSRLayout, + mcontext: EffectCSRLayout, + dcsr: EffectCSRLayout, + dpc: EffectCSRLayout, + dscratch0: EffectCSRLayout, + dscratch1: EffectCSRLayout, } ); diff --git a/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs b/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs index f9b6f0fe5774..4b510552689f 100644 --- a/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs +++ b/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs @@ -107,21 +107,21 @@ impl MStatusValue { } #[inline(always)] - pub fn mie_write(&mut self, value: bool) -> CSREffect + pub fn mie_write(&mut self, value: bool) -> Option where M: ManagerWrite, { self.mie.write(value); - CSREffect::InvalidateTranslationCacheXIE + Some(CSREffect::InvalidateTranslationCacheXIE) } #[inline(always)] - pub fn mie_replace(&mut self, value: bool) -> (bool, CSREffect) + pub fn mie_replace(&mut self, value: bool) -> (bool, Option) where M: ManagerReadWrite, { let old_value = self.mie.replace(value); - (old_value, CSREffect::InvalidateTranslationCacheXIE) + (old_value, Some(CSREffect::InvalidateTranslationCacheXIE)) } #[inline(always)] @@ -133,21 +133,21 @@ impl MStatusValue { } #[inline(always)] - pub fn sie_write(&mut self, value: bool) -> CSREffect + pub fn sie_write(&mut self, value: bool) -> Option where M: ManagerWrite, { self.sie.write(value); - CSREffect::InvalidateTranslationCacheXIE + Some(CSREffect::InvalidateTranslationCacheXIE) } #[inline(always)] - pub fn sie_replace(&mut self, value: bool) -> (bool, CSREffect) + pub fn sie_replace(&mut self, value: bool) -> (bool, Option) where M: ManagerReadWrite, { let old_value = self.sie.replace(value); - (old_value, CSREffect::InvalidateTranslationCacheXIE) + (old_value, Some(CSREffect::InvalidateTranslationCacheXIE)) } } @@ -218,7 +218,7 @@ impl MStatusValue { /// Write to mstatus the `value` given in 64 bit representation #[inline] - pub fn write(&mut self, value: CSRRepr) -> CSREffect + pub fn write(&mut self, value: CSRRepr) -> Option where M: ManagerWrite, { @@ -227,8 +227,8 @@ impl MStatusValue { let effect_sie = mstatus.sie_write(value.sie()); let effect_mie = mstatus.mie_write(value.mie()); - debug_assert_eq!(effect_sie, CSREffect::InvalidateTranslationCacheXIE); - debug_assert_eq!(effect_mie, CSREffect::InvalidateTranslationCacheXIE); + debug_assert_eq!(effect_sie, Some(CSREffect::InvalidateTranslationCacheXIE)); + debug_assert_eq!(effect_mie, Some(CSREffect::InvalidateTranslationCacheXIE)); mstatus.spie.write(value.spie()); mstatus.ube.write(value.ube()); @@ -248,12 +248,12 @@ impl MStatusValue { mstatus.sbe.write(value.sbe()); mstatus.mbe.write(value.mbe()); - CSREffect::InvalidateTranslationCacheXIE + Some(CSREffect::InvalidateTranslationCacheXIE) } /// Replace mstatus with `value` given in 64 bit representation #[inline] - pub fn replace(&mut self, value: CSRRepr) -> (CSRRepr, CSREffect) + pub fn replace(&mut self, value: CSRRepr) -> (CSRRepr, Option) where M: ManagerReadWrite, { @@ -262,8 +262,8 @@ impl MStatusValue { let (sie, effect_sie) = mstatus.sie_replace(value.sie()); let (mie, effect_mie) = mstatus.mie_replace(value.mie()); - debug_assert_eq!(effect_sie, CSREffect::InvalidateTranslationCacheXIE); - debug_assert_eq!(effect_mie, CSREffect::InvalidateTranslationCacheXIE); + debug_assert_eq!(effect_sie, Some(CSREffect::InvalidateTranslationCacheXIE)); + debug_assert_eq!(effect_mie, Some(CSREffect::InvalidateTranslationCacheXIE)); let spie = mstatus.spie.replace(value.spie()); let ube = mstatus.ube.replace(value.ube()); @@ -314,6 +314,6 @@ impl MStatusValue { ) .to_bits(); - (old_value, CSREffect::InvalidateTranslationCacheXIE) + (old_value, Some(CSREffect::InvalidateTranslationCacheXIE)) } } diff --git a/src/riscv/lib/src/state_backend/effects.rs b/src/riscv/lib/src/state_backend/effects.rs index 7acd4f8a4828..172089d7fe33 100644 --- a/src/riscv/lib/src/state_backend/effects.rs +++ b/src/riscv/lib/src/state_backend/effects.rs @@ -14,7 +14,7 @@ pub trait EffectGetter { type Effect; /// Effect on write/replace operations. - const EFFECT: Self::Effect; + const EFFECT: Option; } pub type EffectCellLayout = Atom; @@ -39,7 +39,7 @@ impl EffectCell { self.inner.read() } - pub fn write(&mut self, value: T) -> EG::Effect + pub fn write(&mut self, value: T) -> Option where M: ManagerWrite, { @@ -47,7 +47,7 @@ impl EffectCell { EG::EFFECT } - pub fn replace(&mut self, value: T) -> (T, EG::Effect) + pub fn replace(&mut self, value: T) -> (T, Option) where M: ManagerReadWrite, { diff --git a/src/riscv/lib/src/state_backend/layout.rs b/src/riscv/lib/src/state_backend/layout.rs index 01c14efda735..14447488ad83 100644 --- a/src/riscv/lib/src/state_backend/layout.rs +++ b/src/riscv/lib/src/state_backend/layout.rs @@ -127,7 +127,7 @@ macro_rules! struct_layout { fn place_with(alloc: &mut $crate::state_backend::Choreographer) -> Self::Placed { [<$layout_t Placed>] { - $($field_name: alloc.alloc()),+ + $($field_name: <$cell_repr>::place_with(alloc)),+ } } -- GitLab From a0c3289179bc5189f4861c6100a1afb84b2a94a7 Mon Sep 17 00:00:00 2001 From: Felix Puscasu Date: Wed, 7 Aug 2024 16:52:37 +0100 Subject: [PATCH 5/6] RISC-V: Use split mstatus fields --- src/riscv/lib/src/interpreter/rv64priv.rs | 52 ++++++++----------- .../src/machine_state/address_translation.rs | 14 +++-- .../lib/src/machine_state/csregisters.rs | 34 ++++++------ 3 files changed, 48 insertions(+), 52 deletions(-) diff --git a/src/riscv/lib/src/interpreter/rv64priv.rs b/src/riscv/lib/src/interpreter/rv64priv.rs index 0abd00afa6a4..bf1423c35b2a 100644 --- a/src/riscv/lib/src/interpreter/rv64priv.rs +++ b/src/riscv/lib/src/interpreter/rv64priv.rs @@ -2,7 +2,8 @@ use crate::{ machine_state::{ bus::{main_memory, Address}, csregisters::{ - xstatus::{MPPValue, MStatus, SPPValue}, + effects::handle_csr_effect, + xstatus::{MPPValue, SPPValue}, CSRegister, }, hart_state::HartState, @@ -10,7 +11,7 @@ use crate::{ registers::XRegister, AccessType, MachineState, }, - state_backend as backend, + state_backend::{self as backend}, traps::Exception, }; use strum::IntoEnumIterator; @@ -29,25 +30,21 @@ where Mode::Machine => (), } - let mstatus: MStatus = self.csregisters.read(CSRegister::mstatus); + let csrs = &mut self.csregisters; // get MPP - let prev_privilege = mstatus.mpp(); + let prev_privilege = csrs.mstatus().mpp.read(); // Set MIE to MPIE - let prev_mie = mstatus.mpie(); - let mstatus = mstatus.with_mie(prev_mie); + let prev_mie = csrs.mstatus().mpie.read(); + let effect = csrs.mstatus_mut().mie_write(prev_mie); + handle_csr_effect(csrs, effect); // set MPIE to 1 - let mstatus = mstatus.with_mpie(true); + csrs.mstatus_mut().mpie.write(true); // Set MPP to least p.with_ivilege-mode supported - let mstatus = mstatus.with_mpp(MPPValue::User); + csrs.mstatus_mut().mpp.write(MPPValue::User); // Set MPRV to 0 when leaving M-mode. (MPP != M-mode) - let mstatus = if prev_privilege != MPPValue::Machine { - mstatus.with_mprv(false) - } else { - mstatus - }; - - // Commit the mstatus - self.csregisters.write(CSRegister::mstatus, mstatus); + if prev_privilege != MPPValue::Machine { + csrs.mstatus_mut().mprv.write(false) + } // Set the mode after handling mret, according to MPP read initially self.mode.write(match prev_privilege { @@ -69,27 +66,25 @@ where Mode::User => return Err(Exception::IllegalInstruction), Mode::Supervisor | Mode::Machine => (), } + let csrs = &mut self.csregisters; // Section 3.1.6.5 // SRET raises IllegalInstruction exception when TSR (Trap SRET) bit is on. - let mstatus: MStatus = self.csregisters.read(CSRegister::mstatus); - if mstatus.tsr() { + if csrs.mstatus().tsr.read() { return Err(Exception::IllegalInstruction); } // get SPP - let prev_privilege = mstatus.spp(); + let prev_privilege = csrs.mstatus().spp.read(); // Set SIE to SPIE - let prev_sie = mstatus.spie(); - let mstatus = mstatus.with_sie(prev_sie); + let prev_sie = csrs.mstatus().spie.read(); + let effect = csrs.mstatus_mut().sie_write(prev_sie); + handle_csr_effect(csrs, effect); // set SPIE to 1 - let mstatus = mstatus.with_spie(true); + csrs.mstatus_mut().spie.write(true); // Set SPP to least privilege-mode supported - let mstatus = mstatus.with_spp(SPPValue::User); + csrs.mstatus_mut().spp.write(SPPValue::User); // Set MPRV to 0 when leaving M-mode. (SPP != M-mode) // Since SPP can only hold User / Supervisor, it is always set to 0 - let mstatus = mstatus.with_mprv(false); - - // Commit the mstatus - self.csregisters.write(CSRegister::mstatus, mstatus); + csrs.mstatus_mut().mprv.write(false); // Set the mode after handling sret, according to SPP read initially self.mode.write(match prev_privilege { @@ -128,8 +123,7 @@ where self.translation_cache.invalidate(AccessType::iter()); let mode = self.hart.mode.read(); - let mstatus: MStatus = self.hart.csregisters.read(CSRegister::mstatus); - let tvm = mstatus.tvm(); + let tvm = self.hart.csregisters.mstatus().tvm.read(); if tvm && mode == Mode::Supervisor { return Err(Exception::IllegalInstruction); diff --git a/src/riscv/lib/src/machine_state/address_translation.rs b/src/riscv/lib/src/machine_state/address_translation.rs index ba444b914300..7d1dc930a41b 100644 --- a/src/riscv/lib/src/machine_state/address_translation.rs +++ b/src/riscv/lib/src/machine_state/address_translation.rs @@ -6,15 +6,16 @@ use super::{ bus::{main_memory, Address, AddressableRead, Bus, OutOfBounds}, csregisters::{ satp::{Satp, SvLength, TranslationAlgorithm}, - xstatus::MStatus, CSRRepr, CSRegister, }, mode::Mode, MachineState, }; use crate::{ - bits::Bits64, machine_state::address_translation::pte::PageTableEntry, - state_backend as backend, traps::Exception, + bits::Bits64, + machine_state::address_translation::pte::PageTableEntry, + state_backend::{self as backend}, + traps::Exception, }; use strum::{EnumCount, EnumIter}; @@ -203,9 +204,12 @@ impl MachineState mstatus.mpp().into(), + AccessType::Store | AccessType::Load if mstatus.mprv.read() => { + mstatus.mpp.read().into() + } _ => mode, } } diff --git a/src/riscv/lib/src/machine_state/csregisters.rs b/src/riscv/lib/src/machine_state/csregisters.rs index d7e81741f66f..95c9d09f9622 100644 --- a/src/riscv/lib/src/machine_state/csregisters.rs +++ b/src/riscv/lib/src/machine_state/csregisters.rs @@ -1056,10 +1056,9 @@ fn check_fs_access(csr: CSRegister, fs_field: ExtensionValue) -> Result<()> { pub fn access_checks(csr: CSRegister, hart_state: &HartState) -> Result<()> { let mode = hart_state.mode.read(); check_privilege(csr, mode)?; - let mstatus: MStatus = hart_state.csregisters.read(CSRegister::mstatus); - let tvm = mstatus.tvm(); + let tvm = hart_state.csregisters.mstatus().tvm.read(); check_satp_access(csr, tvm)?; - let fs = mstatus.fs(); + let fs = hart_state.csregisters.mstatus().fs.read(); check_fs_access(csr, fs) } @@ -1243,21 +1242,17 @@ impl CSRegisters { match current_mode { Mode::User => Interrupt::SUPERVISOR_BIT_MASK | Interrupt::MACHINE_BIT_MASK, Mode::Supervisor => { - let mstatus: MStatus = self.read(CSRegister::mstatus); - let ie_supervisor = match mstatus.sie() { + let ie_supervisor = match self.mstatus().sie_read() { true => self.read(CSRegister::sie), false => 0, }; ie_supervisor | Interrupt::MACHINE_BIT_MASK } - Mode::Machine => { - let mstatus: MStatus = self.read(CSRegister::mstatus); - match mstatus.mie() { - true => self.read(CSRegister::mie), - false => 0, - } - } + Mode::Machine => match self.mstatus().mie_read() { + true => self.read(CSRegister::mie), + false => 0, + }, } } @@ -1363,8 +1358,8 @@ impl CSRegisters { where M: backend::ManagerRead, { - let mstatus: MStatus = self.read(CSRegister::mstatus); - mstatus.fs() == ExtensionValue::Off + let fs = self.mstatus().fs.read(); + fs == ExtensionValue::Off } } @@ -1372,14 +1367,17 @@ impl CSRegisters { #[allow(clippy::identity_op)] mod tests { use crate::{ - backend_test, create_backend, create_state, + backend_test, + bits::Bits64, + create_backend, create_state, machine_state::{ backend::{ tests::{test_determinism, ManagerFor}, Backend, Layout, }, csregisters::{ - values::CSRValue, CSRRepr, CSRegister, CSRegisters, CSRegistersLayout, Exception, + values::CSRValue, xstatus::MStatus, CSRRepr, CSRegister, CSRegisters, + CSRegistersLayout, Exception, }, mode::Mode, }, @@ -1598,9 +1596,9 @@ mod tests { 1u64 << 37 | 0b01 << 34 | 0b11 << 32 | 0b11 << 15 | 0b11 << 11 | 1 << 8 | 1 << 7, ); // SXL, UXL should be set to MXL (WARL), SD bit should be 1 - let read_mstatus: CSRValue = csrs.read(CSRegister::mstatus); + let read_mstatus: MStatus = csrs.read(CSRegister::mstatus); assert_eq!( - read_mstatus.repr(), + read_mstatus.to_bits(), 1u64 << 63 | 1 << 37 | 0b10 << 34 -- GitLab From 3648686904cc1f9925428452b575fcd71d73f0ae Mon Sep 17 00:00:00 2001 From: Felix Puscasu Date: Fri, 23 Aug 2024 16:22:36 +0100 Subject: [PATCH 6/6] RISC-V: Make mstatus.mie/sie fields public --- src/riscv/lib/src/interpreter/rv64priv.rs | 4 +- .../lib/src/machine_state/csregisters.rs | 9 ++- .../src/machine_state/csregisters/effects.rs | 3 +- .../src/machine_state/csregisters/values.rs | 7 +- .../csregisters/values/mstatus.rs | 76 +++---------------- src/riscv/lib/src/state_backend/effects.rs | 5 ++ 6 files changed, 26 insertions(+), 78 deletions(-) diff --git a/src/riscv/lib/src/interpreter/rv64priv.rs b/src/riscv/lib/src/interpreter/rv64priv.rs index bf1423c35b2a..201dc75ecb45 100644 --- a/src/riscv/lib/src/interpreter/rv64priv.rs +++ b/src/riscv/lib/src/interpreter/rv64priv.rs @@ -35,7 +35,7 @@ where let prev_privilege = csrs.mstatus().mpp.read(); // Set MIE to MPIE let prev_mie = csrs.mstatus().mpie.read(); - let effect = csrs.mstatus_mut().mie_write(prev_mie); + let effect = csrs.mstatus_mut().mie.write(prev_mie); handle_csr_effect(csrs, effect); // set MPIE to 1 csrs.mstatus_mut().mpie.write(true); @@ -76,7 +76,7 @@ where let prev_privilege = csrs.mstatus().spp.read(); // Set SIE to SPIE let prev_sie = csrs.mstatus().spie.read(); - let effect = csrs.mstatus_mut().sie_write(prev_sie); + let effect = csrs.mstatus_mut().sie.write(prev_sie); handle_csr_effect(csrs, effect); // set SPIE to 1 csrs.mstatus_mut().spie.write(true); diff --git a/src/riscv/lib/src/machine_state/csregisters.rs b/src/riscv/lib/src/machine_state/csregisters.rs index 95c9d09f9622..609441585d8d 100644 --- a/src/riscv/lib/src/machine_state/csregisters.rs +++ b/src/riscv/lib/src/machine_state/csregisters.rs @@ -1056,9 +1056,10 @@ fn check_fs_access(csr: CSRegister, fs_field: ExtensionValue) -> Result<()> { pub fn access_checks(csr: CSRegister, hart_state: &HartState) -> Result<()> { let mode = hart_state.mode.read(); check_privilege(csr, mode)?; - let tvm = hart_state.csregisters.mstatus().tvm.read(); + let mstatus = hart_state.csregisters.mstatus(); + let tvm = mstatus.tvm.read(); check_satp_access(csr, tvm)?; - let fs = hart_state.csregisters.mstatus().fs.read(); + let fs = mstatus.fs.read(); check_fs_access(csr, fs) } @@ -1242,14 +1243,14 @@ impl CSRegisters { match current_mode { Mode::User => Interrupt::SUPERVISOR_BIT_MASK | Interrupt::MACHINE_BIT_MASK, Mode::Supervisor => { - let ie_supervisor = match self.mstatus().sie_read() { + let ie_supervisor = match self.mstatus().sie.read() { true => self.read(CSRegister::sie), false => 0, }; ie_supervisor | Interrupt::MACHINE_BIT_MASK } - Mode::Machine => match self.mstatus().mie_read() { + Mode::Machine => match self.mstatus().mie.read() { true => self.read(CSRegister::mie), false => 0, }, diff --git a/src/riscv/lib/src/machine_state/csregisters/effects.rs b/src/riscv/lib/src/machine_state/csregisters/effects.rs index 727cc6d35aa1..1aae3b8ff518 100644 --- a/src/riscv/lib/src/machine_state/csregisters/effects.rs +++ b/src/riscv/lib/src/machine_state/csregisters/effects.rs @@ -26,7 +26,8 @@ macro_rules! create_effect_getter { } create_effect_getter!(NoEffect, None); -create_effect_getter!(MipEffect, Some(CSREffect::InvalidateTranslationCacheXIP)); +create_effect_getter!(XieEffect, Some(CSREffect::InvalidateTranslationCacheXIE)); +create_effect_getter!(XipEffect, Some(CSREffect::InvalidateTranslationCacheXIP)); #[inline(always)] pub fn handle_csr_effect(state: &mut CSRegisters, effect: Option) { diff --git a/src/riscv/lib/src/machine_state/csregisters/values.rs b/src/riscv/lib/src/machine_state/csregisters/values.rs index 5447df463c63..8366ef40c3e6 100644 --- a/src/riscv/lib/src/machine_state/csregisters/values.rs +++ b/src/riscv/lib/src/machine_state/csregisters/values.rs @@ -5,13 +5,12 @@ mod mstatus; use super::{ - effects::{handle_csr_effect, CSREffect, MipEffect, NoEffect}, + effects::{handle_csr_effect, NoEffect, XipEffect}, root::RootCSRegister, CSRegisters, }; use crate::{ bits::Bits64, - state_backend::EffectGetter, state_backend::{AllocatedOf, EffectCell, EffectCellLayout}, struct_layout, }; @@ -67,8 +66,6 @@ macro_rules! csregisters_boilerplate { where M: $crate::state_backend::ManagerBase, { - // pub mstatus: MStatusValue, - // pub mip: MipValue, $($vis $name: $cell_repr,)+ } @@ -122,7 +119,7 @@ macro_rules! csregisters_boilerplate { } type NoEffectCSR = EffectCell; -type MipEffectCSR = EffectCell; +type MipEffectCSR = EffectCell; type EffectCSRLayout = EffectCellLayout; diff --git a/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs b/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs index 4b510552689f..884d9d5fd051 100644 --- a/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs +++ b/src/riscv/lib/src/machine_state/csregisters/values/mstatus.rs @@ -6,11 +6,11 @@ use super::CSRRepr; use crate::{ bits::{Bits64, ConstantBits}, machine_state::csregisters::{ - effects::CSREffect, + effects::{CSREffect, XieEffect}, xstatus::{ExtensionValue, MPPValue, MStatus, SPPValue, XLenValue}, }, state_backend::{ - AllocatedOf, Atom, Cell, EnumCell, EnumCellLayout, ManagerBase, ManagerRead, + AllocatedOf, Atom, Cell, EffectCell, EnumCell, EnumCellLayout, ManagerBase, ManagerRead, ManagerReadWrite, ManagerWrite, }, struct_layout, @@ -23,8 +23,8 @@ pub struct MStatusValue { // Individual fields can be public since they are well typed and respect the WPRI, WARL, WLRL rules. // Except for fields which have side-effects. These ones have custom read/write/replace methods // to return side-effects to be accounted for - sie: Cell, - mie: Cell, + pub sie: EffectCell, + pub mie: EffectCell, pub spie: Cell, pub ube: Cell, pub mpie: Cell, @@ -48,8 +48,8 @@ pub struct MStatusValue { impl MStatusValue { pub fn bind(space: AllocatedOf) -> Self { Self { - sie: space.sie, - mie: space.mie, + sie: EffectCell::bind(space.sie), + mie: EffectCell::bind(space.mie), spie: space.spie, ube: space.ube, mpie: space.mpie, @@ -95,62 +95,6 @@ struct_layout!( } ); -// Impl block for mie & sie fields. -// Required to return side-effects which should be handled with [`super::effects::handle_csr_effect`] -impl MStatusValue { - #[inline(always)] - pub fn mie_read(&self) -> bool - where - M: ManagerRead, - { - self.mie.read() - } - - #[inline(always)] - pub fn mie_write(&mut self, value: bool) -> Option - where - M: ManagerWrite, - { - self.mie.write(value); - Some(CSREffect::InvalidateTranslationCacheXIE) - } - - #[inline(always)] - pub fn mie_replace(&mut self, value: bool) -> (bool, Option) - where - M: ManagerReadWrite, - { - let old_value = self.mie.replace(value); - (old_value, Some(CSREffect::InvalidateTranslationCacheXIE)) - } - - #[inline(always)] - pub fn sie_read(&self) -> bool - where - M: ManagerRead, - { - self.sie.read() - } - - #[inline(always)] - pub fn sie_write(&mut self, value: bool) -> Option - where - M: ManagerWrite, - { - self.sie.write(value); - Some(CSREffect::InvalidateTranslationCacheXIE) - } - - #[inline(always)] - pub fn sie_replace(&mut self, value: bool) -> (bool, Option) - where - M: ManagerReadWrite, - { - let old_value = self.sie.replace(value); - (old_value, Some(CSREffect::InvalidateTranslationCacheXIE)) - } -} - #[inline(always)] fn compute_sd(fs: ExtensionValue, xs: ExtensionValue) -> bool { fs == ExtensionValue::Dirty || xs == ExtensionValue::Dirty @@ -225,8 +169,8 @@ impl MStatusValue { let value = MStatus::from_bits(value); let mstatus = self; - let effect_sie = mstatus.sie_write(value.sie()); - let effect_mie = mstatus.mie_write(value.mie()); + let effect_sie = mstatus.sie.write(value.sie()); + let effect_mie = mstatus.mie.write(value.mie()); debug_assert_eq!(effect_sie, Some(CSREffect::InvalidateTranslationCacheXIE)); debug_assert_eq!(effect_mie, Some(CSREffect::InvalidateTranslationCacheXIE)); @@ -260,8 +204,8 @@ impl MStatusValue { let value = MStatus::from_bits(value); let mstatus = self; - let (sie, effect_sie) = mstatus.sie_replace(value.sie()); - let (mie, effect_mie) = mstatus.mie_replace(value.mie()); + let (sie, effect_sie) = mstatus.sie.replace(value.sie()); + let (mie, effect_mie) = mstatus.mie.replace(value.mie()); debug_assert_eq!(effect_sie, Some(CSREffect::InvalidateTranslationCacheXIE)); debug_assert_eq!(effect_mie, Some(CSREffect::InvalidateTranslationCacheXIE)); diff --git a/src/riscv/lib/src/state_backend/effects.rs b/src/riscv/lib/src/state_backend/effects.rs index 172089d7fe33..ffdeaf9a5bcb 100644 --- a/src/riscv/lib/src/state_backend/effects.rs +++ b/src/riscv/lib/src/state_backend/effects.rs @@ -32,6 +32,7 @@ impl EffectCell { } } + #[inline(always)] pub fn read(&self) -> T where M: ManagerRead, @@ -39,6 +40,8 @@ impl EffectCell { self.inner.read() } + #[inline(always)] + #[must_use = "CSR Effect must be handled. Use 'handle_csr_effect()'"] pub fn write(&mut self, value: T) -> Option where M: ManagerWrite, @@ -47,6 +50,8 @@ impl EffectCell { EG::EFFECT } + #[inline(always)] + #[must_use = "CSR Effect must be handled. Use 'handle_csr_effect()'"] pub fn replace(&mut self, value: T) -> (T, Option) where M: ManagerReadWrite, -- GitLab