if (WARN_ON_ONCE(!svm->nested.initialized))
return -EINVAL;
- vmcb12_gpa = svm->vmcb->save.rax;
+ vmcb12_gpa = kvm_register_read(vcpu, VCPU_REGS_RAX);
+ if (!page_address_valid(vcpu, vmcb12_gpa)) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
ret = nested_svm_copy_vmcb12_to_cache(vcpu, vmcb12_gpa);
if (ret) {
static int vmload_vmsave_interception(struct kvm_vcpu *vcpu, bool vmload)
{
+ u64 vmcb12_gpa = kvm_register_read(vcpu, VCPU_REGS_RAX);
struct vcpu_svm *svm = to_svm(vcpu);
struct vmcb *vmcb12;
struct kvm_host_map map;
if (nested_svm_check_permissions(vcpu))
return 1;
- ret = kvm_vcpu_map(vcpu, gpa_to_gfn(svm->vmcb->save.rax), &map);
+ if (!page_address_valid(vcpu, vmcb12_gpa)) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+ }
+
+ ret = kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map);
if (ret) {
if (ret == -EINVAL)
kvm_inject_gp(vcpu, 0);
/* FIXME: Handle SVM instructions through the emulator */
svm_exit_code = svm_get_decoded_instr_exit_code(vcpu);
if (svm_exit_code) {
- if (!page_address_valid(vcpu, kvm_register_read(vcpu, VCPU_REGS_RAX)))
- goto reinject;
-
if (!is_guest_mode(vcpu))
return svm_invoke_exit_handler(vcpu, svm_exit_code);
+ if (!page_address_valid(vcpu, kvm_register_read(vcpu, VCPU_REGS_RAX)))
+ goto reinject;
+
+ /*
+ * FIXME: Only synthesize a #VMEXIT if L1 sets the intercept,
+ * but only after the VMLOAD/VMSAVE exit handlers can properly
+ * handle VMLOAD/VMSAVE from L2 with VLS enabled in L1 (i.e.
+ * RAX is an L2 GPA that needs translation through L1's NPT).
+ */
nested_svm_simple_vmexit(svm, svm_exit_code);
return 1;
}