Skip to content
This repository has been archived by the owner on Sep 7, 2021. It is now read-only.

Commit

Permalink
Addressed PR comments
Browse files Browse the repository at this point in the history
- Added #[deny(missing_docs)] and added documentation everywhere
- Divided VcpuExits by platform (conditionally compiled) and reordered
  by definition in platform-specific headers
- Fixed licenses
  • Loading branch information
jennymankin committed Apr 30, 2019
1 parent 8f775bd commit ec9817b
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 63 deletions.
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Default owners for everything in the repo. Later matches take precedence.
* @jennymankin
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ kvm-bindings = "0.1"
[target.'cfg(unix)'.dev-dependencies]
kvm-ioctls = "0.1.0"

libc = ">=0.2.39"
libc = ">=0.2.39"
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@ architecturally, rather than hypervisor, specific.)

## License

This project is licensed under Apache License, Version 2.0, (LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
This project is licensed under either of:

* Apache License, Version 2.0 (LICENSE-APACHE or (https://www.apache.org/licenses/LICENSE-2.0))

* MIT license (LICENSE-MIT or (https://opensource.org/licenses/MIT))
19 changes: 18 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
// Copyright 2018-2019 CrowdStrike, Inc.
// SPDX-License-Identifier: Apache-2.0 OR MIT

#![allow(unused)]
#![deny(missing_docs)]

//! A generic abstraction around virtual CPU (vCPU) functionality
//!
//! This crate offers a trait abstraction for vCPUs, as well as architecture
//! and platform-dependent structure definitions necessary for vCPU functions.
//!
//! # Platform support
//!
//! - x86_64
//! - arm64 (experimental)
//!

/// Module defining vCPU trait and required data structures
pub mod vcpu;

#[cfg(unix)]
extern crate kvm_bindings;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
/// Module defining x86_64 architecture-dependent structures
pub mod x86_64;

#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
mod arm;
/// Module defining arm architecture-dependent structures
pub mod arm;
85 changes: 70 additions & 15 deletions src/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,64 +25,118 @@ pub use x86_64::{
};

///
/// Reasons for vCPU exits.
///
/// Exit reasons are drawn a superset of exit reasons for various VMMs.
/// Reasons for vCPU exits for Windows (Hyper-V) platforms
///
#[derive(Debug)]
pub enum VcpuExit<'a> {
#[cfg(windows)]
pub enum VcpuExit {

/// Corresponds to WHvRunVpExitReasonNone
None,
/// Corresponds to WHvRunVpExitReasonMemoryAccess
MemoryAccess,
/// Corresponds to WHvRunVpExitReasonX64IoPortAccess
IoPortAccess,
/// Corresponds to WHvRunVpExitReasonUnrecoverableException
UnrecoverableException,
/// Corresponds to WHvRunVpExitReasonInvalidVpRegisterValue
InvalidVpRegisterValue,
/// Corresponds to WHvRunVpExitReasonUnsupportedFeature
UnsupportedFeature,
/// Corresponds to WHvRunVpExitReasonX64InterruptWindow
IrqWindowOpen,
/// Corresponds to WHvRunVpExitReasonX64Halt
Hlt,
/// Corresponds to WHvRunVpExitReasonX64ApicEoi
IoapicEoi,
/// Corresponds to WHvRunVpExitReasonX64MsrAccess
MsrAccess,
/// Corresponds to WHvRunVpExitReasonX64Cpuid
Cpuid,
/// Corresponds to WHvRunVpExitReasonException
Exception,
/// Corresponds to WHvRunVpExitReasonCanceled
Canceled,
}

///
/// Reasons for vCPU exits for Unix-based (KVM) platforms
///
#[derive(Debug)]
#[cfg(unix)]
pub enum VcpuExit<'a> {
/// Corresponds to KVM_EXIT_UNKNOWN.
Unknown,
/// Corresponds to KVM_EXIT_EXCEPTION.
Exception,
/// An out port instruction was run on the given port with the given data.
IoOut(u16 /* port */, &'a [u8] /* data */),
/// An in port instruction was run on the given port.
///
/// The given slice should be filled in before Vcpu::run() is called again.
/// The given slice should be filled in before [run()](struct.VcpuFd.html#method.run)
/// is called again.
IoIn(u16 /* port */, &'a mut [u8] /* data */),
/// Corresponds to KVM_EXIT_HYPERCALL.
Hypercall,
/// Corresponds to KVM_EXIT_DEBUG.
Debug,
/// Corresponds to KVM_EXIT_HLT.
Hlt,
/// A read instruction was run against the given MMIO address.
///
/// The given slice should be filled in before Vcpu::run() is called again.
/// The given slice should be filled in before [run()](struct.VcpuFd.html#method.run)
/// is called again.
MmioRead(u64 /* address */, &'a mut [u8]),
/// A write instruction was run against the given MMIO address with the given data.
MmioWrite(u64 /* address */, &'a [u8]),
Unknown,
Hypercall,
Debug,
/// Corresponds to KVM_EXIT_IRQ_WINDOW_OPEN.
IrqWindowOpen,
/// Corresponds to KVM_EXIT_SHUTDOWN.
Shutdown,
/// Corresponds to KVM_EXIT_FAIL_ENTRY.
FailEntry,
/// Corresponds to KVM_EXIT_INTR.
Intr,
/// Corresponds to KVM_EXIT_SET_TPR.
SetTpr,
/// Corresponds to KVM_EXIT_TPR_ACCESS.
TprAccess,
/// Corresponds to KVM_EXIT_S390_SIEIC.
S390Sieic,
/// Corresponds to KVM_EXIT_S390_RESET.
S390Reset,
/// Corresponds to KVM_EXIT_DCR.
Dcr,
/// Corresponds to KVM_EXIT_NMI.
Nmi,
/// Corresponds to KVM_EXIT_INTERNAL_ERROR.
InternalError,
/// Corresponds to KVM_EXIT_OSI.
Osi,
/// Corresponds to KVM_EXIT_PAPR_HCALL.
PaprHcall,
/// Corresponds to KVM_EXIT_S390_UCONTROL.
S390Ucontrol,
/// Corresponds to KVM_EXIT_WATCHDOG.
Watchdog,
/// Corresponds to KVM_EXIT_S390_TSCH.
S390Tsch,
/// Corresponds to KVM_EXIT_EPR.
Epr,
/// Corresponds to KVM_EXIT_SYSTEM_EVENT.
SystemEvent,
/// Corresponds to KVM_EXIT_S390_STSI.
S390Stsi,
Hyperv,

Hlt,
/// Corresponds to KVM_EXIT_IOAPIC_EOI.
IoapicEoi,
Exception,
IrqWindowOpen,
/// Corresponds to KVM_EXIT_HYPERV.
Hyperv,
}

/// A specialized `Result` type for VCPU operations
///
/// This typedef is generally used to avoid writing out io::Error directly and
/// is otherwise a direct mapping to Result.
pub type Result<T> = result::Result<T, io::Error>;

///
Expand All @@ -92,6 +146,7 @@ pub type Result<T> = result::Result<T, io::Error>;
/// functionality
///
pub trait Vcpu {
/// Associated type representing the run context on a vCPU exit
type RunContextType;

/// Reads the standard registers from the virtual CPU
Expand Down Expand Up @@ -137,7 +192,7 @@ pub trait Vcpu {
/// Reads the floating point state from the vCPU
///
/// - Floating Point MMX Registers 0-7
/// - Floating Pointer Control, Status, Tag Registers (FCW, FSW, FTW)
/// - Floating Point Control, Status, Tag Registers (FCW, FSW, FTW)
/// - Floating point exception state (Last FIP, FOP, FCS, FDS, FDP)
/// - XMM Registers 0-15
/// - MXCSR Control and Status Register
Expand Down
38 changes: 20 additions & 18 deletions src/x86_64/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2018-2019 CrowdStrike, Inc.
// SPDX-License-Identifier: Apache-2.0 OR MIT

/// Windows definitions of data structures
#[cfg(windows)]
pub mod windows;

Expand All @@ -17,6 +18,7 @@ pub use {
self::windows::MsrEntries,
self::windows::MsrEntry,
self::windows::SegmentRegister,
self::windows::DescriptorTable,
self::windows::CpuId2,
self::windows::CpuIdEntry2,
self::windows::LapicState,
Expand All @@ -39,7 +41,7 @@ pub use {
kvm_bindings::kvm_lapic_state as LapicState,
};

// Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`.
/// Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`.
fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> {
let rounded_size = (size_in_bytes + size_of::<T>() - 1) / size_of::<T>();
let mut v = Vec::with_capacity(rounded_size);
Expand All @@ -49,21 +51,21 @@ fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> {
v
}

// The kvm API has many structs that resemble the following `Foo` structure:
//
// ```
// #[repr(C)]
// struct Foo {
// some_data: u32
// entries: __IncompleteArrayField<__u32>,
// }
// ```
//
// In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would not
// include any space for `entries`. To make the allocation large enough while still being aligned
// for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually be used
// as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be contiguous
// with `Foo`. This function is used to make the `Vec<Foo>` with enough space for `count` entries.
/// The kvm API has many structs that resemble the following `Foo` structure:
///
/// ```
/// #[repr(C)]
/// struct Foo {
/// some_data: u32
/// entries: __IncompleteArrayField<__u32>,
/// }
/// ```
///
/// In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would not
/// include any space for `entries`. To make the allocation large enough while still being aligned
/// for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually be used
/// as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be contiguous
/// with `Foo`. This function is used to make the `Vec<Foo>` with enough space for `count` entries.
pub fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> {
let element_space = count * size_of::<F>();
let vec_size_bytes = size_of::<T>() + element_space;
Expand All @@ -82,9 +84,9 @@ pub const MAX_CPUID_ENTRIES: usize = 80;
/// The structure has a zero length array at the end, hidden behind bounds check.
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub struct CpuId {
// Wrapper over `CpuId2` from which we only use the first element.
/// Wrapper over `CpuId2` from which we only use the first element.
pub cpuid_vec: Vec<CpuId2>,
// Number of `CpuIdEntry2` structs at the end of CpuId2.
/// Number of `CpuIdEntry2` structs at the end of CpuId2.
pub allocated_len: usize,
}

Expand Down
Loading

0 comments on commit ec9817b

Please sign in to comment.