Copy the LBRv2 state on nested VMRUN and #VMEXIT just like the legacy LBR state. If L1 enables V_LBR for L2, L2 has its own LBRv2 state in vmcb12. If L1 does not enable V_LBR, L2 uses the LBRv2 state of L1. Add svm_copy_lbrs_v2() macro to copy this state. Keep it separate from svm_copy_lbrs(), because the LBR stack is 256 bytes and KVM copies it only when LBRv2 is supported. Signed-off-by: Shivansh Dhiman --- Changes in v2: * New patch. --- arch/x86/kvm/svm/nested.c | 28 +++++++++++++++++++++++++++- arch/x86/kvm/svm/svm.h | 18 ++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index af0ef678433d..b356a091e320 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -608,6 +608,9 @@ static void __nested_copy_vmcb_save_to_cache(struct vmcb_save_area_cached *to, to->g_pat = from->g_pat; svm_copy_lbrs(to, from); + + if (kvm_cpu_cap_has(X86_FEATURE_AMD_LBR_V2)) + svm_copy_lbrs_v2(to, from); } void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm, @@ -819,8 +822,17 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm *svm) */ svm_copy_lbrs(&vmcb02->save, save); vmcb02->save.dbgctl &= svm_get_supported_debugctl(vcpu); + + if (guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_V2)) { + svm_copy_lbrs_v2(&vmcb02->save, save); + vmcb02->save.dbg_extn_cfg &= ~DBG_EXTN_CFG_RESERVED_BITS; + vmcb02->save.lbr_select &= ~LBR_SELECT_RESERVED_BITS; + } } else { svm_copy_lbrs(&vmcb02->save, &vmcb01->save); + + if (guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_V2)) + svm_copy_lbrs_v2(&vmcb02->save, &vmcb01->save); } vmcb_mark_dirty(vmcb02, VMCB_LBR); svm_update_lbrv(&svm->vcpu); @@ -1236,6 +1248,12 @@ void svm_copy_vmrun_state(struct kvm_vcpu *vcpu, struct vmcb_save_area *to_save, svm_copy_lbrs(to_save, from_save); to_save->dbgctl &= svm_get_supported_debugctl(vcpu); } + + if (kvm_cpu_cap_has(X86_FEATURE_AMD_LBR_V2)) { + svm_copy_lbrs_v2(to_save, from_save); + to_save->dbg_extn_cfg &= ~DBG_EXTN_CFG_RESERVED_BITS; + to_save->lbr_select &= ~LBR_SELECT_RESERVED_BITS; + } } void svm_copy_vmloadsave_state(struct vmcb *to_vmcb, struct vmcb *from_vmcb) @@ -1305,9 +1323,13 @@ static int nested_svm_vmexit_update_vmcb12(struct kvm_vcpu *vcpu) if (guest_cpu_cap_has(vcpu, X86_FEATURE_NRIPS)) vmcb12->control.next_rip = vmcb02->control.next_rip; - if (svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR) + if (svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR) { svm_copy_lbrs(&vmcb12->save, &vmcb02->save); + if (guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_V2)) + svm_copy_lbrs_v2(&vmcb12->save, &vmcb02->save); + } + vmcb12->control.event_inj = 0; vmcb12->control.event_inj_err = 0; vmcb12->control.int_ctl = svm->nested.ctl.int_ctl; @@ -1384,6 +1406,10 @@ void nested_svm_vmexit(struct vcpu_svm *svm) if (!(svm->nested.ctl.misc_ctl2 & SVM_MISC2_ENABLE_V_LBR)) { svm_copy_lbrs(&vmcb01->save, &vmcb02->save); + + if (guest_cpu_cap_has(vcpu, X86_FEATURE_AMD_LBR_V2)) + svm_copy_lbrs_v2(&vmcb01->save, &vmcb02->save); + vmcb_mark_dirty(vmcb01, VMCB_LBR); } diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 72f19053fb4c..01be2fc05d70 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -176,6 +176,12 @@ struct vmcb_save_area_cached { u64 br_to; u64 last_excp_from; u64 last_excp_to; + u64 dbg_extn_cfg; + struct { + u64 lbr_stack_from; + u64 lbr_stack_to; + } lbr[SVM_LBR_V2_STACK_SIZE]; + u64 lbr_select; }; struct vmcb_ctrl_area_cached { @@ -820,6 +826,18 @@ do { \ (to)->last_excp_to = (from)->last_excp_to; \ } while (0) +/* + * Kept separate from svm_copy_lbrs() as the branch record stack is 256 bytes, + * i.e. is only worth copying when LBR v2 is exposed to the guest. + */ +#define svm_copy_lbrs_v2(to, from) \ +do { \ + BUILD_BUG_ON(sizeof((to)->lbr) != sizeof((from)->lbr)); \ + (to)->dbg_extn_cfg = (from)->dbg_extn_cfg; \ + (to)->lbr_select = (from)->lbr_select; \ + memcpy((to)->lbr, (from)->lbr, sizeof((to)->lbr)); \ +} while (0) + void svm_vcpu_free_msrpm(void *msrpm); void svm_enable_lbrv(struct kvm_vcpu *vcpu); void svm_update_lbrv(struct kvm_vcpu *vcpu); -- 2.43.0