asterinas/kernel/src/lib.rs

182 lines
4.7 KiB
Rust
Raw Normal View History

// SPDX-License-Identifier: MPL-2.0
2024-08-19 11:15:22 +00:00
//! Aster-nix is the Asterinas kernel, a safe, efficient unix-like
//! operating system kernel built on top of OSTD and OSDK.
#![no_std]
#![no_main]
#![deny(unsafe_code)]
#![expect(incomplete_features)]
2024-08-19 11:15:22 +00:00
#![feature(btree_cursors)]
#![feature(btree_extract_if)]
2024-08-17 08:06:35 +00:00
#![feature(debug_closure_helpers)]
2024-08-19 11:15:22 +00:00
#![feature(extend_one)]
#![feature(fn_traits)]
#![feature(format_args_nl)]
#![feature(int_roundings)]
#![feature(let_chains)]
#![feature(linked_list_cursors)]
2024-08-19 11:15:22 +00:00
#![feature(linked_list_remove)]
#![feature(linked_list_retain)]
2024-08-19 11:15:22 +00:00
#![feature(negative_impls)]
#![feature(panic_can_unwind)]
2024-08-19 11:15:22 +00:00
#![feature(register_tool)]
// FIXME: This feature is used to support vm capbility now as a work around.
// Since this is an incomplete feature, use this feature is unsafe.
// We should find a proper method to replace this feature with min_specialization, which is a sound feature.
#![feature(specialization)]
#![feature(step_trait)]
#![feature(trait_alias)]
#![feature(trait_upcasting)]
#![register_tool(component_access_control)]
2024-12-31 06:29:49 +00:00
use kcmdline::KCmdlineArg;
2024-08-19 11:15:22 +00:00
use ostd::{
arch::qemu::{exit_qemu, QemuExitCode},
boot::boot_info,
2024-12-13 13:22:40 +00:00
cpu::{CpuId, CpuSet, PinCurrentCpu},
2024-08-19 11:15:22 +00:00
};
use process::Process;
2025-01-22 06:08:35 +00:00
use sched::SchedPolicy;
2024-08-19 11:15:22 +00:00
use crate::{
prelude::*,
2024-11-10 08:48:35 +00:00
thread::{kernel_thread::ThreadOptions, Thread},
2024-08-19 11:15:22 +00:00
};
extern crate alloc;
extern crate lru;
#[macro_use]
extern crate controlled;
#[macro_use]
extern crate getset;
pub mod arch;
pub mod context;
pub mod cpu;
pub mod device;
pub mod driver;
pub mod error;
pub mod events;
pub mod fs;
pub mod ipc;
2024-12-31 06:29:49 +00:00
pub mod kcmdline;
2024-08-19 11:15:22 +00:00
pub mod net;
pub mod prelude;
mod process;
mod sched;
pub mod syscall;
pub mod thread;
pub mod time;
mod util;
pub(crate) mod vdso;
pub mod vm;
2024-06-20 06:16:04 +00:00
#[ostd::main]
2024-08-19 11:15:22 +00:00
#[controlled]
2024-03-01 03:23:47 +00:00
pub fn main() {
2024-08-19 11:15:22 +00:00
ostd::early_println!("[kernel] OSTD initialized. Preparing components.");
component::init_all(component::parse_metadata!()).unwrap();
2024-08-19 11:15:22 +00:00
init();
2024-08-22 11:23:33 +00:00
// Spawn all AP idle threads.
ostd::boot::smp::register_ap_entry(ap_init);
// Spawn the first kernel thread on BSP.
2024-12-13 13:22:40 +00:00
let mut affinity = CpuSet::new_empty();
affinity.add(CpuId::bsp());
2024-11-10 08:48:35 +00:00
ThreadOptions::new(init_thread)
2024-12-13 13:22:40 +00:00
.cpu_affinity(affinity)
2025-01-22 06:08:35 +00:00
.sched_policy(SchedPolicy::Idle)
2024-11-10 08:48:35 +00:00
.spawn();
2024-08-19 11:15:22 +00:00
}
pub fn init() {
util::random::init();
driver::init();
time::init();
2024-09-24 14:14:30 +00:00
#[cfg(target_arch = "x86_64")]
2024-08-19 11:15:22 +00:00
net::init();
sched::init();
fs::rootfs::init(boot_info().initramfs.expect("No initramfs found!")).unwrap();
2024-08-19 11:15:22 +00:00
device::init().unwrap();
2024-11-28 05:53:22 +00:00
syscall::init();
2024-08-19 11:15:22 +00:00
vdso::init();
process::init();
}
2024-10-31 02:00:19 +00:00
fn ap_init() {
2024-08-22 11:23:33 +00:00
fn ap_idle_thread() {
let preempt_guard = ostd::task::disable_preempt();
let cpu_id = preempt_guard.current_cpu();
drop(preempt_guard);
log::info!("Kernel idle thread for CPU #{} started.", cpu_id.as_usize());
2024-08-22 11:23:33 +00:00
loop {
Thread::yield_now();
}
}
let preempt_guard = ostd::task::disable_preempt();
let cpu_id = preempt_guard.current_cpu();
drop(preempt_guard);
2024-11-10 08:48:35 +00:00
ThreadOptions::new(ap_idle_thread)
.cpu_affinity(cpu_id.into())
2025-01-22 06:08:35 +00:00
.sched_policy(SchedPolicy::Idle)
2024-11-10 08:48:35 +00:00
.spawn();
2024-08-22 11:23:33 +00:00
}
2024-08-19 11:15:22 +00:00
fn init_thread() {
2024-09-12 04:48:33 +00:00
println!("[kernel] Spawn init thread");
2024-08-19 11:15:22 +00:00
// Work queue should be initialized before interrupt is enabled,
// in case any irq handler uses work queue as bottom half
thread::work_queue::init();
2024-09-24 14:14:30 +00:00
#[cfg(target_arch = "x86_64")]
2024-08-19 11:15:22 +00:00
net::lazy_init();
fs::lazy_init();
ipc::init();
// driver::pci::virtio::block::block_device_test();
2024-11-10 08:48:35 +00:00
let thread = ThreadOptions::new(|| {
2024-08-19 11:15:22 +00:00
println!("[kernel] Hello world from kernel!");
2024-11-10 08:48:35 +00:00
})
.spawn();
2024-08-19 11:15:22 +00:00
thread.join();
print_banner();
2024-12-31 06:29:49 +00:00
let karg: KCmdlineArg = boot_info().kernel_cmdline.as_str().into();
2024-08-19 11:15:22 +00:00
let initproc = Process::spawn_user_process(
karg.get_initproc_path().unwrap(),
karg.get_initproc_argv().to_vec(),
karg.get_initproc_envp().to_vec(),
)
.expect("Run init process failed.");
// Wait till initproc become zombie.
2024-11-23 14:08:38 +00:00
while !initproc.status().is_zombie() {
2024-08-19 11:15:22 +00:00
// We don't have preemptive scheduler now.
// The long running init thread should yield its own execution to allow other tasks to go on.
Thread::yield_now();
}
// TODO: exit via qemu isa debug device should not be the only way.
2024-11-23 14:08:38 +00:00
let exit_code = if initproc.status().exit_code() == 0 {
2024-08-19 11:15:22 +00:00
QemuExitCode::Success
} else {
QemuExitCode::Failed
};
exit_qemu(exit_code);
}
fn print_banner() {
println!("\x1B[36m");
println!(
r"
_ ___ _____ ___ ___ ___ _ _ _ ___
/_\ / __|_ _| __| _ \_ _| \| | /_\ / __|
/ _ \\__ \ | | | _|| /| || .` |/ _ \\__ \
/_/ \_\___/ |_| |___|_|_\___|_|\_/_/ \_\___/
"
);
println!("\x1B[0m");
}