From 5674337d5a610b47465445071a9164e19a3d0eab Mon Sep 17 00:00:00 2001 From: isrc-riscv-port Date: Wed, 13 May 2026 03:16:38 +0000 Subject: [PATCH 1/4] riscv64: Enable sstateen0 for KVM vCPUs KVM initializes RISC-V vCPUs with sstateen0 cleared. When AIA is exposed to the guest, Linux touches supervisor AIA CSRs while bringing up the IMSIC path, and those accesses fail if the stateen bits remain disabled. Program sstateen0 for newly created vCPUs and after core register setup so the guest can use the supervisor interrupt state needed by AIA. Signed-off-by: isrc-riscv-port --- hypervisor/src/kvm/mod.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 259009151..95d673597 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -570,6 +570,25 @@ impl vm::Vm for KvmVm { .create_vcpu(id as u64) .map_err(|e| vm::HypervisorVmError::CreateVcpu(e.into()))?; + #[cfg(target_arch = "riscv64")] + { + // KVM defaults sstateen0 to zero for new RISC-V vCPUs. When AIA is + // exposed, Linux accesses supervisor AIA CSRs during IMSIC init; + // leave all state enabled so those CSR accesses do not trap as + // illegal instructions in the guest. + let sstateen0 = u64::MAX; + let sstateen0_id = kvm_bindings::KVM_REG_RISCV as u64 + | u64::from(kvm_bindings::KVM_REG_SIZE_U64) + | u64::from(kvm_bindings::KVM_REG_RISCV_CSR) + | u64::from(kvm_bindings::KVM_REG_RISCV_CSR_SMSTATEEN); + fd.set_one_reg(sstateen0_id, &sstateen0.to_le_bytes()) + .map_err(|e| { + vm::HypervisorVmError::CreateVcpu(anyhow!( + "failed to enable RISC-V sstateen0 for vCPU {id}: {e}" + )) + })?; + } + #[cfg(target_arch = "x86_64")] // Safety: `xsave_size` will not change after vcpu creation because: // 1. `xsave_size` depends on cpuid @@ -2303,6 +2322,15 @@ impl cpu::Vcpu for KvmVcpu { ) .map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?; + let sstateen0 = u64::MAX; + let sstateen0_id = kvm_bindings::KVM_REG_RISCV as u64 + | u64::from(kvm_bindings::KVM_REG_SIZE_U64) + | u64::from(kvm_bindings::KVM_REG_RISCV_CSR) + | u64::from(kvm_bindings::KVM_REG_RISCV_CSR_SMSTATEEN); + self.fd + .set_one_reg(sstateen0_id, &sstateen0.to_le_bytes()) + .map_err(|e| cpu::HypervisorCpuError::SetRiscvCoreRegister(e.into()))?; + Ok(()) } From f4e394133021e9eec516a6e1175a5d6dce492628 Mon Sep 17 00:00:00 2001 From: isrc-riscv-port Date: Wed, 13 May 2026 03:16:39 +0000 Subject: [PATCH 2/4] riscv64: Report KVM IMSIC interrupt IDs The RISC-V AIA FDT node currently advertises a fixed riscv,num-ids value. That can diverge from the interrupt identity count configured by KVM, which matters for guests running with an emulated IMSIC. Initialize the KVM AIA device in emulation mode, record the NR_IDS value reported by KVM, and expose that value through the generated device tree. Signed-off-by: isrc-riscv-port --- arch/src/riscv64/fdt.rs | 4 ++-- hypervisor/src/arch/riscv64/aia.rs | 3 +++ hypervisor/src/kvm/riscv64/aia.rs | 22 ++++++++++++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/arch/src/riscv64/fdt.rs b/arch/src/riscv64/fdt.rs index f97e6d6b5..b4a6160f3 100644 --- a/arch/src/riscv64/fdt.rs +++ b/arch/src/riscv64/fdt.rs @@ -231,8 +231,8 @@ fn create_aia_node(fdt: &mut FdtWriter, aia_device: &Arc>) -> Fd fdt.property_u32("#interrupt-cells", 0u32)?; fdt.property_null("interrupt-controller")?; fdt.property_null("msi-controller")?; - // TODO complete num-ids - fdt.property_u32("riscv,num-ids", 2047u32)?; + let imsic_num_ids = aia_device.lock().unwrap().imsic_num_ids(); + fdt.property_u32("riscv,num-ids", imsic_num_ids)?; fdt.property_u32("phandle", AIA_IMSIC_PHANDLE)?; let mut irq_cells = Vec::new(); diff --git a/hypervisor/src/arch/riscv64/aia.rs b/hypervisor/src/arch/riscv64/aia.rs index 2ba8d70eb..0172f4b39 100644 --- a/hypervisor/src/arch/riscv64/aia.rs +++ b/hypervisor/src/arch/riscv64/aia.rs @@ -46,6 +46,9 @@ pub trait Vaia: Send + Sync { /// Returns an array with IMSIC device properties fn imsic_properties(&self) -> [u32; 4]; + /// Returns the number of IMSIC interrupt identities exposed to the guest + fn imsic_num_ids(&self) -> u32; + /// Returns the number of vCPUs this AIA handles fn vcpu_count(&self) -> u32; diff --git a/hypervisor/src/kvm/riscv64/aia.rs b/hypervisor/src/kvm/riscv64/aia.rs index 67857c6ae..bb10767fd 100644 --- a/hypervisor/src/kvm/riscv64/aia.rs +++ b/hypervisor/src/kvm/riscv64/aia.rs @@ -24,6 +24,9 @@ pub struct KvmAiaImsics { /// Number of CPUs handled by the device vcpu_count: u32, + + /// Number of IMSIC interrupt identities configured by KVM + imsic_num_ids: u32, } #[derive(Clone, Default, Serialize, Deserialize)] @@ -40,12 +43,21 @@ impl KvmAiaImsics { // AIA part attributes // Getting the working mode of RISC-V AIA, defaults to EMUL, passible // variants are EMUL, HW_ACCL, AUTO - let mut aia_mode = kvm_bindings::KVM_DEV_RISCV_AIA_MODE_EMUL; + let aia_mode = kvm_bindings::KVM_DEV_RISCV_AIA_MODE_EMUL; + Self::set_device_attribute( + &self.device, + kvm_bindings::KVM_DEV_RISCV_AIA_GRP_CONFIG, + u64::from(kvm_bindings::KVM_DEV_RISCV_AIA_CONFIG_MODE), + &aia_mode as *const u32 as u64, + 0, + )?; + + let mut aia_mode_readback: u32 = 0; Self::get_device_attribute( &self.device, kvm_bindings::KVM_DEV_RISCV_AIA_GRP_CONFIG, u64::from(kvm_bindings::KVM_DEV_RISCV_AIA_CONFIG_MODE), - &mut aia_mode as *mut u32 as u64, + &mut aia_mode_readback as *mut u32 as u64, 0, )?; @@ -71,6 +83,7 @@ impl KvmAiaImsics { )?; // Report NR_IDS + self.imsic_num_ids = aia_nr_ids; // Setting up hart_bits let max_hart_index = self.vcpu_count as u64 - 1; @@ -191,6 +204,7 @@ impl KvmAiaImsics { vcpu_count: config.vcpu_count, aplic_addr: config.aplic_addr, imsic_addr: config.imsic_addr, + imsic_num_ids: 0, }; aia_device.init_device_attributes(config.nr_irqs)?; @@ -226,6 +240,10 @@ impl Vaia for KvmAiaImsics { ] } + fn imsic_num_ids(&self) -> u32 { + self.imsic_num_ids + } + fn vcpu_count(&self) -> u32 { self.vcpu_count } From 70461c559e5510e36523ff7f5feb5c0bcfb5ebae Mon Sep 17 00:00:00 2001 From: isrc-riscv-port Date: Wed, 13 May 2026 03:16:39 +0000 Subject: [PATCH 3/4] vmm: Allow unlinkat on riscv64 seccomp filters riscv64 does not provide the legacy unlink syscall, so libc uses unlinkat for file removal paths that are otherwise allowed on other architectures. Permit unlinkat for the VMM and vCPU seccomp filters on riscv64, matching the existing aarch64 rule. Signed-off-by: isrc-riscv-port --- vmm/src/seccomp_filters.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index bb40b99f6..657fa7f6b 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -689,7 +689,7 @@ fn vmm_thread_rules( ), #[cfg(target_arch = "x86_64")] (libc::SYS_unlink, vec![]), - #[cfg(target_arch = "aarch64")] + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] (libc::SYS_unlinkat, vec![]), (libc::SYS_wait4, vec![]), (libc::SYS_write, vec![]), @@ -831,7 +831,7 @@ fn vcpu_thread_rules( (libc::SYS_tkill, vec![]), #[cfg(target_arch = "x86_64")] (libc::SYS_unlink, vec![]), - #[cfg(target_arch = "aarch64")] + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] (libc::SYS_unlinkat, vec![]), (libc::SYS_write, vec![]), (libc::SYS_writev, vec![]), From 6e345aad85f22d1b8fcc0a9b3bb4a29850de9f2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 08:50:43 +0000 Subject: [PATCH 4/4] build: Bump crate-ci/typos from 1.43.5 to 1.46.2 Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.43.5 to 1.46.2. - [Release notes](https://github.com/crate-ci/typos/releases) - [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md) - [Commits](https://github.com/crate-ci/typos/compare/v1.43.5...v1.46.2) --- updated-dependencies: - dependency-name: crate-ci/typos dependency-version: 1.46.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/quality.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/quality.yaml b/.github/workflows/quality.yaml index 042770845..34b5cc459 100644 --- a/.github/workflows/quality.yaml +++ b/.github/workflows/quality.yaml @@ -167,4 +167,4 @@ jobs: steps: - uses: actions/checkout@v6 # Executes "typos ." - - uses: crate-ci/typos@v1.43.5 + - uses: crate-ci/typos@v1.46.2