Skip to main content

axvcpu/
arch_vcpu.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
15use axaddrspace::{GuestPhysAddr, HostPhysAddr};
16use axerrno::AxResult;
17use axvisor_api::vmm::{VCpuId, VMId};
18
19use crate::exit::AxVCpuExitReason;
20
21/// Architecture-specific virtual CPU trait definition.
22///
23/// This trait provides an abstraction layer for implementing virtual CPUs across
24/// different hardware architectures (x86_64, ARM64, RISC-V, etc.). Each architecture
25/// must implement this trait to provide the necessary low-level virtualization primitives.
26pub trait AxArchVCpu: Sized {
27    /// Architecture-specific configuration for VCpu creation.
28    ///
29    /// This associated type allows each architecture to define its own
30    /// configuration parameters needed during VCpu initialization.
31    type CreateConfig;
32
33    /// Architecture-specific configuration for VCpu setup.
34    ///
35    /// This associated type allows each architecture to specify additional
36    /// configuration parameters needed after basic VCpu creation but before execution.
37    type SetupConfig;
38
39    /// Creates a new architecture-specific VCpu instance.
40    fn new(vm_id: VMId, vcpu_id: VCpuId, config: Self::CreateConfig) -> AxResult<Self>;
41
42    /// Sets the guest entry point where VCpu execution will begin.
43    ///
44    /// It's guaranteed that this function is called only once, before [`AxArchVCpu::setup`] being called.
45    fn set_entry(&mut self, entry: GuestPhysAddr) -> AxResult;
46
47    /// Sets the Extended Page Table (EPT) root for memory translation.
48    ///
49    /// The EPT root defines the top-level page table used for guest-to-host
50    /// physical address translation in hardware virtualization.
51    fn set_ept_root(&mut self, ept_root: HostPhysAddr) -> AxResult;
52
53    /// Completes VCpu initialization and prepares it for execution.
54    ///
55    /// This method performs any final architecture-specific setup needed
56    /// before the VCpu can be bound and executed.
57    fn setup(&mut self, config: Self::SetupConfig) -> AxResult;
58
59    /// Executes the VCpu until a VM exit occurs.
60    ///
61    /// This is the core execution method that transfers control to the guest VCpu
62    /// and runs until the guest triggers a VM exit condition that requires
63    /// hypervisor intervention.
64    fn run(&mut self) -> AxResult<AxVCpuExitReason>;
65
66    /// Binds the VCpu to the current physical CPU for execution.
67    ///
68    /// This method performs any necessary architecture-specific initialization
69    /// to prepare the VCpu for execution on the current physical CPU.
70    fn bind(&mut self) -> AxResult;
71
72    /// Unbinds the VCpu from the current physical CPU.
73    ///
74    /// This method performs cleanup and state preservation when moving
75    /// the VCpu away from the current physical CPU.
76    fn unbind(&mut self) -> AxResult;
77
78    /// Sets the value of a general-purpose register.
79    fn set_gpr(&mut self, reg: usize, val: usize);
80
81    /// Inject an interrupt to the VCpu.
82    ///
83    /// It's guaranteed (for implementors, and required for callers) that this function is called
84    /// on the physical CPU where the VCpu is running or queueing.
85    ///
86    /// It's not guaranteed that the VCpu is running or bound to the current physical CPU when this
87    /// function is called. It means sometimes an irq queue is necessary to buffer the interrupts
88    /// until the VCpu is running.
89    fn inject_interrupt(&mut self, vector: usize) -> AxResult;
90
91    /// Sets the return value that will be delivered to the guest.
92    fn set_return_value(&mut self, val: usize);
93}