diff --git a/kernel/src/arch/x86_64/apic/mod.rs b/kernel/src/arch/x86_64/apic/mod.rs index d4135aa..9199a09 100644 --- a/kernel/src/arch/x86_64/apic/mod.rs +++ b/kernel/src/arch/x86_64/apic/mod.rs @@ -1,5 +1,6 @@ use core::arch::x86_64::__cpuid; +use libk::drivers::memory::FoundryOSFrameAllocator; use spin::Lazy; use x86_64::{ PhysAddr, VirtAddr, @@ -12,10 +13,7 @@ use x86_64::{ use crate::serial_print; -use super::{ - cpu::model_specific_registers::*, memmap::PHYSICAL_MEMORY_OFFSET, - memory::FoundryOSFrameAllocator, -}; +use super::{cpu::model_specific_registers::*, memmap::PHYSICAL_MEMORY_OFFSET}; const IA32_APIC_BASE_MSR: u32 = 0x1b; const IA32_APIC_BASE_MSR_BSP: u64 = 0x100; diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index a324417..7476eb6 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -1,7 +1,10 @@ +use libk::drivers::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE}; use libk::prelude::*; use pic8259::ChainedPics; use x86_64::registers::control::Cr2; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode}; +use x86_64::structures::paging::mapper::MapperFlushAll; +use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB}; use spin::{Lazy, Mutex}; @@ -52,12 +55,19 @@ impl InterruptIndex { pub fn init_idt() { IDT.load(); - // enable_apic(); - // TODO: fix apic - // unsafe { - // PICS.lock().initialize(); - // PICS.lock().write_masks(0xfc, 0xff); - // } +} + +pub fn enable_pic() { + unsafe { + PICS.lock().initialize(); + PICS.lock().write_masks(0xfc, 0xff); + } +} + +pub fn disable_pic() { + unsafe { + PICS.lock().disable(); + } } extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) { @@ -118,10 +128,28 @@ extern "x86-interrupt" fn page_fault_handler( stack_frame: InterruptStackFrame, error_code: PageFaultErrorCode, ) { - serial_println!("Exception: Page Fault"); - serial_println!("Accessed Address: {:?}", Cr2::read()); - serial_println!("Error Code: {:?}", error_code); - serial_println!("{:#?}", stack_frame); + // serial_println!("Exception: Page Fault"); + // serial_println!("Accessed Address: {:?}", Cr2::read()); + // serial_println!("Error Code: {:?}", error_code); + // serial_println!("{:#?}", stack_frame); - panic!("page fault"); + if let Some(frame_allocator) = FRAME_ALLOCATOR.get() { + let mut f = frame_allocator.lock(); + + let frame = f.allocate_frame().unwrap(); + let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; + let page: Page = Page::containing_address(Cr2::read().unwrap()); + + unsafe { + let mut mapper = OFFSET_PAGE_TABLE.get().unwrap().lock(); + + match mapper.map_to(page, frame, flags, &mut *f) { + Ok(_) => {} + Err(why) => panic!("failed to map page: {:?}", why), + } + } + MapperFlushAll::new().flush_all(); + } else { + panic!("failed to get frame allocator"); + } } diff --git a/kernel/src/arch/x86_64/memmap.rs b/kernel/src/arch/x86_64/memmap.rs index 17362e1..1df8437 100644 --- a/kernel/src/arch/x86_64/memmap.rs +++ b/kernel/src/arch/x86_64/memmap.rs @@ -14,6 +14,10 @@ static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new(); #[unsafe(link_section = ".requests")] static HIGHER_HALF_DIRECT_MAP_REQUEST: HhdmRequest = HhdmRequest::new(); +#[used] +#[unsafe(link_section = ".requests")] +static KERNEL_ADDRESS_REQUEST: KernelAddressRequest = KernelAddressRequest::new(); + /// ```rs /// let virt_addr = phys_addr + offset; /// let phys_addr = virt_addr - offset; // (given VA is in the HHDM). Do not use for executable code. @@ -25,10 +29,6 @@ pub static PHYSICAL_MEMORY_OFFSET: Lazy = Lazy::new(|| { .offset() }); -#[used] -#[unsafe(link_section = ".requests")] -static KERNEL_ADDRESS_REQUEST: KernelAddressRequest = KernelAddressRequest::new(); - /// Converts virtual addresses in the kernel to a physical address like this: /// ```rs /// let phys_addr = virt_addr - virtual_base + physical_base; diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index bb3543c..7ffe935 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -2,8 +2,6 @@ pub mod gdt; pub mod interrupts; -pub mod memory; - pub mod memmap; pub mod apic; diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 8e22926..48d4c75 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -15,6 +15,7 @@ extern crate alloc; use arch::x86_64::apic::enable_apic; use core::arch::asm; +use libk::drivers::memory; use limine::BaseRevision; use libk::drivers::kalloc::allocator::init_heap; @@ -57,7 +58,7 @@ pub fn boot() -> Result<(), &'static str> { return Err("base revision not supported"); } - use arch::x86_64::{gdt, interrupts, memmap, memory}; + use arch::x86_64::{gdt, interrupts, memmap}; let memory_map = memmap::get_memory_map(); @@ -72,29 +73,37 @@ pub fn boot() -> Result<(), &'static str> { gdt::init(); println_log!("[Success]"); - print_log!(" Initialising Memory Subsystem... "); - let physical_memory_offset = VirtAddr::new(*memmap::PHYSICAL_MEMORY_OFFSET); - let mut l4_table = unsafe { memory::init(physical_memory_offset) }; - println_log!("[Success]"); - - print_log!(" Setting Up Page Table... "); - let mut frame_allocator = unsafe { memory::FoundryOSFrameAllocator::init(memory_map) }; - println_log!("[Success]"); - - print_log!(" Initialising Heap... "); - if init_heap(&mut l4_table, &mut frame_allocator).is_err() { - return Err("Failed to initialise heap: error"); - } - println_log!("[Success]"); - print_log!(" Setting Up Interrupt Descriptor Table... "); interrupts::init_idt(); println_log!("[Success]"); - print_log!(" Initialising APIC"); - enable_apic(&mut l4_table, &mut frame_allocator); + print_log!(" Initialising Memory Subsystem... "); + let physical_memory_offset = VirtAddr::new(*memmap::PHYSICAL_MEMORY_OFFSET); + let mut l4_table = memory::init_page_table(physical_memory_offset); println_log!("[Success]"); + print_log!(" Setting Up Page Table... "); + memory::init_frame_allocator(memory_map); + println_log!("[Success]"); + + print_log!(" Initialising Heap... "); + if init_heap().is_err() { + return Err("Failed to initialise heap: error"); + } + println_log!("[Success]"); + + print_log!(" Enabling PICs... "); + interrupts::enable_pic(); + println_log!("[Success]"); + + // print_log!(" Disabling PICs... "); + // interrupts::disable_pic(); + // println_log!("[Success]"); + // + // print_log!(" Initialising APIC"); + // enable_apic(&mut l4_table, &mut frame_allocator); + // println_log!("[Success]"); + print_log!(" Enabling Interrupts... "); x86_64::instructions::interrupts::enable(); println_log!("[Success]"); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 1eb77f5..ecb3ef4 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -28,6 +28,13 @@ extern "C" fn kmain() -> ! { println!("Dimensions: {}x{} (chars)", dimensions.0, dimensions.1); let mut executor = Executor::new(); + + let mut v = Vec::with_capacity(1000 * 1000); + for i in 0..1000 * 1000 { + v.push(i); + } + println!("v.len(): {}", v.len()); + executor.spawn(Task::new(shell())); executor.run(); } diff --git a/libk/src/drivers/kalloc/allocator.rs b/libk/src/drivers/kalloc/allocator.rs index 6e87949..5f8949b 100644 --- a/libk/src/drivers/kalloc/allocator.rs +++ b/libk/src/drivers/kalloc/allocator.rs @@ -2,10 +2,16 @@ use linked_list_allocator::LockedHeap; use x86_64::{ VirtAddr, structures::paging::{ - FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB, mapper::MapToError, + FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB, + mapper::{MapToError, MapperFlushAll}, }, }; +use crate::{ + drivers::memory::{FRAME_ALLOCATOR, OFFSET_PAGE_TABLE}, + serial_print, serial_println, +}; + /// We are currently using a linked list heap allocator which uses our underlying page allocator. pub type FoundryAllocator = LockedHeap; @@ -14,28 +20,50 @@ pub type FoundryAllocator = LockedHeap; static ALLOCATOR: FoundryAllocator = FoundryAllocator::empty(); pub const HEAP_START: usize = 0x4444_4444_0000; -pub const HEAP_SIZE: usize = 1000 * 1024; +pub const HEAP_SIZE: usize = 1024 * 1024 * 1024; /// Sets up the heap using the backing page frame allocator. -pub fn init_heap( - mapper: &mut impl Mapper, - frame_allocator: &mut impl FrameAllocator, -) -> Result<(), MapToError> { - let range = { - let heap_start = VirtAddr::new(HEAP_START as u64); - let heap_end = heap_start + HEAP_SIZE as u64 - 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) - }; +pub fn init_heap() -> Result<(), MapToError> { + // let mut frame_allocator = if let Some(f) = FRAME_ALLOCATOR.get() { + // f.lock() + // } else { + // return Err(MapToError::FrameAllocationFailed); + // }; - for page in range { - let frame = frame_allocator - .allocate_frame() - .ok_or(MapToError::FrameAllocationFailed)?; - let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; - unsafe { mapper.map_to(page, frame, flags, frame_allocator)?.flush() }; - } + // let mut mapper = if let Some(m) = OFFSET_PAGE_TABLE.get() { + // m.lock() + // } else { + // return Err(MapToError::FrameAllocationFailed); + // }; + + // let range = { + // let heap_start = VirtAddr::new(HEAP_START as u64); + // let heap_end = heap_start + HEAP_SIZE as u64 - 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 usable_frames = frame_allocator.count_usable_frames(); + // serial_println!("usable frames: {}", usable_frames); + + // let mut i = 0; + // for page in range { + // i += 1; + // if i % 128 == 0 { + // serial_println!("allocated {} pages", i); + // } + // let frame = frame_allocator + // .allocate_frame() + // .ok_or(MapToError::FrameAllocationFailed)?; + // let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; + // unsafe { + // // IMPORTANT: make sure to flush the mapper!!!! + // let _ = mapper.map_to(page, frame, flags, &mut *frame_allocator)?; + // } + // } + + // MapperFlushAll::new().flush_all(); unsafe { ALLOCATOR.lock().init(HEAP_START as *mut u8, HEAP_SIZE); diff --git a/kernel/src/arch/x86_64/memory.rs b/libk/src/drivers/memory.rs similarity index 87% rename from kernel/src/arch/x86_64/memory.rs rename to libk/src/drivers/memory.rs index fe44264..2e53a01 100644 --- a/kernel/src/arch/x86_64/memory.rs +++ b/libk/src/drivers/memory.rs @@ -1,5 +1,6 @@ // use lib_alloc::allocator::FoundryAllocator; use limine::{memory_map::EntryType, response::MemoryMapResponse}; +use spin::{Mutex, Once}; use x86_64::{ PhysAddr, VirtAddr, registers::control::Cr3, @@ -9,6 +10,8 @@ use x86_64::{ }, }; +pub static FRAME_ALLOCATOR: Once> = Once::new(); +pub static OFFSET_PAGE_TABLE: Once> = Once::new(); /// Returns a mutable reference to the current level 4 page table. /// /// # Safety @@ -42,10 +45,11 @@ unsafe fn active_l4_table(physical_memory_offset: VirtAddr) -> &'static mut Page /// /// Returns an `OffsetPageTable` that allows for manipulation of the page /// tables for the current CPU architecture. -pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> { +pub fn init_page_table(physical_memory_offset: VirtAddr) { unsafe { let l4_table = active_l4_table(physical_memory_offset); - OffsetPageTable::new(l4_table, physical_memory_offset) + let offset_table = OffsetPageTable::new(l4_table, physical_memory_offset); + OFFSET_PAGE_TABLE.call_once(|| Mutex::new(offset_table)); } } @@ -54,6 +58,12 @@ pub struct FoundryOSFrameAllocator { next: usize, } +pub fn init_frame_allocator(memory_map: &'static MemoryMapResponse) { + unsafe { + FRAME_ALLOCATOR.call_once(|| Mutex::new(FoundryOSFrameAllocator::init(memory_map))); + } +} + impl FoundryOSFrameAllocator { /// Creates a new `FoundryOSFrameAllocator` from a memory map. /// @@ -67,6 +77,10 @@ impl FoundryOSFrameAllocator { } } + pub fn count_usable_frames(&self) -> u32 { + self.usable_frames().count() as u32 + } + /// An iterator over all usable frames in the memory map. /// /// Yields one `PhysFrame` for each available 4KiB frame in the memory map. diff --git a/libk/src/drivers/mod.rs b/libk/src/drivers/mod.rs index 6ad525d..c3e42d1 100644 --- a/libk/src/drivers/mod.rs +++ b/libk/src/drivers/mod.rs @@ -2,4 +2,5 @@ pub mod io; pub mod kalloc; pub mod async_io; +pub mod memory; pub mod pic;