Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate MemoryFault exit reason in KVM_RUN #270

Merged
merged 3 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions src/cap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
34 changes: 33 additions & 1 deletion src/ioctls/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
}
}
}

Expand Down