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}