mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 18:20:34 +00:00
Make KVM path configurable
Most users will want to keep the default `/dev/kvm` path. However, in certain environments, namely Borg, the KVM device node may be located elsewhere. This is the first of a set of related changes that will make hard-coded device paths configurable. BUG=None TEST=./ci/builder --vm ./run_tests Change-Id: I6087879c535be3779e20eff1f8fb5080f80cf020 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2736520 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Dylan Reid <dgreid@chromium.org> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Commit-Queue: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
d854217d99
commit
33d5677804
6 changed files with 46 additions and 15 deletions
|
@ -16,9 +16,11 @@ use std::cell::RefCell;
|
|||
use std::cmp::{min, Reverse};
|
||||
use std::collections::{BTreeMap, BinaryHeap};
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CString;
|
||||
use std::mem::{size_of, ManuallyDrop};
|
||||
use std::os::raw::{c_char, c_int, c_ulong, c_void};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::os::raw::{c_int, c_ulong, c_void};
|
||||
use std::os::unix::{io::AsRawFd, prelude::OsStrExt};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::ptr::copy_nonoverlapping;
|
||||
use std::sync::atomic::AtomicU64;
|
||||
use std::sync::Arc;
|
||||
|
@ -94,11 +96,10 @@ pub struct Kvm {
|
|||
type KvmCap = kvm::Cap;
|
||||
|
||||
impl Kvm {
|
||||
/// Opens `/dev/kvm/` and returns a Kvm object on success.
|
||||
pub fn new() -> Result<Kvm> {
|
||||
// Open calls are safe because we give a constant nul-terminated string and verify the
|
||||
// result.
|
||||
let ret = unsafe { open("/dev/kvm\0".as_ptr() as *const c_char, O_RDWR | O_CLOEXEC) };
|
||||
pub fn new_with_path(device_path: &Path) -> Result<Kvm> {
|
||||
// Open calls are safe because we give a nul-terminated string and verify the result.
|
||||
let c_path = CString::new(device_path.as_os_str().as_bytes()).unwrap();
|
||||
let ret = unsafe { open(c_path.as_ptr(), O_RDWR | O_CLOEXEC) };
|
||||
if ret < 0 {
|
||||
return errno_result();
|
||||
}
|
||||
|
@ -108,6 +109,11 @@ impl Kvm {
|
|||
})
|
||||
}
|
||||
|
||||
/// Opens `/dev/kvm/` and returns a Kvm object on success.
|
||||
pub fn new() -> Result<Kvm> {
|
||||
Kvm::new_with_path(&PathBuf::from("/dev/kvm"))
|
||||
}
|
||||
|
||||
/// Gets the size of the mmap required to use vcpu's `kvm_run` structure.
|
||||
pub fn get_vcpu_mmap_size(&self) -> Result<usize> {
|
||||
// Safe because we know that our file is a KVM fd and we verify the return result.
|
||||
|
|
|
@ -9,10 +9,13 @@ mod cap;
|
|||
use std::cell::RefCell;
|
||||
use std::cmp::{min, Ordering};
|
||||
use std::collections::{BTreeMap, BinaryHeap};
|
||||
use std::ffi::CString;
|
||||
use std::fs::File;
|
||||
use std::mem::size_of;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::os::raw::*;
|
||||
use std::os::unix::prelude::OsStrExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::ptr::copy_nonoverlapping;
|
||||
use std::sync::Arc;
|
||||
use sync::Mutex;
|
||||
|
@ -94,9 +97,14 @@ pub struct Kvm {
|
|||
impl Kvm {
|
||||
/// Opens `/dev/kvm/` and returns a Kvm object on success.
|
||||
pub fn new() -> Result<Kvm> {
|
||||
// Open calls are safe because we give a constant nul-terminated string and verify the
|
||||
// result.
|
||||
let ret = unsafe { open("/dev/kvm\0".as_ptr() as *const c_char, O_RDWR | O_CLOEXEC) };
|
||||
Kvm::new_with_path(&PathBuf::from("/dev/kvm"))
|
||||
}
|
||||
|
||||
/// Opens a KVM device at `device_path` and returns a Kvm object on success.
|
||||
pub fn new_with_path(device_path: &Path) -> Result<Kvm> {
|
||||
// Open calls are safe because we give a nul-terminated string and verify the result.
|
||||
let c_path = CString::new(device_path.as_os_str().as_bytes()).unwrap();
|
||||
let ret = unsafe { open(c_path.as_ptr(), O_RDWR | O_CLOEXEC) };
|
||||
if ret < 0 {
|
||||
return errno_result();
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ use devices::ProtectionType;
|
|||
use libc::{getegid, geteuid};
|
||||
use vm_control::BatteryType;
|
||||
|
||||
static KVM_PATH: &str = "/dev/kvm";
|
||||
static SECCOMP_POLICY_DIR: &str = "/usr/share/policy/crosvm";
|
||||
|
||||
/// Indicates the location and kind of executable kernel for a VM.
|
||||
|
@ -174,6 +175,7 @@ impl Default for SharedDir {
|
|||
|
||||
/// Aggregate of all configurable options for a running VM.
|
||||
pub struct Config {
|
||||
pub kvm_device_path: PathBuf,
|
||||
pub vcpu_count: Option<usize>,
|
||||
pub rt_cpus: Vec<usize>,
|
||||
pub vcpu_affinity: Option<VcpuAffinity>,
|
||||
|
@ -234,6 +236,7 @@ pub struct Config {
|
|||
impl Default for Config {
|
||||
fn default() -> Config {
|
||||
Config {
|
||||
kvm_device_path: PathBuf::from(KVM_PATH),
|
||||
vcpu_count: None,
|
||||
rt_cpus: Vec::new(),
|
||||
vcpu_affinity: None,
|
||||
|
|
10
src/linux.rs
10
src/linux.rs
|
@ -2164,8 +2164,8 @@ fn file_to_i64<P: AsRef<Path>>(path: P, nth: usize) -> io::Result<i64> {
|
|||
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "empty file"))
|
||||
}
|
||||
|
||||
fn create_kvm(mem: GuestMemory) -> base::Result<KvmVm> {
|
||||
let kvm = Kvm::new()?;
|
||||
fn create_kvm(device_path: &Path, mem: GuestMemory) -> base::Result<KvmVm> {
|
||||
let kvm = Kvm::new_with_path(device_path)?;
|
||||
let vm = KvmVm::new(&kvm, mem)?;
|
||||
Ok(vm)
|
||||
}
|
||||
|
@ -2190,6 +2190,8 @@ fn create_kvm_split_irq_chip(
|
|||
}
|
||||
|
||||
pub fn run_config(cfg: Config) -> Result<()> {
|
||||
let kvm_device_path = cfg.kvm_device_path.clone();
|
||||
let create_kvm_with_path = |mem| create_kvm(&kvm_device_path, mem);
|
||||
if cfg.split_irqchip {
|
||||
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||
{
|
||||
|
@ -2198,10 +2200,10 @@ pub fn run_config(cfg: Config) -> Result<()> {
|
|||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
{
|
||||
run_vm::<_, KvmVcpu, _, _, _>(cfg, create_kvm, create_kvm_split_irq_chip)
|
||||
run_vm::<_, KvmVcpu, _, _, _>(cfg, create_kvm_with_path, create_kvm_split_irq_chip)
|
||||
}
|
||||
} else {
|
||||
run_vm::<_, KvmVcpu, _, _, _>(cfg, create_kvm, create_kvm_kernel_irq_chip)
|
||||
run_vm::<_, KvmVcpu, _, _, _>(cfg, create_kvm_with_path, create_kvm_kernel_irq_chip)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -676,6 +676,17 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
|
|||
}
|
||||
cfg.executable_path = Some(Executable::Kernel(kernel_path));
|
||||
}
|
||||
"kvm-device" => {
|
||||
let kvm_device_path = PathBuf::from(value.unwrap());
|
||||
if !kvm_device_path.exists() {
|
||||
return Err(argument::Error::InvalidValue {
|
||||
value: value.unwrap().to_owned(),
|
||||
expected: String::from("this kvm device path does not exist"),
|
||||
});
|
||||
}
|
||||
|
||||
cfg.kvm_device_path = kvm_device_path;
|
||||
}
|
||||
"android-fstab" => {
|
||||
if cfg.android_fstab.is_some()
|
||||
&& !cfg.android_fstab.as_ref().unwrap().as_os_str().is_empty()
|
||||
|
@ -1595,6 +1606,7 @@ fn validate_arguments(cfg: &mut Config) -> std::result::Result<(), argument::Err
|
|||
fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> {
|
||||
let arguments =
|
||||
&[Argument::positional("KERNEL", "bzImage of kernel to run"),
|
||||
Argument::value("kvm-device", "PATH", "Path to the KVM device. (default /dev/kvm)"),
|
||||
Argument::value("android-fstab", "PATH", "Path to Android fstab"),
|
||||
Argument::short_value('i', "initrd", "PATH", "Initial ramdisk to load."),
|
||||
Argument::short_value('p',
|
||||
|
|
|
@ -691,7 +691,7 @@ pub fn run_config(cfg: Config) -> Result<()> {
|
|||
};
|
||||
let vcpu_count = cfg.vcpu_count.unwrap_or(1) as u32;
|
||||
let mem = GuestMemory::new(&[]).unwrap();
|
||||
let kvm = Kvm::new().map_err(Error::CreateKvm)?;
|
||||
let kvm = Kvm::new_with_path(&cfg.kvm_device_path).map_err(Error::CreateKvm)?;
|
||||
let mut vm = Vm::new(&kvm, mem).map_err(Error::CreateVm)?;
|
||||
vm.create_irq_chip().map_err(Error::CreateIrqChip)?;
|
||||
vm.create_pit().map_err(Error::CreatePIT)?;
|
||||
|
|
Loading…
Reference in a new issue