Skip to content

Commit fc62d40

Browse files
n1tram1Martin Schmidt
authored and
Martin Schmidt
committed
refactor(ReentrantSpinlock): core_id from generics
1 parent f8aa8f8 commit fc62d40

File tree

8 files changed

+79
-31
lines changed

8 files changed

+79
-31
lines changed

hal_aarch64/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,18 @@ unsafe extern "C" fn _start() -> ! {
4242
options(noreturn)
4343
);
4444
}
45+
46+
pub struct Aarch64CoreInfo;
47+
48+
impl hal_core::CoreInfo for Aarch64CoreInfo {
49+
fn init(_core_id: usize) {
50+
// We just read MPIDR_EL1 on aarch64.
51+
}
52+
53+
fn core_id() -> usize {
54+
let mpidr = MPIDR_EL1.get() as usize;
55+
assert!(mpidr < usize::MAX);
56+
57+
mpidr
58+
}
59+
}

hal_core/src/hal.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,25 @@ use super::Error;
44
use super::{IrqOps, TimerCallbackFn};
55
use super::ReentrantSpinlock;
66
use super::once_lock::OnceLock;
7+
use super::CoreInfo;
78

8-
pub struct Hal<P: PageMap + 'static, I: IrqOps> {
9-
kpt: OnceLock<ReentrantSpinlock<&'static mut P>>,
9+
pub struct Hal<P: PageMap + 'static, I: IrqOps, G: CoreInfo> {
10+
kpt: OnceLock<ReentrantSpinlock<G, &'static mut P>>,
1011
irq_ops: I,
1112
}
1213

13-
impl<P: PageMap + Mmu + 'static, I: IrqOps> Hal<P, I> {
14-
pub const fn new(irq_ops: I) -> Hal<P, I> {
14+
impl<P: PageMap + Mmu + 'static, I: IrqOps, G: CoreInfo> Hal<P, I, G> {
15+
pub const fn new(irq_ops: I) -> Hal<P, I, G> {
1516
Self {
1617
kpt: OnceLock::new(),
1718
irq_ops,
1819
}
1920
}
2021

22+
pub fn init_core_info(&self, core_id: usize) {
23+
G::init(core_id)
24+
}
25+
2126
pub fn init_irqs(&'static self) {
2227
self.irq_ops.init();
2328
}
@@ -82,7 +87,7 @@ impl<P: PageMap + Mmu + 'static, I: IrqOps> Hal<P, I> {
8287
mm::align_down(val, self.page_size())
8388
}
8489

85-
pub fn kpt(&'static self) -> &ReentrantSpinlock<&'static mut P> {
90+
pub fn kpt(&'static self) -> &ReentrantSpinlock<G, &'static mut P> {
8691
self.kpt.get().unwrap()
8792
}
8893
}

hal_core/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ pub mod once_lock;
1313
mod reentrant_spinlock;
1414
pub use reentrant_spinlock::ReentrantSpinlock;
1515

16+
pub trait CoreInfo {
17+
fn init(core_id: usize);
18+
fn core_id() -> usize;
19+
}
20+
1621
pub trait IrqOps {
1722
fn init(&'static self);
1823
fn init_irq_chip(&self, allocator: &impl mm::PageAlloc) -> Result<(), Error>;

hal_core/src/reentrant_spinlock.rs

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,20 @@
11
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
2+
use core::marker::PhantomData;
23
use lock_api::{GuardSend, RawMutex};
34

4-
pub struct RawReentrantSpinlock {
5+
use crate::CoreInfo;
6+
7+
pub struct RawReentrantSpinlock<G> {
58
user: AtomicUsize,
69
lock: AtomicBool,
10+
_marker: PhantomData<G>,
711
}
812

9-
fn core_id() -> usize {
10-
let mut id: u64;
11-
12-
#[cfg(target_arch="aarch64")]
13-
unsafe { core::arch::asm!("mrs {:x}, mpidr_el1", out(reg) id) };
14-
15-
#[cfg(target_arch="riscv64")]
16-
{
17-
// unsafe { core::arch::asm!("csrr {}, mhartid", out(reg) id) };
18-
id = 0;
19-
}
20-
21-
id as usize
22-
}
23-
24-
unsafe impl RawMutex for RawReentrantSpinlock {
25-
const INIT: RawReentrantSpinlock = RawReentrantSpinlock {
13+
unsafe impl<G: CoreInfo> RawMutex for RawReentrantSpinlock<G> {
14+
const INIT: RawReentrantSpinlock<G> = RawReentrantSpinlock::<G> {
2615
user: AtomicUsize::new(usize::MAX),
2716
lock: AtomicBool::new(false),
17+
_marker: PhantomData,
2818
};
2919

3020
// A spinlock guard can be sent to another thread and unlocked there
@@ -37,7 +27,7 @@ unsafe impl RawMutex for RawReentrantSpinlock {
3727
}
3828

3929
fn try_lock(&self) -> bool {
40-
let my_id = core_id();
30+
let my_id = G::core_id();
4131

4232
if self.user.load(Ordering::Acquire) == my_id {
4333
assert_eq!(self.lock.load(Ordering::Relaxed), true);
@@ -53,7 +43,7 @@ unsafe impl RawMutex for RawReentrantSpinlock {
5343
.is_ok()
5444
&& self
5545
.user
56-
.compare_exchange(usize::MAX, core_id(), Ordering::Acquire, Ordering::Relaxed)
46+
.compare_exchange(usize::MAX, my_id, Ordering::Acquire, Ordering::Relaxed)
5747
.is_ok()
5848
}
5949

@@ -63,4 +53,4 @@ unsafe impl RawMutex for RawReentrantSpinlock {
6353
}
6454
}
6555

66-
pub type ReentrantSpinlock<T> = lock_api::Mutex<RawReentrantSpinlock, T>;
56+
pub type ReentrantSpinlock<G, T> = lock_api::Mutex<RawReentrantSpinlock<G>, T>;

hal_riscv64/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,16 @@ pub fn panic_info() {}
1717
unsafe extern "C" fn _start() -> ! {
1818
asm!("la sp, STACK_START", "call k_main", options(noreturn));
1919
}
20+
21+
pub struct Riscv64CoreInfo;
22+
23+
impl hal_core::CoreInfo for Riscv64CoreInfo {
24+
fn init(core_id: usize) {
25+
// The core_id is the value in the mhartid CSR we got from the machine-level firmware.
26+
registers::set_sscratch(core_id);
27+
}
28+
fn core_id() -> usize {
29+
// Early kernel code called Self::init and putthe core_id argument into the sscratch.
30+
registers::get_sscratch()
31+
}
32+
}

hal_riscv64/src/registers.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,19 @@ pub fn set_stvec(addr: usize) {
2929
asm!("csrw stvec, {}", in(reg)(addr));
3030
}
3131
}
32+
33+
pub fn set_sscratch(val: usize) {
34+
unsafe {
35+
asm!("csrw sscratch, {}", in(reg)(val));
36+
}
37+
}
38+
39+
pub fn get_sscratch() -> usize {
40+
let mut val: usize;
41+
42+
unsafe {
43+
asm!("csrr {}, sscratch", out(reg)(val));
44+
}
45+
46+
val
47+
}

kernel/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,19 @@ cfg_if::cfg_if! {
3838
use hal_aarch64::{
3939
mm::pgt48,
4040
irq::Aarch64Irqs,
41+
Aarch64CoreInfo,
4142
};
4243
use hal_core::Hal;
43-
pub static HAL: Hal<pgt48::PageTable, Aarch64Irqs> = Hal::new(Aarch64Irqs::new());
44+
pub static HAL: Hal<pgt48::PageTable, Aarch64Irqs, Aarch64CoreInfo> = Hal::new(Aarch64Irqs::new());
4445
} else if #[cfg(target_arch = "riscv64")] {
4546
pub type ConsoleImpl = drivers::ns16550::Ns16550;
4647
use hal_riscv64::{
4748
mm::sv39,
4849
irq::Riscv64Irqs,
50+
Riscv64CoreInfo,
4951
};
5052
use hal_core::Hal;
51-
pub static HAL: Hal<sv39::PageTable, Riscv64Irqs> = Hal::new(Riscv64Irqs::new());
53+
pub static HAL: Hal<sv39::PageTable, Riscv64Irqs, Riscv64CoreInfo> = Hal::new(Riscv64Irqs::new());
5254
}
5355
}
5456

riscv64_qemuvirt/src/main.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@ pub const UART_INTERRUPT_NUMBER: u16 = 10;
1515
const LAUNCH_TESTS: bool = cfg!(feature = "launch_tests");
1616

1717
#[no_mangle]
18-
extern "C" fn k_main(_core_id: usize, device_tree_ptr: usize) -> ! {
18+
extern "C" fn k_main(core_id: usize, device_tree_ptr: usize) -> ! {
19+
kernel::HAL.init_core_info(core_id);
20+
kernel::HAL.init_irqs();
21+
1922
static NS16550: Ns16550 = Ns16550::new(UART_ADDR);
2023
kernel::kernel_console::set_earlyinit_console(&NS16550);
2124

2225
kernel::kernel_console::init_logging().unwrap();
2326

27+
assert_eq!(core_id, 0, "Kernel must be booted on the first core with id == 0");
2428
info!("GoOSe is booting");
2529

26-
kernel::HAL.init_irqs();
27-
2830
let device_tree = kernel::device_tree::DeviceTree::new(device_tree_ptr).unwrap();
2931
kernel::generic_main::generic_main::<LAUNCH_TESTS>(device_tree, &[&NS16550]);
3032
}

0 commit comments

Comments
 (0)