#![no_std]
#![forbid(unsafe_code)]
#![deny(missing_docs)]
#![deny(clippy::all)]
#![warn(clippy::pedantic)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
use rvm_types::{GuestPhysAddr, PartitionId, PhysAddr, RvmError, RvmResult};
pub mod allocator;
pub mod reconstruction;
pub mod region;
pub mod tier;
pub use allocator::BuddyAllocator;
pub use reconstruction::{
create_checkpoint, CheckpointId, CompressedCheckpoint, ReconstructionPipeline,
ReconstructionResult, WitnessDelta,
};
pub use region::{AddressMapping, OwnedRegion, RegionConfig, RegionManager};
pub use tier::{RegionTierState, Tier, TierManager, TierThresholds};
pub const PAGE_SIZE: usize = 4096;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MemoryPermissions {
pub read: bool,
pub write: bool,
pub execute: bool,
}
impl MemoryPermissions {
pub const READ_ONLY: Self = Self {
read: true,
write: false,
execute: false,
};
pub const READ_WRITE: Self = Self {
read: true,
write: true,
execute: false,
};
pub const READ_EXECUTE: Self = Self {
read: true,
write: false,
execute: true,
};
}
#[derive(Debug, Clone, Copy)]
pub struct MemoryRegion {
pub guest_base: GuestPhysAddr,
pub host_base: PhysAddr,
pub page_count: usize,
pub permissions: MemoryPermissions,
pub owner: PartitionId,
}
pub fn validate_region(region: &MemoryRegion) -> RvmResult<()> {
if !region.guest_base.is_page_aligned() {
return Err(RvmError::AlignmentError);
}
if !region.host_base.is_page_aligned() {
return Err(RvmError::AlignmentError);
}
if region.page_count == 0 {
return Err(RvmError::ResourceLimitExceeded);
}
if !region.permissions.read && !region.permissions.write && !region.permissions.execute {
return Err(RvmError::Unsupported);
}
Ok(())
}
#[must_use]
pub fn regions_overlap(a: &MemoryRegion, b: &MemoryRegion) -> bool {
if a.owner != b.owner {
return false; }
let a_start = a.guest_base.as_u64();
let a_end = a_start + (a.page_count as u64 * PAGE_SIZE as u64);
let b_start = b.guest_base.as_u64();
let b_end = b_start + (b.page_count as u64 * PAGE_SIZE as u64);
a_start < b_end && b_start < a_end
}
#[must_use]
pub fn regions_overlap_host(a: &MemoryRegion, b: &MemoryRegion) -> bool {
let a_start = a.host_base.as_u64();
let a_end = a_start + (a.page_count as u64 * PAGE_SIZE as u64);
let b_start = b.host_base.as_u64();
let b_end = b_start + (b.page_count as u64 * PAGE_SIZE as u64);
a_start < b_end && b_start < a_end
}