Skip to content

Commit

Permalink
vm: create_vcpu takes u64 argument rust-vmm#123
Browse files Browse the repository at this point in the history
Changed the passed parameter type from `u8` to `u64`, which the
underlying `ioctl` uses.

Added a missing cap `MaxVcpuId` (It is defined in kvm-bindings for both
arm* and x86* but was missing inside cap.rs. This was required by a test
case.)

Added a test case to assert failure if we pass parameter higher than the
`max_vcpu_id`.

Signed-off-by: Abhijit Gadgil <gabhijit@iitbombay.org>
  • Loading branch information
gabhijit authored and alexandruag committed Jan 15, 2021
1 parent 6aa32c7 commit 4f61bba
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/cap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub enum Cap {
PpcSmt = KVM_CAP_PPC_SMT,
PpcRma = KVM_CAP_PPC_RMA,
MaxVcpus = KVM_CAP_MAX_VCPUS,
MaxVcpuId = KVM_CAP_MAX_VCPU_ID,
PpcHior = KVM_CAP_PPC_HIOR,
PpcPapr = KVM_CAP_PPC_PAPR,
SwTlb = KVM_CAP_SW_TLB,
Expand Down
4 changes: 2 additions & 2 deletions src/ioctls/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1411,7 +1411,7 @@ mod tests {
assert!(ncpuids <= KVM_MAX_CPUID_ENTRIES);
let nr_vcpus = kvm.get_nr_vcpus();
for cpu_idx in 0..nr_vcpus {
let vcpu = vm.create_vcpu(cpu_idx as u8).unwrap();
let vcpu = vm.create_vcpu(cpu_idx as u64).unwrap();
vcpu.set_cpuid2(&cpuid).unwrap();
let retrieved_cpuid = vcpu.get_cpuid2(ncpuids).unwrap();
// Only check the first few leafs as some (e.g. 13) are reserved.
Expand Down Expand Up @@ -1443,7 +1443,7 @@ mod tests {
assert!(ncpuids <= KVM_MAX_CPUID_ENTRIES);
let nr_vcpus = kvm.get_nr_vcpus();
for cpu_idx in 0..nr_vcpus {
let vcpu = vm.create_vcpu(cpu_idx as u8).unwrap();
let vcpu = vm.create_vcpu(cpu_idx as u64).unwrap();
vcpu.set_cpuid2(&cpuid).unwrap();
let err = vcpu.get_cpuid2(ncpuids - 1 as usize).err();
assert_eq!(err.unwrap().errno(), libc::E2BIG);
Expand Down
34 changes: 33 additions & 1 deletion src/ioctls/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ impl VmFd {
/// let vcpu = vm.create_vcpu(0);
/// ```
///
pub fn create_vcpu(&self, id: u8) -> Result<VcpuFd> {
pub fn create_vcpu(&self, id: u64) -> Result<VcpuFd> {
// Safe because we know that vm is a VM fd and we verify the return result.
#[allow(clippy::cast_lossless)]
let vcpu_fd = unsafe { ioctl_with_val(&self.vm, KVM_CREATE_VCPU(), id as c_ulong) };
Expand Down Expand Up @@ -1799,6 +1799,38 @@ mod tests {
assert!(vm.set_gsi_routing(&irq_routing).is_ok());
}

#[test]
fn create_vcpu_different_cpuids() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();

// Fails when an arbitrarily large value
let err = vm.create_vcpu(65537 as u64).err();
assert_eq!(err.unwrap().errno(), libc::EINVAL);

// Note: We can request up to KVM_MAX_VCPU_ID if it exists or up to KVM_MAX_VCPUS or
// NR_CPUS or 4. This is determined by the appropriate capability being present.
// We check near boundry conditions `max_vcpus - 1` should succeed but `max_vcpus` as
// determined by the appropriate capability should fail.
//
// Ref: https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-create-vcpu
//
let mut max_vcpus = vm.check_extension_int(Cap::MaxVcpuId);
if max_vcpus == 0 {
max_vcpus = vm.check_extension_int(Cap::MaxVcpus);
}
if max_vcpus == 0 {
max_vcpus = vm.check_extension_int(Cap::NrVcpus);
}
if max_vcpus == 0 {
max_vcpus = 4
}
let vcpu = vm.create_vcpu((max_vcpus - 1) as u64);
assert!(vcpu.is_ok());
let vcpu_err = vm.create_vcpu(max_vcpus as u64).err();
assert_eq!(vcpu_err.unwrap().errno(), libc::EINVAL);
}

#[test]
fn test_check_extension() {
let kvm = Kvm::new().unwrap();
Expand Down

0 comments on commit 4f61bba

Please sign in to comment.