yggdrasil/kernel/src/main.rs

187 lines
4.2 KiB
Rust

//! osdev-x kernel crate
#![feature(
if_let_guard,
step_trait,
decl_macro,
naked_functions,
optimize_attribute,
const_trait_impl,
maybe_uninit_slice,
arbitrary_self_types,
let_chains,
linked_list_cursors,
rustc_private,
allocator_api,
trait_alias,
slice_ptr_get,
slice_split_once,
iter_collect_into,
iter_next_chunk,
exact_size_is_empty,
maybe_uninit_uninit_array,
never_type,
format_args_nl,
associated_type_defaults
)]
#![allow(
clippy::new_without_default,
clippy::fn_to_numeric_cast,
clippy::match_ref_pats,
clippy::match_single_binding,
clippy::missing_transmute_annotations,
clippy::modulo_one,
async_fn_in_trait
)]
#![deny(missing_docs)]
#![no_std]
#![no_main]
use abi::{error::Error, io::FileMode};
use alloc::string::String;
use arch::Platform;
use git_version::git_version;
use kernel_arch::{Architecture, ArchitectureImpl};
use libk::{
arch::Cpu,
debug,
fs::{
devfs,
sysfs::{
self,
attribute::{StringAttribute, StringAttributeOps},
},
},
};
use libk_util::sync::SpinFence;
use crate::{arch::PLATFORM, task::spawn_kernel_closure};
extern crate yggdrasil_abi as abi;
extern crate alloc;
#[cfg(not(rust_analyzer))]
extern crate compiler_builtins;
extern crate ygg_driver_ahci;
extern crate ygg_driver_net_rtl81xx;
extern crate ygg_driver_nvme;
extern crate ygg_driver_usb_xhci;
extern crate ygg_driver_virtio_gpu;
extern crate ygg_driver_virtio_net;
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
extern crate ygg_driver_net_igbe;
}
}
#[macro_use]
pub mod arch;
#[cfg(any(target_arch = "riscv64", rust_analyzer))]
extern crate ygg_driver_net_stmmac;
pub mod device;
pub mod fs;
pub mod init;
pub mod mem;
pub mod panic;
pub mod proc;
pub mod syscall;
pub mod task;
pub mod util;
static CPU_INIT_FENCE: SpinFence = SpinFence::new();
/// Common kernel main function for application processors
pub fn kernel_secondary_main() -> ! {
// Synchronize the CPUs to this point
CPU_INIT_FENCE.signal();
CPU_INIT_FENCE.wait_all(ArchitectureImpl::cpu_count());
unsafe {
task::enter();
}
}
fn register_sysfs_attributes() {
struct Version;
struct Arch;
impl StringAttributeOps for Version {
const NAME: &'static str = "version";
fn read(_state: &Self::Data) -> Result<String, Error> {
Ok(git_version!().into())
}
}
impl StringAttributeOps for Arch {
const NAME: &'static str = "arch";
fn read(_state: &Self::Data) -> Result<String, Error> {
Ok(util::arch_str().into())
}
}
let kernel = sysfs::kernel().unwrap();
let kernel_node = kernel.node();
kernel.add_attribute(StringAttribute::from(Version)).ok();
kernel.add_attribute(StringAttribute::from(Arch)).ok();
debug::add_kernel_log_file(kernel_node);
}
/// Common kernel main function. Must be called for BSP processor only.
///
/// # Prerequisites
///
/// Before the function can be called, the following preparations must be made:
///
/// * Virtual memory set up according to the architecture's memory map
/// * Physical memory
/// * Heap
/// * Basic debugging facilities
/// * Initrd
#[inline(never)]
pub fn kernel_main() -> ! {
log::info!(
"Yggdrasil v{} ({})",
env!("CARGO_PKG_VERSION"),
git_version!()
);
libk::panic::set_handler(panic::panic_handler);
unsafe {
PLATFORM.start_application_processors();
}
Cpu::init_ipi_queues(ArchitectureImpl::cpu_count());
// Setup the sysfs
register_sysfs_attributes();
fs::add_pseudo_devices().unwrap();
// Wait until all APs initialize
CPU_INIT_FENCE.signal();
CPU_INIT_FENCE.wait_all(ArchitectureImpl::cpu_count());
// Add keyboard device
if let Err(error) =
devfs::add_named_char_device(ygg_driver_input::setup(), "kbd", FileMode::new(0o660))
{
log::error!("Couldn't add keyboard device: {error:?}");
}
task::init().expect("Failed to initialize the scheduler");
spawn_kernel_closure("[kinit]", init::kinit).expect("Could not spawn [kinit]");
log::info!("All cpus ready");
unsafe {
task::enter();
}
}