diff --git a/Cargo.lock b/Cargo.lock index 471917a..568f700 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -580,14 +580,18 @@ dependencies = [ [[package]] name = "kernel" -version = "0.1.2" +version = "0.2.0" dependencies = [ "crossbeam-queue", + "limine", "linked_list_allocator", "log", "slab", "spin 0.9.4", + "tracing", + "uart_16550", "versioning", + "x86_64", ] [[package]] diff --git a/ableos/json_targets/x86_64-ableos.json b/ableos/json_targets/x86_64-ableos.json index e400195..cd32752 100644 --- a/ableos/json_targets/x86_64-ableos.json +++ b/ableos/json_targets/x86_64-ableos.json @@ -16,7 +16,7 @@ "pre-link-args": { "ld.lld": [ "--gc-sections", - "--script=ableos/src/arch/x86_64/kernel.ld" + "--script=kernel/lds/x86_64.ld" ] } } \ No newline at end of file diff --git a/kernel/.cargo/config.toml b/kernel/.cargo/config.toml index 0277493..e8fc403 100644 --- a/kernel/.cargo/config.toml +++ b/kernel/.cargo/config.toml @@ -1,2 +1,9 @@ +[unstable] +build-std = ["core", "compiler_builtins", "alloc"] +build-std-features = ["compiler-builtins-mem"] + [build] -target = "./json_targets/x86_64-ableos.json" +target = "./targets/x86_64-ableos.json" + +[target.'cfg(target_arch = "x86_64")'] +rustflags = ["-C", "target-feature=+rdrand"] \ No newline at end of file diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 7d56e3d..36458c5 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -1,18 +1,22 @@ [package] edition = "2021" name = "kernel" -version = "0.1.2" +version = "0.2.0" [dependencies] linked_list_allocator = "0.9" log = "0.4.14" slab = { version = "0.4", default-features = false } spin = "0.9" +versioning = { git = "https://git.ablecorp.us/able/aos_userland" } +tracing = { version = "0.1.37", default-features = false, features = ["attributes"] } [dependencies.crossbeam-queue] version = "0.3" default-features = false features = ["alloc"] -[dependencies.versioning] -git = "https://git.ablecorp.us/able/aos_userland" +[target.'cfg(target_arch = "x86_64")'.dependencies] +limine = "0.1" +uart_16550 = "0.2" +x86_64 = "0.14" diff --git a/ableos/src/arch/x86_64/kernel.ld b/kernel/lds/x86_64.ld similarity index 93% rename from ableos/src/arch/x86_64/kernel.ld rename to kernel/lds/x86_64.ld index a3af617..499b8fc 100644 --- a/ableos/src/arch/x86_64/kernel.ld +++ b/kernel/lds/x86_64.ld @@ -2,8 +2,7 @@ OUTPUT_FORMAT(elf64-x86-64) OUTPUT_ARCH(i386:x86-64) -/* We want the symbol `x86_64_start` to be our entry point */ -ENTRY(x86_64_start) +ENTRY(_kernel_start) /* Define the program headers we want so the bootloader gives us the right */ /* MMU permissions */ diff --git a/kernel/src/allocator.rs b/kernel/src/allocator.rs index 3c98c5d..a4d48cc 100644 --- a/kernel/src/allocator.rs +++ b/kernel/src/allocator.rs @@ -1,6 +1,5 @@ //! Memory allocator -use linked_list_allocator::LockedHeap; use log::trace; /// @@ -15,10 +14,6 @@ pub const HEAP_BASE: usize = 100; /// pub const HEAP_SIZE: usize = HEAP_BASE * HEAP_MULTIPLIER; -/// Global allocator -#[global_allocator] -pub static ALLOCATOR: LockedHeap = LockedHeap::empty(); - #[alloc_error_handler] fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! { trace!("allocation error: {:?}", layout); diff --git a/kernel/src/arch/mod.rs b/kernel/src/arch/mod.rs index 649461a..60d76d5 100644 --- a/kernel/src/arch/mod.rs +++ b/kernel/src/arch/mod.rs @@ -5,7 +5,7 @@ macro_rules! arch_cond { #[cfg(target_arch = $str)] pub mod $arch; #[cfg(target_arch = $str)] - pub use $arch::*; + pub use ::$arch::*; )*}; } diff --git a/kernel/src/arch/x86_64/allocator.rs b/kernel/src/arch/x86_64/allocator.rs new file mode 100644 index 0000000..2f77f39 --- /dev/null +++ b/kernel/src/arch/x86_64/allocator.rs @@ -0,0 +1,48 @@ +use linked_list_allocator::LockedHeap; +use x86_64::{ + structures::paging::{ + mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB, + }, + VirtAddr, +}; + +use crate::allocator::{HEAP_SIZE, HEAP_START}; + +#[global_allocator] +static ALLOCATOR: LockedHeap = LockedHeap::empty(); + +pub unsafe fn init_alloc() -> Result<(), MapToError> { + let page_range = { + let heap_start = VirtAddr::new(HEAP_START as u64); + let heap_end = heap_start + HEAP_SIZE - 1u64; + let heap_start_page = Page::containing_address(heap_start); + let heap_end_page = Page::containing_address(heap_end); + Page::range_inclusive(heap_start_page, heap_end_page) + }; + + let mut frame_allocator = super::memory::FRAME_ALLOC + .get() + .expect("frame allocator is not initialised") + .lock(); + + let mut mapper = super::memory::PAGE_TABLE + .get() + .expect("page table is not initialised") + .lock(); + + for page in page_range { + let frame = frame_allocator + .allocate_frame() + .ok_or(MapToError::FrameAllocationFailed)?; + let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; + mapper + .map_to(page, frame, flags, &mut *frame_allocator)? + .flush(); + } + + ALLOCATOR + .lock() + .init(crate::allocator::HEAP_START, crate::allocator::HEAP_SIZE); + + Ok(()) +} diff --git a/kernel/src/arch/x86_64/memory.rs b/kernel/src/arch/x86_64/memory.rs new file mode 100644 index 0000000..866bbde --- /dev/null +++ b/kernel/src/arch/x86_64/memory.rs @@ -0,0 +1,64 @@ +use limine::{LimineMemmapEntry, LimineMemoryMapEntryType}; +use spin::{Mutex, Once}; +use x86_64::{ + structures::paging::{FrameAllocator, FrameDeallocator, OffsetPageTable, PhysFrame, Size4KiB}, + PhysAddr, VirtAddr, +}; + +pub static PAGE_TABLE: Once> = Once::new(); +pub static FRAME_ALLOC: Once> = Once::new(); + +/// Initialise page table +pub unsafe fn init_pt(phys_base: VirtAddr) { + PAGE_TABLE.call_once(|| { + Mutex::new(OffsetPageTable::new( + &mut *((phys_base + + x86_64::registers::control::Cr3::read() + .0 + .start_address() + .as_u64()) + .as_mut_ptr()), + phys_base, + )) + }); +} + +/// Initialise page frame allocator +pub unsafe fn init_falloc(mmap: &'static [LimineMemmapEntry]) { + FRAME_ALLOC.call_once(|| Mutex::new(FrameAlloc::new(mmap))); +} + +pub struct FrameAlloc { + mmap: &'static [LimineMemmapEntry], + next: usize, +} + +impl FrameAlloc { + pub unsafe fn new(mmap: &'static [LimineMemmapEntry]) -> Self { + Self { mmap, next: 0 } + } + + fn usable_frames(&self) -> impl Iterator { + self.mmap + .iter() + .filter(|e| e.typ == LimineMemoryMapEntryType::Usable) + .map(|e| e.base..e.base + e.len) + .flat_map(|r| r.step_by(4096)) + .map(PhysAddr::new) + .map(PhysFrame::containing_address) + } +} + +unsafe impl FrameAllocator for FrameAlloc { + fn allocate_frame(&mut self) -> Option> { + let f = self.usable_frames().nth(self.next); + self.next += 1; + f + } +} + +impl FrameDeallocator for FrameAlloc { + unsafe fn deallocate_frame(&mut self, frame: PhysFrame) { + // TODO + } +} diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index cfeed09..c4e7f77 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -1 +1,39 @@ -//! \ No newline at end of file +use limine::{LimineHhdmRequest, LimineMmapRequest}; +use x86_64::VirtAddr; + +mod allocator; +mod memory; + +#[no_mangle] +unsafe extern "C" fn _kernel_start() -> ! { + static HDHM_REQ: LimineHhdmRequest = LimineHhdmRequest::new(0); + static MMAP_REQ: LimineMmapRequest = LimineMmapRequest::new(0); + + memory::init_pt(VirtAddr::new( + HDHM_REQ + .get_response() + .get() + .expect("tried to get physical memory mapping offset from Limine") + .offset, + )); + + memory::init_falloc( + MMAP_REQ + .get_response() + .get() + .and_then(limine::LimineMemmapResponse::mmap) + .expect("tried to get memory map from Limine"), + ); + + allocator::init_alloc().expect("tried to initialise allocator"); + + unsafe { + use uart_16550::SerialPort; + use core::fmt::Write; + let mut sp = SerialPort::new(0x3F8); + sp.init(); + sp.write_str("Hello from AbleOS x86_64 entrypoint!"); + } + + crate::kmain::kmain() +} diff --git a/kernel/src/kmain.rs b/kernel/src/kmain.rs new file mode 100644 index 0000000..577589a --- /dev/null +++ b/kernel/src/kmain.rs @@ -0,0 +1,5 @@ +//! AbleOS Kernel Entrypoint + +pub fn kmain() -> ! { + loop {} +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index d783ab5..8a4a0df 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -2,12 +2,12 @@ #![feature(alloc_error_handler, prelude_import)] #![no_std] -#![deny(missing_docs)] extern crate alloc; pub mod allocator; pub mod arch; +pub mod kmain; pub mod task; use versioning::Version; @@ -15,6 +15,11 @@ use versioning::Version; /// Kernel's version pub const KERNEL_VERSION: Version = Version { major: 0, - minor: 1, - patch: 2, + minor: 2, + patch: 0, }; + +#[panic_handler] +fn panic(info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/kernel/src/main.rs b/kernel/src/main.rs new file mode 100644 index 0000000..973e301 --- /dev/null +++ b/kernel/src/main.rs @@ -0,0 +1,4 @@ +#![no_std] +#![no_main] + +extern crate kernel; diff --git a/kernel/targets/x86_64-ableos.json b/kernel/targets/x86_64-ableos.json new file mode 100644 index 0000000..cd32752 --- /dev/null +++ b/kernel/targets/x86_64-ableos.json @@ -0,0 +1,22 @@ +{ + "llvm-target": "x86_64-unknown-none", + "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", + "arch": "x86_64", + "target-endian": "little", + "target-pointer-width": "64", + "target-c-int-width": "32", + "os": "none", + "executables": true, + "linker-flavor": "ld.lld", + "linker": "rust-lld", + "panic-strategy": "abort", + "disable-redzone": true, + "features": "-mmx,-sse,+soft-float", + "code-model": "kernel", + "pre-link-args": { + "ld.lld": [ + "--gc-sections", + "--script=kernel/lds/x86_64.ld" + ] + } +} \ No newline at end of file diff --git a/repbuild/src/main.rs b/repbuild/src/main.rs index 323d9cc..f376e5a 100644 --- a/repbuild/src/main.rs +++ b/repbuild/src/main.rs @@ -76,7 +76,7 @@ fn main() -> Result<(), Box> { // Build ableOS in release mode Command::new("cargo") .args(["build", "--release"]) - .current_dir(fs::canonicalize("./ableos").unwrap()) + .current_dir(fs::canonicalize("./kernel").unwrap()) .status() .unwrap(); @@ -167,7 +167,7 @@ fn main() -> Result<(), Box> { // copy the kernel over to ./disk/boot/kernel Command::new("cp") - .arg("./target/x86_64-ableos/release/ableos") + .arg("./target/x86_64-ableos/release/kernel") .arg(&format!("{mountpoint}/boot/kernel")) .status()?; @@ -254,7 +254,7 @@ fn main() -> Result<(), Box> { // Build ableOS Command::new("cargo") .arg("build") - .current_dir(fs::canonicalize("./ableos").unwrap()) + .current_dir(fs::canonicalize("./kernel").unwrap()) .status() .unwrap(); @@ -294,7 +294,7 @@ fn main() -> Result<(), Box> { // copy the kernel over to ./disk/boot/kernel Command::new("cp") - .arg("./target/x86_64-ableos/debug/ableos") + .arg("./target/x86_64-ableos/debug/kernel") .arg(format!("{mountpoint}/boot/kernel")) .status() .unwrap(); @@ -333,7 +333,7 @@ fn main() -> Result<(), Box> { // Build ableOS Command::new("cargo") .args(["build", "--release"]) - .current_dir(fs::canonicalize("./ableos").unwrap()) + .current_dir(fs::canonicalize("./kernel").unwrap()) .status() .unwrap(); @@ -372,7 +372,7 @@ fn main() -> Result<(), Box> { // copy the kernel over to ./disk/boot/kernel Command::new("cp") - .arg("./target/x86_64-ableos/release/ableos") + .arg("./target/x86_64-ableos/release/kernel") .arg(format!("{mountpoint}/boot/kernel")) .status() .unwrap();