Browse Source

Use heap for dma_alloc rather than bump allocator.

This lets us implement dma_dealloc properly.
Andrew Walbran 1 year ago
parent
commit
2caca1ec53
4 changed files with 20 additions and 19 deletions
  1. 0 1
      examples/aarch64/Cargo.toml
  2. 0 1
      examples/aarch64/image.ld
  3. 18 17
      examples/aarch64/src/hal.rs
  4. 2 0
      examples/aarch64/src/main.rs

+ 0 - 1
examples/aarch64/Cargo.toml

@@ -7,7 +7,6 @@ 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"

+ 0 - 1
examples/aarch64/image.ld

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

+ 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
     }
 

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

@@ -1,6 +1,8 @@
 #![no_std]
 #![no_main]
 
+extern crate alloc;
+
 mod exceptions;
 mod hal;
 mod logger;