Skip to content

Commit 2b3de3d

Browse files
committed
feat(sbi): 只向状态是可以接受核间中断的核发中断
1 parent 5fd115b commit 2b3de3d

File tree

5 files changed

+58
-41
lines changed

5 files changed

+58
-41
lines changed

rustsbi-qemu/src/clint.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@ use spin::Once;
99

1010
pub(crate) struct Clint {
1111
base: usize,
12-
smp: usize,
1312
}
1413

1514
static CLINT: Once<Clint> = Once::new();
1615

17-
pub(crate) fn init(base: usize, smp: usize) {
18-
CLINT.call_once(|| Clint { base, smp });
16+
pub(crate) fn init(base: usize) {
17+
CLINT.call_once(|| Clint { base });
1918
}
2019

2120
pub(crate) fn get() -> &'static Clint {
@@ -42,9 +41,9 @@ impl Clint {
4241
impl Ipi for &'static Clint {
4342
#[inline]
4443
fn send_ipi_many(&self, hart_mask: HartMask) -> SbiRet {
45-
// println!("[rustsbi] send ipi many, {:?}", hart_mask);
46-
for i in 0..self.smp {
47-
if hart_mask.has_bit(i) {
44+
let hsm = crate::HSM.wait();
45+
for i in 0..crate::NUM_HART_MAX {
46+
if hart_mask.has_bit(i) && hsm.is_ipi_allowed(i) {
4847
self.send_soft(i);
4948
}
5049
}

rustsbi-qemu/src/execute/context.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ impl Context {
4040
// self.x[n - 1]
4141
// }
4242

43-
#[inline]
44-
pub fn x_mut(&mut self, n: usize) -> &mut usize {
45-
&mut self.x[n - 1]
46-
}
43+
// #[inline]
44+
// pub fn x_mut(&mut self, n: usize) -> &mut usize {
45+
// &mut self.x[n - 1]
46+
// }
4747
}

rustsbi-qemu/src/execute/mod.rs

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,29 +33,24 @@ pub(crate) fn execute_supervisor(supervisor: Supervisor) {
3333

3434
loop {
3535
use crate::qemu_hsm::{EID_HSM, FID_HART_STOP, FID_HART_SUSPEND, SUSPEND_NON_RETENTIVE};
36-
use riscv::register::mcause::{self, Exception as E, Interrupt as I, Trap as T};
36+
use riscv::register::{
37+
mcause::{self, Exception as E, Interrupt as I, Trap as T},
38+
mip,
39+
};
3740

3841
unsafe { m_to_s(&mut ctx) };
3942

4043
match mcause::read().cause() {
4144
T::Interrupt(I::MachineTimer) => unsafe {
42-
use riscv::register::mip;
45+
mie::clear_mtimer();
4346
mip::clear_mtimer();
4447
mip::set_stimer();
4548
},
4649
T::Interrupt(I::MachineSoft) => {
47-
use riscv::register::{mip, scause};
48-
4950
crate::clint::get().clear_soft(hart_id());
50-
unsafe { mip::clear_msoft() };
51-
if transfer_trap::should_transfer_trap(&ctx) {
52-
transfer_trap::do_transfer_trap(
53-
&mut ctx,
54-
scause::Trap::Interrupt(scause::Interrupt::SupervisorSoft),
55-
);
56-
} else {
57-
println!("{:?}", I::MachineSoft);
58-
break;
51+
unsafe {
52+
mip::clear_msoft();
53+
mip::set_ssoft();
5954
}
6055
}
6156
T::Exception(E::SupervisorEnvCall) => {
@@ -74,23 +69,24 @@ pub(crate) fn execute_supervisor(supervisor: Supervisor) {
7469
ctx.mepc = ctx.mepc.wrapping_add(4);
7570
}
7671
T::Exception(E::IllegalInstruction) => {
77-
use riscv::register::{mtval, scause};
72+
use riscv::register::scause;
7873

79-
const OPCODE_MASK: usize = (1 << 7) - 1;
80-
const REG_MASK: usize = (1 << 5) - 1;
81-
const OPCODE_CSR: usize = 0b1110011;
82-
const CSR_TIME: usize = 0xc01;
83-
let instruction = mtval::read();
74+
// const OPCODE_MASK: usize = (1 << 7) - 1;
75+
// const REG_MASK: usize = (1 << 5) - 1;
76+
// const OPCODE_CSR: usize = 0b1110011;
77+
// const CSR_TIME: usize = 0xc01;
78+
// let instruction = mtval::read();
8479
// 标准 20191213 的表 24.3 列出了一些特殊的 CSR,SBI 软件负责将它们模拟出来
85-
if let OPCODE_CSR = instruction & OPCODE_MASK {
86-
if instruction >> 20 == CSR_TIME {
87-
match (instruction >> 7) & REG_MASK {
88-
0 => {}
89-
rd => *ctx.x_mut(rd) = crate::clint::get().get_mtime() as _,
90-
}
91-
continue;
92-
}
93-
}
80+
// Qemu 似乎不需要模拟 time
81+
// if let OPCODE_CSR = instruction & OPCODE_MASK {
82+
// if instruction >> 20 == CSR_TIME {
83+
// match (instruction >> 7) & REG_MASK {
84+
// 0 => {}
85+
// rd => *ctx.x_mut(rd) = crate::clint::get().get_mtime() as _,
86+
// }
87+
// continue;
88+
// }
89+
// }
9490
// 如果不是可修正的指令,且不是 M 态本身发出的,转交给 S 态处理
9591
// mpp != machine
9692
if transfer_trap::should_transfer_trap(&ctx) {

rustsbi-qemu/src/main.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,20 +105,31 @@ extern "C" fn early_trap() -> ! {
105105
}
106106
}
107107

108+
use core::sync::atomic::{
109+
AtomicBool, AtomicUsize,
110+
Ordering::{AcqRel, Acquire},
111+
};
108112
use spin::Once;
109113

110114
#[link_section = ".bss.uninit"]
111115
static HSM: Once<qemu_hsm::QemuHsm> = Once::new();
112116

117+
#[link_section = ".bss.uninit"]
118+
static SMP: AtomicUsize = AtomicUsize::new(0);
119+
113120
/// rust 入口。
114121
extern "C" fn rust_main(_hartid: usize, opaque: usize) {
115-
use core::sync::atomic::{AtomicBool, Ordering::AcqRel};
116-
117122
unsafe { set_mtcev(early_trap as _) };
118123

119124
#[link_section = ".bss.uninit"]
120125
static GENESIS: AtomicBool = AtomicBool::new(false);
121126

127+
let mut smp = SMP.load(Acquire);
128+
let mask = 1 << hart_id();
129+
while let Err(val) = SMP.compare_exchange(smp, smp | mask, AcqRel, Acquire) {
130+
smp = val;
131+
}
132+
122133
// 全局初始化过程
123134
if !GENESIS.swap(true, AcqRel) {
124135
// 清零 bss 段
@@ -128,7 +139,7 @@ extern "C" fn rust_main(_hartid: usize, opaque: usize) {
128139
// 解析设备树,需要堆来保存结果里的字符串等
129140
let board_info = device_tree::parse(opaque);
130141
// 初始化外设
131-
clint::init(board_info.clint.start, board_info.smp);
142+
clint::init(board_info.clint.start);
132143
test_device::init(board_info.test.start);
133144
let uart = unsafe { ns16550a::Ns16550a::new(board_info.uart.start) };
134145
let hsm = HSM.call_once(|| qemu_hsm::QemuHsm::new(clint::get(), board_info.smp, opaque));

rustsbi-qemu/src/qemu_hsm.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,17 @@ impl QemuHsm {
136136
use core::sync::atomic::Ordering::Release;
137137
self.state[hart_id()].store(STARTED, Release);
138138
}
139+
140+
/// 如果一个核可以接受 ipi,返回 `true`。
141+
///
142+
/// 运行状态的核可以接受权限低于 SBI 软件的核间中断,将转交给特权软件。
143+
/// 挂起状态的核可以接受核间中断以恢复运行。
144+
pub fn is_ipi_allowed(&self, hart_id: usize) -> bool {
145+
use core::sync::atomic::Ordering::Acquire;
146+
self.state
147+
.get(hart_id)
148+
.map_or(false, |s| matches!(s.load(Acquire), STARTED | SUSPEND))
149+
}
139150
}
140151

141152
// Adapt RustSBI interface to RustSBI-QEMU's QemuHsm.

0 commit comments

Comments
 (0)