From af4526d4bd421697a12980183639ee064f68745a Mon Sep 17 00:00:00 2001 From: Egor Lazarchuk Date: Fri, 15 Nov 2024 11:59:35 +0000 Subject: [PATCH] feat: query host page size Define global variable with host page size and update it at the very beginning of the main function in Firecracker. This way data types which rely on specific host page size can adapt to it. Signed-off-by: Egor Lazarchuk --- src/firecracker/src/main.rs | 3 +++ src/vmm/src/arch/mod.rs | 25 ++++++++++++++++++++++++- src/vmm/src/devices/virtio/iov_deque.rs | 5 +++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/firecracker/src/main.rs b/src/firecracker/src/main.rs index 8fb5392afcf3..f742d94760d6 100644 --- a/src/firecracker/src/main.rs +++ b/src/firecracker/src/main.rs @@ -20,6 +20,7 @@ use seccomp::FilterError; use seccompiler::BpfThreadMap; use utils::arg_parser::{ArgParser, Argument}; use utils::validators::validate_instance_id; +use vmm::arch::update_host_page_size; use vmm::builder::StartMicrovmError; use vmm::logger::{ debug, error, info, LoggerConfig, ProcessTimeReporter, StoreMetric, LOGGER, METRICS, @@ -108,6 +109,8 @@ fn main_exec() -> Result<(), MainError> { // Initialize the logger. LOGGER.init().map_err(MainError::SetLogger)?; + update_host_page_size(); + // We need this so that we can reset terminal to canonical mode if panic occurs. let stdin = io::stdin(); diff --git a/src/vmm/src/arch/mod.rs b/src/vmm/src/arch/mod.rs index 0f3bd6e46ef2..e3d8ac30ab48 100644 --- a/src/vmm/src/arch/mod.rs +++ b/src/vmm/src/arch/mod.rs @@ -3,6 +3,7 @@ use std::fmt; +use log::warn; use serde::{Deserialize, Serialize}; /// Module for aarch64 related functionality. @@ -56,7 +57,29 @@ pub struct InitrdConfig { pub const GUEST_PAGE_SIZE: usize = 4096; /// Default page size for the host OS. -pub const HOST_PAGE_SIZE: usize = 4096; +static mut HOST_PAGE_SIZE: usize = 4096; + +/// Updates the HOST_PAGE_SIZE global variable to the output of +/// sysconf(_SC_PAGESIZE). If call is unsuccessfull the default +/// value of 4096 remains. +pub fn update_host_page_size() { + // # Safety: + // There is nothing unsafe here. + let r = unsafe { libc::sysconf(libc::_SC_PAGESIZE) }; + if r < 0 { + warn!("Could not get host page size with sysconf, assuming default 4K host pages"); + } else { + // # Safety: + // The value is checked. + unsafe { HOST_PAGE_SIZE = usize::try_from(r).unwrap() }; + } +} + +/// Get the size of the host page size. +pub fn host_page_size() -> usize { + // # Safety: Value always valid + unsafe { HOST_PAGE_SIZE } +} impl fmt::Display for DeviceType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/vmm/src/devices/virtio/iov_deque.rs b/src/vmm/src/devices/virtio/iov_deque.rs index 994ba5cd3204..e3a2534994af 100644 --- a/src/vmm/src/devices/virtio/iov_deque.rs +++ b/src/vmm/src/devices/virtio/iov_deque.rs @@ -6,7 +6,7 @@ use std::os::fd::AsRawFd; use libc::{c_int, c_void, iovec, off_t, size_t}; use memfd; -use crate::arch::HOST_PAGE_SIZE; +use crate::arch::host_page_size; #[derive(Debug, thiserror::Error, displaydoc::Display)] pub enum IovDequeError { @@ -93,7 +93,6 @@ unsafe impl Send for IovDeque {} impl IovDeque { const BYTES: usize = L as usize * std::mem::size_of::(); - const _ASSERT: () = assert!(Self::BYTES % HOST_PAGE_SIZE == 0); /// Create a [`memfd`] object that represents a single physical page fn create_memfd() -> Result { @@ -153,6 +152,8 @@ impl IovDeque { /// Create a new [`IovDeque`] that can hold memory described by a single VirtIO queue. pub fn new() -> Result { + assert!(Self::BYTES % host_page_size() == 0); + let memfd = Self::create_memfd()?; let raw_memfd = memfd.as_file().as_raw_fd(); let buffer = Self::allocate_ring_buffer_memory()?;