Bladeren bron

Merge pull request #82 from rcore-os/aarch64-heap

Add a heap allocator to aarch64 example
Andrew Walbran 1 jaar geleden
bovenliggende
commit
0d961c7869

+ 2 - 2
examples/aarch64/Cargo.toml

@@ -5,12 +5,12 @@ authors = ["Andrew Walbran <[email protected]>"]
 edition = "2021"
 
 [dependencies]
+buddy_system_allocator = "0.9.0"
 fdt = "0.1.5"
-lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
 log = "0.4.17"
 smccc = "0.1.1"
 spin = "0.9.8"
-virtio-drivers = { path = "../..", default-features = false }
+virtio-drivers = { path = "../.." }
 
 [build-dependencies]
 cc = "1.0.73"

+ 1 - 1
examples/aarch64/crosvm.ld

@@ -1,4 +1,4 @@
 MEMORY
 {
-	image : ORIGIN = 0x80200000, LENGTH = 2M
+	image : ORIGIN = 0x80200000, LENGTH = 32M
 }

+ 0 - 1
examples/aarch64/image.ld

@@ -66,7 +66,6 @@ SECTIONS
 	} >image
 
 	. = ALIGN(4K);
-	PROVIDE(dma_region = .);
 
 	/*
 	 * Remove unused sections from the image.

+ 1 - 1
examples/aarch64/qemu.ld

@@ -1,4 +1,4 @@
 MEMORY
 {
-	image : ORIGIN = 0x40080000, LENGTH = 2M
+	image : ORIGIN = 0x40080000, LENGTH = 32M
 }

+ 18 - 17
examples/aarch64/src/hal.rs

@@ -1,32 +1,33 @@
-use core::{
-    ptr::NonNull,
-    sync::atomic::{AtomicUsize, Ordering},
-};
-use lazy_static::lazy_static;
+use alloc::alloc::{alloc_zeroed, dealloc, handle_alloc_error};
+use core::{alloc::Layout, ptr::NonNull};
 use log::trace;
 use virtio_drivers::{BufferDirection, Hal, PhysAddr, PAGE_SIZE};
 
-extern "C" {
-    static dma_region: u8;
-}
-
-lazy_static! {
-    static ref DMA_PADDR: AtomicUsize =
-        AtomicUsize::new(unsafe { &dma_region as *const u8 as usize });
-}
-
 pub struct HalImpl;
 
 unsafe impl Hal for HalImpl {
     fn dma_alloc(pages: usize, _direction: BufferDirection) -> (PhysAddr, NonNull<u8>) {
-        let paddr = DMA_PADDR.fetch_add(PAGE_SIZE * pages, Ordering::SeqCst);
+        let layout = Layout::from_size_align(pages * PAGE_SIZE, PAGE_SIZE).unwrap();
+        // Safe because the layout has a non-zero size.
+        let vaddr = unsafe { alloc_zeroed(layout) };
+        let vaddr = if let Some(vaddr) = NonNull::new(vaddr) {
+            vaddr
+        } else {
+            handle_alloc_error(layout)
+        };
+        let paddr = virt_to_phys(vaddr.as_ptr() as _);
         trace!("alloc DMA: paddr={:#x}, pages={}", paddr, pages);
-        let vaddr = NonNull::new(paddr as _).unwrap();
         (paddr, vaddr)
     }
 
-    unsafe fn dma_dealloc(paddr: PhysAddr, _vaddr: NonNull<u8>, pages: usize) -> i32 {
+    unsafe fn dma_dealloc(paddr: PhysAddr, vaddr: NonNull<u8>, pages: usize) -> i32 {
         trace!("dealloc DMA: paddr={:#x}, pages={}", paddr, pages);
+        let layout = Layout::from_size_align(pages * PAGE_SIZE, PAGE_SIZE).unwrap();
+        // Safe because the memory was allocated by `dma_alloc` above using the same allocator, and
+        // the layout is the same as was used then.
+        unsafe {
+            dealloc(vaddr.as_ptr(), layout);
+        }
         0
     }
 

+ 16 - 0
examples/aarch64/src/main.rs

@@ -1,6 +1,8 @@
 #![no_std]
 #![no_main]
 
+extern crate alloc;
+
 mod exceptions;
 mod hal;
 mod logger;
@@ -13,6 +15,7 @@ mod uart8250;
 #[cfg(platform = "crosvm")]
 use uart8250 as uart;
 
+use buddy_system_allocator::LockedHeap;
 use core::{
     mem::size_of,
     panic::PanicInfo,
@@ -47,6 +50,11 @@ pub const UART_BASE_ADDRESS: usize = 0x900_0000;
 #[cfg(platform = "crosvm")]
 pub const UART_BASE_ADDRESS: usize = 0x3f8;
 
+#[global_allocator]
+static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::new();
+
+static mut HEAP: [u8; 0x1000000] = [0; 0x1000000];
+
 #[no_mangle]
 extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
     logger::init(LevelFilter::Debug).unwrap();
@@ -56,6 +64,14 @@ extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
         x0, x1, x2, x3
     );
 
+    // Safe because `HEAP` is only used here and `entry` is only called once.
+    unsafe {
+        // Give the allocator some memory to allocate.
+        HEAP_ALLOCATOR
+            .lock()
+            .init(HEAP.as_mut_ptr() as usize, HEAP.len());
+    }
+
     info!("Loading FDT from {:#018x}", x0);
     // Safe because the pointer is a valid pointer to unaliased memory.
     let fdt = unsafe { Fdt::from_ptr(x0 as *const u8).unwrap() };