support dmabuf in virtio_wl

This commit is contained in:
Bruce Leidl 2019-09-23 15:20:28 -04:00
parent 3e5b802487
commit 0a06043e32
12 changed files with 417 additions and 18 deletions

View File

@ -160,6 +160,12 @@ impl InitServer {
}
pub fn run_daemons(&mut self) -> Result<()> {
if !Path::new("/dev/wl0").exists() {
return Ok(());
}
chmod("/dev/wl0", 0o666)?;
let dbus = ServiceLaunch::new("dbus-daemon", "/usr/bin/dbus-daemon")
.base_environment()
.uidgid(1000,1000)
@ -178,20 +184,34 @@ impl InitServer {
self.services.insert(dbus.pid(), dbus);
let shm_driver = if self.cmdline.has_var("phinit.virtwl_dmabuf") {
"virtwl-dmabuf"
} else {
"virtwl"
};
let sommelier = ServiceLaunch::new("sommelier", "/opt/ph/usr/bin/sommelier")
.base_environment()
.uidgid(1000,1000)
.env("SOMMELIER_SHM_DRIVER", shm_driver)
.arg("--master")
.pipe_output()
.launch()?;
self.services.insert(sommelier.pid(), sommelier);
Self::write_xauth().map_err(Error::XAuthFail)?;
if self.cmdline.has_var("phinit.no_x11") {
return Ok(());
}
mkdir_mode("/tmp/.X11-unix", 0o1777)?;
self.write_xauth().map_err(Error::XAuthFail)?;
let sommelierx = ServiceLaunch::new("sommelier-x", "/opt/ph/usr/bin/sommelier")
.base_environment()
.uidgid(1000,1000)
.env("SOMMELIER_SHM_DRIVER", shm_driver)
.arg("-X")
.arg("--x-display=0")
.arg("--no-exit-with-child")

View File

@ -4,10 +4,19 @@ use std::thread;
use crate::{vm, system};
use crate::system::EPoll;
use crate::memory::MemoryManager;
use crate::memory::{MemoryManager, DrmDescriptor};
use crate::virtio::{VirtQueue, EventFd, Chain, VirtioBus, VirtioDeviceOps};
use crate::devices::virtio_wl::{vfd::VfdManager, consts::*, Error, Result, VfdObject};
use crate::system::ioctl::ioctl_with_ref;
use std::os::raw::{c_ulong, c_uint, c_ulonglong};
#[repr(C)]
struct dma_buf_sync {
flags: c_ulonglong,
}
const DMA_BUF_IOCTL_BASE: c_uint = 0x62;
const DMA_BUF_IOCTL_SYNC: c_ulong = iow!(DMA_BUF_IOCTL_BASE, 0, ::std::mem::size_of::<dma_buf_sync>() as i32);
pub struct VirtioWayland {
feature_bits: u64,
@ -165,6 +174,8 @@ impl <'a> MessageHandler<'a> {
VIRTIO_WL_CMD_VFD_NEW => self.cmd_new_alloc(),
VIRTIO_WL_CMD_VFD_CLOSE => self.cmd_close(),
VIRTIO_WL_CMD_VFD_SEND => self.cmd_send(),
VIRTIO_WL_CMD_VFD_NEW_DMABUF => self.cmd_new_dmabuf(),
VIRTIO_WL_CMD_VFD_DMABUF_SYNC => self.cmd_dmabuf_sync(),
VIRTIO_WL_CMD_VFD_NEW_CTX => self.cmd_new_ctx(),
VIRTIO_WL_CMD_VFD_NEW_PIPE => self.cmd_new_pipe(),
v => {
@ -198,6 +209,70 @@ impl <'a> MessageHandler<'a> {
Ok(())
}
fn cmd_new_dmabuf(&mut self) -> Result<()> {
let id = self.chain.r32()?;
let _flags = self.chain.r32()?;
let _pfn = self.chain.r64()?;
let _size = self.chain.r32()?;
let width = self.chain.r32()?;
let height = self.chain.r32()?;
let format = self.chain.r32()?;
match self.device.vfd_manager.create_dmabuf(id, width,height, format) {
Ok((pfn, size, desc)) => self.resp_dmabuf_new(id, pfn, size as u32, desc),
Err(e) => {
if !(height == 0 && width == 0) {
warn!("virtio_wl: Failed to create dmabuf: {}", e);
}
self.responded = true;
self.send_err()
}
}
}
fn resp_dmabuf_new(&mut self, id: u32, pfn: u64, size: u32, desc: DrmDescriptor) -> Result<()> {
self.chain.w32(VIRTIO_WL_RESP_VFD_NEW_DMABUF)?;
self.chain.w32(0)?;
self.chain.w32(id)?;
self.chain.w32(0)?;
self.chain.w64(pfn)?;
self.chain.w32(size)?;
self.chain.w32(0)?;
self.chain.w32(0)?;
self.chain.w32(0)?;
self.chain.w32(desc.planes[0].stride)?;
self.chain.w32(desc.planes[1].stride)?;
self.chain.w32(desc.planes[2].stride)?;
self.chain.w32(desc.planes[0].offset)?;
self.chain.w32(desc.planes[1].offset)?;
self.chain.w32(desc.planes[2].offset)?;
self.responded = true;
Ok(())
}
fn cmd_dmabuf_sync(&mut self) -> Result<()> {
let id = self.chain.r32()?;
let flags = self.chain.r32()?;
let vfd = match self.device.get_mut_vfd(id) {
Some(vfd) => vfd,
None => return self.send_invalid_id(),
};
let fd = match vfd.send_fd() {
Some(fd) => fd,
None => return self.send_invalid_id(),
};
unsafe {
let sync = dma_buf_sync {
flags: flags as u64,
};
ioctl_with_ref(fd, DMA_BUF_IOCTL_SYNC, &sync).map_err(Error::DmaSync)?;
}
self.send_ok()
}
fn cmd_close(&mut self) -> Result<()> {
let id = self.chain.r32()?;
self.device.vfd_manager.close_vfd(id)?;

View File

@ -23,8 +23,11 @@ mod consts {
pub const VIRTIO_WL_CMD_VFD_NEW_CTX: u32 = 260;
pub const VIRTIO_WL_CMD_VFD_NEW_PIPE: u32 = 261;
pub const VIRTIO_WL_CMD_VFD_HUP: u32 = 262;
pub const VIRTIO_WL_CMD_VFD_NEW_DMABUF: u32 = 263;
pub const VIRTIO_WL_CMD_VFD_DMABUF_SYNC: u32 = 264;
pub const VIRTIO_WL_RESP_OK: u32 = 4096;
pub const VIRTIO_WL_RESP_VFD_NEW: u32 = 4097;
pub const VIRTIO_WL_RESP_VFD_NEW_DMABUF: u32 = 4098;
pub const VIRTIO_WL_RESP_ERR: u32 = 4352;
pub const VIRTIO_WL_RESP_OUT_OF_MEMORY: u32 = 4353;
pub const VIRTIO_WL_RESP_INVALID_ID: u32 = 4354;
@ -93,6 +96,9 @@ pub enum Error {
TooManySendVfds(usize),
FailedPollContextCreate(system::Error),
FailedPollAdd(system::Error),
DmaSync(vm::Error),
DmaBuf(MemError),
DmaBufSize(system::Error),
}
impl fmt::Display for Error {
@ -113,6 +119,9 @@ impl fmt::Display for Error {
TooManySendVfds(n) => write!(f, "message has too many vfd ids: {}", n),
FailedPollContextCreate(e) => write!(f, "failed creating poll context: {}", e),
FailedPollAdd(e) => write!(f, "failed adding fd to poll context: {}", e),
DmaSync(e) => write!(f, "error calling dma sync: {}", e),
DmaBuf(e) => write!(f, "failed creating DMA buf: {}", e),
DmaBufSize(e) => write!(f, "failed getting DMA buf size: {}", e),
}
}
}

View File

@ -1,6 +1,6 @@
use std::os::unix::io::{AsRawFd,RawFd};
use crate::memory::MemoryManager;
use crate::memory::{MemoryManager, DrmDescriptor};
use crate::system::MemoryFd;
use crate::devices::virtio_wl::{
@ -37,6 +37,15 @@ impl VfdSharedMemory {
.map_err(Error::RegisterMemoryFailed)?;
Ok(Self::new(vfd_id, transition_flags, mm.clone(), memfd, slot, pfn))
}
pub fn create_dmabuf(vfd_id: u32, tflags: bool, width: u32, height: u32, format: u32, mm: &MemoryManager) -> Result<(Self, DrmDescriptor)> {
let (pfn, slot, fd, desc) = mm.allocate_drm_buffer(width, height, format)
.map_err(Error::DmaBuf)?;
let memfd = MemoryFd::from_filedesc(fd)
.map_err(Error::DmaBufSize)?;
let vfd = Self::new(vfd_id, tflags, mm.clone(), memfd, slot, pfn);
Ok((vfd, desc))
}
}
impl VfdObject for VfdSharedMemory {

View File

@ -4,7 +4,7 @@ use std::os::unix::io::{AsRawFd,RawFd};
use std::path::PathBuf;
use std::time::Duration;
use crate::memory::MemoryManager;
use crate::memory::{MemoryManager, DrmDescriptor};
use crate::system::{FileDesc, FileFlags,EPoll,MemoryFd};
use crate::virtio::{VirtQueue, Chain};
@ -68,6 +68,13 @@ impl VfdManager {
Ok((pfn,size))
}
pub fn create_dmabuf(&mut self, vfd_id: u32, width: u32, height: u32, format: u32) -> Result<(u64, u64, DrmDescriptor)> {
let (vfd, desc) = VfdSharedMemory::create_dmabuf(vfd_id, self.use_transition_flags, width, height, format, &self.mm)?;
let (pfn, size) = vfd.pfn_and_size().unwrap();
self.vfd_map.insert(vfd_id, Box::new(vfd));
Ok((pfn, size, desc))
}
pub fn create_socket(&mut self, vfd_id: u32) -> Result<u32> {
let sock = VfdSocket::open(vfd_id, self.use_transition_flags,&self.wayland_path)?;
self.poll_ctx.add_read(sock.poll_fd().unwrap(), vfd_id as u64)

View File

@ -4,9 +4,9 @@
#[macro_use] mod log;
mod vm;
mod memory;
#[macro_use]
mod system;
mod memory;
mod devices;
mod kvm;
mod virtio;

192
src/memory/drm.rs Normal file
View File

@ -0,0 +1,192 @@
use std::fs::{OpenOptions, File};
use std::os::raw::{c_ulong, c_int, c_uint};
use std::os::unix::io::{RawFd,AsRawFd};
use std::path::Path;
use std::sync::Arc;
use crate::system::{self, ioctl::ioctl_with_mut_ref, FileDesc };
use crate::memory::{Error,Result};
#[derive(Default,Debug)]
pub struct DrmPlaneDescriptor {
pub stride: u32,
pub offset: u32,
}
#[derive(Default,Debug)]
pub struct DrmDescriptor {
pub planes: [DrmPlaneDescriptor; 3]
}
#[derive(Clone)]
pub struct DrmBufferAllocator {
dev: Arc<DrmDevice>,
}
impl DrmBufferAllocator {
pub fn open() -> Result<Self> {
let dev = DrmDevice::open_render_node()?;
Ok(DrmBufferAllocator{
dev: Arc::new(dev)
})
}
pub fn allocate(&self, width: u32, height: u32, format: u32) -> Result<(FileDesc, DrmDescriptor)> {
const GBM_BO_USE_LINEAR: u32 = 16;
let buffer = self.create_buffer(width, height, format, GBM_BO_USE_LINEAR)?;
let fd = buffer.buffer_fd()?;
Ok((fd, buffer.drm_descriptor()))
}
fn create_buffer(&self, width: u32, height: u32, format: u32, flags: u32) -> Result<DrmBuffer> {
let bo = unsafe {
gbm_bo_create(self.dev.gbm, width, height, format, flags)
};
if bo.is_null() {
let e = system::Error::last_os_error();
Err(Error::GbmCreateBuffer(e))
} else {
Ok(DrmBuffer::new(self.dev.clone(), bo))
}
}
}
struct DrmDevice {
file: File,
gbm: *mut GbmDevice,
}
impl DrmDevice {
fn open_render_node() -> Result<Self> {
let path = Path::new("/dev/dri/renderD128");
let file = OpenOptions::new()
.read(true)
.write(true)
.open(path)
.map_err(Error::OpenRenderNode)?;
Self::create(file)
}
fn create(file: File) -> Result<Self> {
let gbm = unsafe { gbm_create_device(file.as_raw_fd()) };
if gbm.is_null() {
let e = system::Error::last_os_error();
Err(Error::GbmCreateDevice(e))
} else {
Ok(DrmDevice{ file, gbm })
}
}
}
impl Drop for DrmDevice {
fn drop(&mut self) {
unsafe { gbm_device_destroy(self.gbm); }
}
}
impl AsRawFd for DrmDevice {
fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
}
}
pub struct DrmBuffer {
dev: Arc<DrmDevice>,
bo: *mut GbmBo,
}
unsafe impl Send for DrmDevice {}
unsafe impl Sync for DrmDevice {}
impl DrmBuffer {
fn new(dev: Arc<DrmDevice>, bo: *mut GbmBo) -> Self {
DrmBuffer { dev, bo }
}
fn drm_descriptor(&self) -> DrmDescriptor {
let mut desc = DrmDescriptor::default();
for i in 0..self.plane_count() {
if self.plane_handle(i) == self.plane_handle(0) {
desc.planes[i].stride = self.plane_stride(i);
desc.planes[i].offset = self.plane_offset(i);
}
}
desc
}
fn plane_count(&self) -> usize {
unsafe { gbm_bo_get_plane_count(self.bo) }
}
fn plane_handle(&self, plane: usize) -> u32 {
unsafe { gbm_bo_get_handle_for_plane(self.bo, plane).u32 }
}
fn plane_offset(&self, plane: usize) -> u32 {
unsafe { gbm_bo_get_offset(self.bo, plane) }
}
fn plane_stride(&self, plane: usize) -> u32 {
unsafe { gbm_bo_get_stride_for_plane(self.bo, plane) }
}
fn buffer_fd(&self) -> Result<FileDesc> {
const DRM_CLOEXEC: u32 = libc::O_CLOEXEC as u32;
const DRM_RDWR: u32 = libc::O_RDWR as u32;
let mut prime = DrmPrimeHandle {
handle: self.plane_handle(0),
flags: DRM_CLOEXEC | DRM_RDWR,
..Default::default()
};
unsafe {
ioctl_with_mut_ref(self.dev.as_raw_fd(), DRM_IOCTL_PRIME_HANDLE_TO_FD, &mut prime)
.map_err(Error::PrimeHandleToFD)?;
}
Ok(FileDesc::new(prime.fd))
}
}
impl Drop for DrmBuffer {
fn drop(&mut self) {
unsafe { gbm_bo_destroy(self.bo); }
}
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
struct DrmPrimeHandle {
pub handle: c_uint,
pub flags: c_uint,
pub fd: c_int,
}
const DRM_IOCTL_BASE: c_uint = 0x64;
const DRM_IOCTL_PRIME_HANDLE_TO_FD: c_ulong = iorw!(DRM_IOCTL_BASE, 0x2d, ::std::mem::size_of::<DrmPrimeHandle>() as i32);
#[repr(C)]
struct GbmDevice([u8; 0]);
#[repr(C)]
struct GbmBo([u8; 0]);
#[repr(C)]
pub union GbmBoHandle {
pub u32: u32,
_align: u64,
}
#[link(name = "gbm")]
extern "C" {
fn gbm_bo_create(gbm: *mut GbmDevice, width: u32, height: u32, format: u32, flags: u32) -> *mut GbmBo;
fn gbm_create_device(fd: libc::c_int) -> *mut GbmDevice;
fn gbm_device_destroy(gbm: *mut GbmDevice);
fn gbm_bo_destroy(bo: *mut GbmBo);
fn gbm_bo_get_plane_count(bo: *mut GbmBo) -> usize;
fn gbm_bo_get_handle_for_plane(bo: *mut GbmBo, plane: usize) -> GbmBoHandle;
fn gbm_bo_get_offset(bo: *mut GbmBo, plane: usize) -> u32;
fn gbm_bo_get_stride_for_plane(bo: *mut GbmBo, plane: usize) -> u32;
}

View File

@ -1,25 +1,34 @@
use std::collections::HashMap;
use std::os::unix::io::RawFd;
use std::os::unix::io::{AsRawFd,RawFd};
use std::sync::{Arc, RwLock};
use crate::memory::{GuestRam, SystemAllocator, Mapping, Error, Result};
use crate::kvm::Kvm;
use crate::system::BitVec;
use crate::system::{BitVec, FileDesc};
use crate::memory::drm::{DrmBufferAllocator, DrmDescriptor};
use std::io::SeekFrom;
#[derive(Clone)]
pub struct MemoryManager {
kvm: Kvm,
ram: GuestRam,
device_memory: Arc<RwLock<DeviceMemory>>,
drm_allocator: Option<DrmBufferAllocator>,
}
impl MemoryManager {
pub fn new(kvm: Kvm, ram: GuestRam, allocator: SystemAllocator) -> Self {
pub fn new(kvm: Kvm, ram: GuestRam, allocator: SystemAllocator, use_drm: bool) -> Result<Self> {
let device_memory = RwLock::new(DeviceMemory::new(ram.region_count(), allocator)).into();
MemoryManager {
let drm_allocator = if use_drm {
DrmBufferAllocator::open().ok()
} else {
None
};
Ok(MemoryManager {
kvm, ram, device_memory,
}
drm_allocator,
})
}
pub fn guest_ram(&self) -> &GuestRam {
@ -43,6 +52,22 @@ impl MemoryManager {
let mut devmem = self.device_memory.write().unwrap();
devmem.unregister(self.kvm(), slot)
}
pub fn drm_available(&self) -> bool {
self.drm_allocator.is_some()
}
pub fn allocate_drm_buffer(&self, width: u32, height: u32, format: u32) -> Result<(u64, u32, FileDesc, DrmDescriptor)> {
if let Some(drm_allocator) = self.drm_allocator.as_ref() {
let (fd, desc) = drm_allocator.allocate(width, height, format)?;
let size = fd.seek(SeekFrom::End(0)).map_err(Error::CreateBuffer)?;
let (pfn, slot) = self.register_device_memory(fd.as_raw_fd(), size as usize)?;
Ok((pfn, slot, fd, desc))
} else {
Err(Error::NoDrmAllocator)
}
}
}
pub struct MemoryRegistration {

View File

@ -1,4 +1,5 @@
mod ram;
mod drm;
mod manager;
mod mmap;
mod address;
@ -10,8 +11,12 @@ pub use self::mmap::Mapping;
pub use self::ram::GuestRam;
pub use self::ram::{PCI_MMIO_RESERVED_BASE,HIMEM_BASE};
pub use manager::MemoryManager;
pub use drm::{DrmDescriptor,DrmPlaneDescriptor};
use crate::vm::Error as VmError;
use std::{result, fmt};
use std::{result, fmt, io};
use crate::system;
pub const KVM_KERNEL_LOAD_ADDRESS: u64 = 0x1000000;
pub const KERNEL_CMDLINE_ADDRESS: u64 = 0x20000;
@ -23,6 +28,12 @@ pub enum Error {
MappingFailed(VmError),
RegisterMemoryFailed(VmError),
UnregisterMemoryFailed(VmError),
GbmCreateDevice(system::Error),
GbmCreateBuffer(system::Error),
OpenRenderNode(io::Error),
PrimeHandleToFD(VmError),
CreateBuffer(io::Error),
NoDrmAllocator,
}
impl fmt::Display for Error {
@ -33,6 +44,12 @@ impl fmt::Display for Error {
MappingFailed(e) => write!(f, "failed to create memory mapping for device memory: {}", e),
RegisterMemoryFailed(e) => write!(f, "failed to register memory for device memory: {}", e),
UnregisterMemoryFailed(e) => write!(f, "failed to unregister memory for device memory: {}", e),
GbmCreateDevice(e) => write!(f, "failed to open device with libgbm: {}", e),
GbmCreateBuffer(e) => write!(f, "failed to allocate buffer with libgbm: {}", e),
PrimeHandleToFD(err) => write!(f, "exporting prime handle to fd failed: {}", err),
OpenRenderNode(err) => write!(f, "error opening render node: {}", err),
CreateBuffer(err) => write!(f, "failed to create buffer: {}", err),
NoDrmAllocator => write!(f, "no DRM allocator is available"),
}
}
}

View File

@ -11,6 +11,8 @@ pub struct VmConfig {
ncpus: usize,
verbose: bool,
rootshell: bool,
wayland: bool,
dmabuf: bool,
home: String,
launch_systemd: bool,
kernel_path: Option<PathBuf>,
@ -31,8 +33,9 @@ impl VmConfig {
ncpus: 1,
verbose: false,
rootshell: false,
home: String::from("/home/user"),
launch_systemd: false,
wayland: true,
dmabuf: false,
home: Self::default_homedir(),
kernel_path: None,
init_path: None,
init_cmd: None,
@ -45,6 +48,15 @@ impl VmConfig {
config
}
fn default_homedir() -> String {
if let Ok(home) = env::var("HOME") {
if Path::new(&home).exists() {
return home;
}
}
String::from("/home/user")
}
pub fn ram_size_megs(mut self, megs: usize) -> Self {
self.ram_size = megs * 1024 * 1024;
self
@ -155,6 +167,21 @@ impl VmConfig {
self.realm_name.as_ref().map(|s| s.as_str())
}
pub fn is_wayland_enabled(&self) -> bool {
if !self.wayland {
return false;
}
let display = env::var("WAYLAND_DISPLAY").unwrap_or("wayland-0".to_string());
let xdg_runtime = env::var("XDG_RUNTIME_DIR").unwrap_or("/run/user/1000".to_string());
let socket= Path::new(xdg_runtime.as_str()).join(display);
socket.exists()
}
pub fn is_dmabuf_enabled(&self) -> bool {
self.dmabuf
}
fn add_realmfs_by_name(&mut self, realmfs: &str) {
let path = Path::new("/realms/realmfs-images")
.join(format!("{}-realmfs.img", realmfs));
@ -184,6 +211,13 @@ impl VmConfig {
if args.has_arg("--root") {
self.rootshell = true;
}
if args.has_arg("--no-wayland") {
self.wayland = false;
self.dmabuf = false;
}
if args.has_arg("--use-dmabuf") {
self.dmabuf = true;
}
if let Some(home) = args.arg_with_value("--home") {
self.home = home.to_string();
}

View File

@ -25,6 +25,7 @@ pub enum ErrorKind {
DiskImageOpen(disk::Error),
TerminalTermios(io::Error),
IoError(io::Error),
MemoryManagerCreate,
}
impl ErrorKind {
@ -45,6 +46,7 @@ impl ErrorKind {
ErrorKind::DiskImageOpen(_) => "failed to open disk image",
ErrorKind::TerminalTermios(_) => "failed termios",
ErrorKind::IoError(_) => "i/o error",
ErrorKind::MemoryManagerCreate => "memory manager",
}
}
}
@ -58,6 +60,7 @@ impl fmt::Display for ErrorKind {
ErrorKind::DiskImageOpen(ref e) => write!(f, "failed to open disk image: {}", e),
ErrorKind::TerminalTermios(ref e) => write!(f, "error reading/restoring terminal state: {}", e),
ErrorKind::IoError(ref e) => write!(f, "i/o error: {}", e),
ErrorKind::MemoryManagerCreate => write!(f, "error creating memory manager"),
_ => write!(f, "{}", self.as_str()),
}
}

View File

@ -67,20 +67,22 @@ impl Vm {
kvm.create_irqchip()?;
Ok(kvm)
}
fn create_memory_manager(ram_size: usize) -> Result<MemoryManager> {
fn create_memory_manager(ram_size: usize, use_drm: bool) -> Result<MemoryManager> {
let kvm = Self::create_kvm()?;
let ram = GuestRam::new(ram_size, &kvm)?;
let dev_addr_start = get_base_dev_pfn(ram_size as u64) * 4096;
let dev_addr_size = u64::max_value() - dev_addr_start;
let allocator = SystemAllocator::new(AddressRange::new(dev_addr_start,dev_addr_size as usize));
Ok(MemoryManager::new(kvm, ram, allocator))
Ok(MemoryManager::new(kvm, ram, allocator, use_drm).map_err(|_| ErrorKind::MemoryManagerCreate)?)
}
fn setup_virtio(config: &mut VmConfig, cmdline: &mut KernelCmdLine, virtio: &mut VirtioBus) -> Result<()> {
devices::VirtioSerial::create(virtio)?;
devices::VirtioRandom::create(virtio)?;
devices::VirtioWayland::create(virtio)?;
devices::VirtioP9::create(virtio, "home", config.homedir(), false, false)?;
if config.is_wayland_enabled() {
devices::VirtioWayland::create(virtio)?;
}
let mut block_root = false;
@ -131,7 +133,8 @@ impl Vm {
pub fn open(mut config: VmConfig) -> Result<Vm> {
let mut memory = Self::create_memory_manager(config.ram_size())?;
let with_drm = config.is_wayland_enabled() && config.is_dmabuf_enabled();
let mut memory = Self::create_memory_manager(config.ram_size(), with_drm)?;
let mut cmdline = KernelCmdLine::new_default();
@ -152,6 +155,11 @@ impl Vm {
if config.rootshell() {
cmdline.push("phinit.rootshell");
}
if memory.drm_available() && config.is_dmabuf_enabled() {
cmdline.push("phinit.virtwl_dmabuf");
}
if let Some(realm) = config.realm_name() {
cmdline.push_set_val("phinit.realm", realm);
}