Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33740e40 authored by Joerg Roedel's avatar Joerg Roedel Committed by Avi Kivity
Browse files

KVM: SVM: optimize nested #vmexit



It is more efficient to copy only the relevant parts of the vmcb back to
the nested vmcb when we emulate an vmexit.

Signed-off-by: default avatarJoerg Roedel <joerg.roedel@amd.com>
Acked-by: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 2af9194d
Loading
Loading
Loading
Loading
+33 −35
Original line number Diff line number Diff line
@@ -1572,53 +1572,52 @@ static int nested_svm_vmexit_real(struct vcpu_svm *svm, void *arg1,
{
	struct vmcb *nested_vmcb = (struct vmcb *)arg1;
	struct vmcb *hsave = svm->hsave;
	u64 nested_save[] = { nested_vmcb->save.cr0,
			      nested_vmcb->save.cr3,
			      nested_vmcb->save.cr4,
			      nested_vmcb->save.efer,
			      nested_vmcb->control.intercept_cr_read,
			      nested_vmcb->control.intercept_cr_write,
			      nested_vmcb->control.intercept_dr_read,
			      nested_vmcb->control.intercept_dr_write,
			      nested_vmcb->control.intercept_exceptions,
			      nested_vmcb->control.intercept,
			      nested_vmcb->control.msrpm_base_pa,
			      nested_vmcb->control.iopm_base_pa,
			      nested_vmcb->control.tsc_offset };
	struct vmcb *vmcb = svm->vmcb;

	/* Give the current vmcb to the guest */
	memcpy(nested_vmcb, svm->vmcb, sizeof(struct vmcb));
	nested_vmcb->save.cr0 = nested_save[0];
	if (!npt_enabled)
		nested_vmcb->save.cr3 = nested_save[1];
	nested_vmcb->save.cr4 = nested_save[2];
	nested_vmcb->save.efer = nested_save[3];
	nested_vmcb->control.intercept_cr_read = nested_save[4];
	nested_vmcb->control.intercept_cr_write = nested_save[5];
	nested_vmcb->control.intercept_dr_read = nested_save[6];
	nested_vmcb->control.intercept_dr_write = nested_save[7];
	nested_vmcb->control.intercept_exceptions = nested_save[8];
	nested_vmcb->control.intercept = nested_save[9];
	nested_vmcb->control.msrpm_base_pa = nested_save[10];
	nested_vmcb->control.iopm_base_pa = nested_save[11];
	nested_vmcb->control.tsc_offset = nested_save[12];
	disable_gif(svm);

	nested_vmcb->save.es     = vmcb->save.es;
	nested_vmcb->save.cs     = vmcb->save.cs;
	nested_vmcb->save.ss     = vmcb->save.ss;
	nested_vmcb->save.ds     = vmcb->save.ds;
	nested_vmcb->save.gdtr   = vmcb->save.gdtr;
	nested_vmcb->save.idtr   = vmcb->save.idtr;
	if (npt_enabled)
		nested_vmcb->save.cr3    = vmcb->save.cr3;
	nested_vmcb->save.cr2    = vmcb->save.cr2;
	nested_vmcb->save.rflags = vmcb->save.rflags;
	nested_vmcb->save.rip    = vmcb->save.rip;
	nested_vmcb->save.rsp    = vmcb->save.rsp;
	nested_vmcb->save.rax    = vmcb->save.rax;
	nested_vmcb->save.dr7    = vmcb->save.dr7;
	nested_vmcb->save.dr6    = vmcb->save.dr6;
	nested_vmcb->save.cpl    = vmcb->save.cpl;

	nested_vmcb->control.int_ctl           = vmcb->control.int_ctl;
	nested_vmcb->control.int_vector        = vmcb->control.int_vector;
	nested_vmcb->control.int_state         = vmcb->control.int_state;
	nested_vmcb->control.exit_code         = vmcb->control.exit_code;
	nested_vmcb->control.exit_code_hi      = vmcb->control.exit_code_hi;
	nested_vmcb->control.exit_info_1       = vmcb->control.exit_info_1;
	nested_vmcb->control.exit_info_2       = vmcb->control.exit_info_2;
	nested_vmcb->control.exit_int_info     = vmcb->control.exit_int_info;
	nested_vmcb->control.exit_int_info_err = vmcb->control.exit_int_info_err;
	nested_vmcb->control.tlb_ctl           = 0;
	nested_vmcb->control.event_inj         = 0;
	nested_vmcb->control.event_inj_err     = 0;

	/* We always set V_INTR_MASKING and remember the old value in hflags */
	if (!(svm->vcpu.arch.hflags & HF_VINTR_MASK))
		nested_vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK;

	if ((nested_vmcb->control.int_ctl & V_IRQ_MASK) &&
	    (nested_vmcb->control.int_vector)) {
		nsvm_printk("WARNING: IRQ 0x%x still enabled on #VMEXIT\n",
				nested_vmcb->control.int_vector);
	}

	/* Restore the original control entries */
	svm->vmcb->control = hsave->control;

	/* Kill any pending exceptions */
	if (svm->vcpu.arch.exception.pending == true)
		nsvm_printk("WARNING: Pending Exception\n");

	kvm_clear_exception_queue(&svm->vcpu);
	kvm_clear_interrupt_queue(&svm->vcpu);

@@ -1646,7 +1645,6 @@ static int nested_svm_vmexit_real(struct vcpu_svm *svm, void *arg1,
	svm->vmcb->save.cpl = 0;
	svm->vmcb->control.exit_int_info = 0;

	disable_gif(svm);
	/* Exit nested SVM mode */
	svm->nested_vmcb = 0;