| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- #![no_std]
- #![no_main]
- #![feature(c_size_t)]
- #![feature(concat_idents)]
- #![feature(arbitrary_self_types)]
- #![feature(get_mut_unchecked)]
- #![feature(macro_metavar_expr)]
- extern crate alloc;
- mod driver;
- mod elf;
- mod fs;
- mod hash;
- mod io;
- mod kernel;
- mod kernel_init;
- mod net;
- mod path;
- mod prelude;
- mod rcu;
- mod sync;
- use alloc::{ffi::CString, sync::Arc};
- use core::{
- hint::spin_loop,
- sync::atomic::{AtomicBool, Ordering},
- };
- use elf::ParsedElf32;
- use eonix_hal::{processor::CPU, trap::disable_irqs_save};
- use eonix_mm::address::PRange;
- use eonix_runtime::{run::FutureRun, scheduler::Scheduler, task::Task};
- use kernel::{
- mem::GlobalPageAlloc,
- task::{new_thread_runnable, KernelStack, ProcessBuilder, ProcessList, ThreadBuilder},
- vfs::{
- dentry::Dentry,
- mount::{do_mount, MS_NOATIME, MS_NODEV, MS_NOSUID, MS_RDONLY},
- FsContext,
- },
- CharDevice,
- };
- use kernel_init::setup_memory;
- use path::Path;
- use prelude::*;
- #[panic_handler]
- fn panic(info: &core::panic::PanicInfo) -> ! {
- if let Some(location) = info.location() {
- println_fatal!(
- "panicked at {}:{}:{}",
- location.file(),
- location.line(),
- location.column()
- );
- } else {
- println_fatal!("panicked at <UNKNOWN>");
- }
- println_fatal!();
- println_fatal!("{}", info.message());
- loop {}
- }
- static BSP_OK: AtomicBool = AtomicBool::new(false);
- #[eonix_hal::main]
- fn kernel_init(mut data: eonix_hal::bootstrap::BootStrapData) -> ! {
- setup_memory(&mut data);
- BSP_OK.store(true, Ordering::Release);
- #[cfg(target_arch = "riscv64")]
- {
- driver::sbi_console::init_console();
- }
- kernel::pcie::init_pcie().expect("Unable to initialize PCIe bus");
- // To satisfy the `Scheduler` "preempt count == 0" assertion.
- eonix_preempt::disable();
- // We need root dentry to be present in constructor of `FsContext`.
- // So call `init_vfs` first, then `init_multitasking`.
- Scheduler::init_local_scheduler::<KernelStack>();
- Scheduler::get().spawn::<KernelStack, _>(FutureRun::new(init_process(data.get_early_stack())));
- drop(data);
- unsafe {
- // SAFETY: `preempt::count()` == 1.
- Scheduler::goto_scheduler_noreturn()
- }
- }
- #[eonix_hal::ap_main]
- fn kernel_ap_main(_stack_range: PRange) -> ! {
- while BSP_OK.load(Ordering::Acquire) == false {
- // Wait for BSP to finish initializing.
- spin_loop();
- }
- Scheduler::init_local_scheduler::<KernelStack>();
- println_debug!("AP{} started", CPU::local().cpuid());
- eonix_preempt::disable();
- // TODO!!!!!: Free the stack after having switched to idle task.
- unsafe {
- // SAFETY: `preempt::count()` == 1.
- Scheduler::goto_scheduler_noreturn()
- }
- }
- async fn init_process(early_kstack: PRange) {
- unsafe {
- let irq_ctx = disable_irqs_save();
- // SAFETY: IRQ is disabled.
- GlobalPageAlloc::add_pages(early_kstack);
- irq_ctx.restore();
- }
- CharDevice::init().unwrap();
- #[cfg(target_arch = "x86_64")]
- {
- // We might want the serial initialized as soon as possible.
- driver::serial::init().unwrap();
- driver::e1000e::register_e1000e_driver();
- driver::ahci::register_ahci_driver();
- }
- #[cfg(target_arch = "riscv64")]
- {
- driver::virtio::init_virtio_devices();
- driver::e1000e::register_e1000e_driver();
- driver::ahci::register_ahci_driver();
- }
- fs::tmpfs::init();
- fs::procfs::init();
- fs::fat32::init();
- let (ip, sp, mm_list) = {
- // mount fat32 /mnt directory
- let fs_context = FsContext::global();
- let mnt_dir = Dentry::open(fs_context, Path::new(b"/mnt/").unwrap(), true).unwrap();
- mnt_dir.mkdir(0o755).unwrap();
- do_mount(
- &mnt_dir,
- "/dev/sda",
- "/mnt",
- "fat32",
- MS_RDONLY | MS_NOATIME | MS_NODEV | MS_NOSUID,
- )
- .unwrap();
- let init = Dentry::open(fs_context, Path::new(b"/mnt/busybox").unwrap(), true)
- .expect("busybox should be present in /mnt");
- let argv = vec![
- CString::new("/mnt/busybox").unwrap(),
- CString::new("sh").unwrap(),
- CString::new("/mnt/initsh").unwrap(),
- ];
- let envp = vec![
- CString::new("LANG=C").unwrap(),
- CString::new("HOME=/root").unwrap(),
- CString::new("PATH=/mnt").unwrap(),
- CString::new("PWD=/").unwrap(),
- ];
- let elf = ParsedElf32::parse(init.clone()).unwrap();
- elf.load(argv, envp).unwrap()
- };
- let thread_builder = ThreadBuilder::new()
- .name(Arc::from(&b"busybox"[..]))
- .entry(ip, sp);
- let mut process_list = Task::block_on(ProcessList::get().write());
- let (thread, process) = ProcessBuilder::new()
- .mm_list(mm_list)
- .thread_builder(thread_builder)
- .build(&mut process_list);
- process_list.set_init_process(process);
- // TODO!!!: Remove this.
- thread.files.open_console();
- Scheduler::get().spawn::<KernelStack, _>(new_thread_runnable(thread));
- }
|