186 lines
4.8 KiB
Rust
186 lines
4.8 KiB
Rust
#![feature(abi_x86_interrupt)]
|
|
#![allow(clippy::needless_return)]
|
|
#![no_std]
|
|
#![no_main]
|
|
|
|
mod arch;
|
|
mod boot;
|
|
mod debug;
|
|
mod format;
|
|
mod memory;
|
|
mod platform;
|
|
mod syscall;
|
|
mod task;
|
|
|
|
use core::arch::global_asm;
|
|
|
|
use crate::{
|
|
debug::serial,
|
|
memory::{AddressSpace, KernelStackPool, MemoryRegionKind, UserStack},
|
|
task::tcb::Tcb,
|
|
};
|
|
|
|
pub struct KernelHandoff {
|
|
allocator: memory::FrameAllocator,
|
|
address_space: AddressSpace,
|
|
direct_map: memory::DirectMap,
|
|
boot_info: boot::BootInfo,
|
|
kernel_stack_pool: KernelStackPool,
|
|
handoff_frame: memory::OwnedFrame,
|
|
}
|
|
|
|
const _: () = assert!(core::mem::size_of::<KernelHandoff>() <= memory::FRAME_SIZE);
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub extern "C" fn _start() -> ! {
|
|
serial::init().unwrap();
|
|
|
|
let arch_state = arch::init();
|
|
let boot_info = boot::load_boot_info().unwrap();
|
|
let direct_map = memory::DirectMap::new(boot_info.hhdm_offset);
|
|
|
|
let mut allocator = memory::FrameAllocator::new(boot_info.memory_regions(), direct_map)
|
|
.expect("failed to create frame allocator");
|
|
|
|
println!("Initializing page table...");
|
|
let mut address_space = AddressSpace::new_kernel(
|
|
direct_map,
|
|
boot_info.memory_regions(),
|
|
&boot_info.kernel_layout,
|
|
arch_state.paging,
|
|
&mut allocator,
|
|
)
|
|
.expect("failed to create page table");
|
|
|
|
println!("Entering kernel main...");
|
|
|
|
let mut kernel_stack_pool = KernelStackPool::new();
|
|
|
|
let kernel_stack = kernel_stack_pool
|
|
.allocate(&mut address_space, &mut allocator)
|
|
.expect("failed to allocate bootstrap stack");
|
|
|
|
let handoff_frame = allocator
|
|
.alloc()
|
|
.expect("failed to allocate frame for kernel handoff");
|
|
let handoff_addr = address_space
|
|
.to_virtual(handoff_frame.frame_address().start_address())
|
|
.expect("failed to map kernel handoff");
|
|
|
|
let bootstrap_stack_top = kernel_stack.top();
|
|
let handoff = KernelHandoff {
|
|
allocator,
|
|
address_space,
|
|
direct_map,
|
|
boot_info,
|
|
kernel_stack_pool,
|
|
handoff_frame,
|
|
};
|
|
|
|
unsafe {
|
|
handoff_addr.as_mut_ptr::<KernelHandoff>().write(handoff);
|
|
(*handoff_addr.as_mut_ptr::<KernelHandoff>())
|
|
.address_space
|
|
.activate();
|
|
|
|
arch::enter_kernel(
|
|
bootstrap_stack_top,
|
|
handoff_addr.as_mut_ptr::<KernelHandoff>(),
|
|
);
|
|
}
|
|
}
|
|
|
|
pub unsafe extern "C" fn kernel_main(handoff: *mut KernelHandoff) -> ! {
|
|
let (
|
|
mut allocator,
|
|
mut address_space,
|
|
direct_map,
|
|
boot_info,
|
|
mut kernel_stack_pool,
|
|
handoff_frame,
|
|
) = unsafe {
|
|
let handoff = handoff.read();
|
|
(
|
|
handoff.allocator,
|
|
handoff.address_space,
|
|
handoff.direct_map,
|
|
handoff.boot_info,
|
|
handoff.kernel_stack_pool,
|
|
handoff.handoff_frame,
|
|
)
|
|
};
|
|
|
|
unsafe {
|
|
allocator.dealloc(handoff_frame);
|
|
}
|
|
|
|
allocator.reclaim_regions(
|
|
boot_info.memory_regions(),
|
|
MemoryRegionKind::BootloaderReclaimable,
|
|
);
|
|
|
|
let init_code = format::cpio::find_file(boot_info.initramfs.data(), "init.elf")
|
|
.expect("Failed to load init program from initramfs");
|
|
|
|
println!("Initializing local ACPI...",);
|
|
|
|
let acpi = platform::acpi::init(&boot_info, direct_map).expect("failed to initialize ACPI");
|
|
|
|
println!("Parsing MADT...");
|
|
|
|
let madt = acpi
|
|
.madt()
|
|
.expect("failed to parse ACPI")
|
|
.expect("MADT not found");
|
|
|
|
println!("Initializing interrupt controller...");
|
|
|
|
let interrupt_controller =
|
|
arch::init_interrupt_controller(&madt, &mut allocator, &mut address_space)
|
|
.expect("failed to initialize interrupt controller");
|
|
|
|
let user_kernel_stack = kernel_stack_pool
|
|
.allocate(&mut address_space, &mut allocator)
|
|
.expect("failed to allocate task kernel stack");
|
|
|
|
let mut user_address_space = address_space
|
|
.new_user(&mut allocator)
|
|
.expect("failed to create user address space");
|
|
|
|
let image = task::loader::load_elf(
|
|
init_code,
|
|
&mut user_address_space,
|
|
&mut allocator,
|
|
direct_map,
|
|
);
|
|
|
|
let user_stack = UserStack::allocate(&mut user_address_space, &mut allocator)
|
|
.expect("failed to allocate user stack");
|
|
let task = Tcb::new_user(
|
|
0, // overwritten by add_task for now
|
|
user_address_space,
|
|
user_kernel_stack,
|
|
image.expect("Failed to load elf"),
|
|
user_stack.top(),
|
|
);
|
|
|
|
task::scheduler::add_task(task).expect("scheduler is full");
|
|
task::scheduler::start();
|
|
|
|
hcf();
|
|
}
|
|
|
|
#[panic_handler]
|
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
|
println!("Uh oh, something went wrong!");
|
|
println!("{}", info);
|
|
|
|
hcf();
|
|
}
|
|
|
|
pub fn hcf() -> ! {
|
|
loop {
|
|
arch::halt();
|
|
}
|
|
}
|