diff --git a/kernel/src/arch/aarch64/boot/mod.rs b/kernel/src/arch/aarch64/boot/mod.rs index 2a16d89..2124d2a 100644 --- a/kernel/src/arch/aarch64/boot/mod.rs +++ b/kernel/src/arch/aarch64/boot/mod.rs @@ -1,8 +1,13 @@ //! aarch64 common boot logic use crate::arch::{aarch64::asm::CPACR_EL1, machine}; -use crate::dev::{Device, fdt::DeviceTree}; -use crate::mem::virt; +use crate::dev::{fdt::DeviceTree, Device}; +use crate::mem::{ + self, + heap, + phys::{self, PageUsage}, + virt, +}; use cortex_a::asm::barrier::{self, dsb, isb}; use cortex_a::registers::{DAIF, SCTLR_EL1, VBAR_EL1}; use tock_registers::interfaces::{ReadWriteable, Writeable}; @@ -32,6 +37,18 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) { // Enable MMU virt::enable().expect("Failed to initialize virtual memory"); + // Most basic machine init: initialize proper debug output + // physical memory + machine::init_board_early().unwrap(); + + // Setup a heap + unsafe { + let heap_base_phys = phys::alloc_contiguous_pages(PageUsage::KernelHeap, 4096) + .expect("Failed to allocate memory for heap"); + let heap_base_virt = mem::virtualize(heap_base_phys); + heap::init(heap_base_virt, 16 * 1024 * 1024); + } + machine::init_board().unwrap(); if fdt_base != 0 { @@ -42,6 +59,8 @@ extern "C" fn __aa64_bsp_main(fdt_base: usize) { } else { debugln!("Failed to init FDT"); } + } else { + debugln!("No FDT present"); } debugln!("Machine init finished"); diff --git a/kernel/src/arch/aarch64/mach_qemu/mod.rs b/kernel/src/arch/aarch64/mach_qemu/mod.rs index 2858839..dc144be 100644 --- a/kernel/src/arch/aarch64/mach_qemu/mod.rs +++ b/kernel/src/arch/aarch64/mach_qemu/mod.rs @@ -17,24 +17,30 @@ use error::Errno; pub use gic::IrqNumber; +// TODO extract this from device tree const UART0_BASE: usize = 0x09000000; const RTC_BASE: usize = 0x09010000; const GICD_BASE: usize = 0x08000000; const GICC_BASE: usize = 0x08010000; -// TODO extract this from device tree const ECAM_BASE: usize = 0x4010000000; const PHYS_BASE: usize = 0x40000000; const PHYS_SIZE: usize = 0x10000000; #[allow(missing_docs)] -pub fn init_board() -> Result<(), Errno> { +pub fn init_board_early() -> Result<(), Errno> { unsafe { // Enable UART early on UART0.enable()?; phys::init_from_region(PHYS_BASE, PHYS_SIZE); + } + Ok(()) +} +#[allow(missing_docs)] +pub fn init_board() -> Result<(), Errno> { + unsafe { GIC.enable()?; UART0.init_irqs()?; @@ -43,7 +49,7 @@ pub fn init_board() -> Result<(), Errno> { RTC.init_irqs()?; PCIE.enable()?; - PCIE.map()?; + // PCIE.map()?; } Ok(()) } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index ce25d40..4cd6452 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -8,7 +8,8 @@ const_fn_fn_ptr_basics, const_fn_trait_bound, const_panic, - panic_info_message + panic_info_message, + alloc_error_handler, )] #![no_std] #![no_main] @@ -16,6 +17,7 @@ #[macro_use] extern crate cfg_if; +extern crate alloc; #[macro_use] pub mod debug; diff --git a/kernel/src/mem/heap.rs b/kernel/src/mem/heap.rs new file mode 100644 index 0000000..a04c509 --- /dev/null +++ b/kernel/src/mem/heap.rs @@ -0,0 +1,63 @@ +use crate::util::InitOnce; +use crate::sync::IrqSafeNullLock; +use core::alloc::{GlobalAlloc, Layout}; +use core::ptr::null_mut; + +struct SystemAlloc; + +struct Heap { + base: usize, + size: usize, + ptr: usize, +} + +unsafe impl GlobalAlloc for SystemAlloc { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + HEAP.get().lock().alloc(layout) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + HEAP.get().lock().dealloc(ptr, layout) + } +} + +impl Heap { + unsafe fn alloc(&mut self, layout: Layout) -> *mut u8 { + // Simple bump allocation + assert!(layout.align() <= 16); + let size = (layout.size() + 15) & !15; + if self.ptr + size >= self.size { + return null_mut(); + } + + let ptr = self.ptr; + self.ptr += size; + + (self.base + ptr) as *mut u8 + } + + unsafe fn dealloc(&mut self, _ptr: *mut u8, _layout: Layout) { + } +} + +#[alloc_error_handler] +fn alloc_error_handler(layout: Layout) -> ! { + panic!("Allocation failed: {:?}", layout) +} + +#[global_allocator] +static SYSTEM_ALLOC: SystemAlloc = SystemAlloc; + +static HEAP: InitOnce> = InitOnce::new(); + +pub unsafe fn init(base: usize, size: usize) { + let heap = Heap { + base, + size, + ptr: 0 + }; + + debugln!("Kernel heap: {:#x}..{:#x}", base, base + size); + + HEAP.init(IrqSafeNullLock::new(heap)); +} diff --git a/kernel/src/mem/mod.rs b/kernel/src/mem/mod.rs index 21b6598..79dfd5b 100644 --- a/kernel/src/mem/mod.rs +++ b/kernel/src/mem/mod.rs @@ -3,6 +3,7 @@ pub mod phys; pub mod virt; +pub mod heap; /// Virtual offset applied to kernel address space pub const KERNEL_OFFSET: usize = 0xFFFFFF8000000000; diff --git a/kernel/src/mem/phys/mod.rs b/kernel/src/mem/phys/mod.rs index 633550b..2b6b819 100644 --- a/kernel/src/mem/phys/mod.rs +++ b/kernel/src/mem/phys/mod.rs @@ -1,5 +1,6 @@ use crate::mem::PAGE_SIZE; use core::mem::size_of; +use error::Errno; mod reserved; mod manager; @@ -15,7 +16,8 @@ const MAX_PAGES: usize = 1024 * 1024; pub enum PageUsage { Reserved, Available, - Kernel + Kernel, + KernelHeap } pub struct PageInfo { @@ -46,6 +48,10 @@ impl Iterator for SimpleMemoryIterator { } } +pub fn alloc_contiguous_pages(pu: PageUsage, count: usize) -> Result { + MANAGER.lock().as_mut().unwrap().alloc_contiguous_pages(pu, count) +} + fn find_contiguous>( iter: T, count: usize,