1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Copyright 2025 The Axvisor Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! `axvisor_api` is the bottom-most crate of the AxVisor Hypervisor project. It
//! provides a standardized set of APIs for the components of the Hypervisor and
//! grants them access to OS-level and Hypervisor-level functionalities, like
//! memory allocation, address conversion, time and timer management, cross-vcpu
//! operations, and so on.
//!
//! `axvisor_api` is designed for two main purposes:
//! - **Replace generic-based API-injection mechanism.**
//!
//! Generic-based API-injection mechanism, for example:
//!
//! ```rust
//! pub trait VCpuHal {
//! /* ... */
//! }
//! pub struct VCpu<H: VCpuHal> {
//! /* ... */
//! # _marker: core::marker::PhantomData<H>,
//! }
//! ```
//!
//! has been widely used previously here and in other related projects. It's
//! definitely great, with zero overhead, good readability, and no link-time
//! magic. However, it turns out that passing generic parameters down through
//! multiple layers of modules and components is quite inconvenient, and it's
//! always a pain to decide how to categorize the APIs into different traits
//! properly.
//!
//! Finally, the author decided to just use a big monolithic trait for every
//! component, and use `crate_interface` to eliminate the generic parameter.
//! (Although there are multiple traits in this crate, technically in the
//! current implementation the link-time symbol space is used as a big
//! monolithic trait.) Theoretically, this may slightly increase the
//! difficulty of re-using a single component in a new software project, but
//! the author believes that it will reduce the overall complexity when not
//! one but a few related components are re-used together.
//!
//! - **Enable portability of the Hypervisor across different unikernels.**
//!
//! Technically, the whole AxVisor Hypervisor can be ported to different
//! unikernels by implementing the APIs defined in this crate (although not
//! tested yet). If such porting is successful, this crate can also be used as
//! a tested hardware-and-unikernel abstraction layer for other hypervisor
//! projects.
//!
//! This crate also provides a standard way to define and implement APIs, with
//! the [`api_def`] and [`api_impl`] procedural macros. They are built on top of
//! the `crate_interface` crate, which provides the low-level functionalities
//! of defining and implementing crate-level interfaces.
//!
//! # How to define and implement APIs
//!
//! ## Define APIs
//!
//! To define APIs, you can use the `api_def` attribute on a trait defining the
//! API, with each API function defined as a regular function in the trait. It's
//! recommended to pack the trait definition and related definitions (like type
//! aliases) into a module for better organization.
//!
//! ```rust, standalone_crate
//! # // some inconvenience brought by proc-macro-name and doctest
//! # use axvisor_api::__priv;
//! # fn main() {}
//! mod example {
//! # // some inconvenience brought by proc-macro-name and doctest
//! # use axvisor_api::api_def;
//! /// Example API definition
//! #[api_def]
//! pub trait ExampleIf {
//! /// An example API function
//! fn example_func(arg: usize) -> usize;
//! /// Another example API function
//! fn another_func();
//! }
//! }
//!
//! fn use_example_api() {
//! let result = example::example_func(42);
//! example::another_func();
//! }
//! ```
//!
//! `api_def` will generate a caller function for each API function defined in
//! the trait, at the same level as the trait definition. The generated callers
//! can be used to invoke the API functions, as demonstrated above.
//!
//! ## Implement APIs
//!
//! Defined APIs should be implemented somewhere, unless they are not used
//! anywhere. To implement APIs, the implementer should define an empty struct
//! and implement the API trait for the struct, with the `api_impl` attribute on
//! the `impl` block. For example,
//!
//! ```rust, standalone_crate
//! # // some inconvenience brought by proc-macro-name and doctest
//! # use axvisor_api::{api_impl, __priv};
//! mod example {
//! # // some inconvenience brought by proc-macro-name and doctest
//! # use axvisor_api::{api_def, __priv};
//! /// Example API definition
//! #[api_def]
//! pub trait ExampleIf {
//! /// An example API function
//! fn example_func(arg: usize) -> usize;
//! /// Another example API function
//! fn another_func();
//! }
//! }
//!
//! struct ExampleImpl;
//!
//! #[api_impl]
//! impl example::ExampleIf for ExampleImpl {
//! fn example_func(arg: usize) -> usize {
//! arg + 1
//! }
//!
//! fn another_func() {
//! println!("Another function called");
//! }
//! }
//!
//! fn main() {
//! let result = example::example_func(42);
//! assert_eq!(result, 43);
//! example::another_func(); // prints "Another function called"
//! }
//! ```
//!
pub use ;