return true;
}
- static bool nested_vmcb_check_save(struct kvm_vcpu *vcpu)
- {
- struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb_save_area_cached *save = &svm->nested.save;
-
- return __nested_vmcb_check_save(vcpu, save);
- }
-
- static bool nested_vmcb_check_controls(struct kvm_vcpu *vcpu)
++int nested_svm_check_cached_vmcb12(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb_ctrl_area_cached *ctl = &svm->nested.ctl;
+
- return __nested_vmcb_check_controls(vcpu, ctl);
- }
-
- int nested_svm_check_cached_vmcb12(struct kvm_vcpu *vcpu)
- {
- if (!nested_vmcb_check_save(vcpu) ||
- !nested_vmcb_check_controls(vcpu))
++ if (!nested_vmcb_check_save(vcpu, &svm->nested.save) ||
++ !nested_vmcb_check_controls(vcpu, &svm->nested.ctl))
+ return -EINVAL;
+
+ return 0;
+}
+
/*
* If a feature is not advertised to L1, clear the corresponding vmcb12
* intercept.
return 0;
}
- if (!nested_vmcb_check_save(vcpu, &svm->nested.save) ||
- !nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) {
+ static int nested_svm_copy_vmcb12_to_cache(struct kvm_vcpu *vcpu, u64 vmcb12_gpa)
+ {
+ struct vcpu_svm *svm = to_svm(vcpu);
+ struct kvm_host_map map;
+ struct vmcb *vmcb12;
+ int r = 0;
+
+ if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map))
+ return -EFAULT;
+
+ vmcb12 = map.hva;
+ nested_copy_vmcb_control_to_cache(svm, &vmcb12->control);
+ nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);
+
++ if (nested_svm_check_cached_vmcb12(vcpu) < 0) {
+ vmcb12->control.exit_code = SVM_EXIT_ERR;
+ vmcb12->control.exit_info_1 = 0;
+ vmcb12->control.exit_info_2 = 0;
+ vmcb12->control.event_inj = 0;
+ vmcb12->control.event_inj_err = 0;
+ svm_set_gif(svm, false);
+ r = -EINVAL;
+ }
+
+ kvm_vcpu_unmap(vcpu, &map);
+ return r;
+ }
+
int nested_svm_vmrun(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
vmcb12 = map.hva;
nested_copy_vmcb_control_to_cache(svm, &vmcb12->control);
nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);
- ret = enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa, false);
- if (ret)
+ if (nested_svm_check_cached_vmcb12(vcpu) < 0)
+ goto unmap_save;
+
- if (enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa,
- vmcb12, false) != 0)
++ if (enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa, false) != 0)
goto unmap_save;
- svm->nested.nested_run_pending = 1;
+ ret = 0;
+ vcpu->arch.nested_run_pending = KVM_NESTED_RUN_PENDING;
unmap_save:
kvm_vcpu_unmap(vcpu, &map_save);
}
if (vmx->nested.smm.guest_mode) {
+ /* Triple fault if the state is invalid. */
+ if (nested_vmx_check_restored_vmcs12(vcpu) < 0)
+ return 1;
+
ret = nested_vmx_enter_non_root_mode(vcpu, false);
- if (ret)
- return ret;
+ if (ret != NVMX_VMENTRY_SUCCESS)
+ return 1;
- vmx->nested.nested_run_pending = 1;
+ vcpu->arch.nested_run_pending = KVM_NESTED_RUN_PENDING;
vmx->nested.smm.guest_mode = false;
}
return 0;