Skip to content

Commit 351199b

Browse files
feat: added docs
1 parent 6d32033 commit 351199b

File tree

4 files changed

+146
-26
lines changed

4 files changed

+146
-26
lines changed

opentmk/src/uefi/hypercall.rs

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use hvdef::HvRegisterGuestVsmPartitionConfig;
1111
use hvdef::HvRegisterValue;
1212
use hvdef::HvRegisterVsmPartitionConfig;
1313
use hvdef::HvX64RegisterName;
14-
use minimal_rt::arch::hypercall::{invoke_hypercall_vtl};
1514
use zerocopy::FromZeros;
1615
use core::arch;
1716
use core::cell::RefCell;
@@ -21,7 +20,7 @@ use hvdef::hypercall::HvInputVtl;
2120
use hvdef::Vtl;
2221
use hvdef::HV_PAGE_SIZE;
2322
use memory_range::MemoryRange;
24-
use minimal_rt::arch::hypercall::invoke_hypercall;
23+
use minimal_rt::arch::hypercall::{invoke_hypercall, HYPERCALL_PAGE};
2524
use zerocopy::IntoBytes;
2625
use zerocopy::FromBytes;
2726

@@ -32,6 +31,19 @@ struct HvcallPage {
3231

3332
}
3433

34+
pub fn invoke_hypercall_vtl(control: hvdef::hypercall::Control) {
35+
// SAFETY: the caller guarantees the safety of this operation.
36+
unsafe {
37+
core::arch::asm! {
38+
"call {hypercall_page}",
39+
hypercall_page = sym HYPERCALL_PAGE,
40+
inout("rcx") u64::from(control) => _,
41+
in("rdx") 0,
42+
in("rax") 0,
43+
}
44+
}
45+
}
46+
3547
impl HvcallPage {
3648
pub const fn new() -> Self {
3749
HvcallPage {
@@ -52,6 +64,59 @@ impl HvcallPage {
5264
}
5365

5466
/// Provides mechanisms to invoke hypercalls within the boot shim.
67+
///
68+
/// This module defines the `HvCall` struct and associated methods to interact with
69+
/// hypervisor functionalities through hypercalls. It includes utilities for managing
70+
/// hypercall pages, setting and getting virtual processor (VP) registers, enabling
71+
/// VTL (Virtual Trust Levels), and applying memory protections.
72+
///
73+
/// # Overview
74+
///
75+
/// - **Hypercall Pages**: Manages page-aligned buffers for hypercall input and output.
76+
/// - **VP Registers**: Provides methods to set and get VP registers.
77+
/// - **VTL Management**: Includes methods to enable VTLs, apply VTL protections, and
78+
/// manage VTL-specific operations.
79+
/// - **Memory Protections**: Supports applying VTL protections and accepting VTL2 pages.
80+
///
81+
/// # Safety
82+
///
83+
/// Many methods in this module involve unsafe operations, such as invoking hypercalls
84+
/// or interacting with low-level memory structures. The caller must ensure the safety
85+
/// of these operations by adhering to the requirements of the hypervisor and the
86+
/// underlying architecture.
87+
///
88+
/// # Usage
89+
///
90+
/// This module is designed for use in single-threaded environments, such as the boot
91+
/// shim. It uses static buffers for hypercall pages, so it is not thread-safe.
92+
///
93+
/// # Features
94+
///
95+
/// - **Architecture-Specific Implementations**: Some methods are only available for
96+
/// specific architectures (e.g., `x86_64` or `aarch64`).
97+
/// - **Error Handling**: Methods return `Result` types to handle hypervisor errors.
98+
///
99+
/// # Examples
100+
///
101+
/// ```rust
102+
/// let mut hv_call = HvCall::new();
103+
/// hv_call.initialize();
104+
/// let vtl = hv_call.vtl();
105+
/// println!("Current VTL: {:?}", vtl);
106+
/// hv_call.uninitialize();
107+
/// ```
108+
///
109+
/// # Modules and Types
110+
///
111+
/// - `HvCall`: Main struct for managing hypercalls.
112+
/// - `HvcallPage`: Struct for page-aligned buffers.
113+
/// - `HwId`: Type alias for hardware IDs (APIC ID on `x86_64`, MPIDR on `aarch64`).
114+
///
115+
/// # Notes
116+
///
117+
/// - This module assumes the presence of a hypervisor that supports the required
118+
/// hypercalls.
119+
/// - The boot shim must ensure that hypercalls are invoked in a valid context.
55120
/// Internally uses static buffers for the hypercall page, the input
56121
/// page, and the output page, so this should not be used in any
57122
/// multi-threaded capacity (which the boot shim currently is not).
@@ -62,13 +127,6 @@ pub struct HvCall {
62127
output_page: HvcallPage,
63128
}
64129

65-
/// Returns an [`HvCall`] instance.
66-
///
67-
/// Panics if another instance is already in use.
68-
// #[track_caller]
69-
// pub fn hvcall() -> core::cell::RefMut<'static, HvCall> {
70-
// HVCALL.borrow_mut()
71-
// }
72130

73131
#[expect(unsafe_code)]
74132
impl HvCall {
@@ -384,7 +442,7 @@ impl HvCall {
384442
Ok(context)
385443
}
386444

387-
pub fn high_vtl() {
445+
pub fn vtl_call() {
388446
let control: hvdef::hypercall::Control = hvdef::hypercall::Control::new()
389447
.with_code(hvdef::HypercallCode::HvCallVtlCall.0)
390448
.with_rep_count(0);
@@ -397,7 +455,7 @@ impl HvCall {
397455
}
398456
}
399457

400-
pub fn low_vtl() {
458+
pub fn vtl_return() {
401459
let control: hvdef::hypercall::Control = hvdef::hypercall::Control::new()
402460
.with_code(hvdef::HypercallCode::HvCallVtlReturn.0)
403461
.with_rep_count(0);

opentmk/src/uefi/hypvctx.rs

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use super::{
22
context::{TestCtxTrait, VpExecutor},
33
hypercall::HvCall,
44
};
5-
use crate::{debuglog, slog::AssertResult};
65
use crate::uefi::alloc::ALLOCATOR;
6+
use crate::{debuglog, slog::AssertResult};
77
use crate::{
88
infolog,
99
slog::AssertOption,
@@ -46,10 +46,7 @@ fn register_command_queue(vp_index: u32) {
4646
CMD.lock().insert(vp_index, LinkedList::new());
4747
debuglog!("registered command queue for vp: {}", vp_index);
4848
} else {
49-
debuglog!(
50-
"command queue already registered for vp: {}",
51-
vp_index
52-
);
49+
debuglog!("command queue already registered for vp: {}", vp_index);
5350
}
5451
}
5552
}
@@ -67,6 +64,71 @@ impl Drop for HvTestCtx {
6764
}
6865
}
6966

67+
/// Implementation of the `TestCtxTrait` for the `HvTestCtx` structure, providing
68+
/// various methods to manage and interact with virtual processors (VPs) and
69+
/// Virtual Trust Levels (VTLs) in a hypervisor context.
70+
///
71+
/// # Methods
72+
///
73+
/// - `start_on_vp(&mut self, cmd: VpExecutor)`:
74+
/// Starts a virtual processor (VP) on a specified VTL. Handles enabling VTLs,
75+
/// switching between high and low VTLs, and managing VP execution contexts.
76+
///
77+
/// - `queue_command_vp(&mut self, cmd: VpExecutor)`:
78+
/// Queues a command for a specific VP and VTL.
79+
///
80+
/// - `switch_to_high_vtl(&mut self)`:
81+
/// Switches the current execution context to a high VTL.
82+
///
83+
/// - `switch_to_low_vtl(&mut self)`:
84+
/// Switches the current execution context to a low VTL.
85+
///
86+
/// - `setup_partition_vtl(&mut self, vtl: Vtl)`:
87+
/// Configures the partition to enable a specified VTL.
88+
///
89+
/// - `setup_interrupt_handler(&mut self)`:
90+
/// Sets up the interrupt handler for the architecture.
91+
///
92+
/// - `setup_vtl_protection(&mut self)`:
93+
/// Enables VTL protection for the current partition.
94+
///
95+
/// - `setup_secure_intercept(&mut self, interrupt_idx: u8)`:
96+
/// Configures secure intercept for a specified interrupt index, including
97+
/// setting up the SIMP and SINT0 registers.
98+
///
99+
/// - `apply_vtl_protection_for_memory(&mut self, range: Range<u64>, vtl: Vtl)`:
100+
/// Applies VTL protections to a specified memory range.
101+
///
102+
/// - `write_msr(&mut self, msr: u32, value: u64)`:
103+
/// Writes a value to a specified Model-Specific Register (MSR).
104+
///
105+
/// - `read_msr(&mut self, msr: u32) -> u64`:
106+
/// Reads the value of a specified Model-Specific Register (MSR).
107+
///
108+
/// - `start_running_vp_with_default_context(&mut self, cmd: VpExecutor)`:
109+
/// Starts a VP with the default execution context.
110+
///
111+
/// - `set_default_ctx_to_vp(&mut self, vp_index: u32, vtl: Vtl)`:
112+
/// Sets the default execution context for a specified VP and VTL.
113+
///
114+
/// - `enable_vp_vtl_with_default_context(&mut self, vp_index: u32, vtl: Vtl)`:
115+
/// Enables a VTL for a specified VP using the default execution context.
116+
///
117+
/// - `set_interupt_idx(&mut self, interrupt_idx: u8, handler: fn())`:
118+
/// Sets an interrupt handler for a specified interrupt index. (x86_64 only)
119+
///
120+
/// - `get_vp_count(&self) -> u32`:
121+
/// Retrieves the number of virtual processors available on the system.
122+
///
123+
/// - `get_register(&mut self, reg: u32) -> u128`:
124+
/// Retrieves the value of a specified register. Supports both x86_64 and
125+
/// aarch64 architectures.
126+
///
127+
/// - `get_current_vp(&self) -> u32`:
128+
/// Returns the index of the current virtual processor.
129+
///
130+
/// - `get_current_vtl(&self) -> Vtl`:
131+
/// Returns the current Virtual Trust Level (VTL).
70132
impl TestCtxTrait for HvTestCtx {
71133
fn start_on_vp(&mut self, cmd: VpExecutor) {
72134
let (vp_index, vtl, cmd) = cmd.get();
@@ -145,11 +207,11 @@ impl TestCtxTrait for HvTestCtx {
145207
}
146208

147209
fn switch_to_high_vtl(&mut self) {
148-
HvCall::high_vtl();
210+
HvCall::vtl_call();
149211
}
150212

151213
fn switch_to_low_vtl(&mut self) {
152-
HvCall::low_vtl();
214+
HvCall::vtl_return();
153215
}
154216

155217
fn setup_partition_vtl(&mut self, vtl: Vtl) {

opentmk/src/uefi/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ use uefi::Status;
3232
fn uefi_main() -> Status {
3333
init().expect_assert("Failed to initialize environment");
3434
tests::run_test();
35-
loop {}
35+
Status::SUCCESS
3636
}

opentmk/src/uefi/rt.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
// UNSAFETY: Raw assembly needed for panic handling to abort.
88
#![expect(unsafe_code)]
99

10-
use crate::arch::serial::{Serial, InstrIoAccess};
11-
use core::fmt::Write;
10+
use crate::arch::serial::{InstrIoAccess, Serial};
1211
use crate::slog;
1312
use crate::sync::Mutex;
13+
use core::arch::asm;
14+
use core::fmt::Write;
1415

1516
#[panic_handler]
1617
fn panic_handler(panic: &core::panic::PanicInfo<'_>) -> ! {
17-
18-
let io = InstrIoAccess {};
19-
let mut ser = Mutex::new(Serial::new(io));
2018
crate::errorlog!("Panic at runtime: {}", panic);
21-
crate::errorlog!("Could not shut down... falling back to invoking an undefined instruction");
22-
loop{}
19+
unsafe {
20+
asm!("int 8H");
21+
}
22+
loop {}
2323
}

0 commit comments

Comments
 (0)