From b9f32988c5c50df5bb34c2df5c2d3e2b50d8ff31 Mon Sep 17 00:00:00 2001 From: YanLien Date: Sat, 31 Jan 2026 14:06:11 +0800 Subject: [PATCH 1/4] fix(riscv): Fix RISC-V vCPU initialization and I/O handling --- Cargo.toml | 2 +- src/config.rs | 8 ++++++++ src/vm.rs | 7 ++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fb48501..bd56eed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ axvmconfig = { version = "0.1", default-features = false } x86_vcpu = "0.1" [target.'cfg(target_arch = "riscv64")'.dependencies] -riscv_vcpu = "0.1" +riscv_vcpu = { git = "https://github.com/liulog/riscv_vcpu.git", branch = "master" } [target.'cfg(target_arch = "aarch64")'.dependencies] arm_vcpu = { git = "https://github.com/arceos-hypervisor/arm_vcpu", branch = "next" } diff --git a/src/config.rs b/src/config.rs index 8218f5b..a4a50e7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -209,6 +209,7 @@ impl PhysCpuList { /// - The physical id of the vCpu, equal to vCpu id if not provided. pub fn get_vcpu_affinities_pcpu_ids(&self) -> Vec<(usize, Option, usize)> { let mut vcpu_pcpu_tuples = Vec::new(); + let mut pcpu_mask_flag = false; if let Some(phys_cpu_ids) = &self.phys_cpu_ids && self.cpu_num != phys_cpu_ids.len() @@ -224,6 +225,7 @@ impl PhysCpuList { } if let Some(phys_cpu_sets) = &self.phys_cpu_sets { + pcpu_mask_flag = true; for (vcpu_id, pcpu_mask_bitmap) in phys_cpu_sets.iter().enumerate() { vcpu_pcpu_tuples[vcpu_id].1 = Some(*pcpu_mask_bitmap); } @@ -232,6 +234,12 @@ impl PhysCpuList { if let Some(phys_cpu_ids) = &self.phys_cpu_ids { for (vcpu_id, phys_id) in phys_cpu_ids.iter().enumerate() { vcpu_pcpu_tuples[vcpu_id].2 = *phys_id; + #[cfg(target_arch = "riscv64")] + { + if pcpu_mask_flag == false { // if don't assign pcpu mask yet, assign it manually + vcpu_pcpu_tuples[vcpu_id].1 = Some(1 << (*phys_id)); + } + } } } vcpu_pcpu_tuples diff --git a/src/vm.rs b/src/vm.rs index 07925b8..7f13adf 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -167,6 +167,7 @@ impl AxVM { let dtb_addr = inner_mut.config.image_config().dtb_load_gpa; let vcpu_id_pcpu_sets = inner_mut.config.phys_cpu_ls.get_vcpu_affinities_pcpu_ids(); + info!("dtb_load_gpa: {:?}", dtb_addr); debug!("id: {}, VCpuIdPCpuSets: {vcpu_id_pcpu_sets:#x?}", self.id()); let mut vcpu_list = Vec::with_capacity(vcpu_id_pcpu_sets.len()); @@ -179,7 +180,7 @@ impl AxVM { #[cfg(target_arch = "riscv64")] let arch_config = AxVCpuCreateConfig { hart_id: vcpu_id as _, - dtb_addr: dtb_addr.unwrap_or_default(), + dtb_addr: dtb_addr.unwrap_or_default().as_usize(), }; #[cfg(target_arch = "x86_64")] let arch_config = AxVCpuCreateConfig::default(); @@ -501,8 +502,12 @@ impl AxVM { } AxVCpuExitReason::IoRead { port, width } => { let val = self.get_devices().handle_port_read(*port, *width)?; + #[cfg(not(target_arch = "riscv64"))] vcpu.set_gpr(0, val); // The target is always eax/ax/al, todo: handle access_width correctly + #[cfg(target_arch = "riscv64")] + vcpu.set_gpr(riscv_vcpu::GprIndex::A0 as usize, val); + true } AxVCpuExitReason::IoWrite { port, width, data } => { From 4225b0d4c8ff9f0a4e2069c1dfb7773e652b1d97 Mon Sep 17 00:00:00 2001 From: YanLien Date: Sat, 31 Jan 2026 14:25:58 +0800 Subject: [PATCH 2/4] chore: Update riscv_vcpu dependency source --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index bd56eed..30cbcd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ axvmconfig = { version = "0.1", default-features = false } x86_vcpu = "0.1" [target.'cfg(target_arch = "riscv64")'.dependencies] -riscv_vcpu = { git = "https://github.com/liulog/riscv_vcpu.git", branch = "master" } +riscv_vcpu = { git = "https://github.com/arceos-hypervisor/riscv_vcpu.git", branch = "master" } [target.'cfg(target_arch = "aarch64")'.dependencies] arm_vcpu = { git = "https://github.com/arceos-hypervisor/arm_vcpu", branch = "next" } From 56edf8b114d6984659b6adedf1a0d502c355be8c Mon Sep 17 00:00:00 2001 From: YanLien Date: Mon, 2 Feb 2026 16:18:39 +0800 Subject: [PATCH 3/4] chore: specify axdevice branch and fix code formatting --- Cargo.toml | 2 +- src/config.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 30cbcd8..ff5ff6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ percpu = { version = "0.2.0", features = ["arm-el2"] } # System dependent modules provided by ArceOS-Hypervisor. axvcpu = "0.1" axaddrspace = "0.1" -axdevice = { git = "https://github.com/arceos-hypervisor/axdevice.git" } +axdevice = { git = "https://github.com/arceos-hypervisor/axdevice.git", branch = "next"} axdevice_base = "0.1" axvmconfig = { version = "0.1", default-features = false } diff --git a/src/config.rs b/src/config.rs index a4a50e7..9d47ef5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -236,7 +236,8 @@ impl PhysCpuList { vcpu_pcpu_tuples[vcpu_id].2 = *phys_id; #[cfg(target_arch = "riscv64")] { - if pcpu_mask_flag == false { // if don't assign pcpu mask yet, assign it manually + if pcpu_mask_flag == false { + // if don't assign pcpu mask yet, assign it manually vcpu_pcpu_tuples[vcpu_id].1 = Some(1 << (*phys_id)); } } From 5810e2ce23dc15c563214efa7ce35413e120e3c8 Mon Sep 17 00:00:00 2001 From: YanLien Date: Mon, 2 Feb 2026 16:26:03 +0800 Subject: [PATCH 4/4] docs: add missing documentation comments --- src/config.rs | 10 ++++++++++ src/vm.rs | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/config.rs b/src/config.rs index 9d47ef5..b077700 100644 --- a/src/config.rs +++ b/src/config.rs @@ -51,7 +51,9 @@ pub struct AxVMConfig { #[allow(dead_code)] vm_type: VMType, pub(crate) phys_cpu_ls: PhysCpuList, + /// vCPU configuration. pub cpu_config: AxVCpuConfig, + /// VM image configuration. pub image_config: VMImageConfig, emu_devices: Vec, pass_through_devices: Vec, @@ -122,14 +124,17 @@ impl AxVMConfig { self.cpu_config.ap_entry } + /// Returns a mutable reference to the physical CPU list. pub fn phys_cpu_ls_mut(&mut self) -> &mut PhysCpuList { &mut self.phys_cpu_ls } + /// Returns the list of excluded devices. pub fn excluded_devices(&self) -> &Vec> { &self.excluded_devices } + /// Returns the list of passthrough address configurations. pub fn pass_through_addresses(&self) -> &Vec { &self.pass_through_addresses } @@ -191,6 +196,7 @@ impl AxVMConfig { } } +/// Represents the list of physical CPUs available for the VM. #[derive(Debug, Default, Clone)] pub struct PhysCpuList { cpu_num: usize, @@ -246,18 +252,22 @@ impl PhysCpuList { vcpu_pcpu_tuples } + /// Returns the number of CPUs. pub fn cpu_num(&self) -> usize { self.cpu_num } + /// Returns the physical CPU IDs. pub fn phys_cpu_ids(&self) -> &Option> { &self.phys_cpu_ids } + /// Returns the physical CPU sets. pub fn phys_cpu_sets(&self) -> &Option> { &self.phys_cpu_sets } + /// Sets the guest CPU sets. pub fn set_guest_cpu_sets(&mut self, phys_cpu_sets: Vec) { self.phys_cpu_sets = Some(phys_cpu_sets); } diff --git a/src/vm.rs b/src/vm.rs index 7f13adf..e73a307 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -43,20 +43,26 @@ struct AxVMInnerConst { unsafe impl Send for AxVMInnerConst {} unsafe impl Sync for AxVMInnerConst {} +/// Represents a memory region in a virtual machine. #[derive(Debug, Clone)] pub struct VMMemoryRegion { + /// Guest physical address. pub gpa: GuestPhysAddr, + /// Host virtual address. pub hva: HostVirtAddr, + /// Memory layout of the region. pub layout: Layout, /// Whether this region was allocated by the allocator and needs to be deallocated pub needs_dealloc: bool, } impl VMMemoryRegion { + /// Returns the size of the memory region. pub fn size(&self) -> usize { self.layout.size() } + /// Returns `true` if the guest physical address is identical to the host virtual address. pub fn is_identical(&self) -> bool { self.gpa.as_usize() == self.hva.as_usize() } @@ -337,11 +343,13 @@ impl AxVM { Ok(()) } + /// Sets the VM status. pub fn set_vm_status(&self, status: VMStatus) { let mut inner_mut = self.inner_mut.lock(); inner_mut.vm_status = status; } + /// Returns the current VM status. pub fn vm_status(&self) -> VMStatus { let inner_mut = self.inner_mut.lock(); inner_mut.vm_status @@ -703,6 +711,7 @@ impl AxVM { Ok(()) } + /// Allocates a new memory region for the VM. pub fn alloc_memory_region( &self, layout: Layout, @@ -741,10 +750,12 @@ impl AxVM { Ok(s) } + /// Returns a list of all memory regions in the VM. pub fn memory_regions(&self) -> Vec { self.inner_mut.lock().memory_regions.clone() } + /// Maps a reserved memory region for the VM. pub fn map_reserved_memory_region( &self, layout: Layout,