use bit_field::BitField;
#[derive(Clone, Copy, Debug)]
pub struct Satp {
bits: usize,
}
impl Satp {
#[inline]
pub fn bits(&self) -> usize {
self.bits
}
#[inline]
#[cfg(target_pointer_width = "32")]
pub fn mode(&self) -> Mode {
match self.bits.get_bit(31) {
false => Mode::Bare,
true => Mode::Sv32,
}
}
#[inline]
#[cfg(target_pointer_width = "64")]
pub fn mode(&self) -> Mode {
match self.bits.get_bits(60..64) {
0 => Mode::Bare,
8 => Mode::Sv39,
9 => Mode::Sv48,
10 => Mode::Sv57,
11 => Mode::Sv64,
_ => unreachable!(),
}
}
#[inline]
#[cfg(target_pointer_width = "32")]
pub fn asid(&self) -> usize {
self.bits.get_bits(22..31)
}
#[inline]
#[cfg(target_pointer_width = "64")]
pub fn asid(&self) -> usize {
self.bits.get_bits(44..60)
}
#[inline]
#[cfg(target_pointer_width = "32")]
pub fn ppn(&self) -> usize {
self.bits.get_bits(0..22)
}
#[inline]
#[cfg(target_pointer_width = "64")]
pub fn ppn(&self) -> usize {
self.bits.get_bits(0..44)
}
}
#[cfg(target_pointer_width = "32")]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Mode {
Bare = 0,
Sv32 = 1,
}
#[cfg(target_pointer_width = "64")]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Mode {
Bare = 0,
Sv39 = 8,
Sv48 = 9,
Sv57 = 10,
Sv64 = 11,
}
read_csr_as!(Satp, 0x180);
write_csr_as_usize!(0x180);
#[inline]
#[cfg(target_pointer_width = "32")]
pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
let mut bits = 0usize;
bits.set_bits(31..32, mode as usize);
bits.set_bits(22..31, asid);
bits.set_bits(0..22, ppn);
_write(bits);
}
#[inline]
#[cfg(target_pointer_width = "64")]
pub unsafe fn set(mode: Mode, asid: usize, ppn: usize) {
let mut bits = 0usize;
bits.set_bits(60..64, mode as usize);
bits.set_bits(44..60, asid);
bits.set_bits(0..44, ppn);
_write(bits);
}