Skip to content

Commit 8a03f1b

Browse files
authored
Merge pull request #1685 from stlankes/smp
Improve aarch64 support
2 parents 9b7bb8d + a6bdf8b commit 8a03f1b

File tree

10 files changed

+180
-41
lines changed

10 files changed

+180
-41
lines changed

.github/workflows/ci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,4 @@ jobs:
241241
- run: UHYVE=$CARGO_HOME/bin/uhyve cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package rusty_demo --smp 4 uhyve --sudo
242242
if: matrix.arch == 'x86_64'
243243
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package thread_test --smp 4 qemu ${{ matrix.flags }}
244+
if: matrix.arch == 'x86_64'

src/arch/aarch64/kernel/core_local.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub(crate) struct CoreLocal {
3232

3333
impl CoreLocal {
3434
pub fn install() {
35-
let core_id = CPU_ONLINE.load(Ordering::Relaxed);
35+
let core_id = CPU_ONLINE.0.load(Ordering::Relaxed);
3636

3737
let irq_statistics = if core_id == 0 {
3838
static FIRST_IRQ_STATISTICS: IrqStatistics = IrqStatistics::new();

src/arch/aarch64/kernel/interrupts.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ pub(crate) static GIC: SpinMutex<Option<GicV3<'_>>> = SpinMutex::new(None);
4646
pub fn enable() {
4747
unsafe {
4848
asm!(
49+
"dmb ish",
4950
"msr daifclr, {mask}",
51+
"dmb ish",
5052
mask = const 0b111,
51-
options(nostack, nomem),
53+
options(nostack),
5254
);
5355
}
5456
}
@@ -61,9 +63,11 @@ pub fn enable() {
6163
pub fn enable_and_wait() {
6264
unsafe {
6365
asm!(
66+
"dmb ish",
6467
"msr daifclr, {mask}; wfi",
68+
"dmb ish",
6569
mask = const 0b111,
66-
options(nostack, nomem),
70+
options(nostack),
6771
);
6872
}
6973
}
@@ -73,9 +77,11 @@ pub fn enable_and_wait() {
7377
pub fn disable() {
7478
unsafe {
7579
asm!(
80+
"dmb ish",
7681
"msr daifset, {mask}",
82+
"dmb ish",
7783
mask = const 0b111,
78-
options(nostack, nomem),
84+
options(nostack),
7985
);
8086
}
8187
}
@@ -206,8 +212,14 @@ pub(crate) extern "C" fn do_sync(state: &State) {
206212
}
207213
} else if ec == 0x3c {
208214
error!("Trap to debugger, PC={pc:#x}");
215+
loop {
216+
core::hint::spin_loop();
217+
}
209218
} else {
210219
error!("Unsupported exception class: {ec:#x}, PC={pc:#x}");
220+
loop {
221+
core::hint::spin_loop();
222+
}
211223
}
212224
}
213225

src/arch/aarch64/kernel/mod.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,18 @@ mod start;
1212
pub mod switch;
1313
pub mod systemtime;
1414

15+
use alloc::alloc::{Layout, alloc};
1516
use core::arch::global_asm;
16-
use core::str;
17-
use core::sync::atomic::{AtomicU32, AtomicU64, Ordering};
17+
use core::sync::atomic::{AtomicPtr, AtomicU32, Ordering};
1818
use core::task::Waker;
19+
use core::{ptr, str};
1920

2021
use memory_addresses::arch::aarch64::{PhysAddr, VirtAddr};
2122

2223
use crate::arch::aarch64::kernel::core_local::*;
2324
use crate::arch::aarch64::kernel::serial::SerialPort;
25+
use crate::arch::aarch64::mm::paging::{BasePageSize, PageSize};
26+
use crate::config::*;
2427
use crate::env;
2528

2629
const SERIAL_PORT_BAUDRATE: u32 = 115_200;
@@ -69,12 +72,15 @@ impl Default for Console {
6972
}
7073
}
7174

75+
#[repr(align(8))]
76+
pub(crate) struct AlignedAtomicU32(AtomicU32);
77+
7278
/// `CPU_ONLINE` is the count of CPUs that finished initialization.
7379
///
7480
/// It also synchronizes initialization of CPU cores.
75-
pub(crate) static CPU_ONLINE: AtomicU32 = AtomicU32::new(0);
81+
pub(crate) static CPU_ONLINE: AlignedAtomicU32 = AlignedAtomicU32(AtomicU32::new(0));
7682

77-
pub(crate) static CURRENT_STACK_ADDRESS: AtomicU64 = AtomicU64::new(0);
83+
pub(crate) static CURRENT_STACK_ADDRESS: AtomicPtr<u8> = AtomicPtr::new(ptr::null_mut());
7884

7985
#[cfg(target_os = "none")]
8086
global_asm!(include_str!("start.s"));
@@ -102,12 +108,25 @@ pub fn get_limit() -> usize {
102108

103109
#[cfg(feature = "smp")]
104110
pub fn get_possible_cpus() -> u32 {
105-
CPU_ONLINE.load(Ordering::Acquire)
111+
use hermit_dtb::Dtb;
112+
113+
let dtb = unsafe {
114+
Dtb::from_raw(core::ptr::with_exposed_provenance(
115+
env::boot_info().hardware_info.device_tree.unwrap().get() as usize,
116+
))
117+
.expect(".dtb file has invalid header")
118+
};
119+
120+
dtb.enum_subnodes("/cpus")
121+
.filter(|name| name.contains("cpu@"))
122+
.count()
123+
.try_into()
124+
.unwrap()
106125
}
107126

108127
#[cfg(feature = "smp")]
109128
pub fn get_processor_count() -> u32 {
110-
1
129+
CPU_ONLINE.0.load(Ordering::Acquire)
111130
}
112131

113132
#[cfg(not(feature = "smp"))]
@@ -149,10 +168,16 @@ pub fn application_processor_init() {
149168

150169
fn finish_processor_init() {
151170
debug!("Initialized Processor");
171+
172+
// Allocate stack for the CPU and pass the addresses.
173+
let layout = Layout::from_size_align(KERNEL_STACK_SIZE, BasePageSize::SIZE as usize).unwrap();
174+
let stack = unsafe { alloc(layout) };
175+
assert!(!stack.is_null());
176+
CURRENT_STACK_ADDRESS.store(stack, Ordering::Relaxed);
152177
}
153178

154179
pub fn boot_next_processor() {
155-
CPU_ONLINE.fetch_add(1, Ordering::Release);
180+
CPU_ONLINE.0.fetch_add(1, Ordering::Release);
156181
}
157182

158183
pub fn print_statistics() {

src/arch/aarch64/kernel/scheduler.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ impl TaskStacks {
180180
}
181181

182182
pub fn from_boot_stacks() -> TaskStacks {
183-
let stack = VirtAddr::new(CURRENT_STACK_ADDRESS.load(Ordering::Relaxed));
183+
let stack = VirtAddr::new(CURRENT_STACK_ADDRESS.load(Ordering::Relaxed) as u64);
184184
debug!("Using boot stack {stack:p}");
185185

186186
TaskStacks::Boot(BootStack { stack })

src/arch/aarch64/kernel/start.rs

+29-2
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,36 @@ pub unsafe extern "C" fn _start(boot_info: Option<&'static RawBootInfo>, cpu_id:
2929

3030
unsafe {
3131
naked_asm!(
32-
"msr spsel, {l1}", // we want to use sp_el1
32+
// use core::sync::atomic::{AtomicU32, Ordering};
33+
//
34+
// pub static CPU_ONLINE: AtomicU32 = AtomicU32::new(0);
35+
//
36+
// while CPU_ONLINE.load(Ordering::Acquire) != this {
37+
// core::hint::spin_loop();
38+
// }
39+
"mrs x4, mpidr_el1",
40+
"and x4, x4, #0xff",
41+
"1:",
42+
"adrp x8, {cpu_online}",
43+
"ldr x5, [x8, #:lo12:{cpu_online}]",
44+
"cmp x4, x5",
45+
"b.eq 2f",
46+
"b 1b",
47+
"2:",
48+
49+
// we want to use sp_el1
50+
"msr spsel, #1",
51+
52+
// Overwrite RSP if `CURRENT_STACK_ADDRESS != 0`
3353
"adrp x8, {current_stack_address}",
54+
"ldr x4, [x8, #:lo12:{current_stack_address}]",
55+
"cmp x4, 0",
56+
"b.eq 3f",
57+
"mov sp, x4",
58+
"b 4f",
59+
"3:",
3460
"mov x4, sp",
61+
"4:",
3562
"str x4, [x8, #:lo12:{current_stack_address}]",
3663

3764
// Add stack top offset
@@ -41,7 +68,7 @@ pub unsafe extern "C" fn _start(boot_info: Option<&'static RawBootInfo>, cpu_id:
4168
// Jump to Rust code
4269
"b {pre_init}",
4370

44-
l1 = const 1,
71+
cpu_online = sym super::CPU_ONLINE,
4572
stack_top_offset = const KERNEL_STACK_SIZE - TaskStacks::MARKER_SIZE,
4673
current_stack_address = sym super::CURRENT_STACK_ADDRESS,
4774
pre_init = sym pre_init,

0 commit comments

Comments
 (0)