Skip to content

Commit

Permalink
kernel: initial shared kernel state
Browse files Browse the repository at this point in the history
  • Loading branch information
Qix- committed Sep 10, 2024
1 parent be09be3 commit 4c50371
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 14 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 10 additions & 3 deletions oro-arch-aarch64/src/boot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,23 @@ const SECONDARY_STACK_PAGES: usize = 16;
pub unsafe fn boot_primary() -> ! {
crate::asm::disable_interrupts();

let memory::PreparedMemory { mut pfa, pat } = memory::prepare_memory();
let memory::PreparedMemory { pfa, pat } = memory::prepare_memory();

// We now have a valid physical map; let's re-init
// any MMIO loggers with that offset.
#[cfg(debug_assertions)]
oro_debug::init_with_offset(pat.offset());

// Initialize the primary core.
crate::init::initialize_primary(pfa);
let mut pfa = crate::init::KERNEL_STATE
.assume_init_ref()
.pfa()
.lock::<crate::sync::InterruptController>();

// Boot secondaries.
let num_cores = secondary::boot_secondaries(&mut pfa, &pat, SECONDARY_STACK_PAGES);
let num_cores = secondary::boot_secondaries(&mut *pfa, &pat, SECONDARY_STACK_PAGES);
dbg!("continuing with {num_cores} cores");

crate::asm::halt();
crate::init::boot();
}
2 changes: 1 addition & 1 deletion oro-arch-aarch64/src/boot/secondary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,5 +428,5 @@ unsafe extern "C" fn boot_secondary_entry() {
// by the primary core.
dbg!("secondary core {} booted", boot_block.core_id);

crate::asm::halt();
crate::init::boot();
}
54 changes: 54 additions & 0 deletions oro-arch-aarch64/src/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//! Architecture / core initialization
//! routines and global state definitions.
use core::mem::MaybeUninit;
use oro_kernel::{Kernel, KernelState};
use oro_mem::{pfa::filo::FiloPageFrameAllocator, translate::OffsetTranslator};
use oro_sync::spinlock::unfair_critical::UnfairCriticalSpinlock;

/// Type alias for the PFA (page frame allocator) implementation used
/// by the architecture.
pub type Pfa = FiloPageFrameAllocator<OffsetTranslator>;

/// The global kernel state. Initialized once during boot
/// and re-used across all cores.
pub static mut KERNEL_STATE: MaybeUninit<KernelState<Pfa>> = MaybeUninit::uninit();

/// Initializes the global state of the architecture.
///
/// # Safety
/// Must be called exactly once for the lifetime of the system,
/// only by the boot processor at boot time (_not_ at any
/// subsequent bringup).
pub unsafe fn initialize_primary(pfa: Pfa) {
#[cfg(debug_assertions)]
{
use core::sync::atomic::{AtomicBool, Ordering};

#[doc(hidden)]
static HAS_INITIALIZED: AtomicBool = AtomicBool::new(false);

if HAS_INITIALIZED
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
.is_err()
{
panic!("init() called more than once");
}
}

KERNEL_STATE.write(KernelState::new(UnfairCriticalSpinlock::new(pfa)));
}

/// Main boot sequence for all cores for each bringup
/// (including boot, including the primary core).
///
/// # Safety
/// Must be called _exactly once_ per core, per core lifetime
/// (i.e. boot, or powerdown/subsequent bringup).
pub unsafe fn boot() -> ! {
let _kernel = Kernel::new(KERNEL_STATE.assume_init_ref());

oro_debug::dbg!("boot");

crate::asm::halt();
}
2 changes: 2 additions & 0 deletions oro-arch-aarch64/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub mod psci;
pub mod reg;
pub mod sync;

pub(crate) mod init;

use oro_elf::{ElfClass, ElfEndianness, ElfMachine};

/// The ELF class for the AArch64 architecture.
Expand Down
18 changes: 10 additions & 8 deletions oro-arch-x86_64/src/boot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,7 @@ pub unsafe fn boot_primary() -> ! {
#[cfg(debug_assertions)]
oro_debug::init();

let memory::PreparedMemory {
pat,
has_cs89,
mut pfa,
} = memory::prepare_memory();
let memory::PreparedMemory { pat, has_cs89, pfa } = memory::prepare_memory();

// We now have a valid physical map; let's re-init
// any MMIO loggers with that offset.
Expand Down Expand Up @@ -115,7 +111,13 @@ pub unsafe fn boot_primary() -> ! {
let lapic = crate::lapic::Lapic::new(pat.translate_mut::<u8>(madt.lapic_phys()));
dbg!("local APIC version: {:?}", lapic.version());
let lapic_id = lapic.id();
dbg!("local APIC ID: {lapic_id}",);
dbg!("local APIC ID: {lapic_id}");

crate::init::initialize_primary(pfa);
let mut pfa = crate::init::KERNEL_STATE
.assume_init_ref()
.pfa()
.lock::<crate::sync::InterruptController>();

let num_cores = if has_cs89 {
dbg!("physical pages 0x8000/0x9000 are valid; attempting to boot secondary cores");
Expand All @@ -134,7 +136,7 @@ pub unsafe fn boot_primary() -> ! {
dbg!("cpu {}: booting...", apic.id());
match secondary::boot_secondary(
&mapper,
&mut pfa,
&mut *pfa,
&pat,
&lapic,
apic.id(),
Expand Down Expand Up @@ -162,5 +164,5 @@ pub unsafe fn boot_primary() -> ! {

dbg!("proceeding with {} core(s)", num_cores);

crate::asm::halt();
crate::init::boot()
}
3 changes: 1 addition & 2 deletions oro-arch-x86_64/src/boot/secondary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,5 @@ unsafe extern "C" fn oro_kernel_x86_64_rust_secondary_core_entry() -> ! {
AddressSpaceLayout::secondary_boot_stub_stack().unmap_without_reclaim(&mapper, &pat);
}

// XXX TODO
crate::asm::halt();
crate::init::boot();
}
54 changes: 54 additions & 0 deletions oro-arch-x86_64/src/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//! Architecture / core initialization
//! routines and global state definitions.
use core::mem::MaybeUninit;
use oro_kernel::{Kernel, KernelState};
use oro_mem::{pfa::filo::FiloPageFrameAllocator, translate::OffsetTranslator};
use oro_sync::spinlock::unfair_critical::UnfairCriticalSpinlock;

/// Type alias for the PFA (page frame allocator) implementation used
/// by the architecture.
pub type Pfa = FiloPageFrameAllocator<OffsetTranslator>;

/// The global kernel state. Initialized once during boot
/// and re-used across all cores.
pub static mut KERNEL_STATE: MaybeUninit<KernelState<Pfa>> = MaybeUninit::uninit();

/// Initializes the global state of the architecture.
///
/// # Safety
/// Must be called exactly once for the lifetime of the system,
/// only by the boot processor at boot time (_not_ at any
/// subsequent bringup).
pub unsafe fn initialize_primary(pfa: Pfa) {
#[cfg(debug_assertions)]
{
use core::sync::atomic::{AtomicBool, Ordering};

#[doc(hidden)]
static HAS_INITIALIZED: AtomicBool = AtomicBool::new(false);

if HAS_INITIALIZED
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
.is_err()
{
panic!("init() called more than once");
}
}

KERNEL_STATE.write(KernelState::new(UnfairCriticalSpinlock::new(pfa)));
}

/// Main boot sequence for all cores for each bringup
/// (including boot, including the primary core).
///
/// # Safety
/// Must be called _exactly once_ per core, per core lifetime
/// (i.e. boot, or powerdown/subsequent bringup).
pub unsafe fn boot() -> ! {
let _kernel = Kernel::new(KERNEL_STATE.assume_init_ref());

oro_debug::dbg!("boot");

crate::asm::halt();
}
2 changes: 2 additions & 0 deletions oro-arch-x86_64/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub mod mem;
pub mod reg;
pub mod sync;

pub(crate) mod init;

use oro_elf::{ElfClass, ElfEndianness, ElfMachine};

/// The ELF class of the x86_64 architecture.
Expand Down
1 change: 1 addition & 0 deletions oro-kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ license = "MPL-2.0"
[dependencies]
oro-mem.workspace = true
oro-macro.workspace = true
oro-sync.workspace = true

[lints]
workspace = true
60 changes: 60 additions & 0 deletions oro-kernel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,67 @@
#![allow(incomplete_features)]
#![feature(adt_const_params)]

use oro_mem::pfa::alloc::{PageFrameAllocate, PageFrameFree};
use oro_sync::spinlock::unfair_critical::UnfairCriticalSpinlock;

pub mod id;
pub mod module;
pub mod port;
pub mod ring;

/// Core-local instance of the Oro kernel.
///
/// Intended to live on the core's respective stack,
/// living for the lifetime of the core (and destroyed
/// and re-created on core powerdown/subsequent bringup).
pub struct Kernel<Pfa: 'static> {
/// Global reference to the shared kernel state.
state: &'static KernelState<Pfa>,
}

impl<Pfa: 'static> Kernel<Pfa> {
/// Creates a new core-local instance of the Kernel.
///
/// # Safety
/// Must only be called once per CPU session (i.e.
/// boot or bringup after a powerdown case, where the
/// previous core-local [`Kernel`] was migrated or otherwise
/// destroyed).
///
/// The `state` given to the kernel must be shared for all
/// instances of the kernel that wish to partake in the same
/// Oro kernel universe.
pub unsafe fn new(state: &'static KernelState<Pfa>) -> Self {
Self { state }
}

/// Returns the underlying [`KernelState`] for this kernel instance.
#[must_use]
pub fn state(&self) -> &'static KernelState<Pfa> {
self.state
}
}

/// Global state shared by all [`Kernel`] instances across
/// core boot/powerdown/bringup cycles.
pub struct KernelState<Pfa: 'static> {
/// The shared, spinlocked page frame allocator (PFA) for the
/// entire system.
pfa: UnfairCriticalSpinlock<Pfa>,
}

impl<Pfa> KernelState<Pfa>
where
Pfa: PageFrameAllocate + PageFrameFree + 'static,
{
/// Creates a new instance of the kernel state. Meant to be called
/// once for all cores at boot time.
pub fn new(pfa: UnfairCriticalSpinlock<Pfa>) -> Self {
Self { pfa }
}

/// Returns the underlying PFA belonging to the kernel state.
pub fn pfa(&self) -> &UnfairCriticalSpinlock<Pfa> {
&self.pfa
}
}

0 comments on commit 4c50371

Please sign in to comment.