Skip to content

Commit

Permalink
Add KVM_TRANSLATE and translate_gva
Browse files Browse the repository at this point in the history
This commit adds support for KVM_TRANSLATE and function translate_gva,
translates guest virtual address to the physical address by calling
ioctl as described in [1].

[1] https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt

Signed-off-by: Akira Moroo <retrage01@gmail.com>
Co-authored-by: Adrian Catangiu <adrian@parity.io>
  • Loading branch information
2 people authored and lauralt committed Jan 24, 2022
1 parent 8ab2e37 commit 97ff779
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
2 changes: 1 addition & 1 deletion coverage_config_x86_64.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"coverage_score": 85.9,
"coverage_score": 86.1,
"exclude_path": "",
"crate_features": ""
}
54 changes: 54 additions & 0 deletions src/ioctls/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,43 @@ impl VcpuFd {
Ok(())
}
}

/// Translates a virtual address according to the vCPU's current address translation mode.
///
/// The physical address is returned in a `kvm_translation` structure as defined in the
/// [KVM API documentation](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt).
/// See documentation for `KVM_TRANSLATE`.
///
/// # Arguments
///
/// * `gva` - The virtual address to translate.
///
/// # Example
///
/// ```rust
/// # extern crate kvm_ioctls;
/// # use kvm_ioctls::Kvm;
/// let kvm = Kvm::new().unwrap();
/// let vm = kvm.create_vm().unwrap();
/// let vcpu = vm.create_vcpu(0).unwrap();
/// #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
/// let tr = vcpu.translate_gva(0x10000).unwrap();
/// ```
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn translate_gva(&self, gva: u64) -> Result<kvm_translation> {
let mut tr = kvm_translation {
linear_address: gva,
..Default::default()
};

// Safe because we know that our file is a vCPU fd, we know the kernel will only write the
// correct amount of memory to our pointer, and we verify the return result.
let ret = unsafe { ioctl_with_mut_ref(self, KVM_TRANSLATE(), &mut tr) };
if ret != 0 {
return Err(errno::Error::last());
}
Ok(tr)
}
}

/// Helper function to create a new `VcpuFd`.
Expand Down Expand Up @@ -2172,6 +2209,7 @@ mod tests {
);
assert!(faulty_vcpu_fd.get_tsc_khz().is_err());
assert!(faulty_vcpu_fd.set_tsc_khz(1000000).is_err());
assert!(faulty_vcpu_fd.translate_gva(u64::MAX).is_err());
}

#[test]
Expand Down Expand Up @@ -2337,6 +2375,22 @@ mod tests {
}
}

#[test]
#[cfg(target_arch = "x86_64")]
fn test_translate_gva() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let vcpu = vm.create_vcpu(0).unwrap();
assert!(vcpu.translate_gva(0x10000).is_ok());
assert_eq!(vcpu.translate_gva(0x10000).unwrap().valid, 1);
assert_eq!(
vcpu.translate_gva(0x10000).unwrap().physical_address,
0x10000
);
assert!(vcpu.translate_gva(u64::MAX).is_ok());
assert_eq!(vcpu.translate_gva(u64::MAX).unwrap().valid, 0);
}

#[test]
#[cfg(target_arch = "aarch64")]
fn test_vcpu_attr() {
Expand Down
2 changes: 2 additions & 0 deletions src/kvm_ioctls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ ioctl_ior_nr!(KVM_GET_SREGS, KVMIO, 0x83, kvm_sregs);
target_arch = "powerpc64"
))]
ioctl_iow_nr!(KVM_SET_SREGS, KVMIO, 0x84, kvm_sregs);
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
ioctl_iowr_nr!(KVM_TRANSLATE, KVMIO, 0x85, kvm_translation);
/* Available with KVM_CAP_GET_MSR_FEATURES */
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
ioctl_iowr_nr!(KVM_GET_MSR_INDEX_LIST, KVMIO, 0x02, kvm_msr_list);
Expand Down

0 comments on commit 97ff779

Please sign in to comment.