KVM/arm64 fixes for 5.13, take #2 - Another state update on exit to userspace fix - Prevent the creation of mixed 32/64 VMs
Unified · Split
| @@ -463,4 +463,9 @@ static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu) · 462 unmodified lines | ||
| 463 | 463 | vcpu->arch.flags |= KVM_ARM64_INCREMENT_PC; |
| 464 | 464 | } |
| 465 | 465 | |
| 466 | +static inline bool vcpu_has_feature(struct kvm_vcpu *vcpu, int feature) | |
| 467 | +{ | |
| 468 | + return test_bit(feature, vcpu->arch.features); | |
| 469 | +} | |
| 470 | + | |
| 466 | 471 | #endif /* __ARM64_KVM_EMULATE_H__ */ |
| @@ -720,11 +720,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 719 unmodified lines | ||
| 720 | 720 | return ret; |
| 721 | 721 | } |
| 722 | 722 | |
| 723 | − if (run->immediate_exit) | |
| 724 | − return -EINTR; | |
| 725 | − | |
| 726 | 723 | vcpu_load(vcpu); |
| 727 | 724 | |
| 725 | + if (run->immediate_exit) { | |
| 726 | + ret = -EINTR; | |
| 727 | + goto out; | |
| 728 | + } | |
| 729 | + | |
| 728 | 730 | kvm_sigset_activate(vcpu); |
| 729 | 731 | |
| 730 | 732 | ret = 1; |
| @@ -897,6 +899,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) · 166 unmodified lines | ||
| 897 | 899 | |
| 898 | 900 | kvm_sigset_deactivate(vcpu); |
| 899 | 901 | |
| 902 | +out: | |
| 900 | 903 | /* |
| 901 | 904 | * In the unlikely event that we are returning to userspace |
| 902 | 905 | * with pending exceptions or PC adjustment, commit these |
| @@ -166,6 +166,25 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu) · 165 unmodified lines | ||
| 166 | 166 | return 0; |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | +static bool vcpu_allowed_register_width(struct kvm_vcpu *vcpu) | |
| 170 | +{ | |
| 171 | + struct kvm_vcpu *tmp; | |
| 172 | + bool is32bit; | |
| 173 | + int i; | |
| 174 | + | |
| 175 | + is32bit = vcpu_has_feature(vcpu, KVM_ARM_VCPU_EL1_32BIT); | |
| 176 | + if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1) && is32bit) | |
| 177 | + return false; | |
| 178 | + | |
| 179 | + /* Check that the vcpus are either all 32bit or all 64bit */ | |
| 180 | + kvm_for_each_vcpu(i, tmp, vcpu->kvm) { | |
| 181 | + if (vcpu_has_feature(tmp, KVM_ARM_VCPU_EL1_32BIT) != is32bit) | |
| 182 | + return false; | |
| 183 | + } | |
| 184 | + | |
| 185 | + return true; | |
| 186 | +} | |
| 187 | + | |
| 169 | 188 | /** |
| 170 | 189 | * kvm_reset_vcpu - sets core registers and sys_regs to reset value |
| 171 | 190 | * @vcpu: The VCPU pointer |
| @@ -217,13 +236,14 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) · 45 unmodified lines | ||
| 217 | 236 | } |
| 218 | 237 | } |
| 219 | 238 | |
| 239 | + if (!vcpu_allowed_register_width(vcpu)) { | |
| 240 | + ret = -EINVAL; | |
| 241 | + goto out; | |
| 242 | + } | |
| 243 | + | |
| 220 | 244 | switch (vcpu->arch.target) { |
| 221 | 245 | default: |
| 222 | 246 | if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) { |
| 223 | − if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1)) { | |
| 224 | − ret = -EINVAL; | |
| 225 | − goto out; | |
| 226 | − } | |
| 227 | 247 | pstate = VCPU_RESET_PSTATE_SVC; |
| 228 | 248 | } else { |
| 229 | 249 | pstate = VCPU_RESET_PSTATE_EL1; |