| Crates.io | axvisor_api |
| lib.rs | axvisor_api |
| version | 0.1.0 |
| created_at | 2025-07-30 06:37:25.275772+00 |
| updated_at | 2025-07-30 06:37:25.275772+00 |
| description | Basic API for components of the Hypervisor on ArceOS |
| homepage | |
| repository | https://github.com/arceos-hypervisor/axvisor_api |
| max_upload_size | |
| id | 1773180 |
| size | 114,497 |
> 中文README <
⚠️ This repository is experimental. The list and syntax of the API may change. ⚠️
⚠️ These APIs may eventually be stabilized or may be removed in the future. ⚠️
⚠️ The maintainers will do their best to maintain compatibility, but breaking changes may still occur. ⚠️
Various components of Axvisor need to access functionalities provided by the ArceOS unikernel. For the crate Axvisor itself, ArceOS is a dependency and can be accessed directly. However, to maintain decoupling, other lower-level components should not use ArceOS as a direct dependency and hence cannot directly access its API. Therefore, a form of "dependency injection" is required to provide ArceOS's API to various parts of Axvisor.
Currently, Axvisor mainly uses traits + generic parameters to implement dependency injection and provide APIs to components. For example:
// Component defines the API it needs
pub trait ModAHal {
fn foo() -> u32;
}
pub struct ModA<T: ModAHal> {
state: u32,
}
impl<T: ModAHal> ModA<T> {
pub fn new() -> Self {
Self { state: T::foo() }
}
}
// Axvisor provides the implementation
pub struct ModAHalImpl;
impl ModAHal for ModAHalImpl {
fn foo() -> u32 {
42
}
}
pub fn main() {
let mod_a = ModA::<ModAHalImpl>::new();
println!("ModA state: {}", mod_a.state);
}
This method has some obvious advantages:
However, there are also some disadvantages:
pub trait MemoryHal {
// Memory-related API
}
pub trait VCpuHal {
type Memory: MemoryHal;
// Virtual CPU-related API
}
pub trait VMHal {
type VCpu: VCpuHal;
// Virtual machine-related API
}
axvisor_api aims to solve the above problems. Its design approach is:
crate_interface to define the API interface and wrap the provided API into regular functions.crate_interface trait.Example code of axvisor_api:
// Define an API module
#[api_mod]
mod memory {
pub use memory_addr::{PhysAddr, VirtAddr};
/// Allocate a frame.
extern fn alloc_frame() -> Option<PhysAddr>;
/// Deallocate a frame.
extern fn dealloc_frame(addr: PhysAddr);
}
// Implement the API module
#[api_mod_impl(axvisor_api::memory)]
mod memory_impl {
use crate_interface::memory::{alloc_frame, dealloc_frame, PhysAddr};
extern fn alloc_frame() -> Option<PhysAddr> {
// Call ArceOS's memory allocation function
arceos_memory_alloc()
}
extern fn dealloc_frame(addr: PhysAddr) {
// Call ArceOS's memory deallocation function
arceos_memory_dealloc(addr);
}
}
// Use the API module
use axvisor_api::memory::{alloc_frame, dealloc_frame, PhysAddr};
pub fn main() {
let frame = alloc_frame().expect("Failed to allocate frame");
println!("Allocated frame at address: {:?}", frame);
dealloc_frame(frame);
}
This approach replaces all previous traits with a unified, functionally categorized API collection and eliminates explicit trait dependencies via crate_interface. Its advantages are:
Nonetheless, there are also some downsides:
crate_interface uses traits under the hood for compile-time checks, these checks are weaker than traditional traits. For instance, if an api_mod is not implemented at all, the issue is only caught at link time.axvisor_api. This could be mitigated using feature flags to disable unused parts of axvisor_api (not yet implemented), but it's still a downside.Besides the above drawbacks, the current implementation of axvisor_api has some issues:
#[api_mod] mod x; with x.rs) is currently unsupported due to limitations of Rust procedural macros.extern fn syntax and rustfmt: Marking API functions with extern fn improves readability and consistency, but rustfmt rewrites it to extern "C" fn, causing compile errors. A possible solution is to directly use extern "C" fn, though this may clash with actual external C function declarations.extern keyword and the lack of a body, API functions may not stand out in large code blocks. Currently, detailed documentation is provided as a workaround. In the future, an #[api] attribute might improve readability.Additionally, there are some platform-related issues that are independent of the axvisor_api design or implementation. For example:
axvisor_api makes the modules bloated, but not doing so could hurt readability and maintainability.