devices: gpu: complete investigation of udmabuf driver
Hello everyone ..! After 2.5 years of "on the side" inquiries,
I have finally completed my investigations [1] of the udmabuf!!
udmabuf is a kernel driver that turns memfd pages into dmabufs.
The original hope was it would reduce texture upload costs for
virgl, which it did for larger textures [2]. But no measurable
improvements where seen with real games. In addition, a more
advanced "gfx-streaming" model has since come into the horizon[3][4],
which is more performant, conformant, secure and simpler than
virgl. As such, building more on virgl does not seem to be best
option, but that's another story for another day.
Where does that leave udmabuf, then?!? The investigation was
able to turn up two possible use cases:
1) Intel integrated + dGPU PCI-passthrough resource sharing
When the dGPU is passthroughed into the guest, the dGPU's memory
is not available to the host. Ideally, for zero-copy, we would
like to get the render target out of the guest somehow and then
send to the display. Many approaches have been proposed, such
as Vivek Kasireddy's Vdmabuf driver [5]. The current thinking
is virtgpu guest blobs can be exported, and then imported into
the dGPU -- Vivek is looking into this approach right now ..!!
Sommelier or virtgpu KMS can then share the guest blob with the
host. It's a quite complex use case and requires changes to guest
Mesa GBM to get (such as metadata query) to get the right modifier.
Indeed, some would even say you need a virtgpu context type optimized
for sharing across domain boundaries. minigbm already supports this
for Android upstream's Virtual Graphics Interface (VGI) initiative.
2) Guest VRAM dedicated heap created udmabufs
This use case, proposed by automative virtualization expert Dmitry
Sepp [6], is primarily for automotive hypervisors (such COQOS).
It's typically not easy for such hypervisors to get zero-copy via
BLOB_MEM_HOST3D, and these hypervisors have had their homebrew
versions of udmabuf for many years. It's important to upstream the
workarounds that are currently done for such hypervisors. To increase
security and isolation, a guest dedicated heap is preferred over guest
system memory. We might even need dedicated queues, who knows.
crosvm seems like the most likely upstream target due to it's world
class blob support and open-source nature. As such, this CL adds basic
udmabuf capabilites so these use cases can be developed further via
crosvm.
[1] https://www.youtube.com/watch?v=lp6z3s1Gig0
[2] crrev.com/c/1325515
[3] goto.google.com/address-space-graphics
[4] https://drive.google.com/file/d/19K_6M8QUeOn-x7HVYvoNfnuC6G5vkR8f/view
[5] https://lists.freedesktop.org/archives/dri-devel/2021-February/296177.html
[6] https://gitlab.freedesktop.org/virgl/virglrenderer/-/issues/159
BUG=chromium:892806, b:173630595
TEST=Create a bunch of udmabufs from the guest, with the subsequent
patches
Change-Id: Ia8083c0aa065f303f660ec6875ff5fb76f5d7b4f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2786290
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
2018-10-22 16:16:45 +00:00
|
|
|
// Copyright 2021 The Chromium OS Authors. All rights reservsize.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#![allow(dead_code)]
|
|
|
|
|
|
|
|
use std::fs::{File, OpenOptions};
|
|
|
|
use std::os::raw::c_uint;
|
|
|
|
|
|
|
|
use std::path::Path;
|
|
|
|
use std::{fmt, io};
|
|
|
|
|
|
|
|
use base::{
|
|
|
|
ioctl_iow_nr, ioctl_with_ptr, pagesize, AsRawDescriptor, FromRawDescriptor, MappedRegion,
|
|
|
|
SafeDescriptor,
|
|
|
|
};
|
|
|
|
|
2021-04-23 17:21:52 +00:00
|
|
|
use data_model::{flexible_array_impl, FlexibleArray, FlexibleArrayWrapper};
|
devices: gpu: complete investigation of udmabuf driver
Hello everyone ..! After 2.5 years of "on the side" inquiries,
I have finally completed my investigations [1] of the udmabuf!!
udmabuf is a kernel driver that turns memfd pages into dmabufs.
The original hope was it would reduce texture upload costs for
virgl, which it did for larger textures [2]. But no measurable
improvements where seen with real games. In addition, a more
advanced "gfx-streaming" model has since come into the horizon[3][4],
which is more performant, conformant, secure and simpler than
virgl. As such, building more on virgl does not seem to be best
option, but that's another story for another day.
Where does that leave udmabuf, then?!? The investigation was
able to turn up two possible use cases:
1) Intel integrated + dGPU PCI-passthrough resource sharing
When the dGPU is passthroughed into the guest, the dGPU's memory
is not available to the host. Ideally, for zero-copy, we would
like to get the render target out of the guest somehow and then
send to the display. Many approaches have been proposed, such
as Vivek Kasireddy's Vdmabuf driver [5]. The current thinking
is virtgpu guest blobs can be exported, and then imported into
the dGPU -- Vivek is looking into this approach right now ..!!
Sommelier or virtgpu KMS can then share the guest blob with the
host. It's a quite complex use case and requires changes to guest
Mesa GBM to get (such as metadata query) to get the right modifier.
Indeed, some would even say you need a virtgpu context type optimized
for sharing across domain boundaries. minigbm already supports this
for Android upstream's Virtual Graphics Interface (VGI) initiative.
2) Guest VRAM dedicated heap created udmabufs
This use case, proposed by automative virtualization expert Dmitry
Sepp [6], is primarily for automotive hypervisors (such COQOS).
It's typically not easy for such hypervisors to get zero-copy via
BLOB_MEM_HOST3D, and these hypervisors have had their homebrew
versions of udmabuf for many years. It's important to upstream the
workarounds that are currently done for such hypervisors. To increase
security and isolation, a guest dedicated heap is preferred over guest
system memory. We might even need dedicated queues, who knows.
crosvm seems like the most likely upstream target due to it's world
class blob support and open-source nature. As such, this CL adds basic
udmabuf capabilites so these use cases can be developed further via
crosvm.
[1] https://www.youtube.com/watch?v=lp6z3s1Gig0
[2] crrev.com/c/1325515
[3] goto.google.com/address-space-graphics
[4] https://drive.google.com/file/d/19K_6M8QUeOn-x7HVYvoNfnuC6G5vkR8f/view
[5] https://lists.freedesktop.org/archives/dri-devel/2021-February/296177.html
[6] https://gitlab.freedesktop.org/virgl/virglrenderer/-/issues/159
BUG=chromium:892806, b:173630595
TEST=Create a bunch of udmabufs from the guest, with the subsequent
patches
Change-Id: Ia8083c0aa065f303f660ec6875ff5fb76f5d7b4f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2786290
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
2018-10-22 16:16:45 +00:00
|
|
|
|
|
|
|
use rutabaga_gfx::{RutabagaHandle, RUTABAGA_MEM_HANDLE_TYPE_DMABUF};
|
|
|
|
|
2021-03-23 16:34:00 +00:00
|
|
|
use super::udmabuf_bindings::*;
|
|
|
|
|
devices: gpu: complete investigation of udmabuf driver
Hello everyone ..! After 2.5 years of "on the side" inquiries,
I have finally completed my investigations [1] of the udmabuf!!
udmabuf is a kernel driver that turns memfd pages into dmabufs.
The original hope was it would reduce texture upload costs for
virgl, which it did for larger textures [2]. But no measurable
improvements where seen with real games. In addition, a more
advanced "gfx-streaming" model has since come into the horizon[3][4],
which is more performant, conformant, secure and simpler than
virgl. As such, building more on virgl does not seem to be best
option, but that's another story for another day.
Where does that leave udmabuf, then?!? The investigation was
able to turn up two possible use cases:
1) Intel integrated + dGPU PCI-passthrough resource sharing
When the dGPU is passthroughed into the guest, the dGPU's memory
is not available to the host. Ideally, for zero-copy, we would
like to get the render target out of the guest somehow and then
send to the display. Many approaches have been proposed, such
as Vivek Kasireddy's Vdmabuf driver [5]. The current thinking
is virtgpu guest blobs can be exported, and then imported into
the dGPU -- Vivek is looking into this approach right now ..!!
Sommelier or virtgpu KMS can then share the guest blob with the
host. It's a quite complex use case and requires changes to guest
Mesa GBM to get (such as metadata query) to get the right modifier.
Indeed, some would even say you need a virtgpu context type optimized
for sharing across domain boundaries. minigbm already supports this
for Android upstream's Virtual Graphics Interface (VGI) initiative.
2) Guest VRAM dedicated heap created udmabufs
This use case, proposed by automative virtualization expert Dmitry
Sepp [6], is primarily for automotive hypervisors (such COQOS).
It's typically not easy for such hypervisors to get zero-copy via
BLOB_MEM_HOST3D, and these hypervisors have had their homebrew
versions of udmabuf for many years. It's important to upstream the
workarounds that are currently done for such hypervisors. To increase
security and isolation, a guest dedicated heap is preferred over guest
system memory. We might even need dedicated queues, who knows.
crosvm seems like the most likely upstream target due to it's world
class blob support and open-source nature. As such, this CL adds basic
udmabuf capabilites so these use cases can be developed further via
crosvm.
[1] https://www.youtube.com/watch?v=lp6z3s1Gig0
[2] crrev.com/c/1325515
[3] goto.google.com/address-space-graphics
[4] https://drive.google.com/file/d/19K_6M8QUeOn-x7HVYvoNfnuC6G5vkR8f/view
[5] https://lists.freedesktop.org/archives/dri-devel/2021-February/296177.html
[6] https://gitlab.freedesktop.org/virgl/virglrenderer/-/issues/159
BUG=chromium:892806, b:173630595
TEST=Create a bunch of udmabufs from the guest, with the subsequent
patches
Change-Id: Ia8083c0aa065f303f660ec6875ff5fb76f5d7b4f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2786290
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
2018-10-22 16:16:45 +00:00
|
|
|
use vm_memory::{GuestAddress, GuestMemory, GuestMemoryError};
|
|
|
|
|
|
|
|
const UDMABUF_IOCTL_BASE: c_uint = 0x75;
|
|
|
|
|
|
|
|
ioctl_iow_nr!(UDMABUF_CREATE, UDMABUF_IOCTL_BASE, 0x42, udmabuf_create);
|
|
|
|
ioctl_iow_nr!(
|
|
|
|
UDMABUF_CREATE_LIST,
|
|
|
|
UDMABUF_IOCTL_BASE,
|
|
|
|
0x43,
|
|
|
|
udmabuf_create_list
|
|
|
|
);
|
|
|
|
|
2021-04-23 17:21:52 +00:00
|
|
|
flexible_array_impl!(udmabuf_create_list, udmabuf_create_item, count, list);
|
devices: gpu: complete investigation of udmabuf driver
Hello everyone ..! After 2.5 years of "on the side" inquiries,
I have finally completed my investigations [1] of the udmabuf!!
udmabuf is a kernel driver that turns memfd pages into dmabufs.
The original hope was it would reduce texture upload costs for
virgl, which it did for larger textures [2]. But no measurable
improvements where seen with real games. In addition, a more
advanced "gfx-streaming" model has since come into the horizon[3][4],
which is more performant, conformant, secure and simpler than
virgl. As such, building more on virgl does not seem to be best
option, but that's another story for another day.
Where does that leave udmabuf, then?!? The investigation was
able to turn up two possible use cases:
1) Intel integrated + dGPU PCI-passthrough resource sharing
When the dGPU is passthroughed into the guest, the dGPU's memory
is not available to the host. Ideally, for zero-copy, we would
like to get the render target out of the guest somehow and then
send to the display. Many approaches have been proposed, such
as Vivek Kasireddy's Vdmabuf driver [5]. The current thinking
is virtgpu guest blobs can be exported, and then imported into
the dGPU -- Vivek is looking into this approach right now ..!!
Sommelier or virtgpu KMS can then share the guest blob with the
host. It's a quite complex use case and requires changes to guest
Mesa GBM to get (such as metadata query) to get the right modifier.
Indeed, some would even say you need a virtgpu context type optimized
for sharing across domain boundaries. minigbm already supports this
for Android upstream's Virtual Graphics Interface (VGI) initiative.
2) Guest VRAM dedicated heap created udmabufs
This use case, proposed by automative virtualization expert Dmitry
Sepp [6], is primarily for automotive hypervisors (such COQOS).
It's typically not easy for such hypervisors to get zero-copy via
BLOB_MEM_HOST3D, and these hypervisors have had their homebrew
versions of udmabuf for many years. It's important to upstream the
workarounds that are currently done for such hypervisors. To increase
security and isolation, a guest dedicated heap is preferred over guest
system memory. We might even need dedicated queues, who knows.
crosvm seems like the most likely upstream target due to it's world
class blob support and open-source nature. As such, this CL adds basic
udmabuf capabilites so these use cases can be developed further via
crosvm.
[1] https://www.youtube.com/watch?v=lp6z3s1Gig0
[2] crrev.com/c/1325515
[3] goto.google.com/address-space-graphics
[4] https://drive.google.com/file/d/19K_6M8QUeOn-x7HVYvoNfnuC6G5vkR8f/view
[5] https://lists.freedesktop.org/archives/dri-devel/2021-February/296177.html
[6] https://gitlab.freedesktop.org/virgl/virglrenderer/-/issues/159
BUG=chromium:892806, b:173630595
TEST=Create a bunch of udmabufs from the guest, with the subsequent
patches
Change-Id: Ia8083c0aa065f303f660ec6875ff5fb76f5d7b4f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2786290
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
2018-10-22 16:16:45 +00:00
|
|
|
type UdmabufCreateList = FlexibleArrayWrapper<udmabuf_create_list, udmabuf_create_item>;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum UdmabufError {
|
|
|
|
DriverOpenFailed(io::Error),
|
|
|
|
NotPageAligned,
|
|
|
|
InvalidOffset(GuestMemoryError),
|
|
|
|
DmabufCreationFail(io::Error),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for UdmabufError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
use self::UdmabufError::*;
|
|
|
|
match self {
|
|
|
|
DriverOpenFailed(e) => write!(f, "failed to open udmabuf driver: {:?}", e),
|
|
|
|
NotPageAligned => write!(f, "All guest addresses must aligned to 4KiB"),
|
|
|
|
InvalidOffset(e) => write!(f, "failed to get region offset: {:?}", e),
|
|
|
|
DmabufCreationFail(e) => write!(f, "failed to create buffer: {:?}", e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The result of an operation in this file.
|
|
|
|
pub type UdmabufResult<T> = std::result::Result<T, UdmabufError>;
|
|
|
|
|
|
|
|
// Returns absolute offset within the memory corresponding to a particular guest address.
|
|
|
|
// This offset is not relative to a particular mapping.
|
|
|
|
|
|
|
|
// # Examples
|
|
|
|
//
|
|
|
|
// # fn test_memory_offsets() {
|
|
|
|
// # let start_addr1 = GuestAddress(0x100)
|
|
|
|
// # let start_addr2 = GuestAddress(0x1100);
|
|
|
|
// # let mem = GuestMemory::new(&vec![(start_addr1, 0x1000),(start_addr2, 0x1000)])?;
|
|
|
|
// # assert_eq!(memory_offset(&mem, GuestAddress(0x1100), 0x1000).unwrap(),0x1000);
|
|
|
|
// #}
|
|
|
|
fn memory_offset(mem: &GuestMemory, guest_addr: GuestAddress, len: u64) -> UdmabufResult<u64> {
|
|
|
|
mem.do_in_region(guest_addr, move |mapping, map_offset, memfd_offset| {
|
|
|
|
let map_offset = map_offset as u64;
|
|
|
|
if map_offset
|
|
|
|
.checked_add(len)
|
|
|
|
.map_or(true, |a| a > mapping.size() as u64)
|
|
|
|
{
|
|
|
|
return Err(GuestMemoryError::InvalidGuestAddress(guest_addr));
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ok(memfd_offset + map_offset);
|
|
|
|
})
|
|
|
|
.map_err(UdmabufError::InvalidOffset)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A convenience wrapper for the Linux kernel's udmabuf driver.
|
|
|
|
///
|
|
|
|
/// udmabuf is a kernel driver that turns memfd pages into dmabufs. It can be used for
|
|
|
|
/// zero-copy buffer sharing between the guest and host when guest memory is backed by
|
|
|
|
/// memfd pages.
|
|
|
|
pub struct UdmabufDriver {
|
|
|
|
driver_fd: File,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UdmabufDriver {
|
|
|
|
/// Opens the udmabuf device on success.
|
|
|
|
pub fn new() -> UdmabufResult<UdmabufDriver> {
|
|
|
|
const UDMABUF_PATH: &str = "/dev/udmabuf";
|
|
|
|
let path = Path::new(UDMABUF_PATH);
|
|
|
|
let fd = OpenOptions::new()
|
|
|
|
.read(true)
|
|
|
|
.write(true)
|
|
|
|
.open(path)
|
|
|
|
.map_err(UdmabufError::DriverOpenFailed)?;
|
|
|
|
|
|
|
|
Ok(UdmabufDriver { driver_fd: fd })
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a dma-buf fd for the given scatter-gather list of guest memory pages (`iovecs`).
|
|
|
|
pub fn create_udmabuf(
|
|
|
|
&self,
|
|
|
|
mem: &GuestMemory,
|
|
|
|
iovecs: &[(GuestAddress, usize)],
|
|
|
|
) -> UdmabufResult<RutabagaHandle> {
|
|
|
|
let pgsize = pagesize();
|
|
|
|
|
|
|
|
let mut list = UdmabufCreateList::new(iovecs.len() as usize);
|
|
|
|
let mut items = list.mut_entries_slice();
|
|
|
|
for (i, &(addr, len)) in iovecs.iter().enumerate() {
|
|
|
|
let offset = memory_offset(mem, addr, len as u64)?;
|
|
|
|
|
|
|
|
if offset as usize % pgsize != 0 || len % pgsize != 0 {
|
|
|
|
return Err(UdmabufError::NotPageAligned);
|
|
|
|
}
|
|
|
|
|
2021-01-05 23:46:27 +00:00
|
|
|
// `unwrap` can't panic if `memory_offset obove succeeds.
|
|
|
|
items[i].memfd = mem.shm_region(addr).unwrap().as_raw_descriptor() as u32;
|
devices: gpu: complete investigation of udmabuf driver
Hello everyone ..! After 2.5 years of "on the side" inquiries,
I have finally completed my investigations [1] of the udmabuf!!
udmabuf is a kernel driver that turns memfd pages into dmabufs.
The original hope was it would reduce texture upload costs for
virgl, which it did for larger textures [2]. But no measurable
improvements where seen with real games. In addition, a more
advanced "gfx-streaming" model has since come into the horizon[3][4],
which is more performant, conformant, secure and simpler than
virgl. As such, building more on virgl does not seem to be best
option, but that's another story for another day.
Where does that leave udmabuf, then?!? The investigation was
able to turn up two possible use cases:
1) Intel integrated + dGPU PCI-passthrough resource sharing
When the dGPU is passthroughed into the guest, the dGPU's memory
is not available to the host. Ideally, for zero-copy, we would
like to get the render target out of the guest somehow and then
send to the display. Many approaches have been proposed, such
as Vivek Kasireddy's Vdmabuf driver [5]. The current thinking
is virtgpu guest blobs can be exported, and then imported into
the dGPU -- Vivek is looking into this approach right now ..!!
Sommelier or virtgpu KMS can then share the guest blob with the
host. It's a quite complex use case and requires changes to guest
Mesa GBM to get (such as metadata query) to get the right modifier.
Indeed, some would even say you need a virtgpu context type optimized
for sharing across domain boundaries. minigbm already supports this
for Android upstream's Virtual Graphics Interface (VGI) initiative.
2) Guest VRAM dedicated heap created udmabufs
This use case, proposed by automative virtualization expert Dmitry
Sepp [6], is primarily for automotive hypervisors (such COQOS).
It's typically not easy for such hypervisors to get zero-copy via
BLOB_MEM_HOST3D, and these hypervisors have had their homebrew
versions of udmabuf for many years. It's important to upstream the
workarounds that are currently done for such hypervisors. To increase
security and isolation, a guest dedicated heap is preferred over guest
system memory. We might even need dedicated queues, who knows.
crosvm seems like the most likely upstream target due to it's world
class blob support and open-source nature. As such, this CL adds basic
udmabuf capabilites so these use cases can be developed further via
crosvm.
[1] https://www.youtube.com/watch?v=lp6z3s1Gig0
[2] crrev.com/c/1325515
[3] goto.google.com/address-space-graphics
[4] https://drive.google.com/file/d/19K_6M8QUeOn-x7HVYvoNfnuC6G5vkR8f/view
[5] https://lists.freedesktop.org/archives/dri-devel/2021-February/296177.html
[6] https://gitlab.freedesktop.org/virgl/virglrenderer/-/issues/159
BUG=chromium:892806, b:173630595
TEST=Create a bunch of udmabufs from the guest, with the subsequent
patches
Change-Id: Ia8083c0aa065f303f660ec6875ff5fb76f5d7b4f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2786290
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
2018-10-22 16:16:45 +00:00
|
|
|
items[i].__pad = 0;
|
|
|
|
items[i].offset = offset;
|
|
|
|
items[i].size = len as u64;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Safe because we always allocate enough space for `udmabuf_create_list`.
|
|
|
|
let fd = unsafe {
|
|
|
|
let create_list = list.as_mut_ptr();
|
|
|
|
(*create_list).flags = UDMABUF_FLAGS_CLOEXEC;
|
|
|
|
ioctl_with_ptr(&self.driver_fd, UDMABUF_CREATE_LIST(), create_list)
|
|
|
|
};
|
|
|
|
|
|
|
|
if fd < 0 {
|
|
|
|
return Err(UdmabufError::DmabufCreationFail(io::Error::last_os_error()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Safe because we validated the file exists.
|
|
|
|
let os_handle = unsafe { SafeDescriptor::from_raw_descriptor(fd) };
|
|
|
|
Ok(RutabagaHandle {
|
|
|
|
os_handle,
|
|
|
|
handle_type: RUTABAGA_MEM_HANDLE_TYPE_DMABUF,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use base::kernel_has_memfd;
|
|
|
|
use vm_memory::GuestAddress;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_memory_offsets() {
|
|
|
|
if !kernel_has_memfd() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let start_addr1 = GuestAddress(0x100);
|
|
|
|
let start_addr2 = GuestAddress(0x1100);
|
|
|
|
let start_addr3 = GuestAddress(0x2100);
|
|
|
|
|
|
|
|
let mem = GuestMemory::new(&vec![
|
|
|
|
(start_addr1, 0x1000),
|
|
|
|
(start_addr2, 0x1000),
|
|
|
|
(start_addr3, 0x1000),
|
|
|
|
])
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_eq!(memory_offset(&mem, GuestAddress(0x300), 1).unwrap(), 0x200);
|
|
|
|
assert_eq!(
|
|
|
|
memory_offset(&mem, GuestAddress(0x1200), 1).unwrap(),
|
|
|
|
0x1100
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
memory_offset(&mem, GuestAddress(0x1100), 0x1000).unwrap(),
|
|
|
|
0x1000
|
|
|
|
);
|
|
|
|
assert!(memory_offset(&mem, GuestAddress(0x1100), 0x1001).is_err());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_udmabuf_create() {
|
|
|
|
if !kernel_has_memfd() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let driver_result = UdmabufDriver::new();
|
|
|
|
|
|
|
|
// Most kernels will not have udmabuf support.
|
|
|
|
if driver_result.is_err() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let driver = driver_result.unwrap();
|
|
|
|
|
|
|
|
let start_addr1 = GuestAddress(0x100);
|
|
|
|
let start_addr2 = GuestAddress(0x1100);
|
|
|
|
let start_addr3 = GuestAddress(0x2100);
|
|
|
|
|
|
|
|
let sg_list = vec![
|
|
|
|
(start_addr1, 0x1000),
|
|
|
|
(start_addr2, 0x1000),
|
|
|
|
(start_addr3, 0x1000),
|
|
|
|
];
|
|
|
|
|
|
|
|
let mem = GuestMemory::new(&sg_list[..]).unwrap();
|
|
|
|
|
|
|
|
let mut udmabuf_create_list = vec![
|
|
|
|
(start_addr3, 0x1000 as usize),
|
|
|
|
(start_addr2, 0x1000 as usize),
|
|
|
|
(start_addr1, 0x1000 as usize),
|
|
|
|
(GuestAddress(0x4000), 0x1000 as usize),
|
|
|
|
];
|
|
|
|
|
|
|
|
let result = driver.create_udmabuf(&mem, &udmabuf_create_list[..]);
|
|
|
|
assert_eq!(result.is_err(), true);
|
|
|
|
|
|
|
|
udmabuf_create_list.pop();
|
|
|
|
|
|
|
|
let rutabaga_handle1 = driver
|
|
|
|
.create_udmabuf(&mem, &udmabuf_create_list[..])
|
|
|
|
.unwrap();
|
|
|
|
assert_eq!(
|
|
|
|
rutabaga_handle1.handle_type,
|
|
|
|
RUTABAGA_MEM_HANDLE_TYPE_DMABUF
|
|
|
|
);
|
|
|
|
|
|
|
|
udmabuf_create_list.pop();
|
|
|
|
|
|
|
|
// Multiple udmabufs with same memory backing is allowed.
|
|
|
|
let rutabaga_handle2 = driver
|
|
|
|
.create_udmabuf(&mem, &udmabuf_create_list[..])
|
|
|
|
.unwrap();
|
|
|
|
assert_eq!(
|
|
|
|
rutabaga_handle2.handle_type,
|
|
|
|
RUTABAGA_MEM_HANDLE_TYPE_DMABUF
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|