KVM: nSVM: always use vmcb01 to for vmsave/vmload of guest state
This allows to avoid copying of these fields between vmcb01 and vmcb02 on nested guest entry/exit. Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
committed by
Paolo Bonzini
parent
fb0c4a4fee
commit
cc3ed80ae6
@@ -536,7 +536,6 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb12_gpa,
|
|||||||
|
|
||||||
WARN_ON(svm->vmcb == svm->nested.vmcb02.ptr);
|
WARN_ON(svm->vmcb == svm->nested.vmcb02.ptr);
|
||||||
|
|
||||||
nested_svm_vmloadsave(svm->vmcb01.ptr, svm->nested.vmcb02.ptr);
|
|
||||||
nested_load_control_from_vmcb12(svm, &vmcb12->control);
|
nested_load_control_from_vmcb12(svm, &vmcb12->control);
|
||||||
|
|
||||||
svm_switch_vmcb(svm, &svm->nested.vmcb02);
|
svm_switch_vmcb(svm, &svm->nested.vmcb02);
|
||||||
@@ -726,8 +725,6 @@ int nested_svm_vmexit(struct vcpu_svm *svm)
|
|||||||
vmcb12->control.pause_filter_thresh =
|
vmcb12->control.pause_filter_thresh =
|
||||||
svm->vmcb->control.pause_filter_thresh;
|
svm->vmcb->control.pause_filter_thresh;
|
||||||
|
|
||||||
nested_svm_vmloadsave(svm->nested.vmcb02.ptr, svm->vmcb01.ptr);
|
|
||||||
|
|
||||||
svm_switch_vmcb(svm, &svm->vmcb01);
|
svm_switch_vmcb(svm, &svm->vmcb01);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1589,16 +1589,17 @@ static void svm_clear_vintr(struct vcpu_svm *svm)
|
|||||||
static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg)
|
static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg)
|
||||||
{
|
{
|
||||||
struct vmcb_save_area *save = &to_svm(vcpu)->vmcb->save;
|
struct vmcb_save_area *save = &to_svm(vcpu)->vmcb->save;
|
||||||
|
struct vmcb_save_area *save01 = &to_svm(vcpu)->vmcb01.ptr->save;
|
||||||
|
|
||||||
switch (seg) {
|
switch (seg) {
|
||||||
case VCPU_SREG_CS: return &save->cs;
|
case VCPU_SREG_CS: return &save->cs;
|
||||||
case VCPU_SREG_DS: return &save->ds;
|
case VCPU_SREG_DS: return &save->ds;
|
||||||
case VCPU_SREG_ES: return &save->es;
|
case VCPU_SREG_ES: return &save->es;
|
||||||
case VCPU_SREG_FS: return &save->fs;
|
case VCPU_SREG_FS: return &save01->fs;
|
||||||
case VCPU_SREG_GS: return &save->gs;
|
case VCPU_SREG_GS: return &save01->gs;
|
||||||
case VCPU_SREG_SS: return &save->ss;
|
case VCPU_SREG_SS: return &save->ss;
|
||||||
case VCPU_SREG_TR: return &save->tr;
|
case VCPU_SREG_TR: return &save01->tr;
|
||||||
case VCPU_SREG_LDTR: return &save->ldtr;
|
case VCPU_SREG_LDTR: return &save01->ldtr;
|
||||||
}
|
}
|
||||||
BUG();
|
BUG();
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2648,24 +2649,24 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||||||
|
|
||||||
switch (msr_info->index) {
|
switch (msr_info->index) {
|
||||||
case MSR_STAR:
|
case MSR_STAR:
|
||||||
msr_info->data = svm->vmcb->save.star;
|
msr_info->data = svm->vmcb01.ptr->save.star;
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
case MSR_LSTAR:
|
case MSR_LSTAR:
|
||||||
msr_info->data = svm->vmcb->save.lstar;
|
msr_info->data = svm->vmcb01.ptr->save.lstar;
|
||||||
break;
|
break;
|
||||||
case MSR_CSTAR:
|
case MSR_CSTAR:
|
||||||
msr_info->data = svm->vmcb->save.cstar;
|
msr_info->data = svm->vmcb01.ptr->save.cstar;
|
||||||
break;
|
break;
|
||||||
case MSR_KERNEL_GS_BASE:
|
case MSR_KERNEL_GS_BASE:
|
||||||
msr_info->data = svm->vmcb->save.kernel_gs_base;
|
msr_info->data = svm->vmcb01.ptr->save.kernel_gs_base;
|
||||||
break;
|
break;
|
||||||
case MSR_SYSCALL_MASK:
|
case MSR_SYSCALL_MASK:
|
||||||
msr_info->data = svm->vmcb->save.sfmask;
|
msr_info->data = svm->vmcb01.ptr->save.sfmask;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case MSR_IA32_SYSENTER_CS:
|
case MSR_IA32_SYSENTER_CS:
|
||||||
msr_info->data = svm->vmcb->save.sysenter_cs;
|
msr_info->data = svm->vmcb01.ptr->save.sysenter_cs;
|
||||||
break;
|
break;
|
||||||
case MSR_IA32_SYSENTER_EIP:
|
case MSR_IA32_SYSENTER_EIP:
|
||||||
msr_info->data = svm->sysenter_eip;
|
msr_info->data = svm->sysenter_eip;
|
||||||
@@ -2850,32 +2851,32 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
|||||||
svm->virt_spec_ctrl = data;
|
svm->virt_spec_ctrl = data;
|
||||||
break;
|
break;
|
||||||
case MSR_STAR:
|
case MSR_STAR:
|
||||||
svm->vmcb->save.star = data;
|
svm->vmcb01.ptr->save.star = data;
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
case MSR_LSTAR:
|
case MSR_LSTAR:
|
||||||
svm->vmcb->save.lstar = data;
|
svm->vmcb01.ptr->save.lstar = data;
|
||||||
break;
|
break;
|
||||||
case MSR_CSTAR:
|
case MSR_CSTAR:
|
||||||
svm->vmcb->save.cstar = data;
|
svm->vmcb01.ptr->save.cstar = data;
|
||||||
break;
|
break;
|
||||||
case MSR_KERNEL_GS_BASE:
|
case MSR_KERNEL_GS_BASE:
|
||||||
svm->vmcb->save.kernel_gs_base = data;
|
svm->vmcb01.ptr->save.kernel_gs_base = data;
|
||||||
break;
|
break;
|
||||||
case MSR_SYSCALL_MASK:
|
case MSR_SYSCALL_MASK:
|
||||||
svm->vmcb->save.sfmask = data;
|
svm->vmcb01.ptr->save.sfmask = data;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case MSR_IA32_SYSENTER_CS:
|
case MSR_IA32_SYSENTER_CS:
|
||||||
svm->vmcb->save.sysenter_cs = data;
|
svm->vmcb01.ptr->save.sysenter_cs = data;
|
||||||
break;
|
break;
|
||||||
case MSR_IA32_SYSENTER_EIP:
|
case MSR_IA32_SYSENTER_EIP:
|
||||||
svm->sysenter_eip = data;
|
svm->sysenter_eip = data;
|
||||||
svm->vmcb->save.sysenter_eip = data;
|
svm->vmcb01.ptr->save.sysenter_eip = data;
|
||||||
break;
|
break;
|
||||||
case MSR_IA32_SYSENTER_ESP:
|
case MSR_IA32_SYSENTER_ESP:
|
||||||
svm->sysenter_esp = data;
|
svm->sysenter_esp = data;
|
||||||
svm->vmcb->save.sysenter_esp = data;
|
svm->vmcb01.ptr->save.sysenter_esp = data;
|
||||||
break;
|
break;
|
||||||
case MSR_TSC_AUX:
|
case MSR_TSC_AUX:
|
||||||
if (!boot_cpu_has(X86_FEATURE_RDTSCP))
|
if (!boot_cpu_has(X86_FEATURE_RDTSCP))
|
||||||
@@ -3089,6 +3090,7 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
|
|||||||
struct vcpu_svm *svm = to_svm(vcpu);
|
struct vcpu_svm *svm = to_svm(vcpu);
|
||||||
struct vmcb_control_area *control = &svm->vmcb->control;
|
struct vmcb_control_area *control = &svm->vmcb->control;
|
||||||
struct vmcb_save_area *save = &svm->vmcb->save;
|
struct vmcb_save_area *save = &svm->vmcb->save;
|
||||||
|
struct vmcb_save_area *save01 = &svm->vmcb01.ptr->save;
|
||||||
|
|
||||||
if (!dump_invalid_vmcb) {
|
if (!dump_invalid_vmcb) {
|
||||||
pr_warn_ratelimited("set kvm_amd.dump_invalid_vmcb=1 to dump internal KVM state.\n");
|
pr_warn_ratelimited("set kvm_amd.dump_invalid_vmcb=1 to dump internal KVM state.\n");
|
||||||
@@ -3151,28 +3153,28 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
|
|||||||
save->ds.limit, save->ds.base);
|
save->ds.limit, save->ds.base);
|
||||||
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
||||||
"fs:",
|
"fs:",
|
||||||
save->fs.selector, save->fs.attrib,
|
save01->fs.selector, save01->fs.attrib,
|
||||||
save->fs.limit, save->fs.base);
|
save01->fs.limit, save01->fs.base);
|
||||||
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
||||||
"gs:",
|
"gs:",
|
||||||
save->gs.selector, save->gs.attrib,
|
save01->gs.selector, save01->gs.attrib,
|
||||||
save->gs.limit, save->gs.base);
|
save01->gs.limit, save01->gs.base);
|
||||||
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
||||||
"gdtr:",
|
"gdtr:",
|
||||||
save->gdtr.selector, save->gdtr.attrib,
|
save->gdtr.selector, save->gdtr.attrib,
|
||||||
save->gdtr.limit, save->gdtr.base);
|
save->gdtr.limit, save->gdtr.base);
|
||||||
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
||||||
"ldtr:",
|
"ldtr:",
|
||||||
save->ldtr.selector, save->ldtr.attrib,
|
save01->ldtr.selector, save01->ldtr.attrib,
|
||||||
save->ldtr.limit, save->ldtr.base);
|
save01->ldtr.limit, save01->ldtr.base);
|
||||||
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
||||||
"idtr:",
|
"idtr:",
|
||||||
save->idtr.selector, save->idtr.attrib,
|
save->idtr.selector, save->idtr.attrib,
|
||||||
save->idtr.limit, save->idtr.base);
|
save->idtr.limit, save->idtr.base);
|
||||||
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
|
||||||
"tr:",
|
"tr:",
|
||||||
save->tr.selector, save->tr.attrib,
|
save01->tr.selector, save01->tr.attrib,
|
||||||
save->tr.limit, save->tr.base);
|
save01->tr.limit, save01->tr.base);
|
||||||
pr_err("cpl: %d efer: %016llx\n",
|
pr_err("cpl: %d efer: %016llx\n",
|
||||||
save->cpl, save->efer);
|
save->cpl, save->efer);
|
||||||
pr_err("%-15s %016llx %-13s %016llx\n",
|
pr_err("%-15s %016llx %-13s %016llx\n",
|
||||||
@@ -3186,15 +3188,15 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
|
|||||||
pr_err("%-15s %016llx %-13s %016llx\n",
|
pr_err("%-15s %016llx %-13s %016llx\n",
|
||||||
"rsp:", save->rsp, "rax:", save->rax);
|
"rsp:", save->rsp, "rax:", save->rax);
|
||||||
pr_err("%-15s %016llx %-13s %016llx\n",
|
pr_err("%-15s %016llx %-13s %016llx\n",
|
||||||
"star:", save->star, "lstar:", save->lstar);
|
"star:", save01->star, "lstar:", save01->lstar);
|
||||||
pr_err("%-15s %016llx %-13s %016llx\n",
|
pr_err("%-15s %016llx %-13s %016llx\n",
|
||||||
"cstar:", save->cstar, "sfmask:", save->sfmask);
|
"cstar:", save01->cstar, "sfmask:", save01->sfmask);
|
||||||
pr_err("%-15s %016llx %-13s %016llx\n",
|
pr_err("%-15s %016llx %-13s %016llx\n",
|
||||||
"kernel_gs_base:", save->kernel_gs_base,
|
"kernel_gs_base:", save01->kernel_gs_base,
|
||||||
"sysenter_cs:", save->sysenter_cs);
|
"sysenter_cs:", save01->sysenter_cs);
|
||||||
pr_err("%-15s %016llx %-13s %016llx\n",
|
pr_err("%-15s %016llx %-13s %016llx\n",
|
||||||
"sysenter_esp:", save->sysenter_esp,
|
"sysenter_esp:", save01->sysenter_esp,
|
||||||
"sysenter_eip:", save->sysenter_eip);
|
"sysenter_eip:", save01->sysenter_eip);
|
||||||
pr_err("%-15s %016llx %-13s %016llx\n",
|
pr_err("%-15s %016llx %-13s %016llx\n",
|
||||||
"gpat:", save->g_pat, "dbgctl:", save->dbgctl);
|
"gpat:", save->g_pat, "dbgctl:", save->dbgctl);
|
||||||
pr_err("%-15s %016llx %-13s %016llx\n",
|
pr_err("%-15s %016llx %-13s %016llx\n",
|
||||||
@@ -3717,9 +3719,9 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu)
|
|||||||
} else {
|
} else {
|
||||||
struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
|
struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu);
|
||||||
|
|
||||||
vmload(svm->vmcb_pa);
|
vmload(svm->vmcb01.pa);
|
||||||
__svm_vcpu_run(svm->vmcb_pa, (unsigned long *)&vcpu->arch.regs);
|
__svm_vcpu_run(svm->vmcb_pa, (unsigned long *)&vcpu->arch.regs);
|
||||||
vmsave(svm->vmcb_pa);
|
vmsave(svm->vmcb01.pa);
|
||||||
|
|
||||||
vmload(__sme_page_pa(sd->save_area));
|
vmload(__sme_page_pa(sd->save_area));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user