From abd1092577294c00176b4ef80f21e9a19642af4a Mon Sep 17 00:00:00 2001
From: lkdWind <643840489@qq.com>
Date: Fri, 6 Jun 2025 21:05:48 +0800
Subject: [PATCH 1/3] update ci, readme
---
.github/workflows/ci.yml | 60 +++++++++++++++---
README.md | 134 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 182 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index da39d53..1c650d6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2,14 +2,55 @@ name: CI
on: [push, pull_request]
+env:
+ rust-toolchain: nightly-2025-05-20
+
jobs:
+ clippy:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ arch: [x86_64, riscv64, aarch64, loongarch64]
+ rust-toolchain: [nightly, nightly-2025-05-20]
+ env:
+ RUSTUP_TOOLCHAIN: ${{ matrix.rust-toolchain }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: dtolnay/rust-toolchain@stable
+ with:
+ toolchain: ${{ matrix.rust-toolchain }}
+ components: rust-src, clippy, rustfmt
+ targets: x86_64-unknown-none, riscv64gc-unknown-none-elf, aarch64-unknown-none-softfloat, loongarch64-unknown-none-softfloat
+ - uses: Swatinem/rust-cache@v2
+ with:
+ shared-key: cargo-bin-cache
+ cache-targets: false
+ - name: Check rust version
+ run: rustc --version --verbose
+ - name: Check code format
+ if: ${{ matrix.arch == 'x86_64' }}
+ continue-on-error: ${{ matrix.rust-toolchain == 'nightly' }}
+ run: cargo fmt --all -- --check
+ - name: Clippy for the default target
+ if: ${{ matrix.arch == 'x86_64' }}
+ continue-on-error: ${{ matrix.rust-toolchain == 'nightly' }}
+ run: make clippy
+ - name: Clippy for ${{ matrix.arch }}
+ continue-on-error: ${{ matrix.rust-toolchain == 'nightly' }}
+ run: make clippy ARCH=${{ matrix.arch }}
+
ci:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
- rust-toolchain: [nightly-2024-12-25, nightly]
- targets: [x86_64-unknown-linux-gnu, x86_64-unknown-none, riscv64gc-unknown-none-elf, aarch64-unknown-none-softfloat]
+ rust-toolchain: [nightly-2025-05-20, nightly]
+ targets: [x86_64-unknown-linux-gnu,
+ x86_64-unknown-none,
+ riscv64gc-unknown-none-elf,
+ aarch64-unknown-none-softfloat,
+ loongarch64-unknown-none-softfloat]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
@@ -40,21 +81,22 @@ jobs:
contents: write
env:
default-branch: ${{ format('refs/heads/{0}', github.event.repository.default_branch) }}
- RUSTDOCFLAGS: -D rustdoc::broken_intra_doc_links -D missing-docs
steps:
- uses: actions/checkout@v4
- - uses: dtolnay/rust-toolchain@nightly
+ - uses: dtolnay/rust-toolchain@stable
+ with:
+ toolchain: ${{ env.rust-toolchain }}
+ - uses: Swatinem/rust-cache@v2
with:
- toolchain: nightly-2024-12-25
+ shared-key: cargo-bin-cache
+ cache-targets: false
- name: Build docs
continue-on-error: ${{ github.ref != env.default-branch && github.event_name != 'pull_request' }}
- run: |
- cargo doc --no-deps --all-features
- printf '' $(cargo tree | head -1 | cut -d' ' -f1) > target/doc/index.html
+ run: make doc_check_missing
- name: Deploy to Github Pages
if: ${{ github.ref == env.default-branch }}
uses: JamesIves/github-pages-deploy-action@v4
with:
single-commit: true
branch: gh-pages
- folder: target/doc
+ folder: target/doc
\ No newline at end of file
diff --git a/README.md b/README.md
index a8fb9e1..496dd7a 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,136 @@
+[](https://deepwiki.com/arceos-hypervisor/axvm)
+
# AxVM
+The axvm crate provides a minimal virtual machine monitor (VMM) for the ArceOS hypervisor ecosystem. It implements core virtualization capabilities including virtual CPU management, memory virtualization, and device emulation across multiple hardware architectures.
+
+# APIS
+
+``````
+impl AxVM {
+ /// Creates a new VM with the given configuration.
+ /// Returns an error if the configuration is invalid.
+ /// The VM is not started until `boot` is called.
+ pub fn new(config: AxVMConfig) -> AxResult>
+}
+``````
+
+```
+// Boots the VM by setting the running flag as true.
+boot(&self) -> AxResult
+```
+
+```
+// Run a vCPU according to the given vcpu_id.
+run_vcpu(&self, vcpu_id: usize) -> AxResult
+```
+
+```
+// Returns if the VM is shutting down.
+shutting_down(&self) -> bool
+```
+
+``````
+// Returns guest VM image load region in `Vec<&'static mut [u8]>`
+get_image_load_region(
+ &self,
+ image_load_gpa: GuestPhysAddr,
+ image_size: usize,
+ ) -> AxResult>
+``````
+
+``````
+// Returns the base address of the two-stage address translation page table for the VM.
+ept_root(&self) -> HostPhysAddr
+``````
+
+# Examples
+
+### Implementation for `AxVMHal` trait.
+
+``````
+use std::os::arceos;
+use memory_addr::{PAGE_SIZE_4K, align_up_4k};
+use page_table_multiarch::PagingHandler;
+use arceos::modules::{axalloc, axhal};
+use axaddrspace::{HostPhysAddr, HostVirtAddr};
+use axvcpu::AxVCpuHal;
+use axvm::{AxVMHal, AxVMPerCpu};
+
+pub struct AxVMHalImpl;
+
+impl AxVMHal for AxVMHalImpl {
+ type PagingHandler = axhal::paging::PagingHandlerImpl;
+
+ fn alloc_memory_region_at(base: HostPhysAddr, size: usize) -> bool {
+ axalloc::global_allocator()
+ .alloc_pages_at(
+ base.as_usize(),
+ align_up_4k(size) / PAGE_SIZE_4K,
+ PAGE_SIZE_4K,
+ )
+ .map_err(|err| {
+ error!(
+ "Failed to allocate memory region [{:?}~{:?}]: {:?}",
+ base,
+ base + size,
+ err
+ );
+ })
+ .is_ok()
+ }
+
+ fn dealloc_memory_region_at(base: HostPhysAddr, size: usize) {
+ axalloc::global_allocator().dealloc_pages(base.as_usize(), size / PAGE_SIZE_4K)
+ }
+
+ fn virt_to_phys(vaddr: HostVirtAddr) -> HostPhysAddr {
+ axhal::mem::virt_to_phys(vaddr)
+ }
+
+ fn current_time_nanos() -> u64 {
+ axhal::time::monotonic_time_nanos()
+ }
+}
+
+``````
+
+### Init VM
+
+``````
+let vm_create_config =
+ AxVMCrateConfig::from_toml(raw_cfg_str).expect("Failed to resolve VM config");
+let vm_config = AxVMConfig::from(vm_create_config.clone());
+// Create VM.
+let vm = VM::new(vm_config).expect("Failed to create VM");
+
+// Load corresponding images for VM.
+load_vm_images(vm_create_config, vm.clone()).expect("Failed to load VM images");
+// Sets up the primary vCPU for the given VM,
+// generally the first vCPU in the vCPU list,
+// and initializing their respective wait queues and task lists.
+// VM's secondary vCPUs are not started at this point.
+vcpus::setup_vm_primary_vcpu(vm);
+``````
+
+### Start VM
+
+``````
+match vm.boot() {
+ Ok(_) => {
+ vcpus::notify_primary_vcpu(vm.id());
+ RUNNING_VM_COUNT.fetch_add(1, Ordering::Release);
+ info!("VM[{}] boot success", vm.id())
+ }
+ Err(err) => warn!("VM[{}] boot failed, error {:?}", vm.id(), err),
+ }
+``````
+
+[More detailed usage](https://github.com/arceos-hypervisor/axvisor)
+
Virtual Machine **resource management** crate for [`ArceOS`](https://github.com/arceos-org/arceos)'s hypervisor variant.
* resources:
- * vcpu: [axvcpu](https://github.com/arceos-hypervisor/axvcpu) list
- * memory: [axaddrspace](https://github.com/arceos-hypervisor/axaddrspace) for guest memory management
- * device: [axdevice](https://github.com/arceos-hypervisor/axdevice) list
\ No newline at end of file
+ * vcpu: [axvcpu](https://github.com/arceos-hypervisor/axvcpu) list
+ * memory: [axaddrspace](https://github.com/arceos-hypervisor/axaddrspace) for guest memory management
+ * device: [axdevice](https://github.com/arceos-hypervisor/axdevice) list
\ No newline at end of file
From 732477dab1c01b556889198a54a79d23ab9036ef Mon Sep 17 00:00:00 2001
From: lkdWind <643840489@qq.com>
Date: Mon, 9 Jun 2025 21:33:29 +0800
Subject: [PATCH 2/3] ci test
---
.github/workflows/ci.yml | 48 +++++++++++-----------------------------
1 file changed, 13 insertions(+), 35 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1c650d6..027c957 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- arch: [x86_64, riscv64, aarch64, loongarch64]
+ arch: [x86_64, riscv64, aarch64]
rust-toolchain: [nightly, nightly-2025-05-20]
env:
RUSTUP_TOOLCHAIN: ${{ matrix.rust-toolchain }}
@@ -21,7 +21,7 @@ jobs:
with:
toolchain: ${{ matrix.rust-toolchain }}
components: rust-src, clippy, rustfmt
- targets: x86_64-unknown-none, riscv64gc-unknown-none-elf, aarch64-unknown-none-softfloat, loongarch64-unknown-none-softfloat
+ targets: x86_64-unknown-none, riscv64gc-unknown-none-elf, aarch64-unknown-none-softfloat
- uses: Swatinem/rust-cache@v2
with:
shared-key: cargo-bin-cache
@@ -35,10 +35,17 @@ jobs:
- name: Clippy for the default target
if: ${{ matrix.arch == 'x86_64' }}
continue-on-error: ${{ matrix.rust-toolchain == 'nightly' }}
- run: make clippy
+ run: cargo clippy --all-targets --all-features -- -D warnings
- name: Clippy for ${{ matrix.arch }}
continue-on-error: ${{ matrix.rust-toolchain == 'nightly' }}
- run: make clippy ARCH=${{ matrix.arch }}
+ run: |
+ if [ "${{ matrix.arch }}" = "x86_64" ]; then
+ cargo clippy --target x86_64-unknown-none --all-features -- -D warnings
+ elif [ "${{ matrix.arch }}" = "riscv64" ]; then
+ cargo clippy --target riscv64gc-unknown-none-elf --all-features -- -D warnings
+ elif [ "${{ matrix.arch }}" = "aarch64" ]; then
+ cargo clippy --target aarch64-unknown-none-softfloat --all-features -- -D warnings
+ fi
ci:
runs-on: ubuntu-latest
@@ -49,8 +56,7 @@ jobs:
targets: [x86_64-unknown-linux-gnu,
x86_64-unknown-none,
riscv64gc-unknown-none-elf,
- aarch64-unknown-none-softfloat,
- loongarch64-unknown-none-softfloat]
+ aarch64-unknown-none-softfloat]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
@@ -71,32 +77,4 @@ jobs:
- name: Unit test
if: ${{ matrix.targets == 'x86_64-unknown-linux-gnu' }}
continue-on-error: ${{ matrix.rust-toolchain == 'nightly' }}
- run: cargo test --target ${{ matrix.targets }} -- --nocapture
-
- doc:
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- permissions:
- contents: write
- env:
- default-branch: ${{ format('refs/heads/{0}', github.event.repository.default_branch) }}
- steps:
- - uses: actions/checkout@v4
- - uses: dtolnay/rust-toolchain@stable
- with:
- toolchain: ${{ env.rust-toolchain }}
- - uses: Swatinem/rust-cache@v2
- with:
- shared-key: cargo-bin-cache
- cache-targets: false
- - name: Build docs
- continue-on-error: ${{ github.ref != env.default-branch && github.event_name != 'pull_request' }}
- run: make doc_check_missing
- - name: Deploy to Github Pages
- if: ${{ github.ref == env.default-branch }}
- uses: JamesIves/github-pages-deploy-action@v4
- with:
- single-commit: true
- branch: gh-pages
- folder: target/doc
\ No newline at end of file
+ run: cargo test --target ${{ matrix.targets }} -- --nocapture
\ No newline at end of file
From f4733d4fb91cc1f541270f2e76ff71232d776140 Mon Sep 17 00:00:00 2001
From: lkdWind <643840489@qq.com>
Date: Wed, 11 Jun 2025 15:43:17 +0800
Subject: [PATCH 3/3] update ci, readme
---
.github/workflows/ci.yml | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 027c957..eef95f0 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -77,4 +77,31 @@ jobs:
- name: Unit test
if: ${{ matrix.targets == 'x86_64-unknown-linux-gnu' }}
continue-on-error: ${{ matrix.rust-toolchain == 'nightly' }}
- run: cargo test --target ${{ matrix.targets }} -- --nocapture
\ No newline at end of file
+ run: cargo test --target ${{ matrix.targets }} -- --nocapture
+
+ doc:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ permissions:
+ contents: write
+ env:
+ default-branch: ${{ format('refs/heads/{0}', github.event.repository.default_branch) }}
+ RUSTDOCFLAGS: -D rustdoc::broken_intra_doc_links -D missing-docs
+ steps:
+ - uses: actions/checkout@v4
+ - uses: dtolnay/rust-toolchain@nightly
+ with:
+ toolchain: nightly-2025-05-20
+ - name: Build docs
+ continue-on-error: ${{ github.ref != env.default-branch && github.event_name != 'pull_request' }}
+ run: |
+ cargo doc --no-deps --all-features
+ printf '' $(cargo tree | head -1 | cut -d' ' -f1) > target/doc/index.html
+ - name: Deploy to Github Pages
+ if: ${{ github.ref == env.default-branch }}
+ uses: JamesIves/github-pages-deploy-action@v4
+ with:
+ single-commit: true
+ branch: gh-pages
+ folder: target/doc