mirror of
https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials.git
synced 2024-11-11 07:10:59 +00:00
e7cb61b389
- Don't wildcard-import from arch modules. Make it explicit. - Put translation table code into its own module. - Put boot code in boot.rs instead of cpu.rs - Other minor changes, most memory subsystem.
93 lines
3.0 KiB
Rust
93 lines
3.0 KiB
Rust
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
//
|
|
// Copyright (c) 2020-2021 Andre Richter <andre.o.richter@gmail.com>
|
|
|
|
//! State information about the kernel itself.
|
|
|
|
use core::sync::atomic::{AtomicU8, Ordering};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Private Definitions
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
/// Different stages in the kernel execution.
|
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
|
enum State {
|
|
/// The kernel starts booting in this state.
|
|
Init,
|
|
|
|
/// The kernel transitions to this state when jumping to `kernel_main()` (at the end of
|
|
/// `kernel_init()`, after all init calls are done).
|
|
SingleCoreMain,
|
|
|
|
/// The kernel transitions to this state when it boots the secondary cores, aka switches
|
|
/// exectution mode to symmetric multiprocessing (SMP).
|
|
MultiCoreMain,
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Public Definitions
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
/// Maintains the kernel state and state transitions.
|
|
pub struct StateManager(AtomicU8);
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Global instances
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
static STATE_MANAGER: StateManager = StateManager::new();
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Public Code
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
/// Return a reference to the global StateManager.
|
|
pub fn state_manager() -> &'static StateManager {
|
|
&STATE_MANAGER
|
|
}
|
|
|
|
impl StateManager {
|
|
const INIT: u8 = 0;
|
|
const SINGLE_CORE_MAIN: u8 = 1;
|
|
const MULTI_CORE_MAIN: u8 = 2;
|
|
|
|
/// Create a new instance.
|
|
pub const fn new() -> Self {
|
|
Self(AtomicU8::new(Self::INIT))
|
|
}
|
|
|
|
/// Return the current state.
|
|
fn state(&self) -> State {
|
|
let state = self.0.load(Ordering::Acquire);
|
|
|
|
match state {
|
|
Self::INIT => State::Init,
|
|
Self::SINGLE_CORE_MAIN => State::SingleCoreMain,
|
|
Self::MULTI_CORE_MAIN => State::MultiCoreMain,
|
|
_ => panic!("Invalid KERNEL_STATE"),
|
|
}
|
|
}
|
|
|
|
/// Return if the kernel is init state.
|
|
pub fn is_init(&self) -> bool {
|
|
self.state() == State::Init
|
|
}
|
|
|
|
/// Transition from Init to SingleCoreMain.
|
|
pub fn transition_to_single_core_main(&self) {
|
|
if self
|
|
.0
|
|
.compare_exchange(
|
|
Self::INIT,
|
|
Self::SINGLE_CORE_MAIN,
|
|
Ordering::Acquire,
|
|
Ordering::Relaxed,
|
|
)
|
|
.is_err()
|
|
{
|
|
panic!("transition_to_single_core_main() called while state != Init");
|
|
}
|
|
}
|
|
}
|