Skip to content

Commit 4a89f31

Browse files
bors[bot]mkroening
andauthored
Merge #621
621: Rework Core Local Storage r=stlankes a=mkroening Co-authored-by: Martin Kröning <[email protected]>
2 parents b5f26d7 + 0e29ed0 commit 4a89f31

26 files changed

+165
-299
lines changed

src/arch/aarch64/kernel/percore.rs src/arch/aarch64/kernel/core_local.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,44 @@ use core::ptr;
33
use crate::scheduler::{CoreId, PerCoreScheduler};
44

55
#[no_mangle]
6-
pub static mut PERCORE: PerCoreVariables = PerCoreVariables::new(0);
6+
pub static mut CORE_LOCAL: CoreLocal = CoreLocal::new(0);
77

8-
pub struct PerCoreVariables {
8+
pub struct CoreLocal {
99
/// ID of the current Core.
10-
core_id: PerCoreVariable<CoreId>,
10+
core_id: CoreLocalVariable<CoreId>,
1111
/// Scheduler of the current Core.
12-
scheduler: PerCoreVariable<*mut PerCoreScheduler>,
12+
scheduler: CoreLocalVariable<*mut PerCoreScheduler>,
1313
}
1414

15-
impl PerCoreVariables {
15+
impl CoreLocal {
1616
pub const fn new(core_id: CoreId) -> Self {
1717
Self {
18-
core_id: PerCoreVariable::new(core_id),
19-
scheduler: PerCoreVariable::new(0 as *mut PerCoreScheduler),
18+
core_id: CoreLocalVariable::new(core_id),
19+
scheduler: CoreLocalVariable::new(0 as *mut PerCoreScheduler),
2020
}
2121
}
2222
}
2323

2424
#[repr(C)]
25-
pub struct PerCoreVariable<T> {
25+
pub struct CoreLocalVariable<T> {
2626
data: T,
2727
}
2828

29-
pub trait PerCoreVariableMethods<T: Clone> {
29+
pub trait CoreLocalVariableMethods<T: Clone> {
3030
unsafe fn get(&self) -> T;
3131
unsafe fn set(&mut self, value: T);
3232
}
3333

34-
impl<T> PerCoreVariable<T> {
34+
impl<T> CoreLocalVariable<T> {
3535
const fn new(value: T) -> Self {
3636
Self { data: value }
3737
}
3838
}
3939

4040
// Treat all per-core variables as 64-bit variables by default. This is true for u64, usize, pointers.
41-
// Implement the PerCoreVariableMethods trait functions using 64-bit memory moves.
41+
// Implement the CoreLocalVariableMethods trait functions using 64-bit memory moves.
4242
// The functions are implemented as default functions, which can be overridden in specialized implementations of the trait.
43-
impl<T> PerCoreVariableMethods<T> for PerCoreVariable<T>
43+
impl<T> CoreLocalVariableMethods<T> for CoreLocalVariable<T>
4444
where
4545
T: Clone,
4646
{
@@ -57,18 +57,18 @@ where
5757

5858
#[inline]
5959
pub fn core_id() -> CoreId {
60-
unsafe { PERCORE.core_id.get() }
60+
unsafe { CORE_LOCAL.core_id.get() }
6161
}
6262

6363
#[inline]
6464
pub fn core_scheduler() -> &'static mut PerCoreScheduler {
65-
unsafe { &mut *PERCORE.scheduler.get() }
65+
unsafe { &mut *CORE_LOCAL.scheduler.get() }
6666
}
6767

6868
#[inline]
6969
pub fn set_core_scheduler(scheduler: *mut PerCoreScheduler) {
7070
unsafe {
71-
PERCORE.scheduler.set(scheduler);
71+
CORE_LOCAL.scheduler.set(scheduler);
7272
}
7373
}
7474

src/arch/aarch64/kernel/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
pub mod core_local;
12
pub mod interrupts;
23
pub mod pci;
3-
pub mod percore;
44
pub mod processor;
55
pub mod scheduler;
66
pub mod serial;
@@ -15,7 +15,7 @@ use core::ptr;
1515
use hermit_entry::boot_info::{BootInfo, PlatformInfo, RawBootInfo};
1616
use hermit_sync::TicketMutex;
1717

18-
use crate::arch::aarch64::kernel::percore::*;
18+
use crate::arch::aarch64::kernel::core_local::*;
1919
use crate::arch::aarch64::kernel::serial::SerialPort;
2020
pub use crate::arch::aarch64::kernel::stubs::*;
2121
pub use crate::arch::aarch64::kernel::systemtime::get_boot_time;
@@ -136,7 +136,7 @@ pub fn get_cmdline() -> VirtAddr {
136136

137137
/// Earliest initialization function called by the Boot Processor.
138138
pub fn message_output_init() {
139-
percore::init();
139+
core_local::init();
140140

141141
unsafe {
142142
COM1.port_address = boot_info()
@@ -226,7 +226,7 @@ pub fn boot_application_processors() {
226226

227227
/// Application Processor initialization
228228
pub fn application_processor_init() {
229-
percore::init();
229+
core_local::init();
230230
/*processor::configure();
231231
gdt::add_current_core();
232232
idt::install();

src/arch/aarch64/kernel/scheduler.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use alloc::rc::Rc;
44
use core::cell::RefCell;
55
use core::{mem, ptr};
66

7-
use crate::arch::aarch64::kernel::percore::*;
7+
use crate::arch::aarch64::kernel::core_local::*;
88
use crate::arch::aarch64::kernel::processor;
99
use crate::arch::aarch64::mm::paging::{BasePageSize, PageSize, PageTableEntryFlags};
1010
use crate::arch::aarch64::mm::{PhysAddr, VirtAddr};
@@ -109,7 +109,7 @@ impl TaskStacks {
109109
}
110110

111111
pub fn from_boot_stacks() -> TaskStacks {
112-
//let tss = unsafe { &(*PERCORE.tss.get()) };
112+
//let tss = unsafe { &(*CORE_LOCAL.tss.get()) };
113113
/*let stack = VirtAddr::from_usize(tss.rsp[0] as usize + 0x10 - KERNEL_STACK_SIZE);
114114
debug!("Using boot stack {:#X}", stack);
115115
let ist0 = VirtAddr::from_usize(tss.ist[0] as usize + 0x10 - KERNEL_STACK_SIZE);

src/arch/aarch64/mm/paging.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use core::arch::asm;
22
use core::marker::PhantomData;
33
use core::{fmt, mem, ptr, usize};
44

5-
use crate::arch::aarch64::kernel::percore::*;
5+
use crate::arch::aarch64::kernel::core_local::*;
66
use crate::arch::aarch64::kernel::{
77
get_base_address, get_boot_info_address, get_image_size, get_ram_address, is_uhyve, processor,
88
};

src/arch/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ pub mod x86_64;
77

88
// Export our platform-specific modules.
99
#[cfg(target_arch = "aarch64")]
10-
pub use crate::arch::aarch64::kernel::interrupts;
10+
pub use crate::arch::aarch64::kernel::core_local;
1111
#[cfg(target_arch = "aarch64")]
12-
pub use crate::arch::aarch64::kernel::percore;
12+
use crate::arch::aarch64::kernel::core_local::core_scheduler;
1313
#[cfg(target_arch = "aarch64")]
14-
use crate::arch::aarch64::kernel::percore::core_scheduler;
14+
pub use crate::arch::aarch64::kernel::interrupts;
1515
#[cfg(target_arch = "aarch64")]
1616
pub use crate::arch::aarch64::kernel::processor;
1717
#[cfg(target_arch = "aarch64")]
@@ -34,12 +34,12 @@ pub use crate::arch::x86_64::kernel::apic::{set_oneshot_timer, wakeup_core};
3434
#[cfg(all(target_arch = "x86_64", target_os = "none", feature = "smp"))]
3535
pub use crate::arch::x86_64::kernel::application_processor_init;
3636
#[cfg(target_arch = "x86_64")]
37+
pub use crate::arch::x86_64::kernel::core_local;
38+
#[cfg(target_arch = "x86_64")]
3739
pub use crate::arch::x86_64::kernel::gdt::set_current_kernel_stack;
3840
#[cfg(target_arch = "x86_64")]
3941
pub use crate::arch::x86_64::kernel::interrupts;
4042
#[cfg(target_arch = "x86_64")]
41-
pub use crate::arch::x86_64::kernel::percore;
42-
#[cfg(target_arch = "x86_64")]
4343
pub use crate::arch::x86_64::kernel::processor;
4444
#[cfg(target_arch = "x86_64")]
4545
pub use crate::arch::x86_64::kernel::scheduler;

src/arch/x86_64/kernel/apic.rs

+6-34
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use alloc::boxed::Box;
21
use alloc::vec::Vec;
32
#[cfg(any(feature = "pci", feature = "smp"))]
43
use core::arch::x86_64::_mm_mfence;
@@ -8,19 +7,18 @@ use core::ptr;
87
use core::sync::atomic::Ordering;
98
use core::{cmp, fmt, mem, u32};
109

11-
use arch::x86_64::kernel::percore::*;
10+
#[cfg(feature = "smp")]
11+
use arch::x86_64::kernel::core_local::*;
1212
use arch::x86_64::kernel::{interrupts, processor};
13-
use crossbeam_utils::CachePadded;
1413
use hermit_sync::without_interrupts;
1514
#[cfg(feature = "smp")]
1615
use x86::controlregs::*;
1716
use x86::msr::*;
1817
use x86_64::structures::idt::InterruptDescriptorTable;
1918

20-
use super::interrupts::{IDT, IRQ_COUNTERS};
19+
use super::interrupts::IDT;
2120
#[cfg(feature = "acpi")]
2221
use crate::arch::x86_64::kernel::acpi;
23-
use crate::arch::x86_64::kernel::interrupts::IrqStatistics;
2422
use crate::arch::x86_64::kernel::CURRENT_STACK_ADDRESS;
2523
use crate::arch::x86_64::mm::paging::{
2624
BasePageSize, PageSize, PageTableEntryFlags, PageTableEntryFlagsExt,
@@ -512,13 +510,6 @@ pub extern "C" fn eoi() {
512510
}
513511

514512
pub fn init() {
515-
let boxed_irq = Box::new(IrqStatistics::new());
516-
let boxed_irq_raw = Box::into_raw(boxed_irq);
517-
unsafe {
518-
IRQ_COUNTERS.insert(0, &(*boxed_irq_raw));
519-
PERCORE.irq_statistics.set(boxed_irq_raw);
520-
}
521-
522513
// Initialize an empty vector for the Local APIC IDs of all CPUs.
523514
unsafe {
524515
CPU_LOCAL_APIC_IDS = Some(Vec::new());
@@ -736,30 +727,11 @@ pub fn init_x2apic() {
736727
}
737728

738729
/// Initialize the required _start variables for the next CPU to be booted.
739-
pub fn init_next_processor_variables(core_id: CoreId) {
740-
// Allocate stack and PerCoreVariables structure for the CPU and pass the addresses.
730+
pub fn init_next_processor_variables() {
731+
// Allocate stack for the CPU and pass the addresses.
741732
// Keep the stack executable to possibly support dynamically generated code on the stack (see https://security.stackexchange.com/a/47825).
742733
let stack = mm::allocate(KERNEL_STACK_SIZE, true);
743-
let mut boxed_percore = Box::new(CachePadded::new(PerCoreInnerVariables::new(core_id)));
744-
let boxed_irq = Box::new(IrqStatistics::new());
745-
let boxed_irq_raw = Box::into_raw(boxed_irq);
746-
747-
unsafe {
748-
IRQ_COUNTERS.insert(core_id, &(*boxed_irq_raw));
749-
boxed_percore.irq_statistics = PerCoreVariable::new(boxed_irq_raw);
750-
}
751-
752734
CURRENT_STACK_ADDRESS.store(stack.as_u64(), Ordering::Relaxed);
753-
754-
let current_percore = Box::leak(boxed_percore);
755-
756-
trace!(
757-
"Initialize per core data at {:p} (size {} bytes)",
758-
current_percore,
759-
mem::size_of_val(current_percore)
760-
);
761-
762-
CURRENT_PERCORE_ADDRESS.store(current_percore as *mut _ as u64, Ordering::Release);
763735
}
764736

765737
/// Boot all Application Processors
@@ -836,7 +808,7 @@ pub fn boot_application_processors() {
836808
"Waking up CPU {} with Local APIC ID {}",
837809
core_id_to_boot, apic_id
838810
);
839-
init_next_processor_variables(core_id_to_boot);
811+
init_next_processor_variables();
840812

841813
// Save the current number of initialized CPUs.
842814
let current_processor_count = arch::get_processor_count();

src/arch/x86_64/kernel/core_local.rs

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use alloc::boxed::Box;
2+
use core::arch::asm;
3+
use core::cell::Cell;
4+
use core::ptr;
5+
use core::sync::atomic::Ordering;
6+
7+
use x86_64::registers::model_specific::GsBase;
8+
use x86_64::structures::tss::TaskStateSegment;
9+
use x86_64::VirtAddr;
10+
11+
use super::interrupts::{IrqStatistics, IRQ_COUNTERS};
12+
use super::CPU_ONLINE;
13+
use crate::scheduler::{CoreId, PerCoreScheduler};
14+
15+
pub struct CoreLocal {
16+
this: *const Self,
17+
/// Sequential ID of this CPU Core.
18+
core_id: CoreId,
19+
/// Scheduler for this CPU Core.
20+
scheduler: Cell<*mut PerCoreScheduler>,
21+
/// Task State Segment (TSS) allocated for this CPU Core.
22+
pub tss: Cell<*mut TaskStateSegment>,
23+
/// start address of the kernel stack
24+
pub kernel_stack: Cell<u64>,
25+
/// Interface to the interrupt counters
26+
irq_statistics: &'static IrqStatistics,
27+
}
28+
29+
impl CoreLocal {
30+
pub fn install() {
31+
assert_eq!(VirtAddr::zero(), GsBase::read());
32+
33+
let core_id = CPU_ONLINE.load(Ordering::Relaxed);
34+
35+
let irq_statistics = &*Box::leak(Box::new(IrqStatistics::new()));
36+
IRQ_COUNTERS.lock().insert(core_id, irq_statistics);
37+
38+
let this = Self {
39+
this: ptr::null_mut(),
40+
core_id,
41+
scheduler: Cell::new(ptr::null_mut()),
42+
tss: Cell::new(ptr::null_mut()),
43+
kernel_stack: Cell::new(0),
44+
irq_statistics,
45+
};
46+
let mut this = Box::leak(Box::new(this));
47+
this.this = &*this;
48+
49+
GsBase::write(VirtAddr::from_ptr(this));
50+
}
51+
52+
pub fn get() -> &'static Self {
53+
debug_assert_ne!(VirtAddr::zero(), GsBase::read());
54+
unsafe {
55+
let raw: *const Self;
56+
asm!("mov {}, gs:0", out(reg) raw, options(nomem, nostack, preserves_flags));
57+
&*raw
58+
}
59+
}
60+
}
61+
62+
pub fn core_id() -> CoreId {
63+
if cfg!(target_os = "none") {
64+
CoreLocal::get().core_id
65+
} else {
66+
0
67+
}
68+
}
69+
70+
pub fn core_scheduler() -> &'static mut PerCoreScheduler {
71+
unsafe { &mut *CoreLocal::get().scheduler.get() }
72+
}
73+
74+
pub fn set_core_scheduler(scheduler: *mut PerCoreScheduler) {
75+
CoreLocal::get().scheduler.set(scheduler);
76+
}
77+
78+
pub fn increment_irq_counter(irq_no: usize) {
79+
CoreLocal::get().irq_statistics.inc(irq_no);
80+
}

src/arch/x86_64/kernel/gdt.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use x86_64::VirtAddr;
1010
use super::interrupts::{IST_ENTRIES, IST_SIZE};
1111
use super::scheduler::TaskStacks;
1212
use super::CURRENT_STACK_ADDRESS;
13-
use crate::arch::x86_64::kernel::percore::{core_scheduler, set_kernel_stack, PERCORE};
13+
use crate::arch::x86_64::kernel::core_local::{core_scheduler, CoreLocal};
1414
use crate::config::KERNEL_STACK_SIZE;
1515

1616
pub fn add_current_core() {
@@ -26,7 +26,7 @@ pub fn add_current_core() {
2626
let rsp = CURRENT_STACK_ADDRESS.load(Ordering::Relaxed) + KERNEL_STACK_SIZE as u64
2727
- TaskStacks::MARKER_SIZE as u64;
2828
tss.privilege_stack_table[0] = VirtAddr::new(rsp);
29-
set_kernel_stack(rsp);
29+
CoreLocal::get().kernel_stack.set(rsp);
3030

3131
// Allocate all ISTs for this core.
3232
// Every task later gets its own IST1, so the IST1 allocated here is only used by the Idle task.
@@ -36,9 +36,7 @@ pub fn add_current_core() {
3636
tss.interrupt_stack_table[i] = VirtAddr::new(ist_start);
3737
}
3838

39-
unsafe {
40-
PERCORE.tss.set(tss);
41-
}
39+
CoreLocal::get().tss.set(tss);
4240
let tss_selector = gdt.add_entry(Descriptor::tss_segment(tss));
4341

4442
// Load the GDT for the current core.

0 commit comments

Comments
 (0)