Skip to content

Commit

Permalink
feat(core): add MemoryAccessOptions for fine-tuning memory access mon…
Browse files Browse the repository at this point in the history
…itoring
  • Loading branch information
wbenny committed Feb 4, 2025
1 parent e88feba commit 157f3bc
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 9 deletions.
24 changes: 24 additions & 0 deletions crates/vmi-core/src/core/memory_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,30 @@ bitflags::bitflags! {
}
}

bitflags::bitflags! {
/// Options for controlling memory access monitoring.
///
/// These options can be used to fine-tune the behavior of memory access
/// monitoring, allowing you to ignore certain types of memory accesses
/// and improve performance.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct MemoryAccessOptions: u8 {
/// Ignore page-walk updates caused by the CPU.
///
/// When this flag is set, memory accesses that are solely the result of
/// CPU-initiated page-table walks will not trigger an [`EventMemoryAccess`].
/// This is useful for filtering out irrelevant events when monitoring
/// page-table modifications.
///
/// # Notes
///
/// This option is only effective when the [`MemoryAccess:W`] is not set.
///
/// [`EventMemoryAccess`]: ../vmi_arch_amd64/struct.EventMemoryAccess.html
const IGNORE_PAGE_WALK_UPDATES = 0b00000001;
}
}

impl std::fmt::Display for MemoryAccess {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let mut result = [b'-'; 3];
Expand Down
2 changes: 1 addition & 1 deletion crates/vmi-core/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub use self::{
address_context::AddressContext,
hex::Hex,
info::VmiInfo,
memory_access::MemoryAccess,
memory_access::{MemoryAccess, MemoryAccessOptions},
vcpu_id::VcpuId,
view::View,
};
14 changes: 12 additions & 2 deletions crates/vmi-core/src/driver.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::time::Duration;

use crate::{
Architecture, Gfn, MemoryAccess, VcpuId, View, VmiError, VmiEvent, VmiEventResponse, VmiInfo,
VmiMappedPage,
Architecture, Gfn, MemoryAccess, MemoryAccessOptions, VcpuId, View, VmiError, VmiEvent,
VmiEventResponse, VmiInfo, VmiMappedPage,
};

/// A trait for implementing a VMI driver.
Expand Down Expand Up @@ -39,6 +39,16 @@ pub trait VmiDriver {
fn set_memory_access(&self, gfn: Gfn, view: View, access: MemoryAccess)
-> Result<(), VmiError>;

/// Sets the memory access permissions for a specific GFN with additional
/// options.
fn set_memory_access_with_options(
&self,
gfn: Gfn,
view: View,
access: MemoryAccess,
options: MemoryAccessOptions,
) -> Result<(), VmiError>;

/// Reads a page of memory from the virtual machine.
fn read_page(&self, gfn: Gfn) -> Result<VmiMappedPage, VmiError>;

Expand Down
20 changes: 18 additions & 2 deletions crates/vmi-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ pub use self::{
arch::{Architecture, Registers},
context::{VmiContext, VmiContextProber, VmiOsContext, VmiOsContextProber},
core::{
AccessContext, AddressContext, Gfn, Hex, MemoryAccess, Pa, TranslationMechanism, Va,
VcpuId, View, VmiInfo,
AccessContext, AddressContext, Gfn, Hex, MemoryAccess, MemoryAccessOptions, Pa,
TranslationMechanism, Va, VcpuId, View, VmiInfo,
},
driver::VmiDriver,
error::{PageFault, PageFaults, VmiError},
Expand Down Expand Up @@ -371,6 +371,22 @@ where
self.driver.set_memory_access(gfn, view, access)
}

/// Sets the memory access permissions for a specific guest frame number
/// (GFN) with additional options.
///
/// In addition to the basic read, write, and execute permissions, this
/// method allows you to specify additional options for the memory access.
pub fn set_memory_access_with_options(
&self,
gfn: Gfn,
view: View,
access: MemoryAccess,
options: MemoryAccessOptions,
) -> Result<(), VmiError> {
self.driver
.set_memory_access_with_options(gfn, view, access, options)
}

/// Allocates the next available guest frame number (GFN).
///
/// This method finds and allocates the next free GFN after the current
Expand Down
33 changes: 31 additions & 2 deletions crates/vmi-driver-xen/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use std::{
};

use vmi_core::{
Architecture, Gfn, MemoryAccess, VcpuId, View, VmiEvent, VmiEventResponse, VmiInfo,
VmiMappedPage,
Architecture, Gfn, MemoryAccess, MemoryAccessOptions, VcpuId, View, VmiEvent, VmiEventResponse,
VmiInfo, VmiMappedPage,
};
use xen::{
ctrl::VmEventRing, XenAltP2M, XenAltP2MView, XenControl, XenDeviceModel, XenDomain,
Expand Down Expand Up @@ -136,6 +136,35 @@ where
}
}

pub fn set_memory_access_with_options(
&self,
gfn: Gfn,
view: View,
access: MemoryAccess,
options: MemoryAccessOptions,
) -> Result<(), Error> {
tracing::trace!(%gfn, %view, %access, "set memory access");

let mut xen_access = access.into_ext();

if options.contains(MemoryAccessOptions::IGNORE_PAGE_WALK_UPDATES) {
if access != MemoryAccess::R {
return Err(Error::NotSupported);
}

xen_access = xen::MemoryAccess::R2PW;
}

if view.0 == 0 {
return Ok(self.domain.set_mem_access(gfn.into(), xen_access)?);
}

match self.views.borrow().get(&view.0) {
Some(view) => Ok(view.set_mem_access(gfn.into(), xen_access)?),
None => Err(Error::ViewNotFound),
}
}

pub fn read_page(&self, gfn: Gfn) -> Result<VmiMappedPage, Error> {
let page = self.foreign_memory.map(
self.domain.id(),
Expand Down
16 changes: 14 additions & 2 deletions crates/vmi-driver-xen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ mod error;
use std::time::Duration;

use vmi_core::{
Architecture, Gfn, MemoryAccess, VcpuId, View, VmiDriver, VmiError, VmiEvent, VmiEventResponse,
VmiInfo, VmiMappedPage,
Architecture, Gfn, MemoryAccess, MemoryAccessOptions, VcpuId, View, VmiDriver, VmiError,
VmiEvent, VmiEventResponse, VmiInfo, VmiMappedPage,
};
use xen::XenDomainId;

Expand Down Expand Up @@ -80,6 +80,18 @@ where
Ok(self.inner.set_memory_access(gfn, view, access)?)
}

fn set_memory_access_with_options(
&self,
gfn: Gfn,
view: View,
access: MemoryAccess,
options: MemoryAccessOptions,
) -> Result<(), VmiError> {
Ok(self
.inner
.set_memory_access_with_options(gfn, view, access, options)?)
}

fn read_page(&self, gfn: Gfn) -> Result<VmiMappedPage, VmiError> {
Ok(self.inner.read_page(gfn)?)
}
Expand Down

0 comments on commit 157f3bc

Please sign in to comment.