mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-28 09:33:01 +00:00
rutabaga_gfx: kumquat: support GPU mappings
- dma-buf mmap does not work on Tesla V-100 - system blob does not work on Tesla V-100 - opaque fd mmap does not work on Tesla V-100 - Opaque fd + VK map does work on Tesla V-100 Since we need to make sure the Nvidia ICD is used when calling VK map + unmap, we save and restore VK_ICD_FILENAMES when loading gralloc. This is not super-robust, but the perhaps the best can that can be done on Nvidia. BUG=b:300140266 TEST=see successful memory access with Nvidia Change-Id: I4f4084921b6267b137e7aeeafbfb8839a120c63e Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5698370 Reviewed-by: Jason Macnak <natsu@google.com> Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
This commit is contained in:
parent
ea09e79921
commit
1eade7875e
3 changed files with 89 additions and 17 deletions
|
@ -15,8 +15,11 @@ use rutabaga_gfx::kumquat_gpu_protocol::*;
|
||||||
use rutabaga_gfx::RutabagaDescriptor;
|
use rutabaga_gfx::RutabagaDescriptor;
|
||||||
use rutabaga_gfx::RutabagaError;
|
use rutabaga_gfx::RutabagaError;
|
||||||
use rutabaga_gfx::RutabagaFromRawDescriptor;
|
use rutabaga_gfx::RutabagaFromRawDescriptor;
|
||||||
|
use rutabaga_gfx::RutabagaGralloc;
|
||||||
|
use rutabaga_gfx::RutabagaGrallocBackendFlags;
|
||||||
use rutabaga_gfx::RutabagaHandle;
|
use rutabaga_gfx::RutabagaHandle;
|
||||||
use rutabaga_gfx::RutabagaIntoRawDescriptor;
|
use rutabaga_gfx::RutabagaIntoRawDescriptor;
|
||||||
|
use rutabaga_gfx::RutabagaMappedRegion;
|
||||||
use rutabaga_gfx::RutabagaMapping;
|
use rutabaga_gfx::RutabagaMapping;
|
||||||
use rutabaga_gfx::RutabagaMemoryMapping;
|
use rutabaga_gfx::RutabagaMemoryMapping;
|
||||||
use rutabaga_gfx::RutabagaRawDescriptor;
|
use rutabaga_gfx::RutabagaRawDescriptor;
|
||||||
|
@ -25,6 +28,7 @@ use rutabaga_gfx::RutabagaResult;
|
||||||
use rutabaga_gfx::RutabagaSharedMemory;
|
use rutabaga_gfx::RutabagaSharedMemory;
|
||||||
use rutabaga_gfx::RutabagaStream;
|
use rutabaga_gfx::RutabagaStream;
|
||||||
use rutabaga_gfx::RutabagaWriter;
|
use rutabaga_gfx::RutabagaWriter;
|
||||||
|
use rutabaga_gfx::VulkanInfo;
|
||||||
use rutabaga_gfx::RUTABAGA_FLAG_FENCE;
|
use rutabaga_gfx::RUTABAGA_FLAG_FENCE;
|
||||||
use rutabaga_gfx::RUTABAGA_FLAG_FENCE_HOST_SHAREABLE;
|
use rutabaga_gfx::RUTABAGA_FLAG_FENCE_HOST_SHAREABLE;
|
||||||
use rutabaga_gfx::RUTABAGA_FLAG_INFO_RING_IDX;
|
use rutabaga_gfx::RUTABAGA_FLAG_INFO_RING_IDX;
|
||||||
|
@ -34,22 +38,33 @@ use rutabaga_gfx::RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_FD;
|
||||||
|
|
||||||
use crate::virtgpu::defines::*;
|
use crate::virtgpu::defines::*;
|
||||||
|
|
||||||
|
const VK_ICD_FILENAMES: &str = "VK_ICD_FILENAMES";
|
||||||
|
|
||||||
pub struct VirtGpuResource {
|
pub struct VirtGpuResource {
|
||||||
resource_id: u32,
|
resource_id: u32,
|
||||||
size: usize,
|
size: usize,
|
||||||
handle: RutabagaHandle,
|
handle: RutabagaHandle,
|
||||||
mapping: Option<RutabagaMemoryMapping>,
|
|
||||||
attached_fences: Vec<RutabagaHandle>,
|
attached_fences: Vec<RutabagaHandle>,
|
||||||
|
vulkan_info: VulkanInfo,
|
||||||
|
system_mapping: Option<RutabagaMemoryMapping>,
|
||||||
|
gpu_mapping: Option<Box<dyn RutabagaMappedRegion>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtGpuResource {
|
impl VirtGpuResource {
|
||||||
pub fn new(resource_id: u32, size: usize, handle: RutabagaHandle) -> VirtGpuResource {
|
pub fn new(
|
||||||
|
resource_id: u32,
|
||||||
|
size: usize,
|
||||||
|
handle: RutabagaHandle,
|
||||||
|
vulkan_info: VulkanInfo,
|
||||||
|
) -> VirtGpuResource {
|
||||||
VirtGpuResource {
|
VirtGpuResource {
|
||||||
resource_id,
|
resource_id,
|
||||||
size,
|
size,
|
||||||
handle,
|
handle,
|
||||||
mapping: None,
|
|
||||||
attached_fences: Vec::new(),
|
attached_fences: Vec::new(),
|
||||||
|
vulkan_info,
|
||||||
|
system_mapping: None,
|
||||||
|
gpu_mapping: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,6 +76,7 @@ pub struct VirtGpuKumquat {
|
||||||
stream: RutabagaStream,
|
stream: RutabagaStream,
|
||||||
capsets: Map<u32, Vec<u8>>,
|
capsets: Map<u32, Vec<u8>>,
|
||||||
resources: Map<u32, VirtGpuResource>,
|
resources: Map<u32, VirtGpuResource>,
|
||||||
|
gralloc_opt: Option<RutabagaGralloc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtGpuKumquat {
|
impl VirtGpuKumquat {
|
||||||
|
@ -122,6 +138,7 @@ impl VirtGpuKumquat {
|
||||||
stream,
|
stream,
|
||||||
capsets,
|
capsets,
|
||||||
resources: Default::default(),
|
resources: Default::default(),
|
||||||
|
gralloc_opt: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +227,7 @@ impl VirtGpuKumquat {
|
||||||
let resource = match protocols.remove(0) {
|
let resource = match protocols.remove(0) {
|
||||||
KumquatGpuProtocol::RespResourceCreate(resp, handle) => {
|
KumquatGpuProtocol::RespResourceCreate(resp, handle) => {
|
||||||
let size: usize = create_3d.size.try_into()?;
|
let size: usize = create_3d.size.try_into()?;
|
||||||
VirtGpuResource::new(resp.resource_id, size, handle)
|
VirtGpuResource::new(resp.resource_id, size, handle, resp.vulkan_info)
|
||||||
}
|
}
|
||||||
_ => return Err(RutabagaError::Unsupported),
|
_ => return Err(RutabagaError::Unsupported),
|
||||||
};
|
};
|
||||||
|
@ -268,7 +285,7 @@ impl VirtGpuKumquat {
|
||||||
let resource = match protocols.remove(0) {
|
let resource = match protocols.remove(0) {
|
||||||
KumquatGpuProtocol::RespResourceCreate(resp, handle) => {
|
KumquatGpuProtocol::RespResourceCreate(resp, handle) => {
|
||||||
let size: usize = create_blob.size.try_into()?;
|
let size: usize = create_blob.size.try_into()?;
|
||||||
VirtGpuResource::new(resp.resource_id, size, handle)
|
VirtGpuResource::new(resp.resource_id, size, handle, resp.vulkan_info)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(RutabagaError::Unsupported);
|
return Err(RutabagaError::Unsupported);
|
||||||
|
@ -308,21 +325,50 @@ impl VirtGpuKumquat {
|
||||||
.get_mut(&bo_handle)
|
.get_mut(&bo_handle)
|
||||||
.ok_or(RutabagaError::InvalidResourceId)?;
|
.ok_or(RutabagaError::InvalidResourceId)?;
|
||||||
|
|
||||||
if let Some(ref mapping) = resource.mapping {
|
if let Some(ref system_mapping) = resource.system_mapping {
|
||||||
let rutabaga_mapping = mapping.as_rutabaga_mapping();
|
let rutabaga_mapping = system_mapping.as_rutabaga_mapping();
|
||||||
|
Ok(rutabaga_mapping)
|
||||||
|
} else if let Some(ref gpu_mapping) = resource.gpu_mapping {
|
||||||
|
let rutabaga_mapping = gpu_mapping.as_rutabaga_mapping();
|
||||||
Ok(rutabaga_mapping)
|
Ok(rutabaga_mapping)
|
||||||
} else {
|
} else {
|
||||||
let clone = resource.handle.try_clone()?;
|
let clone = resource.handle.try_clone()?;
|
||||||
|
|
||||||
let mapping = RutabagaMemoryMapping::from_safe_descriptor(
|
if clone.handle_type == RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_FD {
|
||||||
clone.os_handle,
|
if self.gralloc_opt.is_none() {
|
||||||
resource.size,
|
// The idea is to make sure the gfxstream ICD isn't loaded when gralloc starts
|
||||||
RUTABAGA_MAP_CACHE_CACHED | RUTABAGA_MAP_ACCESS_RW,
|
// up. The Nvidia ICD should be loaded.
|
||||||
)?;
|
let vk_driver = std::env::var(VK_ICD_FILENAMES).unwrap();
|
||||||
|
std::env::remove_var(VK_ICD_FILENAMES);
|
||||||
|
self.gralloc_opt =
|
||||||
|
Some(RutabagaGralloc::new(RutabagaGrallocBackendFlags::new())?);
|
||||||
|
std::env::set_var(VK_ICD_FILENAMES, vk_driver);
|
||||||
|
}
|
||||||
|
|
||||||
let rutabaga_mapping = mapping.as_rutabaga_mapping();
|
if let Some(ref mut gralloc) = self.gralloc_opt {
|
||||||
resource.mapping = Some(mapping);
|
let region = gralloc.import_and_map(
|
||||||
Ok(rutabaga_mapping)
|
clone,
|
||||||
|
resource.vulkan_info,
|
||||||
|
resource.size as u64,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let rutabaga_mapping = region.as_rutabaga_mapping();
|
||||||
|
resource.gpu_mapping = Some(region);
|
||||||
|
Ok(rutabaga_mapping)
|
||||||
|
} else {
|
||||||
|
return Err(RutabagaError::SpecViolation("no gralloc"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mapping = RutabagaMemoryMapping::from_safe_descriptor(
|
||||||
|
clone.os_handle,
|
||||||
|
resource.size,
|
||||||
|
RUTABAGA_MAP_CACHE_CACHED | RUTABAGA_MAP_ACCESS_RW,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let rutabaga_mapping = mapping.as_rutabaga_mapping();
|
||||||
|
resource.system_mapping = Some(mapping);
|
||||||
|
Ok(rutabaga_mapping)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,7 +378,8 @@ impl VirtGpuKumquat {
|
||||||
.get_mut(&bo_handle)
|
.get_mut(&bo_handle)
|
||||||
.ok_or(RutabagaError::InvalidResourceId)?;
|
.ok_or(RutabagaError::InvalidResourceId)?;
|
||||||
|
|
||||||
resource.mapping = None;
|
resource.system_mapping = None;
|
||||||
|
resource.gpu_mapping = None;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,7 +629,12 @@ impl VirtGpuKumquat {
|
||||||
|
|
||||||
self.stream
|
self.stream
|
||||||
.write(KumquatGpuProtocolWrite::Cmd(attach_resource))?;
|
.write(KumquatGpuProtocolWrite::Cmd(attach_resource))?;
|
||||||
let resource = VirtGpuResource::new(*resource_handle, VIRTGPU_KUMQUAT_PAGE_SIZE, handle);
|
let resource = VirtGpuResource::new(
|
||||||
|
*resource_handle,
|
||||||
|
VIRTGPU_KUMQUAT_PAGE_SIZE,
|
||||||
|
handle,
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
|
|
||||||
*bo_handle = self.allocate_id();
|
*bo_handle = self.allocate_id();
|
||||||
// Should ask the server about the size long-term.
|
// Should ask the server about the size long-term.
|
||||||
|
|
|
@ -99,6 +99,21 @@ unsafe impl MappedRegion for VulkanoMapping {
|
||||||
fn size(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns rutabaga mapping representation of the region
|
||||||
|
fn as_rutabaga_mapping(&self) -> RutabagaMapping {
|
||||||
|
let ptr: u64 = unsafe {
|
||||||
|
// Will not panic since the requested range of the device memory was verified on
|
||||||
|
// creation
|
||||||
|
let x = self.mapped_memory.write(0..self.size as u64).unwrap();
|
||||||
|
x.as_mut_ptr() as u64
|
||||||
|
};
|
||||||
|
|
||||||
|
RutabagaMapping {
|
||||||
|
ptr,
|
||||||
|
size: self.size as u64,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait DeviceExt {
|
trait DeviceExt {
|
||||||
|
|
|
@ -17,6 +17,8 @@ pub use sys::platform::descriptor::RawDescriptor;
|
||||||
pub use sys::platform::shm::round_up_to_page_size;
|
pub use sys::platform::shm::round_up_to_page_size;
|
||||||
pub use sys::platform::wait_context::WaitContext;
|
pub use sys::platform::wait_context::WaitContext;
|
||||||
|
|
||||||
|
use crate::rutabaga_utils::RutabagaMapping;
|
||||||
|
|
||||||
pub struct WaitEvent {
|
pub struct WaitEvent {
|
||||||
pub connection_id: u64,
|
pub connection_id: u64,
|
||||||
pub hung_up: bool,
|
pub hung_up: bool,
|
||||||
|
@ -40,4 +42,7 @@ pub unsafe trait MappedRegion: Send + Sync {
|
||||||
|
|
||||||
/// Returns the size of the memory region in bytes.
|
/// Returns the size of the memory region in bytes.
|
||||||
fn size(&self) -> usize;
|
fn size(&self) -> usize;
|
||||||
|
|
||||||
|
/// Returns rutabaga mapping representation of the region
|
||||||
|
fn as_rutabaga_mapping(&self) -> RutabagaMapping;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue