Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use DMA framework to create DMAble buffers #722

Draft
wants to merge 62 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
57c366b
Merge branch 'main' of https://github.com/bhargavshah1988/openvmm
bhargavshah1988 Nov 12, 2024
2f4ad18
Merge branch 'main' of https://github.com/bhargavshah1988/openvmm
bhargavshah1988 Dec 23, 2024
a9e19ee
Merge branch 'main' of https://github.com/bhargavshah1988/openvmm
bhargavshah1988 Jan 14, 2025
9882a22
Merge branch 'main' of https://github.com/bhargavshah1988/openvmm
bhargavshah1988 Jan 15, 2025
05d1751
Merge branch 'main' of https://github.com/bhargavshah1988/openvmm
bhargavshah1988 Jan 16, 2025
9806bf8
First cut
bhargavshah1988 Jan 17, 2025
b4595af
VfioBuffer plumbing
bhargavshah1988 Jan 21, 2025
a6c318a
Call DMA API to allocate BB
bhargavshah1988 Jan 23, 2025
3ed8345
Updated the nvme to use Dma client
bhargavshah1988 Jan 23, 2025
7aad388
Cleanup
bhargavshah1988 Jan 23, 2025
ebececf
network plubming
bhargavshah1988 Jan 23, 2025
7057efc
VM starts with disk
bhargavshah1988 Jan 24, 2025
5e2b704
Clenaup
bhargavshah1988 Jan 24, 2025
4ef4853
Add a new boolean cxl_memory_enabled to the platform config json. (#706)
Patrick-Payne Jan 24, 2025
816e8b8
Always support extended ranges for TLB flushing (#721)
smalis-msft Jan 27, 2025
4c9942a
mesh_protobuf,inpsect: use expect_test in tests (#727)
jstarks Jan 27, 2025
cf84f1f
Delete and inline the tempfile_helpers crate (#728)
smalis-msft Jan 27, 2025
517d07a
Petri: Hyper-V support (#644)
tjones60 Jan 27, 2025
ee505b7
Create spawner
bhargavshah1988 Jan 28, 2025
cf4dfb4
format fix
bhargavshah1988 Jan 28, 2025
7b77c2f
xtask: Add support for running fuzzers on a stable toolchain (#731)
smalis-msft Jan 28, 2025
af7659b
petri, diag_client: pass -NoProfile to powershell invocations (#732)
jstarks Jan 28, 2025
941ca53
nvme_driver: fix overflow computing queue size (#703)
gurasinghMS Jan 28, 2025
1c74c1e
virt_mshv_vtl/snp: fix untrusted sint readiness (#725)
jstarks Jan 28, 2025
a21480d
user parking_lot mutex
bhargavshah1988 Jan 28, 2025
cdf1bc2
openhcl: revert #539 (use shared visibility pool for aarch64 dma) (#729)
mattkur Jan 28, 2025
77e5a2e
page_pool_alloc: fix features so cargo check works correctly (#737)
chris-oo Jan 29, 2025
64f36ab
Add plumbing for emulated devices
bhargavshah1988 Jan 29, 2025
a33cad3
Must get DMA client
bhargavshah1988 Jan 29, 2025
6c2ba37
TDX TLB: Properly handle cases of ranges with too large counts (#723)
smalis-msft Jan 29, 2025
1aa929a
user_driver: set pci device command bits appropriately (#675)
jstarks Jan 29, 2025
dfd7c16
virt_mshv_vtl: Share common processing between poll_apic implementati…
smalis-msft Jan 29, 2025
06432c3
flowey: use typestate pattern for gh variables (#643)
justus-camp-microsoft Jan 29, 2025
1b9ba4e
virt_mshv_vtl/mshv_x64: Remove support for emulating APIC (#741)
smalis-msft Jan 30, 2025
c9b59a1
loan_cell: add primitive for lending thread-local data (#743)
jstarks Jan 30, 2025
5654b8c
Petri: Stop and remove Hyper-V VMs on failure and before creation (#748)
tjones60 Jan 30, 2025
0cb7681
Add infrastructure to simulate the OpenHCL test failures (#742)
bhargavshah1988 Jan 31, 2025
a4c8d79
hcl: fix multiple calls to `flush_deferred_actions` (#739)
jstarks Jan 31, 2025
81e97dd
hv1_hypercall: simplify hypercall output handling (#736)
jstarks Jan 31, 2025
2ede4dd
Add private pool and keepalive test to VMM, device tree updates (#740)
yupavlen-ms Jan 31, 2025
88225af
virt_mshv_vtl: Scope startvp handling to CVMs (#726)
sluck-msft Jan 31, 2025
e98eb3c
Do no return error with dma_client
bhargavshah1988 Jan 31, 2025
22362c3
hvdef: make `HvStatus` type distinct from `HvError` (#754)
jstarks Jan 31, 2025
b812e33
Rename hvlite to openvmm in more user-facing strings (#757)
jstarks Jan 31, 2025
495daf6
openhcl_boot: Get alias map from device tree (#733)
tjones60 Feb 1, 2025
8871a24
First cut
bhargavshah1988 Jan 17, 2025
7c558f8
VfioBuffer plumbing
bhargavshah1988 Jan 21, 2025
a0062c9
Call DMA API to allocate BB
bhargavshah1988 Jan 23, 2025
e8fdac1
Updated the nvme to use Dma client
bhargavshah1988 Jan 23, 2025
28bcb12
Cleanup
bhargavshah1988 Jan 23, 2025
b448156
network plubming
bhargavshah1988 Jan 23, 2025
332b0d6
VM starts with disk
bhargavshah1988 Jan 24, 2025
db03555
Clenaup
bhargavshah1988 Jan 24, 2025
48de600
Create spawner
bhargavshah1988 Jan 28, 2025
c9643e9
format fix
bhargavshah1988 Jan 28, 2025
1c008be
user parking_lot mutex
bhargavshah1988 Jan 28, 2025
df479c0
Add plumbing for emulated devices
bhargavshah1988 Jan 29, 2025
fbe274f
Must get DMA client
bhargavshah1988 Jan 29, 2025
71973e2
Do no return error with dma_client
bhargavshah1988 Jan 31, 2025
0b26c3b
Add comments
bhargavshah1988 Feb 3, 2025
8e4e9dd
Merge branch 'user/bhsh/dmaPlumbing' of https://github.com/bhargavsha…
bhargavshah1988 Feb 3, 2025
772a058
Remove comment
bhargavshah1988 Feb 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7029,6 +7029,7 @@ dependencies = [
"netvsp",
"nvme_driver",
"nvme_resources",
"once_cell",
"openhcl_attestation_protocol",
"page_pool_alloc",
"pal",
Expand Down
2 changes: 1 addition & 1 deletion openhcl/page_pool_alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ impl Drop for PagePoolHandle {
/// [`PagePoolAllocatorSpawner::allocator`].
///
/// This struct is considered the "owner" of the pool allowing for save/restore.
#[derive(Inspect)]
#[derive(Inspect, Clone)]
pub struct PagePool {
#[inspect(flatten)]
inner: Arc<Mutex<PagePoolInner>>,
Expand Down
1 change: 1 addition & 0 deletions openhcl/underhill_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ vmotherboard = { workspace = true, features = [

build_info.workspace = true
cvm_tracing.workspace = true
once_cell.workspace = true
diag_proto.workspace = true
diag_server.workspace = true
debug_worker_defs = { workspace = true, optional = true }
Expand Down
4 changes: 4 additions & 0 deletions openhcl/underhill_core/src/dispatch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod pci_shutdown;
pub mod vtl2_settings_worker;

use self::vtl2_settings_worker::DeviceInterfaces;
use crate::dma_manager::GlobalDmaManager;
use crate::emuplat::netvsp::RuntimeSavedState;
use crate::emuplat::EmuplatServicing;
use crate::nvme_manager::NvmeManager;
Expand Down Expand Up @@ -108,6 +109,7 @@ pub trait LoadedVmNetworkSettings: Inspect {
partition: Arc<UhPartition>,
state_units: &StateUnits,
vmbus_server: &Option<VmbusServerHandle>,
dma_manager: GlobalDmaManager,
) -> anyhow::Result<RuntimeSavedState>;

/// Callback when network is removed externally.
Expand Down Expand Up @@ -179,6 +181,7 @@ pub(crate) struct LoadedVm {
pub shared_vis_pool: Option<PagePool>,
pub private_pool: Option<PagePool>,
pub nvme_keep_alive: bool,
pub dma_manager: GlobalDmaManager,
}

pub struct LoadedVmState<T> {
Expand Down Expand Up @@ -736,6 +739,7 @@ impl LoadedVm {
self.partition.clone(),
&self.state_units,
&self.vmbus_server,
self.dma_manager.clone(),
)
.await?;

Expand Down
131 changes: 131 additions & 0 deletions openhcl/underhill_core/src/dma_manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//use std::sync::{Mutex, Weak};

use memory_range::MemoryRange;
use std::{collections::HashMap, sync::{Arc, Mutex}};
use page_pool_alloc::PagePool;
use user_driver::{memory::MemoryBlock, vfio::VfioDmaBuffer};
use user_driver::lockmem::LockedMemorySpawner;

#[derive(Clone)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like page pool, implementing Clone on this type seems odd to me. You want there to be only a single manager, and make it painfully obvious to the user that you do not want to clone this type because it has special internal state that it is responsible for managing. This means that you may need to pass usage of it by ref, or by Arc

pub struct GlobalDmaManager {
_physical_ranges: Vec<MemoryRange>,
_bounce_buffers_manager: Vec<MemoryRange>,
//clients: Mutex<Vec<Weak<DmaClient>>>,
//client_thresholds: Mutex<Vec<(Weak<DmaClient>, usize)>>,

page_pool: Option<PagePool>,
clients: HashMap<String, Arc<DmaClient>>,
}

impl GlobalDmaManager {
pub fn new(page_pool: Option<PagePool>) -> Self {
GlobalDmaManager {
_physical_ranges: Vec::new(),
_bounce_buffers_manager: Vec::new(),
//clients: Mutex::new(Vec::new()),
//client_thresholds: Mutex::new(Vec::new()),
page_pool: page_pool.clone(),
clients: HashMap::new(),
}
}

pub fn create_client(&mut self, pci_id: String) -> DmaClient {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we want to clone DmaClients, as it seems reasonable to me that there is at most one client per pci_id. I'd rather here we make the Arc external, ie don't implement clone, but instead return an Arc<DmaClient>

let client = DmaClient {
dma_manager: Arc::new(Mutex::new(self.clone())),
dma_buffer_allocator: None, // Valid now as `Option<Arc<dyn VfioDmaBuffer>>`
};

let arc_client = Arc::new(client);
self.clients.insert(pci_id, arc_client.clone()); // Store the cloned `Arc` in `clients`.

arc_client.as_ref().clone() // Return the `Arc<DmaClient>`.
}

pub fn get_client(&self, pci_id: &str) -> Option<Arc<DmaClient>> {
self.clients.get(pci_id).cloned()
}

pub fn get_dma_buffer_allocator(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense here - why is this not a method on DmaClient itself?

&mut self,
device_name: String,
) -> anyhow::Result<Arc<dyn VfioDmaBuffer>> {
self.page_pool
.as_ref()
.map(|p : &PagePool| -> anyhow::Result<Arc<dyn VfioDmaBuffer>> {
p.allocator(device_name)
.map(|alloc| Arc::new(alloc) as Arc<dyn VfioDmaBuffer>)
})
.unwrap_or(Ok(Arc::new(LockedMemorySpawner)))
}
}

#[derive(Clone)]
pub struct DmaClient {
dma_manager: Arc<Mutex<GlobalDmaManager>>,
dma_buffer_allocator: Option<Arc<dyn VfioDmaBuffer>>,
}

impl user_driver::DmaClient for DmaClient {
fn map_dma_ranges(
&self,
ranges: i32,
) -> anyhow::Result<Vec<i32>> {
self.map_dma_ranges(ranges)
}

//fn get_dma_buffer_allocator(
// &mut self,
// device_name: String,
//) -> anyhow::Result<Arc<dyn VfioDmaBuffer>> {

// let mut manager = self.dma_manager.lock().unwrap();

// manager.get_dma_buffer_allocator(device_name).map(|allocator| {
// self.dma_buffer_allocator = Some(allocator.clone());
// allocator
// })
//}

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

}

impl DmaClient {
fn map_dma_ranges(
&self,
_ranges: i32,
) -> anyhow::Result<Vec<i32>>
{
Ok(Vec::new())
}

pub fn get_dma_buffer_allocator(
&mut self,
device_name: String,
) -> anyhow::Result<Arc<dyn VfioDmaBuffer>> {

let mut manager = self.dma_manager.lock().unwrap();

manager.get_dma_buffer_allocator(device_name).map(|allocator| {
self.dma_buffer_allocator = Some(allocator.clone());
allocator
})
}
}
31 changes: 17 additions & 14 deletions openhcl/underhill_core/src/emuplat/netvsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// Licensed under the MIT License.

use crate::dispatch::vtl2_settings_worker::wait_for_pci_path;
use crate::dma_manager::GlobalDmaManager;
use crate::vpci::HclVpciBusControl;
use user_driver::DmaClient;
use anyhow::Context;
use async_trait::async_trait;
use futures::lock::Mutex;
Expand Down Expand Up @@ -40,7 +42,6 @@ use uevent::UeventListener;
use user_driver::vfio::vfio_set_device_reset_method;
use user_driver::vfio::PciDeviceResetMethod;
use user_driver::vfio::VfioDevice;
use user_driver::vfio::VfioDmaBuffer;
use vmcore::vm_task::VmTaskDriverSource;
use vpci::bus_control::VpciBusControl;
use vpci::bus_control::VpciBusEvent;
Expand All @@ -60,12 +61,12 @@ enum HclNetworkVfManagerMessage {
PacketCapture(FailableRpc<PacketCaptureParams<Socket>, PacketCaptureParams<Socket>>),
}

async fn create_mana_device(
async fn create_mana_device(
driver_source: &VmTaskDriverSource,
pci_id: &str,
vp_count: u32,
max_sub_channels: u16,
dma_buffer: Arc<dyn VfioDmaBuffer>,
dma_client: Arc<dyn DmaClient>,
) -> anyhow::Result<ManaDevice<VfioDevice>> {
// Disable FLR on vfio attach/detach; this allows faster system
// startup/shutdown with the caveat that the device needs to be properly
Expand All @@ -89,7 +90,7 @@ async fn create_mana_device(
pci_id,
vp_count,
max_sub_channels,
&dma_buffer,
dma_client.clone(),
)
.await
{
Expand Down Expand Up @@ -118,9 +119,9 @@ async fn try_create_mana_device(
pci_id: &str,
vp_count: u32,
max_sub_channels: u16,
dma_buffer: &Arc<dyn VfioDmaBuffer>,
dma_client: Arc<dyn DmaClient>,
) -> anyhow::Result<ManaDevice<VfioDevice>> {
let device = VfioDevice::new(driver_source, pci_id, dma_buffer.clone())
let device = VfioDevice::new(driver_source, pci_id, dma_client)
.await
.context("failed to open device")?;

Expand Down Expand Up @@ -200,9 +201,9 @@ struct HclNetworkVFManagerWorker {
vtl2_bus_control: HclVpciBusControl,
vtl2_pci_id: String,
#[inspect(skip)]
dma_buffer: Arc<dyn VfioDmaBuffer>,
#[inspect(skip)]
dma_mode: GuestDmaMode,
#[inspect(skip)]
dma_manager: GlobalDmaManager,
}

impl HclNetworkVFManagerWorker {
Expand All @@ -217,8 +218,8 @@ impl HclNetworkVFManagerWorker {
endpoint_controls: Vec<DisconnectableEndpointControl>,
vp_count: u32,
max_sub_channels: u16,
dma_buffer: Arc<dyn VfioDmaBuffer>,
dma_mode: GuestDmaMode,
dma_manager: GlobalDmaManager,
) -> (Self, mesh::Sender<HclNetworkVfManagerMessage>) {
let (tx_to_worker, worker_rx) = mesh::channel();
let vtl0_bus_control = if save_state.hidden_vtl0.lock().unwrap_or(false) {
Expand Down Expand Up @@ -247,8 +248,8 @@ impl HclNetworkVFManagerWorker {
vtl0_bus_control,
vtl2_bus_control,
vtl2_pci_id,
dma_buffer,
dma_mode,
dma_manager,
},
tx_to_worker,
)
Expand Down Expand Up @@ -685,12 +686,13 @@ impl HclNetworkVFManagerWorker {
} else {
tracing::info!("VTL2 VF arrived");
}
let pci_id = self.vtl2_pci_id.clone();
let device_bound = match create_mana_device(
&self.driver_source,
&self.vtl2_pci_id,
self.vp_count,
self.max_sub_channels,
self.dma_buffer.clone(),
Arc::new(self.dma_manager.create_client(pci_id))
)
.await
{
Expand Down Expand Up @@ -865,8 +867,9 @@ impl HclNetworkVFManager {
vp_count: u32,
max_sub_channels: u16,
netvsp_state: &Option<Vec<SavedState>>,
dma_buffer: Arc<dyn VfioDmaBuffer>,
dma_mode: GuestDmaMode,
dma_client: Arc<dyn DmaClient>,
dma_manager: GlobalDmaManager,
) -> anyhow::Result<(
Self,
Vec<HclNetworkVFManagerEndpointInfo>,
Expand All @@ -877,7 +880,7 @@ impl HclNetworkVFManager {
&vtl2_pci_id,
vp_count,
max_sub_channels,
dma_buffer.clone(),
dma_client,
)
.await?;
let (mut endpoints, endpoint_controls): (Vec<_>, Vec<_>) = (0..device.num_vports())
Expand Down Expand Up @@ -926,8 +929,8 @@ impl HclNetworkVFManager {
endpoint_controls,
vp_count,
max_sub_channels,
dma_buffer,
dma_mode,
dma_manager,
);

// Queue new endpoints.
Expand Down
1 change: 1 addition & 0 deletions openhcl/underhill_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

mod diag;
mod dispatch;
mod dma_manager;
mod emuplat;
mod get_tracing;
mod inspect_internal;
Expand Down
Loading
Loading