On Tue, Nov 29, 2022, Maxim Levitsky wrote: > the V_IRQ and v_TPR bits don't exist when virtual interrupt > masking is not enabled, therefore the KVM should not copy these > bits regardless of V_IRQ intercept. Hmm, the APM disagrees: The APIC's TPR always controls the task priority for physical interrupts, and the V_TPR always controls virtual interrupts. While running a guest with V_INTR_MASKING cleared to 0: • Writes to CR8 affect both the APIC's TPR and the V_TPR register. ... The three VMCB fields V_IRQ, V_INTR_PRIO, and V_INTR_VECTOR indicate whether there is a virtual interrupt pending, and, if so, what its vector number and priority are. IIUC, V_INTR_MASKING_MASK is mostly about EFLAGS.IF, with a small side effect on TPR. E.g. a VMM could pend a V_IRQ but clear V_INTR_MASKING and expect the guest to take the V_IRQ. At least, that's my reading of things. > Signed-off-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx> > --- > arch/x86/kvm/svm/nested.c | 23 ++++++++--------------- > 1 file changed, 8 insertions(+), 15 deletions(-) > > diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c > index 37af0338da7c32..aad3145b2f62fe 100644 > --- a/arch/x86/kvm/svm/nested.c > +++ b/arch/x86/kvm/svm/nested.c > @@ -412,24 +412,17 @@ void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm, > */ > void nested_sync_control_from_vmcb02(struct vcpu_svm *svm) > { > - u32 mask; > + u32 mask = 0; > svm->nested.ctl.event_inj = svm->vmcb->control.event_inj; > svm->nested.ctl.event_inj_err = svm->vmcb->control.event_inj_err; > > - /* Only a few fields of int_ctl are written by the processor. */ > - mask = V_IRQ_MASK | V_TPR_MASK; > - if (!(svm->nested.ctl.int_ctl & V_INTR_MASKING_MASK) && > - svm_is_intercept(svm, INTERCEPT_VINTR)) { > - /* > - * In order to request an interrupt window, L0 is usurping > - * svm->vmcb->control.int_ctl and possibly setting V_IRQ > - * even if it was clear in L1's VMCB. Restoring it would be > - * wrong. However, in this case V_IRQ will remain true until > - * interrupt_window_interception calls svm_clear_vintr and > - * restores int_ctl. We can just leave it aside. > - */ > - mask &= ~V_IRQ_MASK; > - } > + /* > + * Only a few fields of int_ctl are written by the processor. > + * Copy back only the bits that are passed through to the L2. Just "L2", not "the L2". > + */ > + Unnecessary newline. > + if (svm->nested.ctl.int_ctl & V_INTR_MASKING_MASK) > + mask = V_IRQ_MASK | V_TPR_MASK; > > if (nested_vgif_enabled(svm)) > mask |= V_GIF_MASK; > -- > 2.26.3 >