Skip to content

Deduplicate set_mpp and get_raw_faulting_instr #363

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

Merged
merged 2 commits into from
Dec 26, 2024
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
4 changes: 2 additions & 2 deletions model_checking/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use miralis::arch::pmp::pmplayout::VIRTUAL_PMP_OFFSET;
use miralis::arch::pmp::PmpGroup;
use miralis::arch::userspace::return_userspace_ctx;
use miralis::arch::{mie, Arch, Architecture};
use miralis::arch::{mie, write_pmp};
use miralis::virt::traits::{HwRegisterContextSetter, RegisterContextGetter};
use sail_model::{
execute_MRET, execute_WFI, pmpCheck, readCSR, step_interrupts_only, writeCSR, AccessType,
Expand Down Expand Up @@ -382,7 +382,7 @@ pub fn pmp_equivalence() {
sail_prelude::sys_pmp_count(()),
);
unsafe {
Arch::write_pmp(&pmp_group).flush();
write_pmp(&pmp_group).flush();
}

// Retrieve hardware context
Expand Down
278 changes: 115 additions & 163 deletions src/arch/metal.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
//! Bare metal RISC-V
use core::arch::{asm, global_asm};
use core::marker::PhantomData;
use core::{ptr, usize};

use super::{
menvcfg, Arch, Architecture, Csr, ExtensionsCapability, MCause, Mode, RegistersCapability,
TrapInfo,
};
use crate::arch::pmp::PmpFlush;
use crate::arch::{mie, misa, mstatus, parse_mpp_return_mode, HardwareCapability, PmpGroup, Width};
use core::usize;

use super::{menvcfg, Arch, Architecture, Csr, ExtensionsCapability, Mode, RegistersCapability};
use crate::arch::{mie, misa, mstatus, parse_mpp_return_mode, set_mpp, HardwareCapability, Width};
use crate::decoder::Instr;
use crate::virt::VirtContext;
use crate::{utils, RegisterContextGetter, RegisterContextSetter};
Expand Down Expand Up @@ -45,6 +41,110 @@ impl Architecture for MetalArch {
unsafe { asm!("wfi") };
}

unsafe fn write_pmpaddr(index: usize, pmpaddr: usize) {
macro_rules! asm_write_pmpaddr {
($idx:literal, $addr:expr) => {
asm!(
concat!("csrw pmpaddr", $idx, ", {addr}"),
addr = in(reg) pmpaddr,
options(nomem)
)
};
}

match index {
0 => asm_write_pmpaddr!(0, pmpaddr),
1 => asm_write_pmpaddr!(1, pmpaddr),
2 => asm_write_pmpaddr!(2, pmpaddr),
3 => asm_write_pmpaddr!(3, pmpaddr),
4 => asm_write_pmpaddr!(4, pmpaddr),
5 => asm_write_pmpaddr!(5, pmpaddr),
6 => asm_write_pmpaddr!(6, pmpaddr),
7 => asm_write_pmpaddr!(7, pmpaddr),
8 => asm_write_pmpaddr!(8, pmpaddr),
9 => asm_write_pmpaddr!(9, pmpaddr),
10 => asm_write_pmpaddr!(10, pmpaddr),
11 => asm_write_pmpaddr!(11, pmpaddr),
12 => asm_write_pmpaddr!(12, pmpaddr),
13 => asm_write_pmpaddr!(13, pmpaddr),
14 => asm_write_pmpaddr!(14, pmpaddr),
15 => asm_write_pmpaddr!(15, pmpaddr),
16 => asm_write_pmpaddr!(16, pmpaddr),
17 => asm_write_pmpaddr!(17, pmpaddr),
18 => asm_write_pmpaddr!(18, pmpaddr),
19 => asm_write_pmpaddr!(19, pmpaddr),
20 => asm_write_pmpaddr!(20, pmpaddr),
21 => asm_write_pmpaddr!(21, pmpaddr),
22 => asm_write_pmpaddr!(22, pmpaddr),
23 => asm_write_pmpaddr!(23, pmpaddr),
24 => asm_write_pmpaddr!(24, pmpaddr),
25 => asm_write_pmpaddr!(25, pmpaddr),
26 => asm_write_pmpaddr!(26, pmpaddr),
27 => asm_write_pmpaddr!(27, pmpaddr),
28 => asm_write_pmpaddr!(28, pmpaddr),
29 => asm_write_pmpaddr!(29, pmpaddr),
30 => asm_write_pmpaddr!(30, pmpaddr),
31 => asm_write_pmpaddr!(31, pmpaddr),
32 => asm_write_pmpaddr!(32, pmpaddr),
33 => asm_write_pmpaddr!(33, pmpaddr),
34 => asm_write_pmpaddr!(34, pmpaddr),
35 => asm_write_pmpaddr!(35, pmpaddr),
36 => asm_write_pmpaddr!(36, pmpaddr),
37 => asm_write_pmpaddr!(37, pmpaddr),
38 => asm_write_pmpaddr!(38, pmpaddr),
39 => asm_write_pmpaddr!(39, pmpaddr),
40 => asm_write_pmpaddr!(40, pmpaddr),
41 => asm_write_pmpaddr!(41, pmpaddr),
42 => asm_write_pmpaddr!(42, pmpaddr),
43 => asm_write_pmpaddr!(43, pmpaddr),
44 => asm_write_pmpaddr!(44, pmpaddr),
45 => asm_write_pmpaddr!(45, pmpaddr),
46 => asm_write_pmpaddr!(46, pmpaddr),
47 => asm_write_pmpaddr!(47, pmpaddr),
48 => asm_write_pmpaddr!(48, pmpaddr),
49 => asm_write_pmpaddr!(49, pmpaddr),
50 => asm_write_pmpaddr!(50, pmpaddr),
51 => asm_write_pmpaddr!(51, pmpaddr),
52 => asm_write_pmpaddr!(52, pmpaddr),
53 => asm_write_pmpaddr!(53, pmpaddr),
54 => asm_write_pmpaddr!(54, pmpaddr),
55 => asm_write_pmpaddr!(55, pmpaddr),
56 => asm_write_pmpaddr!(56, pmpaddr),
57 => asm_write_pmpaddr!(57, pmpaddr),
58 => asm_write_pmpaddr!(58, pmpaddr),
59 => asm_write_pmpaddr!(59, pmpaddr),
60 => asm_write_pmpaddr!(60, pmpaddr),
61 => asm_write_pmpaddr!(61, pmpaddr),
62 => asm_write_pmpaddr!(62, pmpaddr),
63 => asm_write_pmpaddr!(63, pmpaddr),
_ => panic!("Invalid pmpaddr register"),
}
}

unsafe fn write_pmpcfg(index: usize, pmpcfg: usize) {
macro_rules! asm_write_pmpcfg {
($idx:literal, $cfg:expr) => {
asm!(
concat!("csrw pmpcfg", $idx, ", {cfg}"),
cfg = in(reg) $cfg,
options(nomem)
)
};
}

match index {
0 => asm_write_pmpcfg!(0, pmpcfg),
2 => asm_write_pmpcfg!(2, pmpcfg),
4 => asm_write_pmpcfg!(4, pmpcfg),
6 => asm_write_pmpcfg!(6, pmpcfg),
8 => asm_write_pmpcfg!(8, pmpcfg),
10 => asm_write_pmpcfg!(10, pmpcfg),
12 => asm_write_pmpcfg!(12, pmpcfg),
14 => asm_write_pmpcfg!(14, pmpcfg),
_ => panic!("Invalid pmpcfg register"),
}
}

unsafe fn write_csr(csr: Csr, value: usize) -> usize {
let mut prev_value: usize = 0;

Expand All @@ -71,7 +171,7 @@ impl Architecture for MetalArch {
Csr::Marchid => asm_write_csr!("marchid"),
Csr::Mimpid => asm_write_csr!("mimpid"),
Csr::Pmpcfg(_) => todo!(),
Csr::Pmpaddr(index) => write_pmpaddr(index, value),
Csr::Pmpaddr(index) => Arch::write_pmpaddr(index, value),
Csr::Mcycle => asm_write_csr!("mcycle"),
Csr::Minstret => asm_write_csr!("minstret"),
Csr::Cycle => todo!(),
Expand Down Expand Up @@ -375,50 +475,6 @@ impl Architecture for MetalArch {
}
}

unsafe fn set_mpp(mode: Mode) -> Mode {
let value = mode.to_bits() << mstatus::MPP_OFFSET;
let prev_mstatus = Self::read_csr(Csr::Mstatus);
Self::write_csr(Csr::Mstatus, (prev_mstatus & !mstatus::MPP_FILTER) | value);
parse_mpp_return_mode(prev_mstatus)
}

unsafe fn write_pmp(pmp: &PmpGroup) -> PmpFlush {
let pmpaddr = pmp.pmpaddr();
let pmpcfg = pmp.pmpcfg();
let nb_pmp = pmp.nb_pmp as usize;

assert!(
nb_pmp as usize <= pmpaddr.len() && nb_pmp as usize <= pmpcfg.len() * 8,
"Invalid number of PMP registers"
);

for idx in 0..nb_pmp {
write_pmpaddr(idx, pmpaddr[idx]);
}
for idx in 0..(nb_pmp / 8) {
let cfg = pmpcfg[idx];
write_pmpcfg(idx * 2, cfg);
}

PmpFlush()
}

unsafe fn get_raw_faulting_instr(trap_info: &TrapInfo) -> usize {
if trap_info.mcause == MCause::IllegalInstr as usize {
// First, try mtval and check if it contains an instruction
if trap_info.mtval != 0 {
return trap_info.mtval;
}
}

let instr_ptr = trap_info.mepc as *const u32;

// With compressed instruction extention ("C") instructions can be misaligned.
// TODO: add support for 16 bits instructions
let instr = ptr::read_unaligned(instr_ptr);
instr as usize
}

unsafe fn run_vcpu(ctx: &mut VirtContext) {
asm!(
// We need to save some registers manually, the compiler can't handle those
Expand Down Expand Up @@ -760,7 +816,7 @@ impl Architecture for MetalArch {
Self::write_csr(Csr::Mcause, 0);

// Set the MPP mode to match the vMPP
let prev_mpp = Self::set_mpp(parse_mpp_return_mode(ctx.csr.mstatus));
let prev_mpp = set_mpp(parse_mpp_return_mode(ctx.csr.mstatus));
let prev_satp = Self::write_csr(Csr::Satp, ctx.csr.satp);

// Changes to SATP require an sfence instruction to take effect
Expand Down Expand Up @@ -877,7 +933,7 @@ impl Architecture for MetalArch {

// Restore the original values
Self::write_csr(Csr::Satp, prev_satp);
Self::set_mpp(prev_mpp);
set_mpp(prev_mpp);

// Ensure memory consistency
Self::sfencevma(None, None);
Expand All @@ -893,7 +949,7 @@ impl Architecture for MetalArch {
let prev_mstatus = Self::read_csr(Csr::Mstatus);

// Set mstatus.MPP to mode
let prev_mode = Self::set_mpp(mode);
let prev_mode = set_mpp(mode);
for i in 0..dest.len() {
let mut byte_read: u8 = 0;
unsafe {
Expand Down Expand Up @@ -941,7 +997,7 @@ impl Architecture for MetalArch {
src += 1;
}

Self::set_mpp(prev_mode);
set_mpp(prev_mode);
Ok(())
}

Expand All @@ -955,7 +1011,7 @@ impl Architecture for MetalArch {
let prev_mstatus = Self::read_csr(Csr::Mstatus);

// Set mstatus.MPP to mode
let prev_mode = Self::set_mpp(mode);
let prev_mode = set_mpp(mode);
for i in 0..src.len() {
let byte_value: u8 = src[i];
unsafe {
Expand Down Expand Up @@ -1000,7 +1056,7 @@ impl Architecture for MetalArch {
dest += 1;
}

Self::set_mpp(prev_mode);
set_mpp(prev_mode);
Ok(())
}
}
Expand Down Expand Up @@ -1124,110 +1180,6 @@ unsafe fn find_nb_of_non_zero_pmp(nb_implemented: usize) -> usize {
return 64;
}

unsafe fn write_pmpaddr(index: usize, pmpaddr: usize) {
macro_rules! asm_write_pmpaddr {
($idx:literal, $addr:expr) => {
asm!(
concat!("csrw pmpaddr", $idx, ", {addr}"),
addr = in(reg) pmpaddr,
options(nomem)
)
};
}

match index {
0 => asm_write_pmpaddr!(0, pmpaddr),
1 => asm_write_pmpaddr!(1, pmpaddr),
2 => asm_write_pmpaddr!(2, pmpaddr),
3 => asm_write_pmpaddr!(3, pmpaddr),
4 => asm_write_pmpaddr!(4, pmpaddr),
5 => asm_write_pmpaddr!(5, pmpaddr),
6 => asm_write_pmpaddr!(6, pmpaddr),
7 => asm_write_pmpaddr!(7, pmpaddr),
8 => asm_write_pmpaddr!(8, pmpaddr),
9 => asm_write_pmpaddr!(9, pmpaddr),
10 => asm_write_pmpaddr!(10, pmpaddr),
11 => asm_write_pmpaddr!(11, pmpaddr),
12 => asm_write_pmpaddr!(12, pmpaddr),
13 => asm_write_pmpaddr!(13, pmpaddr),
14 => asm_write_pmpaddr!(14, pmpaddr),
15 => asm_write_pmpaddr!(15, pmpaddr),
16 => asm_write_pmpaddr!(16, pmpaddr),
17 => asm_write_pmpaddr!(17, pmpaddr),
18 => asm_write_pmpaddr!(18, pmpaddr),
19 => asm_write_pmpaddr!(19, pmpaddr),
20 => asm_write_pmpaddr!(20, pmpaddr),
21 => asm_write_pmpaddr!(21, pmpaddr),
22 => asm_write_pmpaddr!(22, pmpaddr),
23 => asm_write_pmpaddr!(23, pmpaddr),
24 => asm_write_pmpaddr!(24, pmpaddr),
25 => asm_write_pmpaddr!(25, pmpaddr),
26 => asm_write_pmpaddr!(26, pmpaddr),
27 => asm_write_pmpaddr!(27, pmpaddr),
28 => asm_write_pmpaddr!(28, pmpaddr),
29 => asm_write_pmpaddr!(29, pmpaddr),
30 => asm_write_pmpaddr!(30, pmpaddr),
31 => asm_write_pmpaddr!(31, pmpaddr),
32 => asm_write_pmpaddr!(32, pmpaddr),
33 => asm_write_pmpaddr!(33, pmpaddr),
34 => asm_write_pmpaddr!(34, pmpaddr),
35 => asm_write_pmpaddr!(35, pmpaddr),
36 => asm_write_pmpaddr!(36, pmpaddr),
37 => asm_write_pmpaddr!(37, pmpaddr),
38 => asm_write_pmpaddr!(38, pmpaddr),
39 => asm_write_pmpaddr!(39, pmpaddr),
40 => asm_write_pmpaddr!(40, pmpaddr),
41 => asm_write_pmpaddr!(41, pmpaddr),
42 => asm_write_pmpaddr!(42, pmpaddr),
43 => asm_write_pmpaddr!(43, pmpaddr),
44 => asm_write_pmpaddr!(44, pmpaddr),
45 => asm_write_pmpaddr!(45, pmpaddr),
46 => asm_write_pmpaddr!(46, pmpaddr),
47 => asm_write_pmpaddr!(47, pmpaddr),
48 => asm_write_pmpaddr!(48, pmpaddr),
49 => asm_write_pmpaddr!(49, pmpaddr),
50 => asm_write_pmpaddr!(50, pmpaddr),
51 => asm_write_pmpaddr!(51, pmpaddr),
52 => asm_write_pmpaddr!(52, pmpaddr),
53 => asm_write_pmpaddr!(53, pmpaddr),
54 => asm_write_pmpaddr!(54, pmpaddr),
55 => asm_write_pmpaddr!(55, pmpaddr),
56 => asm_write_pmpaddr!(56, pmpaddr),
57 => asm_write_pmpaddr!(57, pmpaddr),
58 => asm_write_pmpaddr!(58, pmpaddr),
59 => asm_write_pmpaddr!(59, pmpaddr),
60 => asm_write_pmpaddr!(60, pmpaddr),
61 => asm_write_pmpaddr!(61, pmpaddr),
62 => asm_write_pmpaddr!(62, pmpaddr),
63 => asm_write_pmpaddr!(63, pmpaddr),
_ => panic!("Invalid pmpaddr register"),
}
}

unsafe fn write_pmpcfg(index: usize, pmpcfg: usize) {
macro_rules! asm_write_pmpcfg {
($idx:literal, $cfg:expr) => {
asm!(
concat!("csrw pmpcfg", $idx, ", {cfg}"),
cfg = in(reg) $cfg,
options(nomem)
)
};
}

match index {
0 => asm_write_pmpcfg!(0, pmpcfg),
2 => asm_write_pmpcfg!(2, pmpcfg),
4 => asm_write_pmpcfg!(4, pmpcfg),
6 => asm_write_pmpcfg!(6, pmpcfg),
8 => asm_write_pmpcfg!(8, pmpcfg),
10 => asm_write_pmpcfg!(10, pmpcfg),
12 => asm_write_pmpcfg!(12, pmpcfg),
14 => asm_write_pmpcfg!(14, pmpcfg),
_ => panic!("Invalid pmpcfg register"),
}
}

// ————————————————————————————— Context Switch ————————————————————————————— //

global_asm!(
Expand Down
Loading