Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions riscv/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- CSR helper macro `write_composite_csr` for writing 64-bit CSRs on 32-bit targets.
- Write utilities for `mcycle`, `minstret`
- Add `senvcfg` CSR

## [v0.13.0] - 2025-02-18

Expand Down
1 change: 1 addition & 0 deletions riscv/src/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub mod stvec;

// Supervisor Trap Handling
pub mod scause;
pub mod senvcfg;
pub mod sepc;
pub mod sip;
pub mod sscratch;
Expand Down
120 changes: 120 additions & 0 deletions riscv/src/register/senvcfg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//! `senvcfg` register.

#[cfg(target_arch = "riscv32")]
const MASK: usize = 0xf5;
#[cfg(not(target_arch = "riscv32"))]
const MASK: usize = 0x3_0000_00fd;

read_write_csr! {
/// `senvcfg` register.
Senvcfg: 0x10a,
mask: MASK,
}

set!(0x10a);
clear!(0x10a);

read_write_csr_field! {
Senvcfg,
/// Gets the `fiom` (Fence of I/O Implies Memory) field value.
fiom: 0,
}

read_write_csr_field! {
Senvcfg,
/// Gets the `lpe` (Landing Pad Enable) field value.
lpe: 2,
}

#[cfg(not(target_arch = "riscv32"))]
read_write_csr_field! {
Senvcfg,
/// Gets the `sse` (Shadow Stack Enable) field value.
sse: 3,
}

csr_field_enum! {
/// Represents CBIE (Cache Block Invalidate instruction Enable) field of the `senvcfg` CSR.
Cbie {
default: IllegalInstruction,
/// The instruction takes an illegal instruction exception.
IllegalInstruction = 0b00,
/// The instruction is executed and performs a flush operation.
Flush = 0b01,
/// The instruction is executed and performs an invalidate operation.
Invalidate = 0b11,
}
}

read_write_csr_field! {
Senvcfg,
/// Gets the `cbie` (Cache Block Invalidate Enable) field value.
cbie,
Cbie: [4:5],
}

read_write_csr_field! {
Senvcfg,
/// Gets the `cbcfe` (Cache Block Clean and Flush Enable) field value.
cbcfe: 6,
}

read_write_csr_field! {
Senvcfg,
/// Gets the `cbze` (Cache Block Zero Enable) field value.
cbze: 7,
}

#[cfg(not(target_arch = "riscv32"))]
csr_field_enum! {
/// Represents PMM (Pointer Masking Mode) field of the `senvcfg` CSR.
Pmm {
default: Disabled,
/// Pointer masking is disabled (PMLEN=0).
Disabled = 0b00,
/// Pointer masking is enabled with PMLEN=XLEN-57 (PMLEN=7 on RV64).
Mask7bit = 0b10,
/// Pointer masking is enabled with PMLEN=XLEN-48 (PMLEN=16 on RV64).
Mask16bit = 0b11,
}
}

#[cfg(not(target_arch = "riscv32"))]
read_write_csr_field! {
Senvcfg,
/// Gets the `pmm` (Pointer Masking Mode) field value.
pmm,
Pmm: [32:33],
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_senvcfg() {
let mut senvcfg = Senvcfg::from_bits(0);

test_csr_field!(senvcfg, fiom);
test_csr_field!(senvcfg, lpe);

#[cfg(not(target_arch = "riscv32"))]
test_csr_field!(senvcfg, sse);

[Cbie::IllegalInstruction, Cbie::Flush, Cbie::Invalidate]
.into_iter()
.for_each(|cbie| {
test_csr_field!(senvcfg, cbie: cbie);
});

test_csr_field!(senvcfg, cbcfe);
test_csr_field!(senvcfg, cbze);

#[cfg(not(target_arch = "riscv32"))]
[Pmm::Disabled, Pmm::Mask7bit, Pmm::Mask16bit]
.into_iter()
.for_each(|pmm| {
test_csr_field!(senvcfg, pmm: pmm);
});
}
}