axvisor_api/vmm.rs
1// Copyright 2025 The Axvisor Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Virtual machine management APIs for the AxVisor hypervisor.
16//!
17//! This module provides APIs for managing virtual machines (VMs) and virtual
18//! CPUs (vCPUs), including querying VM/vCPU information and interrupt
19//! injection.
20//!
21//! # Overview
22//!
23//! The VMM (Virtual Machine Monitor) APIs enable:
24//! - Querying the current VM and vCPU context
25//! - Getting information about VMs and their vCPUs
26//! - Injecting interrupts into virtual CPUs
27//! - Timer expiration notifications
28//!
29//! # Types
30//!
31//! - [`VMId`] - Virtual machine identifier.
32//! - [`VCpuId`] - Virtual CPU identifier.
33//! - [`InterruptVector`] - Interrupt vector number.
34//!
35//! # Helper Functions
36//!
37//! In addition to the core API trait, this module provides helper functions:
38//! - [`current_vm_vcpu_num`] - Get the vCPU count of the current VM.
39//! - [`current_vm_active_vcpus`] - Get the active vCPU mask of the current VM.
40//!
41//! # Implementation
42//!
43//! To implement these APIs, use the [`api_impl`](crate::api_impl) attribute
44//! macro on an impl block:
45//!
46//! ```rust,ignore
47//! struct VmmIfImpl;
48//!
49//! #[axvisor_api::api_impl]
50//! impl axvisor_api::vmm::VmmIf for VmmIfImpl {
51//! fn current_vm_id() -> VMId {
52//! // Return the current VM's ID
53//! }
54//! // ... implement other functions
55//! }
56//! ```
57
58/// Virtual machine identifier type.
59///
60/// Each virtual machine is assigned a unique identifier that can be used
61/// to reference it in API calls.
62pub type VMId = usize;
63
64/// Virtual CPU identifier type.
65///
66/// Each vCPU within a VM is assigned a unique identifier (0-indexed).
67pub type VCpuId = usize;
68
69/// Interrupt vector type.
70///
71/// Represents the interrupt vector number to be injected into a guest.
72pub type InterruptVector = u8;
73
74/// The maximum number of virtual CPUs supported in a virtual machine.
75pub const MAX_VCPU_NUM: usize = 64;
76
77/// A set of virtual CPUs.
78pub type VCpuSet = ax_cpumask::CpuMask<MAX_VCPU_NUM>;
79
80/// The API trait for virtual machine management functionalities.
81///
82/// This trait defines the core VM management interface required by the
83/// hypervisor components. Implementations should be provided by the VMM
84/// layer.
85#[crate::api_def]
86pub trait VmmIf {
87 /// Notify that a virtual CPU timer has expired.
88 /// Get the identifier of the current virtual machine.
89 ///
90 /// This function returns the VM ID of the VM that the calling context
91 /// belongs to.
92 ///
93 /// # Returns
94 ///
95 /// The current VM's identifier.
96 fn current_vm_id() -> VMId;
97
98 /// Get the identifier of the current virtual CPU.
99 ///
100 /// This function returns the vCPU ID within the current VM context.
101 ///
102 /// # Returns
103 ///
104 /// The current vCPU's identifier (0-indexed within the VM).
105 fn current_vcpu_id() -> VCpuId;
106
107 /// Get the number of virtual CPUs in a virtual machine.
108 ///
109 /// # Arguments
110 ///
111 /// * `vm_id` - The identifier of the virtual machine to query.
112 ///
113 /// # Returns
114 ///
115 /// - `Some(count)` - The number of vCPUs in the specified VM.
116 /// - `None` - If the VM ID is invalid.
117 fn vcpu_num(vm_id: VMId) -> Option<usize>;
118
119 /// Get the bitmask of active virtual CPUs in a virtual machine.
120 ///
121 /// Each bit in the returned value represents a vCPU, where bit N is set
122 /// if vCPU N is active (online and running).
123 ///
124 /// # Arguments
125 ///
126 /// * `vm_id` - The identifier of the virtual machine to query.
127 ///
128 /// # Returns
129 ///
130 /// - `Some(mask)` - The active vCPU bitmask for the specified VM.
131 /// - `None` - If the VM ID is invalid.
132 fn active_vcpus(vm_id: VMId) -> Option<usize>;
133
134 /// Inject an interrupt into a specific virtual CPU.
135 ///
136 /// This function queues an interrupt to be delivered to the specified
137 /// vCPU when it is next scheduled.
138 ///
139 /// # Arguments
140 ///
141 /// * `vm_id` - The identifier of the target virtual machine.
142 /// * `vcpu_id` - The identifier of the target virtual CPU.
143 /// * `vector` - The interrupt vector to inject.
144 ///
145 /// # Example
146 ///
147 /// ```rust,ignore
148 /// use axvisor_api::vmm::{inject_interrupt, current_vm_id};
149 ///
150 /// // Inject timer interrupt (vector 0x20) to vCPU 0 of the current VM
151 /// inject_interrupt(current_vm_id(), 0, 0x20);
152 /// ```
153 fn inject_interrupt(vm_id: VMId, vcpu_id: VCpuId, vector: InterruptVector);
154
155 /// Inject an interrupt to a set of virtual CPUs.
156 fn inject_interrupt_to_cpus(vm_id: VMId, vcpu_set: VCpuSet, vector: InterruptVector);
157
158 /// Notify that a virtual CPU's timer has expired.
159 ///
160 /// This function is called when a vCPU's virtual timer expires and needs
161 /// to be handled.
162 ///
163 /// # Arguments
164 ///
165 /// * `vm_id` - The identifier of the virtual machine.
166 /// * `vcpu_id` - The identifier of the virtual CPU whose timer expired.
167 ///
168 /// # Note
169 ///
170 /// This API may be revised in future versions as the timer virtualization
171 /// design evolves.
172 fn notify_vcpu_timer_expired(vm_id: VMId, vcpu_id: VCpuId);
173}
174
175/// Get the number of virtual CPUs in the current virtual machine executing on
176/// the current physical CPU.
177///
178/// This is a convenience function that combines [`current_vm_id`] and
179/// [`vcpu_num`].
180///
181/// # Returns
182///
183/// The number of vCPUs in the current VM.
184///
185/// # Panics
186///
187/// Panics if called outside of a valid VM context (when [`current_vm_id`]
188/// returns an invalid ID).
189pub fn current_vm_vcpu_num() -> usize {
190 vcpu_num(current_vm_id()).unwrap()
191}
192
193/// Get the bitmask of active virtual CPUs in the current virtual machine
194/// executing on the current physical CPU.
195///
196/// This is a convenience function that combines [`current_vm_id`] and
197/// [`active_vcpus`].
198///
199/// # Returns
200///
201/// The active vCPU bitmask for the current VM.
202///
203/// # Panics
204///
205/// Panics if called outside of a valid VM context (when [`current_vm_id`]
206/// returns an invalid ID).
207pub fn current_vm_active_vcpus() -> usize {
208 active_vcpus(current_vm_id()).unwrap()
209}