summary refs log tree commit diff
path: root/hypervisor/src
diff options
context:
space:
mode:
Diffstat (limited to 'hypervisor/src')
-rw-r--r--hypervisor/src/aarch64.rs24
-rw-r--r--hypervisor/src/kvm/aarch64.rs22
-rw-r--r--hypervisor/src/kvm/mod.rs89
-rw-r--r--hypervisor/src/kvm/x86_64.rs32
-rw-r--r--hypervisor/src/lib.rs64
-rw-r--r--hypervisor/src/types/mod.rs9
-rw-r--r--hypervisor/src/types/x86.rs10
-rw-r--r--hypervisor/src/x86_64.rs40
8 files changed, 250 insertions, 40 deletions
diff --git a/hypervisor/src/aarch64.rs b/hypervisor/src/aarch64.rs
new file mode 100644
index 0000000..dc06d8d
--- /dev/null
+++ b/hypervisor/src/aarch64.rs
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use crate::{Vcpu, Vm};
+use sys_util::Result;
+
+/// A wrapper for using a VM on aarch64 and getting/setting its state.
+pub trait VmAArch64: Vm {
+    type Vcpu: VcpuArm;
+
+    /// Create a Vcpu with the specified Vcpu ID.
+    fn create_vcpu(&self, id: usize) -> Result<Self::Vcpu>;
+}
+
+/// A wrapper around creating and using a VCPU on aarch64.
+pub trait VcpuAArch64: Vcpu {
+    /// Sets the value of register on this VCPU.
+    ///
+    /// # Arguments
+    ///
+    /// * `reg_id` - Register ID, specified in the KVM API documentation for KVM_SET_ONE_REG
+    fn set_one_reg(&self, reg_id: u64, data: u64) -> Result<()>;
+}
diff --git a/hypervisor/src/kvm/aarch64.rs b/hypervisor/src/kvm/aarch64.rs
new file mode 100644
index 0000000..f674671
--- /dev/null
+++ b/hypervisor/src/kvm/aarch64.rs
@@ -0,0 +1,22 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use sys_util::Result;
+
+use super::{KvmVcpu, KvmVm};
+use crate::{Regs, VcpuAArch64, VmAarch64};
+
+impl VmAArch64 for KvmVm {
+    type Vcpu = KvmVcpu;
+
+    fn create_vcpu(&self, id: usize) -> Result<Self::Vcpu> {
+        self.create_kvm_vcpu(id)
+    }
+}
+
+impl VcpuAArch64 for KvmVcpu {
+    fn set_one_reg(&self, reg_id: u64, data: u64) -> Result<()> {
+        Ok(())
+    }
+}
diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs
index 7058921..5d78b00 100644
--- a/hypervisor/src/kvm/mod.rs
+++ b/hypervisor/src/kvm/mod.rs
@@ -2,13 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use super::{CpuId, Hypervisor, HypervisorCap};
-use libc::{open, O_CLOEXEC, O_RDWR};
+#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+mod aarch64;
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+mod x86_64;
+
+use std::ops::{Deref, DerefMut};
 use std::os::raw::c_char;
+
+use libc::{open, O_CLOEXEC, O_RDWR};
+
 use sys_util::{
-    errno_result, AsRawDescriptor, FromRawDescriptor, RawDescriptor, Result, SafeDescriptor,
+    errno_result, AsRawDescriptor, FromRawDescriptor, GuestMemory, RawDescriptor, Result,
+    SafeDescriptor,
 };
 
+use crate::{Hypervisor, HypervisorCap, RunnableVcpu, Vcpu, VcpuExit, Vm};
+
 pub struct Kvm {
     kvm: SafeDescriptor,
 }
@@ -39,15 +49,76 @@ impl Hypervisor for Kvm {
     fn check_capability(&self, _cap: &HypervisorCap) -> bool {
         unimplemented!("check_capability for Kvm is not yet implemented");
     }
+}
+
+/// A wrapper around creating and using a KVM VM.
+pub struct KvmVm {
+    guest_mem: GuestMemory,
+}
+
+impl KvmVm {
+    /// Constructs a new `KvmVm` using the given `Kvm` instance.
+    pub fn new(_kvm: &Kvm, guest_mem: GuestMemory) -> Result<KvmVm> {
+        Ok(KvmVm { guest_mem })
+    }
+
+    fn create_kvm_vcpu(&self, _id: usize) -> Result<KvmVcpu> {
+        Ok(KvmVcpu {})
+    }
+}
+
+impl Vm for KvmVm {
+    fn get_guest_mem(&self) -> &GuestMemory {
+        &self.guest_mem
+    }
+}
+
+/// A wrapper around creating and using a KVM Vcpu.
+pub struct KvmVcpu {}
+
+impl Vcpu for KvmVcpu {
+    type Runnable = RunnableKvmVcpu;
+
+    fn to_runnable(self) -> Result<Self::Runnable> {
+        Ok(RunnableKvmVcpu {
+            vcpu: self,
+            phantom: Default::default(),
+        })
+    }
 
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-    fn get_supported_cpuid(&self) -> Result<CpuId> {
-        unimplemented!("get_supported_cpuid for Kvm is not yet implemented");
+    fn request_interrupt_window(&self) -> Result<()> {
+        Ok(())
     }
+}
+
+/// A KvmVcpu that has a thread and can be run.
+pub struct RunnableKvmVcpu {
+    vcpu: KvmVcpu,
+
+    // vcpus must stay on the same thread once they start.
+    // Add the PhantomData pointer to ensure RunnableKvmVcpu is not `Send`.
+    phantom: std::marker::PhantomData<*mut u8>,
+}
+
+impl RunnableVcpu for RunnableKvmVcpu {
+    type Vcpu = KvmVcpu;
+
+    fn run(&self) -> Result<VcpuExit> {
+        Ok(VcpuExit::Unknown)
+    }
+}
+
+impl Deref for RunnableKvmVcpu {
+    type Target = <Self as RunnableVcpu>::Vcpu;
+
+    fn deref(&self) -> &Self::Target {
+        &self.vcpu
+    }
+}
 
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-    fn get_emulated_cpuid(&self) -> Result<CpuId> {
-        unimplemented!("get_emulated_cpuid for Kvm is not yet implemented");
+impl DerefMut for RunnableKvmVcpu {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.vcpu
     }
 }
 
diff --git a/hypervisor/src/kvm/x86_64.rs b/hypervisor/src/kvm/x86_64.rs
new file mode 100644
index 0000000..56681f9
--- /dev/null
+++ b/hypervisor/src/kvm/x86_64.rs
@@ -0,0 +1,32 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use sys_util::Result;
+
+use super::{Kvm, KvmVcpu, KvmVm};
+use crate::{CpuId, HypervisorX86_64, Regs, VcpuX86_64, VmX86_64};
+
+impl HypervisorX86_64 for Kvm {
+    fn get_supported_cpuid(&self) -> Result<CpuId> {
+        unimplemented!("get_supported_cpuid for Kvm is not yet implemented");
+    }
+
+    fn get_emulated_cpuid(&self) -> Result<CpuId> {
+        unimplemented!("get_emulated_cpuid for Kvm is not yet implemented");
+    }
+}
+
+impl VmX86_64 for KvmVm {
+    type Vcpu = KvmVcpu;
+
+    fn create_vcpu(&self, id: usize) -> Result<Self::Vcpu> {
+        self.create_kvm_vcpu(id)
+    }
+}
+
+impl VcpuX86_64 for KvmVcpu {
+    fn get_regs(&self) -> Result<Regs> {
+        Ok(Regs {})
+    }
+}
diff --git a/hypervisor/src/lib.rs b/hypervisor/src/lib.rs
index 056070b..0f4c278 100644
--- a/hypervisor/src/lib.rs
+++ b/hypervisor/src/lib.rs
@@ -3,23 +3,63 @@
 // found in the LICENSE file.
 
 //! A crate for abstracting the underlying kernel hypervisor used in crosvm.
+#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+pub mod aarch64;
 pub mod caps;
 pub mod kvm;
-pub mod types;
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub mod x86_64;
 
-use sys_util::Result;
+use std::ops::{Deref, DerefMut};
 
+use sys_util::{GuestMemory, Result};
+
+#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+pub use crate::aarch64::*;
 pub use crate::caps::*;
-pub use crate::types::*;
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub use crate::x86_64::*;
 
-/// A trait for managing the underlying cpu information for the hypervisor and to check its capabilities.
-trait Hypervisor {
-    // Checks if a particular `HypervisorCap` is available.
+/// A trait for checking hypervisor capabilities.
+pub trait Hypervisor {
+    /// Checks if a particular `HypervisorCap` is available.
     fn check_capability(&self, cap: &HypervisorCap) -> bool;
-    // Get the system supported CPUID values.
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-    fn get_supported_cpuid(&self) -> Result<CpuId>;
-    // Get the system emulated CPUID values.
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-    fn get_emulated_cpuid(&self) -> Result<CpuId>;
+}
+
+/// A wrapper for using a VM and getting/setting its state.
+pub trait Vm {
+    // Gets the guest-mapped memory for the Vm
+    fn get_guest_mem(&self) -> &GuestMemory;
+}
+
+/// A wrapper around creating and using a VCPU.
+/// `Vcpu` provides all functionality except for running. To run, `to_runnable` must be called to
+/// lock the vcpu to a thread. Then the returned `RunnableVcpu` can be used for running.
+pub trait Vcpu {
+    type Runnable: RunnableVcpu;
+
+    /// Consumes `self` and returns a `RunnableVcpu`. A `RunnableVcpu` is required to run the guest.
+    fn to_runnable(self) -> Result<Self::Runnable>;
+
+    /// Request the Vcpu to exit the next time it can accept an interrupt.
+    fn request_interrupt_window(&self) -> Result<()>;
+}
+
+/// A Vcpu that has a thread and can be run. Created by calling `to_runnable` on a `Vcpu`.
+/// Implements `Deref` to a `Vcpu` so all `Vcpu` methods are usable, with the addition of the `run`
+/// function to execute the guest.
+pub trait RunnableVcpu: Deref<Target = <Self as RunnableVcpu>::Vcpu> + DerefMut {
+    type Vcpu: Vcpu;
+
+    /// Runs the VCPU until it exits, returning the reason for the exit.
+    ///
+    /// Note that the state of the VCPU and associated VM must be setup first for this to do
+    /// anything useful.
+    fn run(&self) -> Result<VcpuExit>;
+}
+
+/// A reason why a VCPU exited. One of these returns every time `Vcpu::run` is called.
+#[derive(Debug)]
+pub enum VcpuExit {
+    Unknown,
 }
diff --git a/hypervisor/src/types/mod.rs b/hypervisor/src/types/mod.rs
deleted file mode 100644
index 69fa9e4..0000000
--- a/hypervisor/src/types/mod.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2020 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-pub mod x86;
-
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-pub use self::x86::*;
diff --git a/hypervisor/src/types/x86.rs b/hypervisor/src/types/x86.rs
deleted file mode 100644
index cd5236a..0000000
--- a/hypervisor/src/types/x86.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2020 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-use kvm_sys::kvm_cpuid_entry2;
-
-pub type CpuIdEntry = kvm_cpuid_entry2;
-pub struct CpuId {
-    _cpu_id_entries: Vec<CpuIdEntry>,
-}
diff --git a/hypervisor/src/x86_64.rs b/hypervisor/src/x86_64.rs
new file mode 100644
index 0000000..e05335c
--- /dev/null
+++ b/hypervisor/src/x86_64.rs
@@ -0,0 +1,40 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use kvm_sys::kvm_cpuid_entry2;
+use sys_util::Result;
+
+use crate::{Hypervisor, Vcpu, Vm};
+
+pub type CpuIdEntry = kvm_cpuid_entry2;
+
+/// A trait for managing cpuids for an x86_64 hypervisor and for checking its capabilities.
+pub trait HypervisorX86_64: Hypervisor {
+    /// Get the system supported CPUID values.
+    fn get_supported_cpuid(&self) -> Result<CpuId>;
+
+    /// Get the system emulated CPUID values.
+    fn get_emulated_cpuid(&self) -> Result<CpuId>;
+}
+
+/// A wrapper for using a VM on x86_64 and getting/setting its state.
+pub trait VmX86_64: Vm {
+    type Vcpu: VcpuX86_64;
+
+    /// Create a Vcpu with the specified Vcpu ID.
+    fn create_vcpu(&self, id: usize) -> Result<Self::Vcpu>;
+}
+
+/// A wrapper around creating and using a VCPU on x86_64.
+pub trait VcpuX86_64: Vcpu {
+    /// Gets the VCPU registers.
+    fn get_regs(&self) -> Result<Regs>;
+}
+
+pub struct CpuId {
+    _cpu_id_entries: Vec<CpuIdEntry>,
+}
+
+/// The state of a vcpu's general-purpose registers.
+pub struct Regs {}