Skip to main content

rvm_hal/
lib.rs

1//! # RVM Hardware Abstraction Layer
2//!
3//! Platform-agnostic traits for the RVM microhypervisor, as specified in
4//! ADR-133. Concrete implementations are provided per target (`AArch64`,
5//! RISC-V, x86-64).
6//!
7//! ## Subsystems
8//!
9//! - [`Platform`] -- top-level platform discovery and initialization
10//! - [`MmuOps`] -- stage-2 page table management
11//! - [`TimerOps`] -- monotonic timer and deadline scheduling
12//! - [`InterruptOps`] -- interrupt routing and masking
13//!
14//! ## Design Constraints (ADR-133)
15//!
16//! - All trait methods return `RvmResult`
17//! - No `unsafe` in trait *definitions* (implementations may need it)
18//! - Zero-copy: pass borrowed slices, never owned buffers
19
20#![no_std]
21// NOTE: `deny` instead of `forbid` because the HAL is the hardware boundary.
22// Concrete arch implementations (aarch64, riscv, x86_64) require `unsafe`
23// for register access, MMIO, and inline assembly. Every `unsafe` block in
24// this crate must have a `// SAFETY:` comment documenting its invariant.
25#![deny(unsafe_code)]
26#![deny(missing_docs)]
27#![deny(clippy::all)]
28#![warn(clippy::pedantic)]
29#![allow(clippy::new_without_default)]
30#![allow(clippy::empty_line_after_doc_comments)]
31#![allow(clippy::identity_op)]
32#![allow(clippy::cast_possible_truncation)]
33#![allow(clippy::cast_lossless)]
34#![allow(clippy::missing_errors_doc)]
35#![allow(clippy::missing_panics_doc)]
36#![allow(clippy::must_use_candidate)]
37#![allow(clippy::module_name_repetitions)]
38#![allow(clippy::doc_markdown)]
39#![allow(clippy::similar_names)]
40#![allow(clippy::verbose_bit_mask)]
41#![allow(clippy::needless_pass_by_value)]
42#![allow(clippy::unnecessary_wraps)]
43
44#[cfg(feature = "alloc")]
45extern crate alloc;
46
47#[cfg(feature = "std")]
48extern crate std;
49
50/// AArch64-specific HAL implementation (QEMU virt, Cortex-A72).
51///
52/// This module is only compiled when targeting `aarch64`. It contains
53/// the EL2 boot stubs, stage-2 page table management, PL011 UART
54/// driver, GICv2 interrupt controller, and ARM generic timer.
55///
56/// `unsafe_code` is allowed here because this is the hardware boundary:
57/// register access, MMIO writes, and inline assembly all require it.
58#[cfg(target_arch = "aarch64")]
59#[allow(unsafe_code)]
60pub mod aarch64;
61
62use rvm_types::{GuestPhysAddr, PhysAddr, RvmResult};
63
64/// Top-level platform discovery and initialization.
65pub trait Platform {
66    /// Return the number of physical CPUs available.
67    fn cpu_count(&self) -> usize;
68
69    /// Return the total physical memory in bytes.
70    fn total_memory(&self) -> u64;
71
72    /// Halt the current CPU.
73    fn halt(&self) -> !;
74}
75
76/// Stage-2 MMU operations for guest physical to host physical translation.
77pub trait MmuOps {
78    /// Map a guest physical page to a host physical page.
79    ///
80    /// # Errors
81    ///
82    /// Returns an error if the mapping cannot be established.
83    fn map_page(&mut self, guest: GuestPhysAddr, host: PhysAddr) -> RvmResult<()>;
84
85    /// Unmap a guest physical page.
86    ///
87    /// # Errors
88    ///
89    /// Returns an error if the page is not currently mapped.
90    fn unmap_page(&mut self, guest: GuestPhysAddr) -> RvmResult<()>;
91
92    /// Translate a guest physical address to a host physical address.
93    ///
94    /// # Errors
95    ///
96    /// Returns an error if the address is not mapped.
97    fn translate(&self, guest: GuestPhysAddr) -> RvmResult<PhysAddr>;
98
99    /// Flush TLB entries for the given guest address range.
100    ///
101    /// # Errors
102    ///
103    /// Returns an error if the flush operation fails.
104    fn flush_tlb(&mut self, guest: GuestPhysAddr, page_count: usize) -> RvmResult<()>;
105}
106
107/// Monotonic timer operations for deadline scheduling.
108pub trait TimerOps {
109    /// Return the current monotonic time in nanoseconds.
110    fn now_ns(&self) -> u64;
111
112    /// Set a one-shot timer deadline in nanoseconds from now.
113    ///
114    /// # Errors
115    ///
116    /// Returns an error if the deadline cannot be set.
117    fn set_deadline_ns(&mut self, ns_from_now: u64) -> RvmResult<()>;
118
119    /// Cancel the current deadline.
120    ///
121    /// # Errors
122    ///
123    /// Returns an error if no deadline is currently set.
124    fn cancel_deadline(&mut self) -> RvmResult<()>;
125}
126
127/// Interrupt controller operations.
128pub trait InterruptOps {
129    /// Enable the interrupt with the given ID.
130    ///
131    /// # Errors
132    ///
133    /// Returns an error if the interrupt ID is invalid.
134    fn enable(&mut self, irq: u32) -> RvmResult<()>;
135
136    /// Disable the interrupt with the given ID.
137    ///
138    /// # Errors
139    ///
140    /// Returns an error if the interrupt ID is invalid.
141    fn disable(&mut self, irq: u32) -> RvmResult<()>;
142
143    /// Acknowledge the interrupt and return its ID, or `None` if spurious.
144    fn acknowledge(&mut self) -> Option<u32>;
145
146    /// Signal end-of-interrupt for the given ID.
147    fn end_of_interrupt(&mut self, irq: u32);
148}