187 lines
4.2 KiB
Rust
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();
|
|
}
|
|
}
|