Skip to content

Commit bd21a4e

Browse files
YanLienZR233szybuhenxihuanbullhh
authored
Dev 0.2 (#55)
* chore: bump version to v0.2.1 and migrate from git to published versions (#50) * refactor: deps git to crates-io * fix: feature * refactor: support guest dyn entry * refactor: add Clone trait to VMImageConfig * fix: update arm_vcpu branch to 'next' * add fdt support and add some AxVMConfig impl * fix fmt bug * fix bug: when no phys_cpu_ids panic * add function map_reserved_memory_region (#28) * add function map_reserved_memory_region * add passthrough address (#29) * add pass_through address --------- Co-authored-by: szy <songzhyo@qq.com> * add VMStatus enum and integrate into AxVM lifecycle management (#31) * feat: update axerrno to 0.2 (#33) * feat: update axerrno to 0.2 * fix: clippy * Update riscv_vcpu dependency source (#39) * fix(riscv): Fix RISC-V vCPU initialization and I/O handling * chore: Update riscv_vcpu dependency source * chore: specify axdevice branch and fix code formatting * docs: add missing documentation comments * chore: migrate from git to published versions * chore: bump version to v0.2.1 * fix(vm): remove duplicate code lines * fix(vm): adapt to axvcpu v0.2 API changes * fix(vm): adapt to v0.2 API changes for multi-architecture compatibility --------- Co-authored-by: 周睿 <zrufo747@outlook.com> Co-authored-by: szy <songzhyo@qq.com> Co-authored-by: bhxh <32200913+buhenxihuan@users.noreply.github.com> Co-authored-by: szy <673586548@qq.com> Co-authored-by: 朝倉水希 <asakuramizu111@gmail.com> * ci: fix doc deployment for cross-target builds (#51) * refactor: deps git to crates-io * fix: feature * refactor: support guest dyn entry * refactor: add Clone trait to VMImageConfig * fix: update arm_vcpu branch to 'next' * add fdt support and add some AxVMConfig impl * fix fmt bug * fix bug: when no phys_cpu_ids panic * add function map_reserved_memory_region (#28) * add function map_reserved_memory_region * add passthrough address (#29) * add pass_through address --------- Co-authored-by: szy <songzhyo@qq.com> * add VMStatus enum and integrate into AxVM lifecycle management (#31) * feat: update axerrno to 0.2 (#33) * feat: update axerrno to 0.2 * fix: clippy * Update riscv_vcpu dependency source (#39) * fix(riscv): Fix RISC-V vCPU initialization and I/O handling * chore: Update riscv_vcpu dependency source * chore: specify axdevice branch and fix code formatting * docs: add missing documentation comments * chore: migrate from git to published versions * chore: bump version to v0.2.1 * fix(vm): remove duplicate code lines * fix(vm): adapt to axvcpu v0.2 API changes * fix(vm): adapt to v0.2 API changes for multi-architecture compatibility * ci: fix doc deployment for cross-target builds --------- Co-authored-by: 周睿 <zrufo747@outlook.com> Co-authored-by: szy <songzhyo@qq.com> Co-authored-by: bhxh <32200913+buhenxihuan@users.noreply.github.com> Co-authored-by: szy <673586548@qq.com> Co-authored-by: 朝倉水希 <asakuramizu111@gmail.com> * chore: bump version to 0.2.2 (#53) * chore: update page_table_multiarch to 0.6 * chore: bump version to 0.2.2 * chore: update percpu dependency to version 0.2.3-preview.1 * chore: bump version to 0.2.3 and update dependencies * chore: remove unstable feature `new_range_api` --------- Co-authored-by: 周睿 <zrufo747@outlook.com> Co-authored-by: szy <songzhyo@qq.com> Co-authored-by: bhxh <32200913+buhenxihuan@users.noreply.github.com> Co-authored-by: szy <673586548@qq.com> Co-authored-by: 朝倉水希 <asakuramizu111@gmail.com>
1 parent d759685 commit bd21a4e

File tree

6 files changed

+649
-284
lines changed

6 files changed

+649
-284
lines changed

.github/workflows/deploy.yml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,30 @@ jobs:
8787
env:
8888
RUSTDOCFLAGS: -D rustdoc::broken_intra_doc_links -D missing-docs
8989
run: |
90+
# Build documentation
9091
cargo doc --no-deps --all-features
91-
printf '<meta http-equiv="refresh" content="0;url=%s/index.html">' $(cargo tree | head -1 | cut -d' ' -f1) > target/doc/index.html
92+
93+
# Auto-detect documentation directory
94+
# Check if doc exists in target/doc or target/*/doc
95+
if [ -d "target/doc" ]; then
96+
DOC_DIR="target/doc"
97+
else
98+
# Find doc directory under target/*/doc pattern
99+
DOC_DIR=$(find target -type d -name doc -path "target/*/doc" | head -n 1)
100+
if [ -z "$DOC_DIR" ]; then
101+
echo "Error: Could not find documentation directory"
102+
exit 1
103+
fi
104+
fi
105+
106+
echo "Documentation found in: $DOC_DIR"
107+
printf '<meta http-equiv="refresh" content="0;url=%s/index.html">' $(cargo tree | head -1 | cut -d' ' -f1) > "${DOC_DIR}/index.html"
108+
echo "DOC_DIR=${DOC_DIR}" >> $GITHUB_ENV
92109
93110
- name: Upload artifact
94111
uses: actions/upload-pages-artifact@v3
95112
with:
96-
path: target/doc
113+
path: ${{ env.DOC_DIR }}
97114

98115
deploy:
99116
name: Deploy to GitHub Pages

Cargo.toml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "axvm"
33
authors = ["aarkegz <aarkegz@gmail.com>"]
4-
version = "0.2.0"
4+
version = "0.2.3"
55
edition = "2024"
66
categories = ["virtualization", "no-std"]
77
description = "Virtual Machine resource management crate for ArceOS's hypervisor variant."
@@ -12,35 +12,35 @@ license = "Apache-2.0"
1212
[features]
1313
default = ["vmx"]
1414
vmx = []
15-
4-level-ept = ["arm_vcpu/4-level-ept"] # TODO: Realize 4-level-ept on x86_64 and riscv64.
15+
4-level-ept = ["axaddrspace/4-level-ept"] # TODO: Realize 4-level-ept on x86_64 and riscv64.
1616

1717
[dependencies]
1818
log = "0.4"
1919
cfg-if = "1.0"
2020
spin = "0.9"
2121

2222
# System independent crates provided by ArceOS.
23-
axerrno = "0.1.0"
23+
axerrno = "0.2"
2424
cpumask = "0.1.0"
2525
# kspin = "0.1.0"
2626
memory_addr = "0.4"
27-
page_table_entry = { version = "0.5", features = ["arm-el2"] }
28-
page_table_multiarch = "0.5"
29-
percpu = { version = "0.2.0", features = ["arm-el2"] }
27+
page_table_entry = { version = "0.6", features = ["arm-el2"] }
28+
page_table_multiarch = "0.6"
29+
percpu = { version = "0.2.3-preview.1", features = ["arm-el2"] }
3030

3131
# System dependent modules provided by ArceOS-Hypervisor.
32-
axvcpu = "0.1"
33-
axaddrspace = "0.1"
34-
axdevice = "0.2"
35-
axdevice_base = "0.1"
36-
axvmconfig = { version = "0.1", default-features = false }
32+
axvcpu = "0.2.2"
33+
axaddrspace = "0.1.5"
34+
axdevice = "0.2.1"
35+
axdevice_base = "=0.2.1"
36+
axvmconfig = { version = "0.2", default-features = false }
3737

3838
[target.'cfg(target_arch = "x86_64")'.dependencies]
39-
x86_vcpu = "0.1"
39+
x86_vcpu = "0.2.1"
4040

4141
[target.'cfg(target_arch = "riscv64")'.dependencies]
42-
riscv_vcpu = "0.1"
42+
riscv_vcpu = "0.2.1"
4343

4444
[target.'cfg(target_arch = "aarch64")'.dependencies]
45-
arm_vcpu = "0.1"
46-
arm_vgic = { version = "0.1", features = ["vgicv3"] }
45+
arm_vcpu = "0.2.1"
46+
arm_vgic = { version = "0.2.1", features = ["vgicv3"] }

src/config.rs

Lines changed: 142 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,17 @@
1717
1818
use alloc::string::String;
1919
use alloc::vec::Vec;
20-
use core::ops::Range;
2120

2221
use axaddrspace::GuestPhysAddr;
2322

2423
pub use axvmconfig::{
25-
AxVMCrateConfig, EmulatedDeviceConfig, PassThroughDeviceConfig, VMInterruptMode, VMType,
26-
VmMemConfig, VmMemMappingType,
24+
AxVMCrateConfig, EmulatedDeviceConfig, PassThroughAddressConfig, PassThroughDeviceConfig,
25+
VMInterruptMode, VMType, VmMemConfig, VmMemMappingType,
2726
};
2827

29-
/// A part of `AxVCpuConfig`, which represents an architecture-dependent `VCpu`.
30-
///
31-
/// The concrete type of configuration is defined in `AxArchVCpuImpl`.
28+
// /// A part of `AxVCpuConfig`, which represents an architecture-dependent `VCpu`.
29+
// ///
30+
// /// The concrete type of configuration is defined in `AxArchVCpuImpl`.
3231
// #[derive(Clone, Copy, Debug, Default)]
3332
// pub struct AxArchVCpuConfig<H: AxVMHal> {
3433
// pub create_config: <AxArchVCpuImpl<H> as AxArchVCpu>::CreateConfig,
@@ -45,7 +44,7 @@ pub struct AxVCpuConfig {
4544
}
4645

4746
/// A part of `AxVMConfig`, which stores configuration attributes related to the load address of VM images.
48-
#[derive(Debug, Default)]
47+
#[derive(Debug, Default, Clone)]
4948
pub struct VMImageConfig {
5049
/// The load address in GPA for the kernel image.
5150
pub kernel_load_gpa: GuestPhysAddr,
@@ -64,14 +63,15 @@ pub struct AxVMConfig {
6463
name: String,
6564
#[allow(dead_code)]
6665
vm_type: VMType,
67-
cpu_num: usize,
68-
phys_cpu_ids: Option<Vec<usize>>,
69-
phys_cpu_sets: Option<Vec<usize>>,
70-
cpu_config: AxVCpuConfig,
71-
image_config: VMImageConfig,
72-
memory_regions: Vec<VmMemConfig>,
66+
pub(crate) phys_cpu_ls: PhysCpuList,
67+
/// vCPU configuration.
68+
pub cpu_config: AxVCpuConfig,
69+
/// VM image configuration.
70+
pub image_config: VMImageConfig,
7371
emu_devices: Vec<EmulatedDeviceConfig>,
7472
pass_through_devices: Vec<PassThroughDeviceConfig>,
73+
excluded_devices: Vec<Vec<String>>,
74+
pass_through_addresses: Vec<PassThroughAddressConfig>,
7575
// TODO: improve interrupt passthrough
7676
spi_list: Vec<u32>,
7777
interrupt_mode: VMInterruptMode,
@@ -83,9 +83,11 @@ impl From<AxVMCrateConfig> for AxVMConfig {
8383
id: cfg.base.id,
8484
name: cfg.base.name,
8585
vm_type: VMType::from(cfg.base.vm_type),
86-
cpu_num: cfg.base.cpu_num,
87-
phys_cpu_ids: cfg.base.phys_cpu_ids,
88-
phys_cpu_sets: cfg.base.phys_cpu_sets,
86+
phys_cpu_ls: PhysCpuList {
87+
cpu_num: cfg.base.cpu_num,
88+
phys_cpu_ids: cfg.base.phys_cpu_ids,
89+
phys_cpu_sets: cfg.base.phys_cpu_sets,
90+
},
8991
cpu_config: AxVCpuConfig {
9092
bsp_entry: GuestPhysAddr::from(cfg.kernel.entry_point),
9193
ap_entry: GuestPhysAddr::from(cfg.kernel.entry_point),
@@ -96,9 +98,11 @@ impl From<AxVMCrateConfig> for AxVMConfig {
9698
dtb_load_gpa: cfg.kernel.dtb_load_addr.map(GuestPhysAddr::from),
9799
ramdisk_load_gpa: cfg.kernel.ramdisk_load_addr.map(GuestPhysAddr::from),
98100
},
99-
memory_regions: cfg.kernel.memory_regions,
101+
// memory_regions: cfg.kernel.memory_regions,
100102
emu_devices: cfg.devices.emu_devices,
101103
pass_through_devices: cfg.devices.passthrough_devices,
104+
excluded_devices: cfg.devices.excluded_devices,
105+
pass_through_addresses: cfg.devices.passthrough_addresses,
102106
spi_list: Vec::new(),
103107
interrupt_mode: cfg.devices.interrupt_mode,
104108
}
@@ -116,32 +120,6 @@ impl AxVMConfig {
116120
self.name.clone()
117121
}
118122

119-
/// Returns vCpu id list and its corresponding pCpu affinity list, as well as its physical id.
120-
/// If the pCpu affinity is None, it means the vCpu will be allocated to any available pCpu randomly.
121-
/// if the pCPU id is not provided, the vCpu's physical id will be set as vCpu id.
122-
///
123-
/// Returns a vector of tuples, each tuple contains:
124-
/// - The vCpu id.
125-
/// - The pCpu affinity mask, `None` if not set.
126-
/// - The physical id of the vCpu, equal to vCpu id if not provided.
127-
pub fn get_vcpu_affinities_pcpu_ids(&self) -> Vec<(usize, Option<usize>, usize)> {
128-
let mut vcpu_pcpu_tuples = Vec::new();
129-
for vcpu_id in 0..self.cpu_num {
130-
vcpu_pcpu_tuples.push((vcpu_id, None, vcpu_id));
131-
}
132-
if let Some(phys_cpu_sets) = &self.phys_cpu_sets {
133-
for (vcpu_id, pcpu_mask_bitmap) in phys_cpu_sets.iter().enumerate() {
134-
vcpu_pcpu_tuples[vcpu_id].1 = Some(*pcpu_mask_bitmap);
135-
}
136-
}
137-
if let Some(phys_cpu_ids) = &self.phys_cpu_ids {
138-
for (vcpu_id, phys_id) in phys_cpu_ids.iter().enumerate() {
139-
vcpu_pcpu_tuples[vcpu_id].2 = *phys_id;
140-
}
141-
}
142-
vcpu_pcpu_tuples
143-
}
144-
145123
/// Returns configurations related to VM image load addresses.
146124
pub fn image_config(&self) -> &VMImageConfig {
147125
&self.image_config
@@ -159,22 +137,36 @@ impl AxVMConfig {
159137
self.cpu_config.ap_entry
160138
}
161139

162-
/// Returns configurations related to VM memory regions.
163-
pub fn memory_regions(&self) -> &Vec<VmMemConfig> {
164-
&self.memory_regions
140+
/// Returns a mutable reference to the physical CPU list.
141+
pub fn phys_cpu_ls_mut(&mut self) -> &mut PhysCpuList {
142+
&mut self.phys_cpu_ls
165143
}
166144

167-
/// Adds a new memory region to the VM configuration.
168-
pub fn add_memory_region(&mut self, region: VmMemConfig) {
169-
self.memory_regions.push(region);
145+
/// Returns the list of excluded devices.
146+
pub fn excluded_devices(&self) -> &Vec<Vec<String>> {
147+
&self.excluded_devices
170148
}
171149

172-
/// Checks if the VM memory regions contain a specific range.
173-
pub fn contains_memory_range(&self, range: &Range<usize>) -> bool {
174-
self.memory_regions
175-
.iter()
176-
.any(|region| region.gpa <= range.start && region.gpa + region.size >= range.end)
150+
/// Returns the list of passthrough address configurations.
151+
pub fn pass_through_addresses(&self) -> &Vec<PassThroughAddressConfig> {
152+
&self.pass_through_addresses
177153
}
154+
// /// Returns configurations related to VM memory regions.
155+
// pub fn memory_regions(&self) -> Vec<VmMemConfig> {
156+
// &self.memory_regions
157+
// }
158+
159+
// /// Adds a new memory region to the VM configuration.
160+
// pub fn add_memory_region(&mut self, region: VmMemConfig) {
161+
// self.memory_regions.push(region);
162+
// }
163+
164+
// /// Checks if the VM memory regions contain a specific range.
165+
// pub fn contains_memory_range(&self, range: &Range<usize>) -> bool {
166+
// self.memory_regions
167+
// .iter()
168+
// .any(|region| region.gpa <= range.start && region.gpa + region.size >= range.end)
169+
// }
178170

179171
/// Returns configurations related to VM emulated devices.
180172
pub fn emu_devices(&self) -> &Vec<EmulatedDeviceConfig> {
@@ -191,6 +183,16 @@ impl AxVMConfig {
191183
self.pass_through_devices.push(device);
192184
}
193185

186+
/// Removes passthrough device from the VM configuration.
187+
pub fn remove_pass_through_device(&mut self, device: PassThroughDeviceConfig) {
188+
self.pass_through_devices.retain(|d| d == &device);
189+
}
190+
191+
/// Clears all passthrough devices from the VM configuration.
192+
pub fn clear_pass_through_devices(&mut self) {
193+
self.pass_through_devices.clear();
194+
}
195+
194196
/// Adds a passthrough SPI to the VM configuration.
195197
pub fn add_pass_through_spi(&mut self, spi: u32) {
196198
self.spi_list.push(spi);
@@ -206,3 +208,89 @@ impl AxVMConfig {
206208
self.interrupt_mode
207209
}
208210
}
211+
212+
/// Represents the list of physical CPUs available for the VM.
213+
#[derive(Debug, Default, Clone)]
214+
pub struct PhysCpuList {
215+
cpu_num: usize,
216+
phys_cpu_ids: Option<Vec<usize>>,
217+
phys_cpu_sets: Option<Vec<usize>>,
218+
}
219+
220+
impl PhysCpuList {
221+
/// Returns vCpu id list and its corresponding pCpu affinity list, as well as its physical id.
222+
/// If the pCpu affinity is None, it means the vCpu will be allocated to any available pCpu randomly.
223+
/// if the pCPU id is not provided, the vCpu's physical id will be set as vCpu id.
224+
///
225+
/// Returns a vector of tuples, each tuple contains:
226+
/// - The vCpu id.
227+
/// - The pCpu affinity mask, `None` if not set.
228+
/// - The physical id of the vCpu, equal to vCpu id if not provided.
229+
pub fn get_vcpu_affinities_pcpu_ids(&self) -> Vec<(usize, Option<usize>, usize)> {
230+
let mut vcpu_pcpu_tuples = Vec::new();
231+
#[cfg(target_arch = "riscv64")]
232+
let mut pcpu_mask_flag = false;
233+
234+
if let Some(phys_cpu_ids) = &self.phys_cpu_ids
235+
&& self.cpu_num != phys_cpu_ids.len()
236+
{
237+
error!(
238+
"ERROR!!!: cpu_num: {}, phys_cpu_ids: {:?}",
239+
self.cpu_num, self.phys_cpu_ids
240+
);
241+
}
242+
243+
for vcpu_id in 0..self.cpu_num {
244+
vcpu_pcpu_tuples.push((vcpu_id, None, vcpu_id));
245+
}
246+
247+
#[cfg(target_arch = "riscv64")]
248+
if let Some(phys_cpu_sets) = &self.phys_cpu_sets {
249+
pcpu_mask_flag = true;
250+
for (vcpu_id, pcpu_mask_bitmap) in phys_cpu_sets.iter().enumerate() {
251+
vcpu_pcpu_tuples[vcpu_id].1 = Some(*pcpu_mask_bitmap);
252+
}
253+
}
254+
255+
#[cfg(not(target_arch = "riscv64"))]
256+
if let Some(phys_cpu_sets) = &self.phys_cpu_sets {
257+
for (vcpu_id, pcpu_mask_bitmap) in phys_cpu_sets.iter().enumerate() {
258+
vcpu_pcpu_tuples[vcpu_id].1 = Some(*pcpu_mask_bitmap);
259+
}
260+
}
261+
262+
if let Some(phys_cpu_ids) = &self.phys_cpu_ids {
263+
for (vcpu_id, phys_id) in phys_cpu_ids.iter().enumerate() {
264+
vcpu_pcpu_tuples[vcpu_id].2 = *phys_id;
265+
#[cfg(target_arch = "riscv64")]
266+
{
267+
if !pcpu_mask_flag {
268+
// if don't assign pcpu mask yet, assign it manually
269+
vcpu_pcpu_tuples[vcpu_id].1 = Some(1 << (*phys_id));
270+
}
271+
}
272+
}
273+
}
274+
vcpu_pcpu_tuples
275+
}
276+
277+
/// Returns the number of CPUs.
278+
pub fn cpu_num(&self) -> usize {
279+
self.cpu_num
280+
}
281+
282+
/// Returns the physical CPU IDs.
283+
pub fn phys_cpu_ids(&self) -> &Option<Vec<usize>> {
284+
&self.phys_cpu_ids
285+
}
286+
287+
/// Returns the physical CPU sets.
288+
pub fn phys_cpu_sets(&self) -> &Option<Vec<usize>> {
289+
&self.phys_cpu_sets
290+
}
291+
292+
/// Sets the guest CPU sets.
293+
pub fn set_guest_cpu_sets(&mut self, phys_cpu_sets: Vec<usize>) {
294+
self.phys_cpu_sets = Some(phys_cpu_sets);
295+
}
296+
}

src/hal.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,6 @@ pub trait AxVMHal: Sized {
2020
/// The low-level **OS-dependent** helpers that must be provided for physical address management.
2121
type PagingHandler: page_table_multiarch::PagingHandler;
2222

23-
/// Allocates a memory region at the specified physical address.
24-
///
25-
/// Returns `true` if the memory region is successfully allocated.
26-
fn alloc_memory_region_at(base: HostPhysAddr, size: usize) -> bool;
27-
28-
/// Deallocates a memory region at the specified physical address.
29-
fn dealloc_memory_region_at(base: HostPhysAddr, size: usize);
30-
3123
/// Converts a virtual address to the corresponding physical address.
3224
fn virt_to_phys(vaddr: HostVirtAddr) -> HostPhysAddr;
3325

src/lib.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,6 @@
1313
// limitations under the License.
1414

1515
#![no_std]
16-
#![feature(new_range_api)]
17-
// #![feature(concat_idents)]
18-
// #![feature(naked_functions)]
19-
// #![feature(const_trait_impl)]
2016

2117
//! This crate provides a minimal VM monitor (VMM) for running guest VMs.
2218
//!
@@ -37,6 +33,8 @@ pub use hal::AxVMHal;
3733
pub use vm::AxVCpuRef;
3834
pub use vm::AxVM;
3935
pub use vm::AxVMRef;
36+
pub use vm::VMMemoryRegion;
37+
pub use vm::VMStatus;
4038

4139
/// The architecture-independent per-CPU type.
4240
pub type AxVMPerCpu<U> = axvcpu::AxPerCpu<vcpu::AxVMArchPerCpuImpl<U>>;

0 commit comments

Comments
 (0)