Skip to content
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

arch/riscv: make RISC-V CSR accesses unsafe #3549

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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,026 changes: 796 additions & 230 deletions arch/riscv/src/csr/mod.rs

Large diffs are not rendered by default.

227 changes: 124 additions & 103 deletions arch/rv32i/src/epmp.rs

Large diffs are not rendered by default.

68 changes: 34 additions & 34 deletions arch/rv32i/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,15 @@ pub enum PermissionMode {
/// The trap handler is called on exceptions and for interrupts.
pub unsafe fn configure_trap_handler(mode: PermissionMode) {
match mode {
PermissionMode::Machine => csr::CSR.mtvec.write(
PermissionMode::Machine => csr::CSR.mtvec().write(
csr::mtvec::mtvec::trap_addr.val(_start_trap as usize >> 2)
+ csr::mtvec::mtvec::mode::CLEAR,
),
PermissionMode::Supervisor => csr::CSR.stvec.write(
PermissionMode::Supervisor => csr::CSR.stvec().write(
csr::stvec::stvec::trap_addr.val(_start_trap as usize >> 2)
+ csr::stvec::stvec::mode::CLEAR,
),
PermissionMode::User => csr::CSR.utvec.write(
PermissionMode::User => csr::CSR.utvec().write(
csr::utvec::utvec::trap_addr.val(_start_trap as usize >> 2)
+ csr::utvec::utvec::mode::CLEAR,
),
Expand Down Expand Up @@ -568,12 +568,12 @@ pub unsafe fn print_mcause(mcval: csr::mcause::Trap, writer: &mut dyn Write) {
/// Prints out RISCV machine state, including basic system registers
/// (mcause, mstatus, mtvec, mepc, mtval, interrupt status).
pub unsafe fn print_riscv_state(writer: &mut dyn Write) {
let mcval: csr::mcause::Trap = core::convert::From::from(csr::CSR.mcause.extract());
let mcval: csr::mcause::Trap = core::convert::From::from(csr::CSR.mcause().extract());
let _ = writer.write_fmt(format_args!("\r\n---| RISC-V Machine State |---\r\n"));
let _ = writer.write_fmt(format_args!("Last cause (mcause): "));
print_mcause(mcval, writer);
let interrupt = csr::CSR.mcause.read(csr::mcause::mcause::is_interrupt);
let code = csr::CSR.mcause.read(csr::mcause::mcause::reason);
let interrupt = csr::CSR.mcause().read(csr::mcause::mcause::is_interrupt);
let code = csr::CSR.mcause().read(csr::mcause::mcause::reason);
let _ = writer.write_fmt(format_args!(
" (interrupt={}, exception code={:#010X})",
interrupt, code
Expand All @@ -585,14 +585,14 @@ pub unsafe fn print_riscv_state(writer: &mut dyn Write) {
\r\n mepc: {:#010X} mstatus: {:#010X}\
\r\n mcycle: {:#010X} minstret: {:#010X}\
\r\n mtvec: {:#010X}",
csr::CSR.mtval.get(),
csr::CSR.mepc.get(),
csr::CSR.mstatus.get(),
csr::CSR.mcycle.get(),
csr::CSR.minstret.get(),
csr::CSR.mtvec.get()
csr::CSR.mtval().get(),
csr::CSR.mepc().get(),
csr::CSR.mstatus().get(),
csr::CSR.mcycle().get(),
csr::CSR.minstret().get(),
csr::CSR.mtvec().get()
));
let mstatus = csr::CSR.mstatus.extract();
let mstatus = csr::CSR.mstatus().extract();
let uie = mstatus.is_set(csr::mstatus::mstatus::uie);
let sie = mstatus.is_set(csr::mstatus::mstatus::sie);
let mie = mstatus.is_set(csr::mstatus::mstatus::mie);
Expand All @@ -615,25 +615,25 @@ pub unsafe fn print_riscv_state(writer: &mut dyn Write) {
mpie,
spp
));
let e_usoft = csr::CSR.mie.is_set(csr::mie::mie::usoft);
let e_ssoft = csr::CSR.mie.is_set(csr::mie::mie::ssoft);
let e_msoft = csr::CSR.mie.is_set(csr::mie::mie::msoft);
let e_utimer = csr::CSR.mie.is_set(csr::mie::mie::utimer);
let e_stimer = csr::CSR.mie.is_set(csr::mie::mie::stimer);
let e_mtimer = csr::CSR.mie.is_set(csr::mie::mie::mtimer);
let e_uext = csr::CSR.mie.is_set(csr::mie::mie::uext);
let e_sext = csr::CSR.mie.is_set(csr::mie::mie::sext);
let e_mext = csr::CSR.mie.is_set(csr::mie::mie::mext);

let p_usoft = csr::CSR.mip.is_set(csr::mip::mip::usoft);
let p_ssoft = csr::CSR.mip.is_set(csr::mip::mip::ssoft);
let p_msoft = csr::CSR.mip.is_set(csr::mip::mip::msoft);
let p_utimer = csr::CSR.mip.is_set(csr::mip::mip::utimer);
let p_stimer = csr::CSR.mip.is_set(csr::mip::mip::stimer);
let p_mtimer = csr::CSR.mip.is_set(csr::mip::mip::mtimer);
let p_uext = csr::CSR.mip.is_set(csr::mip::mip::uext);
let p_sext = csr::CSR.mip.is_set(csr::mip::mip::sext);
let p_mext = csr::CSR.mip.is_set(csr::mip::mip::mext);
let e_usoft = csr::CSR.mie().is_set(csr::mie::mie::usoft);
let e_ssoft = csr::CSR.mie().is_set(csr::mie::mie::ssoft);
let e_msoft = csr::CSR.mie().is_set(csr::mie::mie::msoft);
let e_utimer = csr::CSR.mie().is_set(csr::mie::mie::utimer);
let e_stimer = csr::CSR.mie().is_set(csr::mie::mie::stimer);
let e_mtimer = csr::CSR.mie().is_set(csr::mie::mie::mtimer);
let e_uext = csr::CSR.mie().is_set(csr::mie::mie::uext);
let e_sext = csr::CSR.mie().is_set(csr::mie::mie::sext);
let e_mext = csr::CSR.mie().is_set(csr::mie::mie::mext);

let p_usoft = csr::CSR.mip().is_set(csr::mip::mip::usoft);
let p_ssoft = csr::CSR.mip().is_set(csr::mip::mip::ssoft);
let p_msoft = csr::CSR.mip().is_set(csr::mip::mip::msoft);
let p_utimer = csr::CSR.mip().is_set(csr::mip::mip::utimer);
let p_stimer = csr::CSR.mip().is_set(csr::mip::mip::stimer);
let p_mtimer = csr::CSR.mip().is_set(csr::mip::mip::mtimer);
let p_uext = csr::CSR.mip().is_set(csr::mip::mip::uext);
let p_sext = csr::CSR.mip().is_set(csr::mip::mip::sext);
let p_mext = csr::CSR.mip().is_set(csr::mip::mip::mext);
let _ = writer.write_fmt(format_args!(
"\r\n mie: {:#010X} mip: {:#010X}\
\r\n usoft: {:6} {:6}\
Expand All @@ -645,8 +645,8 @@ pub unsafe fn print_riscv_state(writer: &mut dyn Write) {
\r\n uext: {:6} {:6}\
\r\n sext: {:6} {:6}\
\r\n mext: {:6} {:6}\r\n",
csr::CSR.mie.get(),
csr::CSR.mip.get(),
csr::CSR.mie().get(),
csr::CSR.mip().get(),
e_usoft,
p_usoft,
e_ssoft,
Expand Down
121 changes: 65 additions & 56 deletions arch/rv32i/src/pmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,22 +304,24 @@ impl<const MAX_AVAILABLE_REGIONS_OVER_TWO: usize> kernel::platform::mpu::MPU
//
// We want to keep the first region configured, so it is excluded from the loops and
// set separately.
for x in 1..(MAX_AVAILABLE_REGIONS_OVER_TWO * 2) {
csr::CSR.pmpaddr_set(x, 0x0);
}
for x in 1..(MAX_AVAILABLE_REGIONS_OVER_TWO * 2 / 4) {
csr::CSR.pmpconfig_set(x, 0);
unsafe {
for x in 1..(MAX_AVAILABLE_REGIONS_OVER_TWO * 2) {
csr::CSR.pmpaddr_set(x, 0x0);
}
for x in 1..(MAX_AVAILABLE_REGIONS_OVER_TWO * 2 / 4) {
csr::CSR.pmpconfig_set(x, 0);
}
csr::CSR.pmpaddr_set(0, 0xFFFF_FFFF);
// enable R W X fields
csr::CSR.pmpconfig_set(
0,
(csr::pmpconfig::pmpcfg::r0::SET
+ csr::pmpconfig::pmpcfg::w0::SET
+ csr::pmpconfig::pmpcfg::x0::SET
+ csr::pmpconfig::pmpcfg::a0::TOR)
.value,
);
}
csr::CSR.pmpaddr_set(0, 0xFFFF_FFFF);
// enable R W X fields
csr::CSR.pmpconfig_set(
0,
(csr::pmpconfig::pmpcfg::r0::SET
+ csr::pmpconfig::pmpcfg::w0::SET
+ csr::pmpconfig::pmpcfg::x0::SET
+ csr::pmpconfig::pmpcfg::a0::TOR)
.value,
);
// PMP is not configured for any process now
self.last_configured_for.take();
}
Expand Down Expand Up @@ -537,13 +539,16 @@ impl<const MAX_AVAILABLE_REGIONS_OVER_TWO: usize> kernel::platform::mpu::MPU
} else {
(16, 0x0000_FFFF)
};
csr::CSR.pmpconfig_set(
x / 2,
(disable_val | cfg_val << 8) << region_shift
| (csr::CSR.pmpconfig_get(x / 2) & other_region_mask),
);
csr::CSR.pmpaddr_set(x * 2, (start) >> 2);
csr::CSR.pmpaddr_set((x * 2) + 1, (start + size) >> 2);

unsafe {
csr::CSR.pmpconfig_set(
x / 2,
(disable_val | cfg_val << 8) << region_shift
| (csr::CSR.pmpconfig_get(x / 2) & other_region_mask),
);
csr::CSR.pmpaddr_set(x * 2, (start) >> 2);
csr::CSR.pmpaddr_set((x * 2) + 1, (start + size) >> 2);
}
}
None => {}
};
Expand Down Expand Up @@ -625,42 +630,46 @@ impl<const MAX_AVAILABLE_REGIONS_OVER_TWO: usize> kernel::platform::mpu::KernelM

match x % 2 {
0 => {
csr::CSR.pmpaddr_set((x * 2) + 1, (start + size) >> 2);
// Disable access up to the start address
csr::CSR.pmpconfig_modify(
x / 2,
csr::pmpconfig::pmpcfg::r0::CLEAR
+ csr::pmpconfig::pmpcfg::w0::CLEAR
+ csr::pmpconfig::pmpcfg::x0::CLEAR
+ csr::pmpconfig::pmpcfg::a0::CLEAR,
);
csr::CSR.pmpaddr_set(x * 2, start >> 2);

// Set access to end address
let new_cfg =
cfg_val << 8 | (csr::CSR.pmpconfig_get(x / 2) & 0xFFFF_00FF);
csr::CSR.pmpconfig_set(x / 2, new_cfg);
// Lock the CSR
csr::CSR.pmpconfig_modify(x / 2, csr::pmpconfig::pmpcfg::l1::SET);
unsafe {
csr::CSR.pmpaddr_set((x * 2) + 1, (start + size) >> 2);
// Disable access up to the start address
csr::CSR.pmpconfig_modify(
x / 2,
csr::pmpconfig::pmpcfg::r0::CLEAR
+ csr::pmpconfig::pmpcfg::w0::CLEAR
+ csr::pmpconfig::pmpcfg::x0::CLEAR
+ csr::pmpconfig::pmpcfg::a0::CLEAR,
);
csr::CSR.pmpaddr_set(x * 2, start >> 2);

// Set access to end address
let new_cfg =
cfg_val << 8 | (csr::CSR.pmpconfig_get(x / 2) & 0xFFFF_00FF);
csr::CSR.pmpconfig_set(x / 2, new_cfg);
// Lock the CSR
csr::CSR.pmpconfig_modify(x / 2, csr::pmpconfig::pmpcfg::l1::SET);
}
}
1 => {
csr::CSR.pmpaddr_set((x * 2) + 1, (start + size) >> 2);
// Disable access up to the start address
csr::CSR.pmpconfig_modify(
x / 2,
csr::pmpconfig::pmpcfg::r2::CLEAR
+ csr::pmpconfig::pmpcfg::w2::CLEAR
+ csr::pmpconfig::pmpcfg::x2::CLEAR
+ csr::pmpconfig::pmpcfg::a2::CLEAR,
);
csr::CSR.pmpaddr_set(x * 2, start >> 2);

// Set access to end address
let new_cfg =
cfg_val << 24 | (csr::CSR.pmpconfig_get(x / 2) & 0x00FF_FFFF);
csr::CSR.pmpconfig_set(x / 2, new_cfg);
// Lock the CSR
csr::CSR.pmpconfig_modify(x / 2, csr::pmpconfig::pmpcfg::l3::SET);
unsafe {
csr::CSR.pmpaddr_set((x * 2) + 1, (start + size) >> 2);
// Disable access up to the start address
csr::CSR.pmpconfig_modify(
x / 2,
csr::pmpconfig::pmpcfg::r2::CLEAR
+ csr::pmpconfig::pmpcfg::w2::CLEAR
+ csr::pmpconfig::pmpcfg::x2::CLEAR
+ csr::pmpconfig::pmpcfg::a2::CLEAR,
);
csr::CSR.pmpaddr_set(x * 2, start >> 2);

// Set access to end address
let new_cfg =
cfg_val << 24 | (csr::CSR.pmpconfig_get(x / 2) & 0x00FF_FFFF);
csr::CSR.pmpconfig_set(x / 2, new_cfg);
// Lock the CSR
csr::CSR.pmpconfig_modify(x / 2, csr::pmpconfig::pmpcfg::l3::SET);
}
}
_ => break,
}
Expand Down
4 changes: 2 additions & 2 deletions arch/rv32i/src/support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ where
// The result will be the original value of [`mstatus::mie`],
// shifted to the proper position in [`mstatus`].
let original_mie: usize = CSR
.mstatus
.mstatus()
.read_and_clear_bits(mstatus::mie.mask << mstatus::mie.shift)
& mstatus::mie.mask << mstatus::mie.shift;

Expand All @@ -45,7 +45,7 @@ where

// If [`mstatus::mie`] was set before, set it again. Otherwise,
// this function will be a nop.
CSR.mstatus.read_and_set_bits(original_mie);
CSR.mstatus().read_and_set_bits(original_mie);

res
}
Expand Down
2 changes: 1 addition & 1 deletion boards/esp32-c3-devkitM-1/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ unsafe fn setup() -> (
chip.enable_pic_interrupts();

// enable interrupts globally
csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
csr::CSR.mstatus().modify(csr::mstatus::mstatus::mie::SET);

// Setup the console.
let console = components::console::ConsoleComponent::new(
Expand Down
4 changes: 2 additions & 2 deletions boards/hifive1/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,9 @@ pub unsafe fn main() {

// enable interrupts globally
csr::CSR
.mie
.mie()
.modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
csr::CSR.mstatus().modify(csr::mstatus::mstatus::mie::SET);

// Setup the console.
let console = components::console::ConsoleComponent::new(
Expand Down
4 changes: 2 additions & 2 deletions boards/hifive_inventor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,9 @@ pub unsafe fn main() {

// enable interrupts globally
csr::CSR
.mie
.mie()
.modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
csr::CSR.mstatus().modify(csr::mstatus::mstatus::mie::SET);

// Setup the console.
let console = components::console::ConsoleComponent::new(
Expand Down
4 changes: 2 additions & 2 deletions boards/litex/arty/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,9 +475,9 @@ pub unsafe fn main() {

// Enable RISC-V interrupts globally
csr::CSR
.mie
.mie()
.modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET);
csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
csr::CSR.mstatus().modify(csr::mstatus::mstatus::mie::SET);

// Unmask all interrupt sources in the interrupt controller
chip.unmask_interrupts();
Expand Down
4 changes: 2 additions & 2 deletions boards/litex/sim/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,9 @@ pub unsafe fn main() {

// Enable RISC-V interrupts globally
csr::CSR
.mie
.mie()
.modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET);
csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
csr::CSR.mstatus().modify(csr::mstatus::mstatus::mie::SET);

// Unmask all interrupt sources in the interrupt controller
chip.unmask_interrupts();
Expand Down
4 changes: 2 additions & 2 deletions boards/opentitan/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,10 +343,10 @@ unsafe fn setup() -> (
// Need to enable all interrupts for Tock Kernel
chip.enable_plic_interrupts();
// enable interrupts globally
csr::CSR.mie.modify(
csr::CSR.mie().modify(
csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::CLEAR + csr::mie::mie::mext::SET,
);
csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
csr::CSR.mstatus().modify(csr::mstatus::mstatus::mie::SET);

// Setup the console.
let console = components::console::ConsoleComponent::new(
Expand Down
4 changes: 2 additions & 2 deletions boards/qemu_rv32_virt/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,9 @@ pub unsafe fn main() {

// enable interrupts globally
csr::CSR
.mie
.mie()
.modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
csr::CSR.mstatus().modify(csr::mstatus::mstatus::mie::SET);

// ---------- FINAL SYSTEM INITIALIZATION ----------

Expand Down
4 changes: 2 additions & 2 deletions boards/redboard_redv/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,9 @@ pub unsafe fn main() {

// enable interrupts globally
csr::CSR
.mie
.mie()
.modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
csr::CSR.mstatus().modify(csr::mstatus::mstatus::mie::SET);

// Setup the console.
let console = components::console::ConsoleComponent::new(
Expand Down
4 changes: 2 additions & 2 deletions boards/swervolf/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,14 @@ pub unsafe fn main() {
chip.enable_pic_interrupts();

// enable interrupts globally, including timer0 (bit 29) and timer1 (bit 28)
csr::CSR.mie.modify(
csr::CSR.mie().modify(
csr::mie::mie::mext::SET
+ csr::mie::mie::msoft::SET
+ csr::mie::mie::mtimer::SET
+ csr::mie::mie::BIT28::SET
+ csr::mie::mie::BIT29::SET,
);
csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
csr::CSR.mstatus().modify(csr::mstatus::mstatus::mie::SET);

// Setup the console.
let console = components::console::ConsoleComponent::new(
Expand Down
2 changes: 1 addition & 1 deletion chips/arty_e21_chip/src/chip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl<'a, I: InterruptService + 'a> kernel::platform::chip::Chip for ArtyExx<'a,
/// disable it.
#[export_name = "_start_trap_rust_from_kernel"]
pub extern "C" fn start_trap_rust() {
let mcause = rv32i::csr::CSR.mcause.extract();
let mcause = unsafe { rv32i::csr::CSR.mcause().extract() };

match rv32i::csr::mcause::Trap::from(mcause) {
rv32i::csr::mcause::Trap::Interrupt(_interrupt) => {
Expand Down
Loading