From 23c355762c6b617e11f7e3c6009fa4dca17f4e79 Mon Sep 17 00:00:00 2001 From: TheOddGarlic Date: Sat, 20 Aug 2022 09:27:37 +0300 Subject: [PATCH] progress on porting to limine --- Cargo.lock | 14 ++--- ableos/Cargo.toml | 2 +- ableos/json_targets/x86_64-ableos.json | 9 +++- ableos/src/arch/x86_64/init.rs | 16 ++++-- ableos/src/arch/x86_64/kernel.ld | 48 +++++++++++++++++ ableos/src/arch/x86_64/memory.rs | 74 ++++---------------------- ableos/src/arch/x86_64/mod.rs | 27 +++++----- ableos/src/scratchpad.rs | 12 ++++- kernel/src/allocator.rs | 5 +- 9 files changed, 111 insertions(+), 96 deletions(-) create mode 100644 ableos/src/arch/x86_64/kernel.ld diff --git a/Cargo.lock b/Cargo.lock index 3a0df9f9..6a231610 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,7 +30,6 @@ dependencies = [ "acpi", "axel", "bitflags", - "bootloader", "clparse", "cpuio", "ext2", @@ -41,6 +40,7 @@ dependencies = [ "kernel", "lazy_static", "libwasm", + "limine", "linked_list_allocator", "lliw", "log", @@ -150,12 +150,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bootloader" -version = "0.9.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de78decc37247c7cfac5dbf3495c7298c6ac97cb355161caa7e15969c6648e6c" - [[package]] name = "cfg-if" version = "1.0.0" @@ -348,6 +342,12 @@ name = "libwasm" version = "0.1.0" source = "git+https://git.ablecorp.us/able/libwasm.git#4ffcd290f8bc918ca4adf5e23ce2097968e4a8b2" +[[package]] +name = "limine" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac64618e505bab2387986e5b1014f5d344130d609685bbd8b71a10af3ee599d" + [[package]] name = "linked_list_allocator" version = "0.9.1" diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml index 95362377..48ffc681 100644 --- a/ableos/Cargo.toml +++ b/ableos/Cargo.toml @@ -108,7 +108,7 @@ git = "https://git.ablecorp.us:443/able/externc-libm.git" riscv = "*" [target.'cfg(target_arch = "x86_64")'.dependencies] -bootloader = { version = "0.9.8", features = ["map_physical_memory"] } +limine = "0.1" cpuio = { git = "https://git.ablecorp.us/ondra05/cpuio.git" } pic8259 = "0.10.1" uart_16550 = "0.2.0" diff --git a/ableos/json_targets/x86_64-ableos.json b/ableos/json_targets/x86_64-ableos.json index 346fefdc..e4001958 100644 --- a/ableos/json_targets/x86_64-ableos.json +++ b/ableos/json_targets/x86_64-ableos.json @@ -11,5 +11,12 @@ "linker": "rust-lld", "panic-strategy": "abort", "disable-redzone": true, - "features": "-mmx,-sse,+soft-float" + "features": "-mmx,-sse,+soft-float", + "code-model": "kernel", + "pre-link-args": { + "ld.lld": [ + "--gc-sections", + "--script=ableos/src/arch/x86_64/kernel.ld" + ] + } } \ No newline at end of file diff --git a/ableos/src/arch/x86_64/init.rs b/ableos/src/arch/x86_64/init.rs index 88344bcd..d607d788 100644 --- a/ableos/src/arch/x86_64/init.rs +++ b/ableos/src/arch/x86_64/init.rs @@ -17,15 +17,21 @@ pub fn init() { Err(err) => serial_println!("{}", err), } - let mut term = TERM.lock(); + trace!("gdt"); + gdt::init(); + + trace!("idt"); + interrupts::init_idt(); + unsafe { interrupts::PICS.lock().initialize() }; + + trace!("term"); + let term = &*TERM; + trace!("term.lock()"); + let mut term = term.lock(); // term.initialize(); term.set_dirty(true); term.draw_term(); drop(term); - gdt::init(); - - interrupts::init_idt(); - unsafe { interrupts::PICS.lock().initialize() }; x86_64::instructions::interrupts::enable(); } diff --git a/ableos/src/arch/x86_64/kernel.ld b/ableos/src/arch/x86_64/kernel.ld new file mode 100644 index 00000000..a3af6170 --- /dev/null +++ b/ableos/src/arch/x86_64/kernel.ld @@ -0,0 +1,48 @@ +/* Tell the linker that we want an x86_64 ELF64 output file */ +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) + +/* Define the program headers we want so the bootloader gives us the right */ +/* MMU permissions */ +PHDRS +{ + null PT_NULL FLAGS(0) ; /* Null segment */ + text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */ + rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */ + data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */ +} + +SECTIONS +{ + /* We wanna be placed in the topmost 2GiB of the address space, for optimisations */ + /* and because that is what the Limine spec mandates. */ + /* Any address in this region will do, but often 0xffffffff80000000 is chosen as */ + /* that is the beginning of the region. */ + . = 0xffffffff80000000; + + .text : { + *(.text .text.*) + } :text + + /* Move to the next memory page for .rodata */ + . += CONSTANT(MAXPAGESIZE); + + .rodata : { + *(.rodata .rodata.*) + } :rodata + + /* Move to the next memory page for .data */ + . += CONSTANT(MAXPAGESIZE); + + .data : { + *(.data .data.*) + } :data + + .bss : { + *(COMMON) + *(.bss .bss.*) + } :data +} diff --git a/ableos/src/arch/x86_64/memory.rs b/ableos/src/arch/x86_64/memory.rs index df43bb38..c349404d 100644 --- a/ableos/src/arch/x86_64/memory.rs +++ b/ableos/src/arch/x86_64/memory.rs @@ -1,7 +1,7 @@ -use bootloader::bootinfo::{MemoryMap, MemoryRegionType}; +use limine::{LimineMemmapResponse, LimineMemoryMapEntryType}; use x86_64::{ structures::paging::{ - FrameAllocator, FrameDeallocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, + FrameAllocator, FrameDeallocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB, }, PhysAddr, VirtAddr, @@ -25,69 +25,13 @@ unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut &mut *page_table_ptr } -fn translate_addr_inner(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option { - use x86_64::registers::control::Cr3; - use x86_64::structures::paging::page_table::FrameError; - - let (level_4_table_frame, _) = Cr3::read(); - - let table_indexes = [ - addr.p4_index(), - addr.p3_index(), - addr.p2_index(), - addr.p1_index(), - ]; - let mut frame = level_4_table_frame; - - for &index in &table_indexes { - // convert the frame into a page table reference - let virt = physical_memory_offset + frame.start_address().as_u64(); - let table_ptr: *const PageTable = virt.as_ptr(); - let table = unsafe { &*table_ptr }; - - let entry = &table[index]; - frame = match entry.frame() { - Ok(frame) => frame, - Err(FrameError::FrameNotPresent) => return None, - Err(FrameError::HugeFrame) => panic!["huge pages not supported"], - }; - } - - Some(frame.start_address() + u64::from(addr.page_offset())) -} - -pub unsafe fn translate_addr(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option { - translate_addr_inner(addr, physical_memory_offset) -} - -pub fn create_example_mapping( - page: Page, - mapper: &mut OffsetPageTable, - frame_allocator: &mut impl FrameAllocator, -) { - use x86_64::structures::paging::PageTableFlags as Flags; - - let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); - let flags = Flags::PRESENT | Flags::WRITABLE; - - let map_to_result = unsafe { mapper.map_to(page, frame, flags, frame_allocator) }; - map_to_result.expect("map_to failed").flush(); -} - -pub struct EmptyFrameAllocator; -unsafe impl FrameAllocator for EmptyFrameAllocator { - fn allocate_frame(&mut self) -> Option> { - None - } -} - pub struct BootInfoFrameAllocator { - memory_map: &'static MemoryMap, + memory_map: &'static LimineMemmapResponse, next: usize, } impl BootInfoFrameAllocator { - pub unsafe fn init(memory_map: &'static MemoryMap) -> Self { + pub unsafe fn init(memory_map: &'static LimineMemmapResponse) -> Self { Self { memory_map, next: 0, @@ -95,11 +39,11 @@ impl BootInfoFrameAllocator { } fn usable_frames(&self) -> impl Iterator { - let regions = self.memory_map.iter(); - let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable); - let addr_range = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr()); - let frame_address = addr_range.flat_map(|r| r.step_by(4096)); - frame_address.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))) + self.memory_map.mmap().unwrap().iter() + .filter(|r| r.typ == LimineMemoryMapEntryType::Usable) + .map(|r| r.base..r.base + r.len) + .flat_map(|r| r.step_by(4096)) + .map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))) } } diff --git a/ableos/src/arch/x86_64/mod.rs b/ableos/src/arch/x86_64/mod.rs index cabb6bbe..b88e0e31 100644 --- a/ableos/src/arch/x86_64/mod.rs +++ b/ableos/src/arch/x86_64/mod.rs @@ -10,27 +10,24 @@ pub mod init; pub mod interrupts; pub mod memory; -use crate::arch::drivers::allocator; -use bootloader::{entry_point, BootInfo}; +use limine::*; use x86_64::{instructions::hlt, VirtAddr}; -#[cfg(not(test))] -entry_point![start]; +use crate::serial_println; + +use self::drivers::allocator; + +static HHDM: LimineHhdmRequest = LimineHhdmRequest::new(0); +static MMAP: LimineMmapRequest = LimineMmapRequest::new(0); -#[cfg(not(test))] #[no_mangle] -pub fn start(boot_info: &'static BootInfo) -> ! { - let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); +pub fn x86_64_start() -> ! { + let hhdm = HHDM.get_response().get().unwrap(); + let mmap = MMAP.get_response().get().unwrap(); + let phys_mem_offset = VirtAddr::new(hhdm.offset); let mut mapper = unsafe { memory::init(phys_mem_offset) }; - let mut frame_allocator = - unsafe { memory::BootInfoFrameAllocator::init(&boot_info.memory_map) }; - - // let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000)); - // memory::create_example_mapping(page, &mut mapper, &mut frame_allocator); - // - // let page_ptr: *mut u64 = page.start_address().as_mut_ptr(); - // unsafe { page_ptr.offset(400).write_volatile(0xf021_f077_f065_804e) }; + let mut frame_allocator = unsafe { memory::BootInfoFrameAllocator::init(mmap) }; allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed"); diff --git a/ableos/src/scratchpad.rs b/ableos/src/scratchpad.rs index dbe877a5..a6d64311 100644 --- a/ableos/src/scratchpad.rs +++ b/ableos/src/scratchpad.rs @@ -43,7 +43,17 @@ impl acpi::AcpiHandler for AcpiStruct { } } -pub static TERM: Lazy> = Lazy::new(|| spin::Mutex::new(VTerm::new())); +pub static TERM: Lazy> = Lazy::new(|| { + trace!("mutex"); + let mutex = spin::Mutex::new({ + trace!("vterm"); + let vterm = VTerm::new(); + trace!("vterm-done"); + vterm + }); + trace!("mutex-done"); + mutex +}); #[derive(Debug)] pub struct Path { diff --git a/kernel/src/allocator.rs b/kernel/src/allocator.rs index 3c177d48..3c98c5d4 100644 --- a/kernel/src/allocator.rs +++ b/kernel/src/allocator.rs @@ -1,6 +1,7 @@ //! Memory allocator use linked_list_allocator::LockedHeap; +use log::trace; /// pub const HEAP_START: usize = 0x_4444_4444_0000; @@ -20,5 +21,7 @@ pub static ALLOCATOR: LockedHeap = LockedHeap::empty(); #[alloc_error_handler] fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! { - panic!("allocation error: {:?}", layout) + trace!("allocation error: {:?}", layout); + loop {} + // panic!("allocation error: {:?}", layout) }