-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
user_driver: introduce new DMA trait for future DMA infrastructure ch…
…anges (#767) Introduces the initial implementation of the DMA framework, providing a centralized mechanism for DMA-capable memory allocation. It establishes the foundation for managing direct memory access (DMA) operations efficiently in a unified manner. Future enhancements will include pin/unpin support and bounce buffer management. This serves as a stepping stone toward enabling pin/unpin support for the platform, which will be introduced in an upcoming PR. --------- Co-authored-by: Chris Oo <[email protected]>
- Loading branch information
1 parent
feb548c
commit 2ad108b
Showing
18 changed files
with
255 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
//! This module provides a global DMA manager and client implementation. | ||
//! It manages DMA buffers and provides clients with access to these buffers. | ||
//! The `GlobalDmaManager` creates DMA buffers for different devices. | ||
//! The `DmaClientImpl` struct implements the `user_driver::DmaClient` trait. | ||
use parking_lot::Mutex; | ||
use std::sync::Arc; | ||
use user_driver::memory::MemoryBlock; | ||
use user_driver::vfio::VfioDmaBuffer; | ||
|
||
pub struct GlobalDmaManager { | ||
inner: Arc<Mutex<GlobalDmaManagerInner>>, | ||
} | ||
|
||
pub struct GlobalDmaManagerInner { | ||
dma_buffer_spawner: Box<dyn Fn(String) -> anyhow::Result<Arc<dyn VfioDmaBuffer>> + Send>, | ||
} | ||
|
||
impl GlobalDmaManager { | ||
/// Creates a new `GlobalDmaManager` with the given DMA buffer spawner. | ||
pub fn new( | ||
dma_buffer_spawner: Box<dyn Fn(String) -> anyhow::Result<Arc<dyn VfioDmaBuffer>> + Send>, | ||
) -> Self { | ||
let inner = GlobalDmaManagerInner { dma_buffer_spawner }; | ||
|
||
GlobalDmaManager { | ||
inner: Arc::new(Mutex::new(inner)), | ||
} | ||
} | ||
|
||
fn create_client_internal( | ||
inner: &Arc<Mutex<GlobalDmaManagerInner>>, | ||
device_name: String, | ||
) -> anyhow::Result<Arc<DmaClientImpl>> { | ||
let manager_inner = inner.lock(); | ||
let allocator = { | ||
// Access the page_pool and call its allocator method directly | ||
(manager_inner.dma_buffer_spawner)(device_name) | ||
.map_err(|e| anyhow::anyhow!("failed to get DMA buffer allocator: {:?}", e))? | ||
}; | ||
|
||
let client = DmaClientImpl { | ||
_dma_manager_inner: inner.clone(), | ||
dma_buffer_allocator: Some(allocator.clone()), // Set the allocator now | ||
}; | ||
|
||
let arc_client = Arc::new(client); | ||
|
||
Ok(arc_client) | ||
} | ||
|
||
/// Returns a `DmaClientSpawner` for creating DMA clients. | ||
pub fn get_client_spawner(&self) -> DmaClientSpawner { | ||
DmaClientSpawner { | ||
dma_manager_inner: self.inner.clone(), | ||
} | ||
} | ||
} | ||
|
||
pub struct DmaClientImpl { | ||
/// This is added to support map/pin functionality in the future. | ||
_dma_manager_inner: Arc<Mutex<GlobalDmaManagerInner>>, | ||
dma_buffer_allocator: Option<Arc<dyn VfioDmaBuffer>>, | ||
} | ||
|
||
impl user_driver::DmaClient for DmaClientImpl { | ||
fn allocate_dma_buffer(&self, total_size: usize) -> anyhow::Result<MemoryBlock> { | ||
if self.dma_buffer_allocator.is_none() { | ||
return Err(anyhow::anyhow!("DMA buffer allocator is not set")); | ||
} | ||
|
||
let allocator = self.dma_buffer_allocator.as_ref().unwrap(); | ||
|
||
allocator.create_dma_buffer(total_size) | ||
} | ||
|
||
fn attach_dma_buffer(&self, len: usize, base_pfn: u64) -> anyhow::Result<MemoryBlock> { | ||
let allocator = self.dma_buffer_allocator.as_ref().unwrap(); | ||
allocator.restore_dma_buffer(len, base_pfn) | ||
} | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct DmaClientSpawner { | ||
dma_manager_inner: Arc<Mutex<GlobalDmaManagerInner>>, | ||
} | ||
|
||
impl DmaClientSpawner { | ||
/// Creates a new DMA client with the given device name. | ||
pub fn create_client(&self, device_name: String) -> anyhow::Result<Arc<DmaClientImpl>> { | ||
GlobalDmaManager::create_client_internal(&self.dma_manager_inner, device_name) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
|
||
mod diag; | ||
mod dispatch; | ||
mod dma_manager; | ||
mod emuplat; | ||
mod get_tracing; | ||
mod inspect_internal; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.