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

Implement SHM region management and re-enable DAX in virtiofs #212

Merged
merged 7 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
57 changes: 45 additions & 12 deletions include/libkrun.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,24 @@ int32_t krun_add_virtiofs(uint32_t ctx_id,
const char *c_tag,
const char *c_path);

/**
* Adds an independent virtio-fs device pointing to a host's directory with a tag. This
* variant allows specifying the size of the DAX window.
*
* Arguments:
* "ctx_id" - the configuration context ID.
* "c_tag" - tag to identify the filesystem in the guest.
* "c_path" - full path to the directory in the host to be exposed to the guest.
* "shm_size" - size of the DAX SHM window in bytes.
*
* Returns:
* Zero on success or a negative error number on failure.
*/
int32_t krun_add_virtiofs2(uint32_t ctx_id,
const char *c_tag,
const char *c_path,
uint64_t shm_size);

/**
* Configures the networking to use passt.
* Call to this function disables TSI backend to use passt instead.
Expand Down Expand Up @@ -154,7 +172,7 @@ int32_t krun_set_passt_fd(uint32_t ctx_id, int fd);
* Returns:
* Zero on success or a negative error number on failure.
*/
int32_t krun_set_gvproxy_path(uint32_t ctx_id, char* c_path);
int32_t krun_set_gvproxy_path(uint32_t ctx_id, char *c_path);

/**
* Sets the MAC address for the virtio-net device when using the passt backend.
Expand Down Expand Up @@ -196,17 +214,17 @@ int32_t krun_set_net_mac(uint32_t ctx_id, uint8_t *const c_mac);
int32_t krun_set_port_map(uint32_t ctx_id, const char *const port_map[]);

/* Flags for virglrenderer. Copied from virglrenderer bindings. */
#define VIRGLRENDERER_USE_EGL 1 << 0
#define VIRGLRENDERER_THREAD_SYNC 1 << 1
#define VIRGLRENDERER_USE_GLX 1 << 2
#define VIRGLRENDERER_USE_SURFACELESS 1 << 3
#define VIRGLRENDERER_USE_GLES 1 << 4
#define VIRGLRENDERER_USE_EXTERNAL_BLOB 1 << 5
#define VIRGLRENDERER_VENUS 1 << 6
#define VIRGLRENDERER_NO_VIRGL 1 << 7
#define VIRGLRENDERER_USE_EGL 1 << 0
#define VIRGLRENDERER_THREAD_SYNC 1 << 1
#define VIRGLRENDERER_USE_GLX 1 << 2
#define VIRGLRENDERER_USE_SURFACELESS 1 << 3
#define VIRGLRENDERER_USE_GLES 1 << 4
#define VIRGLRENDERER_USE_EXTERNAL_BLOB 1 << 5
#define VIRGLRENDERER_VENUS 1 << 6
#define VIRGLRENDERER_NO_VIRGL 1 << 7
#define VIRGLRENDERER_USE_ASYNC_FENCE_CB 1 << 8
#define VIRGLRENDERER_RENDER_SERVER 1 << 9
#define VIRGLRENDERER_DRM 1 << 10
#define VIRGLRENDERER_RENDER_SERVER 1 << 9
#define VIRGLRENDERER_DRM 1 << 10
/**
* Enables and configures a virtio-gpu device.
*
Expand All @@ -219,6 +237,22 @@ int32_t krun_set_port_map(uint32_t ctx_id, const char *const port_map[]);
*/
int32_t krun_set_gpu_options(uint32_t ctx_id, uint32_t virgl_flags);

/**
* Enables and configures a virtio-gpu device. This variant allows specifying
* the size of the host window (acting as vRAM in the guest).
*
* Arguments:
* "ctx_id" - the configuration context ID.
* "virgl_flags" - flags to pass to virglrenderer.
* "shm_size" - size of the SHM host window in bytes.
*
* Returns:
* Zero on success or a negative error number on failure.
*/
int32_t krun_set_gpu_options2(uint32_t ctx_id,
uint32_t virgl_flags,
uint64_t shm_size);

/**
* Enables or disables a virtio-snd device.
*
Expand Down Expand Up @@ -339,7 +373,6 @@ int32_t krun_add_vsock_port(uint32_t ctx_id,
*/
int32_t krun_get_shutdown_eventfd(uint32_t ctx_id);


/**
* Configures the console device to ignore stdin and write the output to "c_filepath".
*
Expand Down
17 changes: 6 additions & 11 deletions src/arch/src/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ pub mod macos;
#[cfg(target_os = "macos")]
pub use self::macos::*;

use std::cmp::min;
use std::collections::HashMap;
use std::fmt::Debug;

use self::gic::GICDevice;
use crate::ArchMemoryInfo;
use crate::{round_up, ArchMemoryInfo};
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryMmap};

#[cfg(feature = "efi")]
Expand All @@ -42,35 +41,31 @@ pub enum Error {

/// The start of the memory area reserved for MMIO devices.
pub const MMIO_MEM_START: u64 = layout::MAPPED_IO_START;
/// The size of the MMIO shared memory area used by virtio-fs DAX.
pub const MMIO_SHM_SIZE: u64 = 1 << 33;

pub use self::fdt::DeviceInfoForFDT;
use crate::DeviceType;

/// Returns a Vec of the valid memory addresses for aarch64.
/// See [`layout`](layout) module for a drawing of the specific memory model for this platform.
pub fn arch_memory_regions(size: usize) -> (ArchMemoryInfo, Vec<(GuestAddress, usize)>) {
let dram_size = min(size as u64, layout::DRAM_MEM_MAX_SIZE) as usize;
let page_size: usize = unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() };
let dram_size = round_up(size, page_size);
let ram_last_addr = layout::DRAM_MEM_START + (dram_size as u64);
let shm_start_addr = ((ram_last_addr / 0x4000_0000) + 1) * 0x4000_0000;

let info = ArchMemoryInfo {
ram_last_addr,
shm_start_addr,
shm_size: MMIO_SHM_SIZE,
page_size,
};
let regions = if cfg!(feature = "efi") {
vec![
// Space for loading EDK2 and its variables
(GuestAddress(0u64), 0x800_0000),
(GuestAddress(layout::DRAM_MEM_START), dram_size),
(GuestAddress(shm_start_addr), MMIO_SHM_SIZE as usize),
]
} else {
vec![
(GuestAddress(layout::DRAM_MEM_START), dram_size),
(GuestAddress(shm_start_addr), MMIO_SHM_SIZE as usize),
]
vec![(GuestAddress(layout::DRAM_MEM_START), dram_size)]
};

(info, regions)
Expand Down
14 changes: 11 additions & 3 deletions src/arch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::result;
pub struct ArchMemoryInfo {
pub ram_last_addr: u64,
pub shm_start_addr: u64,
pub shm_size: u64,
pub page_size: usize,
}

/// Module for aarch64 related functionality.
Expand All @@ -22,7 +22,6 @@ pub mod aarch64;
pub use aarch64::{
arch_memory_regions, configure_system, get_kernel_start, initrd_load_addr,
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, layout::IRQ_MAX, Error, MMIO_MEM_START,
MMIO_SHM_SIZE,
};

/// Module for x86_64 related functionality.
Expand All @@ -33,7 +32,7 @@ pub mod x86_64;
pub use crate::x86_64::{
arch_memory_regions, configure_system, get_kernel_start, initrd_load_addr,
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, layout::IRQ_MAX, Error, BIOS_SIZE, BIOS_START,
MMIO_MEM_START, MMIO_SHM_SIZE, RESET_VECTOR,
MMIO_MEM_START, RESET_VECTOR,
};

/// Type for returning public functions outcome.
Expand Down Expand Up @@ -66,6 +65,15 @@ pub struct InitrdConfig {
/// Default (smallest) memory page size for the supported architectures.
pub const PAGE_SIZE: usize = 4096;

pub fn round_up(size: usize, align: usize) -> usize {
let page_mask = align - 1;
(size + page_mask) & !page_mask
}
pub fn round_down(size: usize, align: usize) -> usize {
let page_mask = !(align - 1);
size & page_mask
}

impl fmt::Display for DeviceType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{self:?}")
Expand Down
21 changes: 11 additions & 10 deletions src/arch/src/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ pub mod msr;
/// Logic for configuring x86_64 registers.
pub mod regs;

use crate::ArchMemoryInfo;
use crate::InitrdConfig;
use crate::{round_up, ArchMemoryInfo, InitrdConfig};
use arch_gen::x86::bootparam::{boot_params, E820_RAM};
use vm_memory::Bytes;
use vm_memory::{
Expand Down Expand Up @@ -60,8 +59,6 @@ const FIRST_ADDR_PAST_32BITS: u64 = 1 << 32;
const MEM_32BIT_GAP_SIZE: u64 = 768 << 20;
/// The start of the memory area reserved for MMIO devices.
pub const MMIO_MEM_START: u64 = FIRST_ADDR_PAST_32BITS - MEM_32BIT_GAP_SIZE;
/// The size of the MMIO shared memory area used by virtio-fs DAX.
pub const MMIO_SHM_SIZE: u64 = 1 << 33;

/// Returns a Vec of the valid memory addresses.
/// These should be used to configure the GuestMemoryMmap structure for the platform.
Expand All @@ -73,6 +70,9 @@ pub fn arch_memory_regions(
kernel_load_addr: u64,
kernel_size: usize,
) -> (ArchMemoryInfo, Vec<(GuestAddress, usize)>) {
let page_size: usize = unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() };

let size = round_up(size, page_size);
if size < (kernel_load_addr + kernel_size as u64) as usize {
panic!("Kernel doesn't fit in RAM");
}
Expand All @@ -90,7 +90,6 @@ pub fn arch_memory_regions(
vec![
(GuestAddress(0), kernel_load_addr as usize),
(GuestAddress(kernel_load_addr + kernel_size as u64), size),
(GuestAddress(FIRST_ADDR_PAST_32BITS), MMIO_SHM_SIZE as usize),
],
)
}
Expand All @@ -108,15 +107,14 @@ pub fn arch_memory_regions(
(MMIO_MEM_START - (kernel_load_addr + kernel_size as u64)) as usize,
),
(GuestAddress(FIRST_ADDR_PAST_32BITS), remaining),
(GuestAddress(shm_start_addr), MMIO_SHM_SIZE as usize),
],
)
}
};
let info = ArchMemoryInfo {
ram_last_addr,
shm_start_addr,
shm_size: MMIO_SHM_SIZE,
page_size,
};
(info, regions)
}
Expand All @@ -132,6 +130,9 @@ pub fn arch_memory_regions(
kernel_load_addr: u64,
kernel_size: usize,
) -> (ArchMemoryInfo, Vec<(GuestAddress, usize)>) {
let page_size: usize = unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() };

let size = round_up(size, page_size);
if size < (kernel_load_addr + kernel_size as u64) as usize {
panic!("Kernel doesn't fit in RAM");
}
Expand Down Expand Up @@ -170,7 +171,7 @@ pub fn arch_memory_regions(
let info = ArchMemoryInfo {
ram_last_addr,
shm_start_addr,
shm_size: 0,
page_size,
};
(info, regions)
}
Expand Down Expand Up @@ -319,7 +320,7 @@ mod tests {
#[test]
fn regions_lt_4gb() {
let (_info, regions) = arch_memory_regions(1usize << 29, KERNEL_LOAD_ADDR, KERNEL_SIZE);
assert_eq!(3, regions.len());
assert_eq!(2, regions.len());
assert_eq!(GuestAddress(0), regions[0].0);
assert_eq!(KERNEL_LOAD_ADDR as usize, regions[0].1);
assert_eq!(
Expand All @@ -333,7 +334,7 @@ mod tests {
fn regions_gt_4gb() {
let (_info, regions) =
arch_memory_regions((1usize << 32) + 0x8000, KERNEL_LOAD_ADDR, KERNEL_SIZE);
assert_eq!(4, regions.len());
assert_eq!(3, regions.len());
assert_eq!(GuestAddress(0), regions[0].0);
assert_eq!(KERNEL_LOAD_ADDR as usize, regions[0].1);
assert_eq!(
Expand Down
16 changes: 16 additions & 0 deletions src/devices/src/virtio/fs/device.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#[cfg(target_os = "macos")]
use crossbeam_channel::Sender;
use std::cmp;
use std::io::Write;
use std::sync::atomic::AtomicUsize;
use std::sync::{Arc, Mutex};
use std::thread::JoinHandle;

#[cfg(target_os = "macos")]
use hvf::MemoryMapping;
use utils::eventfd::{EventFd, EFD_NONBLOCK};
use virtio_bindings::{virtio_config::VIRTIO_F_VERSION_1, virtio_ring::VIRTIO_RING_F_EVENT_IDX};
use vm_memory::{ByteValued, GuestMemoryMmap};
Expand Down Expand Up @@ -49,6 +53,8 @@ pub struct Fs {
passthrough_cfg: passthrough::Config,
worker_thread: Option<JoinHandle<()>>,
worker_stopfd: EventFd,
#[cfg(target_os = "macos")]
map_sender: Option<Sender<MemoryMapping>>,
}

impl Fs {
Expand Down Expand Up @@ -90,6 +96,8 @@ impl Fs {
passthrough_cfg: fs_cfg,
worker_thread: None,
worker_stopfd: EventFd::new(EFD_NONBLOCK).map_err(FsError::EventFd)?,
#[cfg(target_os = "macos")]
map_sender: None,
})
}

Expand All @@ -112,6 +120,11 @@ impl Fs {
pub fn set_shm_region(&mut self, shm_region: VirtioShmRegion) {
self.shm_region = Some(shm_region);
}

#[cfg(target_os = "macos")]
pub fn set_map_sender(&mut self, map_sender: Sender<MemoryMapping>) {
self.map_sender = Some(map_sender);
}
}

impl VirtioDevice for Fs {
Expand Down Expand Up @@ -199,8 +212,11 @@ impl VirtioDevice for Fs {
self.intc.clone(),
self.irq_line,
mem.clone(),
self.shm_region.clone(),
self.passthrough_cfg.clone(),
self.worker_stopfd.try_clone().unwrap(),
#[cfg(target_os = "macos")]
self.map_sender.clone(),
);
self.worker_thread = Some(worker.run());

Expand Down
7 changes: 7 additions & 0 deletions src/devices/src/virtio/fs/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#[cfg(target_os = "macos")]
use crossbeam_channel::Sender;
#[cfg(target_os = "macos")]
use hvf::MemoryMapping;

use std::convert::TryInto;
use std::ffi::{CStr, CString};
use std::fs::File;
Expand Down Expand Up @@ -1121,6 +1126,7 @@ pub trait FileSystem {
moffset: u64,
host_shm_base: u64,
shm_size: u64,
#[cfg(target_os = "macos")] map_sender: &Option<Sender<MemoryMapping>>,
) -> io::Result<()> {
Err(io::Error::from_raw_os_error(libc::ENOSYS))
}
Expand All @@ -1131,6 +1137,7 @@ pub trait FileSystem {
requests: Vec<RemovemappingOne>,
host_shm_base: u64,
shm_size: u64,
#[cfg(target_os = "macos")] map_sender: &Option<Sender<MemoryMapping>>,
) -> io::Result<()> {
Err(io::Error::from_raw_os_error(libc::ENOSYS))
}
Expand Down
Loading
Loading