|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
| 2 | +/* |
| 3 | + * vcpu_width_config - Test KVM_ARM_VCPU_INIT() with KVM_ARM_VCPU_EL1_32BIT. |
| 4 | + * |
| 5 | + * Copyright (c) 2022 Google LLC. |
| 6 | + * |
| 7 | + * This is a test that ensures that non-mixed-width vCPUs (all 64bit vCPUs |
| 8 | + * or all 32bit vcPUs) can be configured and mixed-width vCPUs cannot be |
| 9 | + * configured. |
| 10 | + */ |
| 11 | + |
| 12 | +#include "kvm_util.h" |
| 13 | +#include "processor.h" |
| 14 | +#include "test_util.h" |
| 15 | + |
| 16 | + |
| 17 | +/* |
| 18 | + * Add a vCPU, run KVM_ARM_VCPU_INIT with @init1, and then |
| 19 | + * add another vCPU, and run KVM_ARM_VCPU_INIT with @init2. |
| 20 | + */ |
| 21 | +static int add_init_2vcpus(struct kvm_vcpu_init *init1, |
| 22 | + struct kvm_vcpu_init *init2) |
| 23 | +{ |
| 24 | + struct kvm_vm *vm; |
| 25 | + int ret; |
| 26 | + |
| 27 | + vm = vm_create(VM_MODE_DEFAULT, DEFAULT_GUEST_PHY_PAGES, O_RDWR); |
| 28 | + |
| 29 | + vm_vcpu_add(vm, 0); |
| 30 | + ret = _vcpu_ioctl(vm, 0, KVM_ARM_VCPU_INIT, init1); |
| 31 | + if (ret) |
| 32 | + goto free_exit; |
| 33 | + |
| 34 | + vm_vcpu_add(vm, 1); |
| 35 | + ret = _vcpu_ioctl(vm, 1, KVM_ARM_VCPU_INIT, init2); |
| 36 | + |
| 37 | +free_exit: |
| 38 | + kvm_vm_free(vm); |
| 39 | + return ret; |
| 40 | +} |
| 41 | + |
| 42 | +/* |
| 43 | + * Add two vCPUs, then run KVM_ARM_VCPU_INIT for one vCPU with @init1, |
| 44 | + * and run KVM_ARM_VCPU_INIT for another vCPU with @init2. |
| 45 | + */ |
| 46 | +static int add_2vcpus_init_2vcpus(struct kvm_vcpu_init *init1, |
| 47 | + struct kvm_vcpu_init *init2) |
| 48 | +{ |
| 49 | + struct kvm_vm *vm; |
| 50 | + int ret; |
| 51 | + |
| 52 | + vm = vm_create(VM_MODE_DEFAULT, DEFAULT_GUEST_PHY_PAGES, O_RDWR); |
| 53 | + |
| 54 | + vm_vcpu_add(vm, 0); |
| 55 | + vm_vcpu_add(vm, 1); |
| 56 | + |
| 57 | + ret = _vcpu_ioctl(vm, 0, KVM_ARM_VCPU_INIT, init1); |
| 58 | + if (ret) |
| 59 | + goto free_exit; |
| 60 | + |
| 61 | + ret = _vcpu_ioctl(vm, 1, KVM_ARM_VCPU_INIT, init2); |
| 62 | + |
| 63 | +free_exit: |
| 64 | + kvm_vm_free(vm); |
| 65 | + return ret; |
| 66 | +} |
| 67 | + |
| 68 | +/* |
| 69 | + * Tests that two 64bit vCPUs can be configured, two 32bit vCPUs can be |
| 70 | + * configured, and two mixed-width vCPUs cannot be configured. |
| 71 | + * Each of those three cases, configure vCPUs in two different orders. |
| 72 | + * The one is running KVM_CREATE_VCPU for 2 vCPUs, and then running |
| 73 | + * KVM_ARM_VCPU_INIT for them. |
| 74 | + * The other is running KVM_CREATE_VCPU and KVM_ARM_VCPU_INIT for a vCPU, |
| 75 | + * and then run those commands for another vCPU. |
| 76 | + */ |
| 77 | +int main(void) |
| 78 | +{ |
| 79 | + struct kvm_vcpu_init init1, init2; |
| 80 | + struct kvm_vm *vm; |
| 81 | + int ret; |
| 82 | + |
| 83 | + if (!kvm_check_cap(KVM_CAP_ARM_EL1_32BIT)) { |
| 84 | + print_skip("KVM_CAP_ARM_EL1_32BIT is not supported"); |
| 85 | + exit(KSFT_SKIP); |
| 86 | + } |
| 87 | + |
| 88 | + /* Get the preferred target type and copy that to init2 for later use */ |
| 89 | + vm = vm_create(VM_MODE_DEFAULT, DEFAULT_GUEST_PHY_PAGES, O_RDWR); |
| 90 | + vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init1); |
| 91 | + kvm_vm_free(vm); |
| 92 | + init2 = init1; |
| 93 | + |
| 94 | + /* Test with 64bit vCPUs */ |
| 95 | + ret = add_init_2vcpus(&init1, &init1); |
| 96 | + TEST_ASSERT(ret == 0, |
| 97 | + "Configuring 64bit EL1 vCPUs failed unexpectedly"); |
| 98 | + ret = add_2vcpus_init_2vcpus(&init1, &init1); |
| 99 | + TEST_ASSERT(ret == 0, |
| 100 | + "Configuring 64bit EL1 vCPUs failed unexpectedly"); |
| 101 | + |
| 102 | + /* Test with 32bit vCPUs */ |
| 103 | + init1.features[0] = (1 << KVM_ARM_VCPU_EL1_32BIT); |
| 104 | + ret = add_init_2vcpus(&init1, &init1); |
| 105 | + TEST_ASSERT(ret == 0, |
| 106 | + "Configuring 32bit EL1 vCPUs failed unexpectedly"); |
| 107 | + ret = add_2vcpus_init_2vcpus(&init1, &init1); |
| 108 | + TEST_ASSERT(ret == 0, |
| 109 | + "Configuring 32bit EL1 vCPUs failed unexpectedly"); |
| 110 | + |
| 111 | + /* Test with mixed-width vCPUs */ |
| 112 | + init1.features[0] = 0; |
| 113 | + init2.features[0] = (1 << KVM_ARM_VCPU_EL1_32BIT); |
| 114 | + ret = add_init_2vcpus(&init1, &init2); |
| 115 | + TEST_ASSERT(ret != 0, |
| 116 | + "Configuring mixed-width vCPUs worked unexpectedly"); |
| 117 | + ret = add_2vcpus_init_2vcpus(&init1, &init2); |
| 118 | + TEST_ASSERT(ret != 0, |
| 119 | + "Configuring mixed-width vCPUs worked unexpectedly"); |
| 120 | + |
| 121 | + return 0; |
| 122 | +} |
0 commit comments