From 60536c5b2065cc58d49c5f5fd0ea3d083a49cae3 Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Thu, 1 Aug 2024 13:23:35 +0000 Subject: [PATCH 1/3] Add MemoryFaultInfo variant to Cap Signed-off-by: Nikita Kalyazin --- src/cap.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cap.rs b/src/cap.rs index 9d31f91f..08265d88 100644 --- a/src/cap.rs +++ b/src/cap.rs @@ -169,4 +169,6 @@ pub enum Cap { X86UserSpaceMsr = KVM_CAP_X86_USER_SPACE_MSR, #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] ExitHypercall = KVM_CAP_EXIT_HYPERCALL, + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + MemoryFaultInfo = KVM_CAP_MEMORY_FAULT_INFO, } From 4d3927fa651287ff1a24ddc65e138b0b660e72c1 Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Thu, 1 Aug 2024 11:32:20 +0000 Subject: [PATCH 2/3] Propagate MemoryFault exit reason in KVM_RUN Signed-off-by: Nikita Kalyazin --- src/ioctls/vcpu.rs | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/ioctls/vcpu.rs b/src/ioctls/vcpu.rs index afa75ada..b3c25dee 100644 --- a/src/ioctls/vcpu.rs +++ b/src/ioctls/vcpu.rs @@ -166,6 +166,15 @@ pub enum VcpuExit<'a> { X86Rdmsr(ReadMsrExit<'a>), /// Corresponds to KVM_EXIT_X86_WRMSR. X86Wrmsr(WriteMsrExit<'a>), + /// Corresponds to KVM_EXIT_MEMORY_FAULT. + MemoryFault { + /// flags + flags: u64, + /// gpa + gpa: u64, + /// size + size: u64, + }, /// Corresponds to an exit reason that is unknown from the current version /// of the kvm-ioctls crate. Let the consumer decide about what to do with /// it. @@ -1569,7 +1578,30 @@ impl VcpuFd { r => Ok(VcpuExit::Unsupported(r)), } } else { - Err(errno::Error::last()) + let errno = errno::Error::last(); + let run = self.kvm_run_ptr.as_mut_ref(); + // From https://docs.kernel.org/virt/kvm/api.html#kvm-run : + // + // KVM_EXIT_MEMORY_FAULT is unique among all KVM exit reasons in that it accompanies + // a return code of ‘-1’, not ‘0’! errno will always be set to EFAULT or EHWPOISON + // when KVM exits with KVM_EXIT_MEMORY_FAULT, userspace should assume kvm_run.exit_reason + // is stale/undefined for all other error numbers. + if ret == -1 + && (errno == errno::Error::new(libc::EFAULT) + || errno == errno::Error::new(libc::EHWPOISON)) + && run.exit_reason == KVM_EXIT_MEMORY_FAULT + { + // SAFETY: Safe because the exit_reason (which comes from the kernel) told us + // which union field to use. + let fault = unsafe { &mut run.__bindgen_anon_1.memory_fault }; + Ok(VcpuExit::MemoryFault { + flags: fault.flags, + gpa: fault.gpa, + size: fault.size, + }) + } else { + Err(errno) + } } } From c52788c2a275de01972682345353dce13ea0f28b Mon Sep 17 00:00:00 2001 From: Nikita Kalyazin Date: Thu, 1 Aug 2024 11:39:41 +0000 Subject: [PATCH 3/3] Update changelog Signed-off-by: Nikita Kalyazin --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5977697f..73f2a61e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added - [[#267](https://github.com/rust-vmm/kvm-ioctls/pull/267)]: Added `HypercallExit` field to `VcpuExit::Hypercall` and added `ExitHypercall` to `Cap`. +- [[#270](https://github.com/rust-vmm/kvm-ioctls/pull/270)]: Added `MemoryFaultInfo` to `Cap` and propagated `MemoryFault` exit reason in `KVM_RUN`. ### Changed