All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
@ 2022-11-18 10:31 Jan Beulich
  2022-11-18 12:31 ` Juergen Gross
                   ` (2 more replies)
  0 siblings, 3 replies; 30+ messages in thread
From: Jan Beulich @ 2022-11-18 10:31 UTC (permalink / raw)
  To: xen-devel; +Cc: Andrew Cooper, Wei Liu, Roger Pau Monné, Paul Durrant

Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
exposed a problem with the marking of the respective vector as
pending: For quite some time Linux has been checking whether any stale
ISR or IRR bits would still be set while preparing the LAPIC for use.
This check is now triggering on the upcall vector, as the registration,
at least for APs, happens before the LAPIC is actually enabled.

In software-disabled state an LAPIC would not accept any interrupt
requests and hence no IRR bit would newly become set while in this
state. As a result it is also wrong for us to mark the upcall vector as
having a pending request when the vLAPIC is in this state.

To compensate for the "enabled" check added to the assertion logic, add
logic to (conditionally) mark the upcall vector as having a request
pending at the time the LAPIC is being software-enabled by the guest.

Fixes: 7b5b8ca7dffd ("x86/upcall: inject a spurious event after setting upcall vector")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
Don't one or both of the Viridian uses of vlapic_set_irq() need similar
guarding?

Is it actually necessary for hvmop_set_evtchn_upcall_vector() and
hvm_set_callback_via() to call hvm_assert_evtchn_irq() when
evtchn_upcall_pending is false?

--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -321,9 +321,10 @@ void hvm_assert_evtchn_irq(struct vcpu *
 
     if ( v->arch.hvm.evtchn_upcall_vector != 0 )
     {
-        uint8_t vector = v->arch.hvm.evtchn_upcall_vector;
+        struct vlapic *vlapic = vcpu_vlapic(v);
 
-        vlapic_set_irq(vcpu_vlapic(v), vector, 0);
+        if ( vlapic_enabled(vlapic) )
+           vlapic_set_irq(vlapic, v->arch.hvm.evtchn_upcall_vector, 0);
     }
     else if ( is_hvm_pv_evtchn_domain(v->domain) )
         vcpu_kick(v);
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -829,6 +829,9 @@ void vlapic_reg_write(struct vcpu *v, un
         {
             vlapic->hw.disabled &= ~VLAPIC_SW_DISABLED;
             pt_may_unmask_irq(vlapic_domain(vlapic), &vlapic->pt);
+            if ( v->arch.hvm.evtchn_upcall_vector &&
+                 vcpu_info(v, evtchn_upcall_pending) )
+                vlapic_set_irq(vlapic, v->arch.hvm.evtchn_upcall_vector, 0);
         }
         break;
 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 10:31 [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled Jan Beulich
@ 2022-11-18 12:31 ` Juergen Gross
  2022-11-18 12:33 ` Andrew Cooper
  2022-11-18 14:26 ` Roger Pau Monné
  2 siblings, 0 replies; 30+ messages in thread
From: Juergen Gross @ 2022-11-18 12:31 UTC (permalink / raw)
  To: Jan Beulich, xen-devel
  Cc: Andrew Cooper, Wei Liu, Roger Pau Monné, Paul Durrant


[-- Attachment #1.1.1: Type: text/plain, Size: 1175 bytes --]

On 18.11.22 11:31, Jan Beulich wrote:
> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
> exposed a problem with the marking of the respective vector as
> pending: For quite some time Linux has been checking whether any stale
> ISR or IRR bits would still be set while preparing the LAPIC for use.
> This check is now triggering on the upcall vector, as the registration,
> at least for APs, happens before the LAPIC is actually enabled.
> 
> In software-disabled state an LAPIC would not accept any interrupt
> requests and hence no IRR bit would newly become set while in this
> state. As a result it is also wrong for us to mark the upcall vector as
> having a pending request when the vLAPIC is in this state.
> 
> To compensate for the "enabled" check added to the assertion logic, add
> logic to (conditionally) mark the upcall vector as having a request
> pending at the time the LAPIC is being software-enabled by the guest.
> 
> Fixes: 7b5b8ca7dffd ("x86/upcall: inject a spurious event after setting upcall vector")
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 10:31 [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled Jan Beulich
  2022-11-18 12:31 ` Juergen Gross
@ 2022-11-18 12:33 ` Andrew Cooper
  2022-11-18 12:51   ` Roger Pau Monné
  2022-11-18 12:54   ` Jan Beulich
  2022-11-18 14:26 ` Roger Pau Monné
  2 siblings, 2 replies; 30+ messages in thread
From: Andrew Cooper @ 2022-11-18 12:33 UTC (permalink / raw)
  To: Jan Beulich, xen-devel; +Cc: Wei Liu, Roger Pau Monne, Paul Durrant

On 18/11/2022 10:31, Jan Beulich wrote:
> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
> exposed a problem with the marking of the respective vector as
> pending: For quite some time Linux has been checking whether any stale
> ISR or IRR bits would still be set while preparing the LAPIC for use.
> This check is now triggering on the upcall vector, as the registration,
> at least for APs, happens before the LAPIC is actually enabled.
>
> In software-disabled state an LAPIC would not accept any interrupt
> requests and hence no IRR bit would newly become set while in this
> state. As a result it is also wrong for us to mark the upcall vector as
> having a pending request when the vLAPIC is in this state.

I agree with this.

> To compensate for the "enabled" check added to the assertion logic, add
> logic to (conditionally) mark the upcall vector as having a request
> pending at the time the LAPIC is being software-enabled by the guest.

But this, I don't think is appropriate.

The point of raising on enable is allegedly to work around setup race
conditions.  I'm unconvinced by this reasoning, but it is what it is,
and the stated behaviour is to raise there and then.

If a guest enables evtchn while the LAPIC is disabled, then the
interrupt is lost.  Like every other interrupt in an x86 system.

I don't think there is any credible way a guest kernel author can expect
the weird evtchn edgecase to wait for an arbitrary point in the future,
and it's a corner case that I think is worth not keeping.

~Andrew

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 12:33 ` Andrew Cooper
@ 2022-11-18 12:51   ` Roger Pau Monné
  2022-11-18 12:54   ` Jan Beulich
  1 sibling, 0 replies; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-18 12:51 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Jan Beulich, xen-devel, Wei Liu, Paul Durrant

On Fri, Nov 18, 2022 at 12:33:00PM +0000, Andrew Cooper wrote:
> On 18/11/2022 10:31, Jan Beulich wrote:
> > Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
> > exposed a problem with the marking of the respective vector as
> > pending: For quite some time Linux has been checking whether any stale
> > ISR or IRR bits would still be set while preparing the LAPIC for use.
> > This check is now triggering on the upcall vector, as the registration,
> > at least for APs, happens before the LAPIC is actually enabled.
> >
> > In software-disabled state an LAPIC would not accept any interrupt
> > requests and hence no IRR bit would newly become set while in this
> > state. As a result it is also wrong for us to mark the upcall vector as
> > having a pending request when the vLAPIC is in this state.
> 
> I agree with this.
> 
> > To compensate for the "enabled" check added to the assertion logic, add
> > logic to (conditionally) mark the upcall vector as having a request
> > pending at the time the LAPIC is being software-enabled by the guest.
> 
> But this, I don't think is appropriate.
> 
> The point of raising on enable is allegedly to work around setup race
> conditions.  I'm unconvinced by this reasoning, but it is what it is,
> and the stated behaviour is to raise there and then.
> 
> If a guest enables evtchn while the LAPIC is disabled, then the
> interrupt is lost.  Like every other interrupt in an x86 system.
> 
> I don't think there is any credible way a guest kernel author can expect
> the weird evtchn edgecase to wait for an arbitrary point in the future,
> and it's a corner case that I think is worth not keeping.

We would then need some kind of fix in order to clear
evtchn_upcall_pending, because having that set without an interrupt
pending on the vLAPIC will result in no further event channel callback
interrupts being injected (see vcpu_mark_events_pending()).

Maybe we want to change vcpu_mark_events_pending() so that it always
tries to inject the vector even if evtchn_upcall_pending is already
set by calling hvm_assert_evtchn_irq() unconditionally?

Thanks, Roger.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 12:33 ` Andrew Cooper
  2022-11-18 12:51   ` Roger Pau Monné
@ 2022-11-18 12:54   ` Jan Beulich
  2022-11-18 13:55     ` Roger Pau Monné
  2022-11-18 14:27     ` Andrew Cooper
  1 sibling, 2 replies; 30+ messages in thread
From: Jan Beulich @ 2022-11-18 12:54 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Wei Liu, Roger Pau Monne, Paul Durrant, xen-devel

On 18.11.2022 13:33, Andrew Cooper wrote:
> On 18/11/2022 10:31, Jan Beulich wrote:
>> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
>> exposed a problem with the marking of the respective vector as
>> pending: For quite some time Linux has been checking whether any stale
>> ISR or IRR bits would still be set while preparing the LAPIC for use.
>> This check is now triggering on the upcall vector, as the registration,
>> at least for APs, happens before the LAPIC is actually enabled.
>>
>> In software-disabled state an LAPIC would not accept any interrupt
>> requests and hence no IRR bit would newly become set while in this
>> state. As a result it is also wrong for us to mark the upcall vector as
>> having a pending request when the vLAPIC is in this state.
> 
> I agree with this.
> 
>> To compensate for the "enabled" check added to the assertion logic, add
>> logic to (conditionally) mark the upcall vector as having a request
>> pending at the time the LAPIC is being software-enabled by the guest.
> 
> But this, I don't think is appropriate.
> 
> The point of raising on enable is allegedly to work around setup race
> conditions.  I'm unconvinced by this reasoning, but it is what it is,
> and the stated behaviour is to raise there and then.
> 
> If a guest enables evtchn while the LAPIC is disabled, then the
> interrupt is lost.  Like every other interrupt in an x86 system.

Edge triggered ones you mean, I suppose, but yes.

> I don't think there is any credible way a guest kernel author can expect
> the weird evtchn edgecase to wait for an arbitrary point in the future,
> and it's a corner case that I think is worth not keeping.

Well - did you look at 7b5b8ca7dffd ("x86/upcall: inject a spurious event
after setting upcall vector"), referenced by the Fixes: tag? The issue is
that with evtchn_upcall_pending once set, there would never again be a
notification. So if what you say is to be the model we follow, then that
earlier change was perhaps wrong as well. Instead it should then have
been a guest change (as also implicit from your reply) to clear
evtchn_upcall_pending after vCPU info registration (there) or LAPIC
enabling (here), perhaps by way of "manually" invoking the handling of
that pending event, or by issuing a self-IPI with that vector.
Especially the LAPIC enabling case would then be yet another Xen-specific
on a guest code path which better wouldn't have to be aware of Xen.

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 12:54   ` Jan Beulich
@ 2022-11-18 13:55     ` Roger Pau Monné
  2022-11-18 13:58       ` Jan Beulich
  2022-11-18 14:27     ` Andrew Cooper
  1 sibling, 1 reply; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-18 13:55 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On Fri, Nov 18, 2022 at 01:54:33PM +0100, Jan Beulich wrote:
> On 18.11.2022 13:33, Andrew Cooper wrote:
> > On 18/11/2022 10:31, Jan Beulich wrote:
> >> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
> >> exposed a problem with the marking of the respective vector as
> >> pending: For quite some time Linux has been checking whether any stale
> >> ISR or IRR bits would still be set while preparing the LAPIC for use.
> >> This check is now triggering on the upcall vector, as the registration,
> >> at least for APs, happens before the LAPIC is actually enabled.
> >>
> >> In software-disabled state an LAPIC would not accept any interrupt
> >> requests and hence no IRR bit would newly become set while in this
> >> state. As a result it is also wrong for us to mark the upcall vector as
> >> having a pending request when the vLAPIC is in this state.
> > 
> > I agree with this.
> > 
> >> To compensate for the "enabled" check added to the assertion logic, add
> >> logic to (conditionally) mark the upcall vector as having a request
> >> pending at the time the LAPIC is being software-enabled by the guest.
> > 
> > But this, I don't think is appropriate.
> > 
> > The point of raising on enable is allegedly to work around setup race
> > conditions.  I'm unconvinced by this reasoning, but it is what it is,
> > and the stated behaviour is to raise there and then.
> > 
> > If a guest enables evtchn while the LAPIC is disabled, then the
> > interrupt is lost.  Like every other interrupt in an x86 system.
> 
> Edge triggered ones you mean, I suppose, but yes.
> 
> > I don't think there is any credible way a guest kernel author can expect
> > the weird evtchn edgecase to wait for an arbitrary point in the future,
> > and it's a corner case that I think is worth not keeping.
> 
> Well - did you look at 7b5b8ca7dffd ("x86/upcall: inject a spurious event
> after setting upcall vector"), referenced by the Fixes: tag? The issue is
> that with evtchn_upcall_pending once set, there would never again be a
> notification. So if what you say is to be the model we follow, then that
> earlier change was perhaps wrong as well. Instead it should then have
> been a guest change (as also implicit from your reply) to clear
> evtchn_upcall_pending after vCPU info registration (there) or LAPIC
> enabling (here), perhaps by way of "manually" invoking the handling of
> that pending event, or by issuing a self-IPI with that vector.
> Especially the LAPIC enabling case would then be yet another Xen-specific
> on a guest code path which better wouldn't have to be aware of Xen.

Another option might be to clear evtchn_upcall_pending once the vLAPIC
is enabled, so that further setting of evtchn_upcall_pending will
inject the vector.  I'm worried however whether that could break
existing users, as this would be an interface behavior change.

Thanks, Roger.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 13:55     ` Roger Pau Monné
@ 2022-11-18 13:58       ` Jan Beulich
  2022-11-18 14:09         ` Roger Pau Monné
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2022-11-18 13:58 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On 18.11.2022 14:55, Roger Pau Monné wrote:
> On Fri, Nov 18, 2022 at 01:54:33PM +0100, Jan Beulich wrote:
>> On 18.11.2022 13:33, Andrew Cooper wrote:
>>> On 18/11/2022 10:31, Jan Beulich wrote:
>>>> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
>>>> exposed a problem with the marking of the respective vector as
>>>> pending: For quite some time Linux has been checking whether any stale
>>>> ISR or IRR bits would still be set while preparing the LAPIC for use.
>>>> This check is now triggering on the upcall vector, as the registration,
>>>> at least for APs, happens before the LAPIC is actually enabled.
>>>>
>>>> In software-disabled state an LAPIC would not accept any interrupt
>>>> requests and hence no IRR bit would newly become set while in this
>>>> state. As a result it is also wrong for us to mark the upcall vector as
>>>> having a pending request when the vLAPIC is in this state.
>>>
>>> I agree with this.
>>>
>>>> To compensate for the "enabled" check added to the assertion logic, add
>>>> logic to (conditionally) mark the upcall vector as having a request
>>>> pending at the time the LAPIC is being software-enabled by the guest.
>>>
>>> But this, I don't think is appropriate.
>>>
>>> The point of raising on enable is allegedly to work around setup race
>>> conditions.  I'm unconvinced by this reasoning, but it is what it is,
>>> and the stated behaviour is to raise there and then.
>>>
>>> If a guest enables evtchn while the LAPIC is disabled, then the
>>> interrupt is lost.  Like every other interrupt in an x86 system.
>>
>> Edge triggered ones you mean, I suppose, but yes.
>>
>>> I don't think there is any credible way a guest kernel author can expect
>>> the weird evtchn edgecase to wait for an arbitrary point in the future,
>>> and it's a corner case that I think is worth not keeping.
>>
>> Well - did you look at 7b5b8ca7dffd ("x86/upcall: inject a spurious event
>> after setting upcall vector"), referenced by the Fixes: tag? The issue is
>> that with evtchn_upcall_pending once set, there would never again be a
>> notification. So if what you say is to be the model we follow, then that
>> earlier change was perhaps wrong as well. Instead it should then have
>> been a guest change (as also implicit from your reply) to clear
>> evtchn_upcall_pending after vCPU info registration (there) or LAPIC
>> enabling (here), perhaps by way of "manually" invoking the handling of
>> that pending event, or by issuing a self-IPI with that vector.
>> Especially the LAPIC enabling case would then be yet another Xen-specific
>> on a guest code path which better wouldn't have to be aware of Xen.
> 
> Another option might be to clear evtchn_upcall_pending once the vLAPIC
> is enabled, so that further setting of evtchn_upcall_pending will
> inject the vector.  I'm worried however whether that could break
> existing users, as this would be an interface behavior change.

You mean _Xen_ clearing the flag? No, that breaks firmly documented
behavior. Xen only ever sets this field.

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 13:58       ` Jan Beulich
@ 2022-11-18 14:09         ` Roger Pau Monné
  0 siblings, 0 replies; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-18 14:09 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On Fri, Nov 18, 2022 at 02:58:10PM +0100, Jan Beulich wrote:
> On 18.11.2022 14:55, Roger Pau Monné wrote:
> > On Fri, Nov 18, 2022 at 01:54:33PM +0100, Jan Beulich wrote:
> >> On 18.11.2022 13:33, Andrew Cooper wrote:
> >>> On 18/11/2022 10:31, Jan Beulich wrote:
> >>>> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
> >>>> exposed a problem with the marking of the respective vector as
> >>>> pending: For quite some time Linux has been checking whether any stale
> >>>> ISR or IRR bits would still be set while preparing the LAPIC for use.
> >>>> This check is now triggering on the upcall vector, as the registration,
> >>>> at least for APs, happens before the LAPIC is actually enabled.
> >>>>
> >>>> In software-disabled state an LAPIC would not accept any interrupt
> >>>> requests and hence no IRR bit would newly become set while in this
> >>>> state. As a result it is also wrong for us to mark the upcall vector as
> >>>> having a pending request when the vLAPIC is in this state.
> >>>
> >>> I agree with this.
> >>>
> >>>> To compensate for the "enabled" check added to the assertion logic, add
> >>>> logic to (conditionally) mark the upcall vector as having a request
> >>>> pending at the time the LAPIC is being software-enabled by the guest.
> >>>
> >>> But this, I don't think is appropriate.
> >>>
> >>> The point of raising on enable is allegedly to work around setup race
> >>> conditions.  I'm unconvinced by this reasoning, but it is what it is,
> >>> and the stated behaviour is to raise there and then.
> >>>
> >>> If a guest enables evtchn while the LAPIC is disabled, then the
> >>> interrupt is lost.  Like every other interrupt in an x86 system.
> >>
> >> Edge triggered ones you mean, I suppose, but yes.
> >>
> >>> I don't think there is any credible way a guest kernel author can expect
> >>> the weird evtchn edgecase to wait for an arbitrary point in the future,
> >>> and it's a corner case that I think is worth not keeping.
> >>
> >> Well - did you look at 7b5b8ca7dffd ("x86/upcall: inject a spurious event
> >> after setting upcall vector"), referenced by the Fixes: tag? The issue is
> >> that with evtchn_upcall_pending once set, there would never again be a
> >> notification. So if what you say is to be the model we follow, then that
> >> earlier change was perhaps wrong as well. Instead it should then have
> >> been a guest change (as also implicit from your reply) to clear
> >> evtchn_upcall_pending after vCPU info registration (there) or LAPIC
> >> enabling (here), perhaps by way of "manually" invoking the handling of
> >> that pending event, or by issuing a self-IPI with that vector.
> >> Especially the LAPIC enabling case would then be yet another Xen-specific
> >> on a guest code path which better wouldn't have to be aware of Xen.
> > 
> > Another option might be to clear evtchn_upcall_pending once the vLAPIC
> > is enabled, so that further setting of evtchn_upcall_pending will
> > inject the vector.  I'm worried however whether that could break
> > existing users, as this would be an interface behavior change.
> 
> You mean _Xen_ clearing the flag? No, that breaks firmly documented
> behavior. Xen only ever sets this field.

So the only other option would be for Xen to ignore
evtchn_upcall_pending and always inject the interrupt in
vcpu_mark_events_pending(), but that would then lead to spurious
interrupts if an event channel triggers while the pending upcall
vector is still set in the ISR and evtchn_upcall_pending has already
been cleared.

Thanks, Roger.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 10:31 [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled Jan Beulich
  2022-11-18 12:31 ` Juergen Gross
  2022-11-18 12:33 ` Andrew Cooper
@ 2022-11-18 14:26 ` Roger Pau Monné
  2022-11-21  8:33   ` Jan Beulich
  2 siblings, 1 reply; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-18 14:26 UTC (permalink / raw)
  To: Jan Beulich; +Cc: xen-devel, Andrew Cooper, Wei Liu, Paul Durrant

On Fri, Nov 18, 2022 at 11:31:28AM +0100, Jan Beulich wrote:
> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
> exposed a problem with the marking of the respective vector as
> pending: For quite some time Linux has been checking whether any stale
> ISR or IRR bits would still be set while preparing the LAPIC for use.
> This check is now triggering on the upcall vector, as the registration,
> at least for APs, happens before the LAPIC is actually enabled.
> 
> In software-disabled state an LAPIC would not accept any interrupt
> requests and hence no IRR bit would newly become set while in this
> state. As a result it is also wrong for us to mark the upcall vector as
> having a pending request when the vLAPIC is in this state.
> 
> To compensate for the "enabled" check added to the assertion logic, add
> logic to (conditionally) mark the upcall vector as having a request
> pending at the time the LAPIC is being software-enabled by the guest.
> 
> Fixes: 7b5b8ca7dffd ("x86/upcall: inject a spurious event after setting upcall vector")
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> ---
> Don't one or both of the Viridian uses of vlapic_set_irq() need similar
> guarding?
> 
> Is it actually necessary for hvmop_set_evtchn_upcall_vector() and
> hvm_set_callback_via() to call hvm_assert_evtchn_irq() when
> evtchn_upcall_pending is false?
> 
> --- a/xen/arch/x86/hvm/irq.c
> +++ b/xen/arch/x86/hvm/irq.c
> @@ -321,9 +321,10 @@ void hvm_assert_evtchn_irq(struct vcpu *
>  
>      if ( v->arch.hvm.evtchn_upcall_vector != 0 )
>      {
> -        uint8_t vector = v->arch.hvm.evtchn_upcall_vector;
> +        struct vlapic *vlapic = vcpu_vlapic(v);
>  
> -        vlapic_set_irq(vcpu_vlapic(v), vector, 0);
> +        if ( vlapic_enabled(vlapic) )
> +           vlapic_set_irq(vlapic, v->arch.hvm.evtchn_upcall_vector, 0);

Shouldn't the vlapic_enabled() check itself be in vlapic_set_irq()? We
certainly don't want any vectors set until the vlapic is enabled, be
it event channel upcalls or any other sources.

Maybe best to add an ASSERT in vlapic_set_irq() to be sure the lapic is
enabled, as other callers already check this before trying to inject?

Also, and not strictly related to your change, isn't this possibly
racy, as by the time you evaluate the return of vlapic_enabled() it is
already stale, as there's no lock to protect it from changing?

Thanks, Roger.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 12:54   ` Jan Beulich
  2022-11-18 13:55     ` Roger Pau Monné
@ 2022-11-18 14:27     ` Andrew Cooper
  2022-11-21  8:56       ` Jan Beulich
  1 sibling, 1 reply; 30+ messages in thread
From: Andrew Cooper @ 2022-11-18 14:27 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Wei Liu, Roger Pau Monne, Paul Durrant, xen-devel

On 18/11/2022 12:54, Jan Beulich wrote:
> On 18.11.2022 13:33, Andrew Cooper wrote:
>> On 18/11/2022 10:31, Jan Beulich wrote:
>>> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
>>> exposed a problem with the marking of the respective vector as
>>> pending: For quite some time Linux has been checking whether any stale
>>> ISR or IRR bits would still be set while preparing the LAPIC for use.
>>> This check is now triggering on the upcall vector, as the registration,
>>> at least for APs, happens before the LAPIC is actually enabled.
>>>
>>> In software-disabled state an LAPIC would not accept any interrupt
>>> requests and hence no IRR bit would newly become set while in this
>>> state. As a result it is also wrong for us to mark the upcall vector as
>>> having a pending request when the vLAPIC is in this state.
>> I agree with this.
>>
>>> To compensate for the "enabled" check added to the assertion logic, add
>>> logic to (conditionally) mark the upcall vector as having a request
>>> pending at the time the LAPIC is being software-enabled by the guest.
>> But this, I don't think is appropriate.
>>
>> The point of raising on enable is allegedly to work around setup race
>> conditions.  I'm unconvinced by this reasoning, but it is what it is,
>> and the stated behaviour is to raise there and then.
>>
>> If a guest enables evtchn while the LAPIC is disabled, then the
>> interrupt is lost.  Like every other interrupt in an x86 system.
> Edge triggered ones you mean, I suppose, but yes.

For IO-APIC systems, you mostly lose line interrupts too, don't you?

The line will remain pending at the IO-APIC, but nothing in the system
will unwedge until someone polls the IO-APIC.

Either way...

>
>> I don't think there is any credible way a guest kernel author can expect
>> the weird evtchn edgecase to wait for an arbitrary point in the future,
>> and it's a corner case that I think is worth not keeping.
> Well - did you look at 7b5b8ca7dffd ("x86/upcall: inject a spurious event
> after setting upcall vector"), referenced by the Fixes: tag? The issue is
> that with evtchn_upcall_pending once set, there would never again be a
> notification.

Ok, so we do need to do something.

>  So if what you say is to be the model we follow, then that
> earlier change was perhaps wrong as well. Instead it should then have
> been a guest change (as also implicit from your reply) to clear
> evtchn_upcall_pending after vCPU info registration (there) or LAPIC
> enabling (here), perhaps by way of "manually" invoking the handling of
> that pending event, or by issuing a self-IPI with that vector.
> Especially the LAPIC enabling case would then be yet another Xen-specific
> on a guest code path which better wouldn't have to be aware of Xen. 

Without trying to prescribe how to fix this specific issue, wherever
possible we should be trying to limit the Xen-isms from non-Xen areas. 
There's a whole lot of poorly described and surprising behaviours which
have not stood the test of time.

In this case, it seems that we have yet another x86 PV-ism which hasn't
translated well x86 HVM.  Specifically, we're trying to overlay an
entirely shared-memory (and delayed return-to-guest) interrupt
controller onto one which is properly constructed to handle events in
realtime.


I even got as far as writing that maybe leaving it as-is was the best
option (principle of least surprise for Xen developers), but our
"friend" apic acceleration strikes again.

Xen doesn't always get a VMExit when the guest clears SW_DISABLE,
because microcode may have accelerated it.

A consequence of this observation is that Xen cannot have
non-LAPIC-archtiectural behaviour in the vlapic emulation.  So I think
we need to find a solution to this problem that doesn't hook APIC_SPIV.

~Andrew

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 14:26 ` Roger Pau Monné
@ 2022-11-21  8:33   ` Jan Beulich
  2022-11-21 10:53     ` Roger Pau Monné
  2022-11-21 12:06     ` Jan Beulich
  0 siblings, 2 replies; 30+ messages in thread
From: Jan Beulich @ 2022-11-21  8:33 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Andrew Cooper, Wei Liu, Paul Durrant

On 18.11.2022 15:26, Roger Pau Monné wrote:
> On Fri, Nov 18, 2022 at 11:31:28AM +0100, Jan Beulich wrote:
>> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
>> exposed a problem with the marking of the respective vector as
>> pending: For quite some time Linux has been checking whether any stale
>> ISR or IRR bits would still be set while preparing the LAPIC for use.
>> This check is now triggering on the upcall vector, as the registration,
>> at least for APs, happens before the LAPIC is actually enabled.
>>
>> In software-disabled state an LAPIC would not accept any interrupt
>> requests and hence no IRR bit would newly become set while in this
>> state. As a result it is also wrong for us to mark the upcall vector as
>> having a pending request when the vLAPIC is in this state.
>>
>> To compensate for the "enabled" check added to the assertion logic, add
>> logic to (conditionally) mark the upcall vector as having a request
>> pending at the time the LAPIC is being software-enabled by the guest.
>>
>> Fixes: 7b5b8ca7dffd ("x86/upcall: inject a spurious event after setting upcall vector")
>> Signed-off-by: Jan Beulich <jbeulich@suse.com>
>> ---
>> Don't one or both of the Viridian uses of vlapic_set_irq() need similar
>> guarding?
>>
>> Is it actually necessary for hvmop_set_evtchn_upcall_vector() and
>> hvm_set_callback_via() to call hvm_assert_evtchn_irq() when
>> evtchn_upcall_pending is false?
>>
>> --- a/xen/arch/x86/hvm/irq.c
>> +++ b/xen/arch/x86/hvm/irq.c
>> @@ -321,9 +321,10 @@ void hvm_assert_evtchn_irq(struct vcpu *
>>  
>>      if ( v->arch.hvm.evtchn_upcall_vector != 0 )
>>      {
>> -        uint8_t vector = v->arch.hvm.evtchn_upcall_vector;
>> +        struct vlapic *vlapic = vcpu_vlapic(v);
>>  
>> -        vlapic_set_irq(vcpu_vlapic(v), vector, 0);
>> +        if ( vlapic_enabled(vlapic) )
>> +           vlapic_set_irq(vlapic, v->arch.hvm.evtchn_upcall_vector, 0);
> 
> Shouldn't the vlapic_enabled() check itself be in vlapic_set_irq()? We
> certainly don't want any vectors set until the vlapic is enabled, be
> it event channel upcalls or any other sources.

In principle yes, and I did consider doing so, but for several callers
(potentially used frequently) this would be redundant with other
checking they do already (first and foremost callers using
vlapic_lowest_prio()). However, looking again I think vioapic_deliver()
and vmsi_deliver() violate this as well in their dest_Fixed handling.
(In both cases I'm actually inclined to also remove the odd *_inj_irq()
helper functions.)

> Maybe best to add an ASSERT in vlapic_set_irq() to be sure the lapic is
> enabled, as other callers already check this before trying to inject?

Perhaps, yes (once we've fixed paths where the check is presently
missing).

> Also, and not strictly related to your change, isn't this possibly
> racy, as by the time you evaluate the return of vlapic_enabled() it is
> already stale, as there's no lock to protect it from changing?

Wouldn't this simply match a signal arriving to a physical LAPIC just
the moment before it is enabled?

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-18 14:27     ` Andrew Cooper
@ 2022-11-21  8:56       ` Jan Beulich
  2022-11-21 12:23         ` Andrew Cooper
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2022-11-21  8:56 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Wei Liu, Roger Pau Monne, Paul Durrant, xen-devel

On 18.11.2022 15:27, Andrew Cooper wrote:
> On 18/11/2022 12:54, Jan Beulich wrote:
>> On 18.11.2022 13:33, Andrew Cooper wrote:
>>> On 18/11/2022 10:31, Jan Beulich wrote:
>>>> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
>>>> exposed a problem with the marking of the respective vector as
>>>> pending: For quite some time Linux has been checking whether any stale
>>>> ISR or IRR bits would still be set while preparing the LAPIC for use.
>>>> This check is now triggering on the upcall vector, as the registration,
>>>> at least for APs, happens before the LAPIC is actually enabled.
>>>>
>>>> In software-disabled state an LAPIC would not accept any interrupt
>>>> requests and hence no IRR bit would newly become set while in this
>>>> state. As a result it is also wrong for us to mark the upcall vector as
>>>> having a pending request when the vLAPIC is in this state.
>>> I agree with this.
>>>
>>>> To compensate for the "enabled" check added to the assertion logic, add
>>>> logic to (conditionally) mark the upcall vector as having a request
>>>> pending at the time the LAPIC is being software-enabled by the guest.
>>> But this, I don't think is appropriate.
>>>
>>> The point of raising on enable is allegedly to work around setup race
>>> conditions.  I'm unconvinced by this reasoning, but it is what it is,
>>> and the stated behaviour is to raise there and then.
>>>
>>> If a guest enables evtchn while the LAPIC is disabled, then the
>>> interrupt is lost.  Like every other interrupt in an x86 system.
>> Edge triggered ones you mean, I suppose, but yes.
> 
> For IO-APIC systems, you mostly lose line interrupts too, don't you?
> 
> The line will remain pending at the IO-APIC, but nothing in the system
> will unwedge until someone polls the IO-APIC.
> 
> Either way...
> 
>>
>>> I don't think there is any credible way a guest kernel author can expect
>>> the weird evtchn edgecase to wait for an arbitrary point in the future,
>>> and it's a corner case that I think is worth not keeping.
>> Well - did you look at 7b5b8ca7dffd ("x86/upcall: inject a spurious event
>> after setting upcall vector"), referenced by the Fixes: tag? The issue is
>> that with evtchn_upcall_pending once set, there would never again be a
>> notification.
> 
> Ok, so we do need to do something.
> 
>>  So if what you say is to be the model we follow, then that
>> earlier change was perhaps wrong as well. Instead it should then have
>> been a guest change (as also implicit from your reply) to clear
>> evtchn_upcall_pending after vCPU info registration (there) or LAPIC
>> enabling (here), perhaps by way of "manually" invoking the handling of
>> that pending event, or by issuing a self-IPI with that vector.
>> Especially the LAPIC enabling case would then be yet another Xen-specific
>> on a guest code path which better wouldn't have to be aware of Xen. 
> 
> Without trying to prescribe how to fix this specific issue, wherever
> possible we should be trying to limit the Xen-isms from non-Xen areas. 
> There's a whole lot of poorly described and surprising behaviours which
> have not stood the test of time.
> 
> In this case, it seems that we have yet another x86 PV-ism which hasn't
> translated well x86 HVM.  Specifically, we're trying to overlay an
> entirely shared-memory (and delayed return-to-guest) interrupt
> controller onto one which is properly constructed to handle events in
> realtime.
> 
> 
> I even got as far as writing that maybe leaving it as-is was the best
> option (principle of least surprise for Xen developers), but our
> "friend" apic acceleration strikes again.
> 
> Xen doesn't always get a VMExit when the guest clears SW_DISABLE,
> because microcode may have accelerated it.

But as per "APIC-Write Emulation" in the SDM we'd still get an APIC-write
VM exit. If we didn't, how would our internal accounting of APIC enabled
state (VLAPIC_SW_DISABLED) work? And the neighboring (to where I'm adding
the new code) pt_may_unmask_irq() call then also wouldn't occur.

I'm actually pretty sure we do too much in this case - in particular none
of the vlapic_set_reg() should be necessary. But we certainly can't get
away with doing nothing, and hence we depend on that VM exit to actually
occur. Plus simply making the vlapic_set_reg() conditional also likely
wouldn't do any good, so if anything we may want to split
vlapic_reg_write() and invoke only the "2nd half" from
vlapic_apicv_write().

Jan

> A consequence of this observation is that Xen cannot have
> non-LAPIC-archtiectural behaviour in the vlapic emulation.  So I think
> we need to find a solution to this problem that doesn't hook APIC_SPIV.
> 
> ~Andrew



^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-21  8:33   ` Jan Beulich
@ 2022-11-21 10:53     ` Roger Pau Monné
  2022-11-21 11:14       ` Jan Beulich
  2022-11-21 12:06     ` Jan Beulich
  1 sibling, 1 reply; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-21 10:53 UTC (permalink / raw)
  To: Jan Beulich; +Cc: xen-devel, Andrew Cooper, Wei Liu, Paul Durrant

On Mon, Nov 21, 2022 at 09:33:53AM +0100, Jan Beulich wrote:
> On 18.11.2022 15:26, Roger Pau Monné wrote:
> > On Fri, Nov 18, 2022 at 11:31:28AM +0100, Jan Beulich wrote:
> >> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
> >> exposed a problem with the marking of the respective vector as
> >> pending: For quite some time Linux has been checking whether any stale
> >> ISR or IRR bits would still be set while preparing the LAPIC for use.
> >> This check is now triggering on the upcall vector, as the registration,
> >> at least for APs, happens before the LAPIC is actually enabled.
> >>
> >> In software-disabled state an LAPIC would not accept any interrupt
> >> requests and hence no IRR bit would newly become set while in this
> >> state. As a result it is also wrong for us to mark the upcall vector as
> >> having a pending request when the vLAPIC is in this state.
> >>
> >> To compensate for the "enabled" check added to the assertion logic, add
> >> logic to (conditionally) mark the upcall vector as having a request
> >> pending at the time the LAPIC is being software-enabled by the guest.
> >>
> >> Fixes: 7b5b8ca7dffd ("x86/upcall: inject a spurious event after setting upcall vector")
> >> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> >> ---
> >> Don't one or both of the Viridian uses of vlapic_set_irq() need similar
> >> guarding?
> >>
> >> Is it actually necessary for hvmop_set_evtchn_upcall_vector() and
> >> hvm_set_callback_via() to call hvm_assert_evtchn_irq() when
> >> evtchn_upcall_pending is false?
> >>
> >> --- a/xen/arch/x86/hvm/irq.c
> >> +++ b/xen/arch/x86/hvm/irq.c
> >> @@ -321,9 +321,10 @@ void hvm_assert_evtchn_irq(struct vcpu *
> >>  
> >>      if ( v->arch.hvm.evtchn_upcall_vector != 0 )
> >>      {
> >> -        uint8_t vector = v->arch.hvm.evtchn_upcall_vector;
> >> +        struct vlapic *vlapic = vcpu_vlapic(v);
> >>  
> >> -        vlapic_set_irq(vcpu_vlapic(v), vector, 0);
> >> +        if ( vlapic_enabled(vlapic) )
> >> +           vlapic_set_irq(vlapic, v->arch.hvm.evtchn_upcall_vector, 0);
> > 
> > Shouldn't the vlapic_enabled() check itself be in vlapic_set_irq()? We
> > certainly don't want any vectors set until the vlapic is enabled, be
> > it event channel upcalls or any other sources.
> 
> In principle yes, and I did consider doing so, but for several callers
> (potentially used frequently) this would be redundant with other
> checking they do already (first and foremost callers using
> vlapic_lowest_prio()). However, looking again I think vioapic_deliver()
> and vmsi_deliver() violate this as well in their dest_Fixed handling.
> (In both cases I'm actually inclined to also remove the odd *_inj_irq()
> helper functions.)
> 
> > Maybe best to add an ASSERT in vlapic_set_irq() to be sure the lapic is
> > enabled, as other callers already check this before trying to inject?
> 
> Perhaps, yes (once we've fixed paths where the check is presently
> missing).

Another option would be to unconditionally return 0 for IRR and ISR
reads when the LAPIC is disabled, that would avoid having to force the
event channel injection when the LAPIC is enabled, but there could be
more than just the event channel vector queued in that way which would
be against the spec.

> > Also, and not strictly related to your change, isn't this possibly
> > racy, as by the time you evaluate the return of vlapic_enabled() it is
> > already stale, as there's no lock to protect it from changing?
> 
> Wouldn't this simply match a signal arriving to a physical LAPIC just
> the moment before it is enabled?

Hm, yes, any guest trying to play this kind of games with the APIC is
free to keep the pieces.

Thanks, Roger.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-21 10:53     ` Roger Pau Monné
@ 2022-11-21 11:14       ` Jan Beulich
  0 siblings, 0 replies; 30+ messages in thread
From: Jan Beulich @ 2022-11-21 11:14 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Andrew Cooper, Wei Liu, Paul Durrant

On 21.11.2022 11:53, Roger Pau Monné wrote:
> On Mon, Nov 21, 2022 at 09:33:53AM +0100, Jan Beulich wrote:
>> On 18.11.2022 15:26, Roger Pau Monné wrote:
>>> Maybe best to add an ASSERT in vlapic_set_irq() to be sure the lapic is
>>> enabled, as other callers already check this before trying to inject?
>>
>> Perhaps, yes (once we've fixed paths where the check is presently
>> missing).
> 
> Another option would be to unconditionally return 0 for IRR and ISR
> reads when the LAPIC is disabled, that would avoid having to force the
> event channel injection when the LAPIC is enabled, but there could be
> more than just the event channel vector queued in that way which would
> be against the spec.

Pre-existing set IRR bits remain set when moving into disabled mode. If
we faked zeros for reads, we'd violate the spec and undermine Linux'es
checking of the bits.

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-21  8:33   ` Jan Beulich
  2022-11-21 10:53     ` Roger Pau Monné
@ 2022-11-21 12:06     ` Jan Beulich
  1 sibling, 0 replies; 30+ messages in thread
From: Jan Beulich @ 2022-11-21 12:06 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: xen-devel, Andrew Cooper, Wei Liu, Paul Durrant

On 21.11.2022 09:33, Jan Beulich wrote:
> On 18.11.2022 15:26, Roger Pau Monné wrote:
>> Maybe best to add an ASSERT in vlapic_set_irq() to be sure the lapic is
>> enabled, as other callers already check this before trying to inject?
> 
> Perhaps, yes (once we've fixed paths where the check is presently
> missing).

Actually - no, such an ASSERT() would then be racy against the vLAPIC
being disabled elsewhere at this very moment. It would at best be valid
when done on the vCPU in question. The SDM also provides for this: "The
reception of any interrupt or transmission of any IPIs that are in
progress when the local APIC is disabled are completed before the local
APIC enters the software-disabled state." We don't follow this to the
letter, but you get the point.

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-21  8:56       ` Jan Beulich
@ 2022-11-21 12:23         ` Andrew Cooper
  2022-11-21 12:34           ` Jan Beulich
  2022-12-05 13:44           ` Jan Beulich
  0 siblings, 2 replies; 30+ messages in thread
From: Andrew Cooper @ 2022-11-21 12:23 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Wei Liu, Roger Pau Monne, Paul Durrant, xen-devel

On 21/11/2022 08:56, Jan Beulich wrote:
> On 18.11.2022 15:27, Andrew Cooper wrote:
>> On 18/11/2022 12:54, Jan Beulich wrote:
>>> On 18.11.2022 13:33, Andrew Cooper wrote:
>>>> On 18/11/2022 10:31, Jan Beulich wrote:
>>>>> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
>>>>> exposed a problem with the marking of the respective vector as
>>>>> pending: For quite some time Linux has been checking whether any stale
>>>>> ISR or IRR bits would still be set while preparing the LAPIC for use.
>>>>> This check is now triggering on the upcall vector, as the registration,
>>>>> at least for APs, happens before the LAPIC is actually enabled.
>>>>>
>>>>> In software-disabled state an LAPIC would not accept any interrupt
>>>>> requests and hence no IRR bit would newly become set while in this
>>>>> state. As a result it is also wrong for us to mark the upcall vector as
>>>>> having a pending request when the vLAPIC is in this state.
>>>> I agree with this.
>>>>
>>>>> To compensate for the "enabled" check added to the assertion logic, add
>>>>> logic to (conditionally) mark the upcall vector as having a request
>>>>> pending at the time the LAPIC is being software-enabled by the guest.
>>>> But this, I don't think is appropriate.
>>>>
>>>> The point of raising on enable is allegedly to work around setup race
>>>> conditions.  I'm unconvinced by this reasoning, but it is what it is,
>>>> and the stated behaviour is to raise there and then.
>>>>
>>>> If a guest enables evtchn while the LAPIC is disabled, then the
>>>> interrupt is lost.  Like every other interrupt in an x86 system.
>>> Edge triggered ones you mean, I suppose, but yes.
>> For IO-APIC systems, you mostly lose line interrupts too, don't you?
>>
>> The line will remain pending at the IO-APIC, but nothing in the system
>> will unwedge until someone polls the IO-APIC.
>>
>> Either way...
>>
>>>> I don't think there is any credible way a guest kernel author can expect
>>>> the weird evtchn edgecase to wait for an arbitrary point in the future,
>>>> and it's a corner case that I think is worth not keeping.
>>> Well - did you look at 7b5b8ca7dffd ("x86/upcall: inject a spurious event
>>> after setting upcall vector"), referenced by the Fixes: tag? The issue is
>>> that with evtchn_upcall_pending once set, there would never again be a
>>> notification.
>> Ok, so we do need to do something.
>>
>>>  So if what you say is to be the model we follow, then that
>>> earlier change was perhaps wrong as well. Instead it should then have
>>> been a guest change (as also implicit from your reply) to clear
>>> evtchn_upcall_pending after vCPU info registration (there) or LAPIC
>>> enabling (here), perhaps by way of "manually" invoking the handling of
>>> that pending event, or by issuing a self-IPI with that vector.
>>> Especially the LAPIC enabling case would then be yet another Xen-specific
>>> on a guest code path which better wouldn't have to be aware of Xen. 
>> Without trying to prescribe how to fix this specific issue, wherever
>> possible we should be trying to limit the Xen-isms from non-Xen areas. 
>> There's a whole lot of poorly described and surprising behaviours which
>> have not stood the test of time.
>>
>> In this case, it seems that we have yet another x86 PV-ism which hasn't
>> translated well x86 HVM.  Specifically, we're trying to overlay an
>> entirely shared-memory (and delayed return-to-guest) interrupt
>> controller onto one which is properly constructed to handle events in
>> realtime.
>>
>>
>> I even got as far as writing that maybe leaving it as-is was the best
>> option (principle of least surprise for Xen developers), but our
>> "friend" apic acceleration strikes again.
>>
>> Xen doesn't always get a VMExit when the guest clears SW_DISABLE,
>> because microcode may have accelerated it.
> But as per "APIC-Write Emulation" in the SDM we'd still get an APIC-write
> VM exit.

Intel isn't the only accelerated implementation, and there future
details not in the public docs.

There will be an implementation we will want to support where Xen
doesn't get a vmexit for a write to SPIV.

> If we didn't, how would our internal accounting of APIC enabled
> state (VLAPIC_SW_DISABLED) work?

It doesn't.

One of many problems on the "known errors" list from an incomplete
original attempt to get acceleration working.

There's no good reason to cache those disables in the first place (both
are both trivially available from other positions in memory), and
correctness reasons not to.

>  And the neighboring (to where I'm adding
> the new code) pt_may_unmask_irq() call then also wouldn't occur.
>
> I'm actually pretty sure we do too much in this case - in particular none
> of the vlapic_set_reg() should be necessary. But we certainly can't get
> away with doing nothing, and hence we depend on that VM exit to actually
> occur.

We must do exactly and only what real hardware does, so that the state
changes emulated by Xen are identical to those accelerated by microcode.

Other than that, I really wouldn't make any presumptions about the
existing vLAPIC logic being correct.

It is, at best, enough of an approximation to the spec for major OSes to
function, with multiple known bugs and no coherent testing.

~Andrew

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-21 12:23         ` Andrew Cooper
@ 2022-11-21 12:34           ` Jan Beulich
  2022-11-23 12:03             ` Roger Pau Monné
  2022-12-05 13:44           ` Jan Beulich
  1 sibling, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2022-11-21 12:34 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Wei Liu, Roger Pau Monne, Paul Durrant, xen-devel

On 21.11.2022 13:23, Andrew Cooper wrote:
> On 21/11/2022 08:56, Jan Beulich wrote:
>> On 18.11.2022 15:27, Andrew Cooper wrote:
>>> On 18/11/2022 12:54, Jan Beulich wrote:
>>>> On 18.11.2022 13:33, Andrew Cooper wrote:
>>>>> On 18/11/2022 10:31, Jan Beulich wrote:
>>>>>> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
>>>>>> exposed a problem with the marking of the respective vector as
>>>>>> pending: For quite some time Linux has been checking whether any stale
>>>>>> ISR or IRR bits would still be set while preparing the LAPIC for use.
>>>>>> This check is now triggering on the upcall vector, as the registration,
>>>>>> at least for APs, happens before the LAPIC is actually enabled.
>>>>>>
>>>>>> In software-disabled state an LAPIC would not accept any interrupt
>>>>>> requests and hence no IRR bit would newly become set while in this
>>>>>> state. As a result it is also wrong for us to mark the upcall vector as
>>>>>> having a pending request when the vLAPIC is in this state.
>>>>> I agree with this.
>>>>>
>>>>>> To compensate for the "enabled" check added to the assertion logic, add
>>>>>> logic to (conditionally) mark the upcall vector as having a request
>>>>>> pending at the time the LAPIC is being software-enabled by the guest.
>>>>> But this, I don't think is appropriate.
>>>>>
>>>>> The point of raising on enable is allegedly to work around setup race
>>>>> conditions.  I'm unconvinced by this reasoning, but it is what it is,
>>>>> and the stated behaviour is to raise there and then.
>>>>>
>>>>> If a guest enables evtchn while the LAPIC is disabled, then the
>>>>> interrupt is lost.  Like every other interrupt in an x86 system.
>>>> Edge triggered ones you mean, I suppose, but yes.
>>> For IO-APIC systems, you mostly lose line interrupts too, don't you?
>>>
>>> The line will remain pending at the IO-APIC, but nothing in the system
>>> will unwedge until someone polls the IO-APIC.
>>>
>>> Either way...
>>>
>>>>> I don't think there is any credible way a guest kernel author can expect
>>>>> the weird evtchn edgecase to wait for an arbitrary point in the future,
>>>>> and it's a corner case that I think is worth not keeping.
>>>> Well - did you look at 7b5b8ca7dffd ("x86/upcall: inject a spurious event
>>>> after setting upcall vector"), referenced by the Fixes: tag? The issue is
>>>> that with evtchn_upcall_pending once set, there would never again be a
>>>> notification.
>>> Ok, so we do need to do something.
>>>
>>>>  So if what you say is to be the model we follow, then that
>>>> earlier change was perhaps wrong as well. Instead it should then have
>>>> been a guest change (as also implicit from your reply) to clear
>>>> evtchn_upcall_pending after vCPU info registration (there) or LAPIC
>>>> enabling (here), perhaps by way of "manually" invoking the handling of
>>>> that pending event, or by issuing a self-IPI with that vector.
>>>> Especially the LAPIC enabling case would then be yet another Xen-specific
>>>> on a guest code path which better wouldn't have to be aware of Xen. 
>>> Without trying to prescribe how to fix this specific issue, wherever
>>> possible we should be trying to limit the Xen-isms from non-Xen areas. 
>>> There's a whole lot of poorly described and surprising behaviours which
>>> have not stood the test of time.
>>>
>>> In this case, it seems that we have yet another x86 PV-ism which hasn't
>>> translated well x86 HVM.  Specifically, we're trying to overlay an
>>> entirely shared-memory (and delayed return-to-guest) interrupt
>>> controller onto one which is properly constructed to handle events in
>>> realtime.
>>>
>>>
>>> I even got as far as writing that maybe leaving it as-is was the best
>>> option (principle of least surprise for Xen developers), but our
>>> "friend" apic acceleration strikes again.
>>>
>>> Xen doesn't always get a VMExit when the guest clears SW_DISABLE,
>>> because microcode may have accelerated it.
>> But as per "APIC-Write Emulation" in the SDM we'd still get an APIC-write
>> VM exit.
> 
> Intel isn't the only accelerated implementation, and there future
> details not in the public docs.
> 
> There will be an implementation we will want to support where Xen
> doesn't get a vmexit for a write to SPIV.

I see.

>> If we didn't, how would our internal accounting of APIC enabled
>> state (VLAPIC_SW_DISABLED) work?
> 
> It doesn't.
> 
> One of many problems on the "known errors" list from an incomplete
> original attempt to get acceleration working.
> 
> There's no good reason to cache those disables in the first place (both
> are both trivially available from other positions in memory), and
> correctness reasons not to.
> 
>>  And the neighboring (to where I'm adding
>> the new code) pt_may_unmask_irq() call then also wouldn't occur.
>>
>> I'm actually pretty sure we do too much in this case - in particular none
>> of the vlapic_set_reg() should be necessary. But we certainly can't get
>> away with doing nothing, and hence we depend on that VM exit to actually
>> occur.
> 
> We must do exactly and only what real hardware does, so that the state
> changes emulated by Xen are identical to those accelerated by microcode.
> 
> Other than that, I really wouldn't make any presumptions about the
> existing vLAPIC logic being correct.
> 
> It is, at best, enough of an approximation to the spec for major OSes to
> function, with multiple known bugs and no coherent testing.

But can we leave resolving of the wider issue then separate, and leave
the change here as it presently is? Yes, mimic-ing the same behavior
later may be "interesting", but if we can't achieve consistent behavior
with yet more advanced acceleration, maybe we simply can't use that
(perhaps until a complete overhaul of everything involved in LAPIC
handling, possibly including a guest side indicator that they're happy
without the extra signaling, at which point that yet-more-advanced
acceleration could then be enabled for that guest).

Otherwise - do you have any suggestion as to alternative logic which I
might use in this patch?

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-21 12:34           ` Jan Beulich
@ 2022-11-23 12:03             ` Roger Pau Monné
  2022-11-24  7:59               ` Jan Beulich
  0 siblings, 1 reply; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-23 12:03 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On Mon, Nov 21, 2022 at 01:34:38PM +0100, Jan Beulich wrote:
> On 21.11.2022 13:23, Andrew Cooper wrote:
> > On 21/11/2022 08:56, Jan Beulich wrote:
> >> On 18.11.2022 15:27, Andrew Cooper wrote:
> >>> On 18/11/2022 12:54, Jan Beulich wrote:
> >>>> On 18.11.2022 13:33, Andrew Cooper wrote:
> >>>>> On 18/11/2022 10:31, Jan Beulich wrote:
> >>>>>> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
> >>>>>> exposed a problem with the marking of the respective vector as
> >>>>>> pending: For quite some time Linux has been checking whether any stale
> >>>>>> ISR or IRR bits would still be set while preparing the LAPIC for use.
> >>>>>> This check is now triggering on the upcall vector, as the registration,
> >>>>>> at least for APs, happens before the LAPIC is actually enabled.
> >>>>>>
> >>>>>> In software-disabled state an LAPIC would not accept any interrupt
> >>>>>> requests and hence no IRR bit would newly become set while in this
> >>>>>> state. As a result it is also wrong for us to mark the upcall vector as
> >>>>>> having a pending request when the vLAPIC is in this state.
> >>>>> I agree with this.
> >>>>>
> >>>>>> To compensate for the "enabled" check added to the assertion logic, add
> >>>>>> logic to (conditionally) mark the upcall vector as having a request
> >>>>>> pending at the time the LAPIC is being software-enabled by the guest.
> >>>>> But this, I don't think is appropriate.
> >>>>>
> >>>>> The point of raising on enable is allegedly to work around setup race
> >>>>> conditions.  I'm unconvinced by this reasoning, but it is what it is,
> >>>>> and the stated behaviour is to raise there and then.
> >>>>>
> >>>>> If a guest enables evtchn while the LAPIC is disabled, then the
> >>>>> interrupt is lost.  Like every other interrupt in an x86 system.
> >>>> Edge triggered ones you mean, I suppose, but yes.
> >>> For IO-APIC systems, you mostly lose line interrupts too, don't you?
> >>>
> >>> The line will remain pending at the IO-APIC, but nothing in the system
> >>> will unwedge until someone polls the IO-APIC.
> >>>
> >>> Either way...
> >>>
> >>>>> I don't think there is any credible way a guest kernel author can expect
> >>>>> the weird evtchn edgecase to wait for an arbitrary point in the future,
> >>>>> and it's a corner case that I think is worth not keeping.
> >>>> Well - did you look at 7b5b8ca7dffd ("x86/upcall: inject a spurious event
> >>>> after setting upcall vector"), referenced by the Fixes: tag? The issue is
> >>>> that with evtchn_upcall_pending once set, there would never again be a
> >>>> notification.
> >>> Ok, so we do need to do something.
> >>>
> >>>>  So if what you say is to be the model we follow, then that
> >>>> earlier change was perhaps wrong as well. Instead it should then have
> >>>> been a guest change (as also implicit from your reply) to clear
> >>>> evtchn_upcall_pending after vCPU info registration (there) or LAPIC
> >>>> enabling (here), perhaps by way of "manually" invoking the handling of
> >>>> that pending event, or by issuing a self-IPI with that vector.
> >>>> Especially the LAPIC enabling case would then be yet another Xen-specific
> >>>> on a guest code path which better wouldn't have to be aware of Xen. 
> >>> Without trying to prescribe how to fix this specific issue, wherever
> >>> possible we should be trying to limit the Xen-isms from non-Xen areas. 
> >>> There's a whole lot of poorly described and surprising behaviours which
> >>> have not stood the test of time.
> >>>
> >>> In this case, it seems that we have yet another x86 PV-ism which hasn't
> >>> translated well x86 HVM.  Specifically, we're trying to overlay an
> >>> entirely shared-memory (and delayed return-to-guest) interrupt
> >>> controller onto one which is properly constructed to handle events in
> >>> realtime.
> >>>
> >>>
> >>> I even got as far as writing that maybe leaving it as-is was the best
> >>> option (principle of least surprise for Xen developers), but our
> >>> "friend" apic acceleration strikes again.
> >>>
> >>> Xen doesn't always get a VMExit when the guest clears SW_DISABLE,
> >>> because microcode may have accelerated it.
> >> But as per "APIC-Write Emulation" in the SDM we'd still get an APIC-write
> >> VM exit.
> > 
> > Intel isn't the only accelerated implementation, and there future
> > details not in the public docs.
> > 
> > There will be an implementation we will want to support where Xen
> > doesn't get a vmexit for a write to SPIV.
> 
> I see.
> 
> >> If we didn't, how would our internal accounting of APIC enabled
> >> state (VLAPIC_SW_DISABLED) work?
> > 
> > It doesn't.
> > 
> > One of many problems on the "known errors" list from an incomplete
> > original attempt to get acceleration working.
> > 
> > There's no good reason to cache those disables in the first place (both
> > are both trivially available from other positions in memory), and
> > correctness reasons not to.
> > 
> >>  And the neighboring (to where I'm adding
> >> the new code) pt_may_unmask_irq() call then also wouldn't occur.
> >>
> >> I'm actually pretty sure we do too much in this case - in particular none
> >> of the vlapic_set_reg() should be necessary. But we certainly can't get
> >> away with doing nothing, and hence we depend on that VM exit to actually
> >> occur.
> > 
> > We must do exactly and only what real hardware does, so that the state
> > changes emulated by Xen are identical to those accelerated by microcode.
> > 
> > Other than that, I really wouldn't make any presumptions about the
> > existing vLAPIC logic being correct.
> > 
> > It is, at best, enough of an approximation to the spec for major OSes to
> > function, with multiple known bugs and no coherent testing.
> 
> But can we leave resolving of the wider issue then separate, and leave
> the change here as it presently is? Yes, mimic-ing the same behavior
> later may be "interesting", but if we can't achieve consistent behavior
> with yet more advanced acceleration, maybe we simply can't use that
> (perhaps until a complete overhaul of everything involved in LAPIC
> handling, possibly including a guest side indicator that they're happy
> without the extra signaling, at which point that yet-more-advanced
> acceleration could then be enabled for that guest).
> 
> Otherwise - do you have any suggestion as to alternative logic which I
> might use in this patch?

Maybe the underlying issue is that we allow executing
HVMOP_set_evtchn_upcall_vector against remote vCPU.  This could be
solved by only allowing HVMOP_set_evtchn_upcall_vector against the
current vCPU and with the LAPIC enabled, but I guess we are too late
for that.

Actually, what about only injecting the spurious event if the vCPU is
online, ie:

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ae4368ec4b..4b84706579 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -4105,7 +4105,8 @@ static int hvmop_set_evtchn_upcall_vector(
     printk(XENLOG_G_INFO "%pv: upcall vector %02x\n", v, op.vector);
 
     v->arch.hvm.evtchn_upcall_vector = op.vector;
-    hvm_assert_evtchn_irq(v);
+    if ( is_vcpu_online(v) )
+        hvm_assert_evtchn_irq(v);
     return 0;
 }
 

I think that should fix the issue seen on Linux.  We would
additionally need to fix hvm_assert_evtchn_irq() to only set the
vector if the vLAPIC is enabled.

Thanks, Roger.


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-23 12:03             ` Roger Pau Monné
@ 2022-11-24  7:59               ` Jan Beulich
  2022-11-24  8:42                 ` Roger Pau Monné
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2022-11-24  7:59 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On 23.11.2022 13:03, Roger Pau Monné wrote:
> On Mon, Nov 21, 2022 at 01:34:38PM +0100, Jan Beulich wrote:
>> On 21.11.2022 13:23, Andrew Cooper wrote:
>>> On 21/11/2022 08:56, Jan Beulich wrote:
>>>> On 18.11.2022 15:27, Andrew Cooper wrote:
>>>>> I even got as far as writing that maybe leaving it as-is was the best
>>>>> option (principle of least surprise for Xen developers), but our
>>>>> "friend" apic acceleration strikes again.
>>>>>
>>>>> Xen doesn't always get a VMExit when the guest clears SW_DISABLE,
>>>>> because microcode may have accelerated it.
>>>> But as per "APIC-Write Emulation" in the SDM we'd still get an APIC-write
>>>> VM exit.
>>>
>>> Intel isn't the only accelerated implementation, and there future
>>> details not in the public docs.
>>>
>>> There will be an implementation we will want to support where Xen
>>> doesn't get a vmexit for a write to SPIV.
>>
>> I see.
>>
>>>> If we didn't, how would our internal accounting of APIC enabled
>>>> state (VLAPIC_SW_DISABLED) work?
>>>
>>> It doesn't.
>>>
>>> One of many problems on the "known errors" list from an incomplete
>>> original attempt to get acceleration working.
>>>
>>> There's no good reason to cache those disables in the first place (both
>>> are both trivially available from other positions in memory), and
>>> correctness reasons not to.
>>>
>>>>  And the neighboring (to where I'm adding
>>>> the new code) pt_may_unmask_irq() call then also wouldn't occur.
>>>>
>>>> I'm actually pretty sure we do too much in this case - in particular none
>>>> of the vlapic_set_reg() should be necessary. But we certainly can't get
>>>> away with doing nothing, and hence we depend on that VM exit to actually
>>>> occur.
>>>
>>> We must do exactly and only what real hardware does, so that the state
>>> changes emulated by Xen are identical to those accelerated by microcode.
>>>
>>> Other than that, I really wouldn't make any presumptions about the
>>> existing vLAPIC logic being correct.
>>>
>>> It is, at best, enough of an approximation to the spec for major OSes to
>>> function, with multiple known bugs and no coherent testing.
>>
>> But can we leave resolving of the wider issue then separate, and leave
>> the change here as it presently is? Yes, mimic-ing the same behavior
>> later may be "interesting", but if we can't achieve consistent behavior
>> with yet more advanced acceleration, maybe we simply can't use that
>> (perhaps until a complete overhaul of everything involved in LAPIC
>> handling, possibly including a guest side indicator that they're happy
>> without the extra signaling, at which point that yet-more-advanced
>> acceleration could then be enabled for that guest).
>>
>> Otherwise - do you have any suggestion as to alternative logic which I
>> might use in this patch?
> 
> Maybe the underlying issue is that we allow executing
> HVMOP_set_evtchn_upcall_vector against remote vCPU.  This could be
> solved by only allowing HVMOP_set_evtchn_upcall_vector against the
> current vCPU and with the LAPIC enabled, but I guess we are too late
> for that.

Allowing things like this ahead of bringing a vCPU online can be
helpful for the OS side implementation, I think.

> Actually, what about only injecting the spurious event if the vCPU is
> online, ie:
> 
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index ae4368ec4b..4b84706579 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -4105,7 +4105,8 @@ static int hvmop_set_evtchn_upcall_vector(
>      printk(XENLOG_G_INFO "%pv: upcall vector %02x\n", v, op.vector);
>  
>      v->arch.hvm.evtchn_upcall_vector = op.vector;
> -    hvm_assert_evtchn_irq(v);
> +    if ( is_vcpu_online(v) )
> +        hvm_assert_evtchn_irq(v);

While this would match what hvm_set_callback_via() does, see my post-
commit-message remark suggesting to key this to evtchn_upcall_pending.
Tying the call to the vCPU being online looks pretty arbitrary to me,
the more that this would continue to be
- racy with the vCPU coming online, and perhaps already being past
  VCPUOP_initialise - after all VCPUOP_up is little more than clearing
  VPF_down,
- problematic wrt evtchn_upcall_pending, once set, preventing event
  injection later on.
As you may have inferred already, I'm inclined to suggest to drop the
the is_vcpu_online() check from hvm_set_callback_via().

One related question here is whether vlapic_do_init() shouldn't have
the non-architectural side effect of clearing evtchn_upcall_pending.
While this again violates the principle of the hypervisor only ever
setting that bit, it would deal with the risk of no further event
injection once the flag is set, considering that vlapic_do_init()
clears IRR (and ISR).

Jan

> I think that should fix the issue seen on Linux.  We would
> additionally need to fix hvm_assert_evtchn_irq() to only set the
> vector if the vLAPIC is enabled.
> 
> Thanks, Roger.



^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-24  7:59               ` Jan Beulich
@ 2022-11-24  8:42                 ` Roger Pau Monné
  2022-11-24  9:06                   ` Roger Pau Monné
  2022-11-24  9:06                   ` Jan Beulich
  0 siblings, 2 replies; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-24  8:42 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On Thu, Nov 24, 2022 at 08:59:00AM +0100, Jan Beulich wrote:
> On 23.11.2022 13:03, Roger Pau Monné wrote:
> > On Mon, Nov 21, 2022 at 01:34:38PM +0100, Jan Beulich wrote:
> >> On 21.11.2022 13:23, Andrew Cooper wrote:
> >>> On 21/11/2022 08:56, Jan Beulich wrote:
> >>>> On 18.11.2022 15:27, Andrew Cooper wrote:
> >>>>> I even got as far as writing that maybe leaving it as-is was the best
> >>>>> option (principle of least surprise for Xen developers), but our
> >>>>> "friend" apic acceleration strikes again.
> >>>>>
> >>>>> Xen doesn't always get a VMExit when the guest clears SW_DISABLE,
> >>>>> because microcode may have accelerated it.
> >>>> But as per "APIC-Write Emulation" in the SDM we'd still get an APIC-write
> >>>> VM exit.
> >>>
> >>> Intel isn't the only accelerated implementation, and there future
> >>> details not in the public docs.
> >>>
> >>> There will be an implementation we will want to support where Xen
> >>> doesn't get a vmexit for a write to SPIV.
> >>
> >> I see.
> >>
> >>>> If we didn't, how would our internal accounting of APIC enabled
> >>>> state (VLAPIC_SW_DISABLED) work?
> >>>
> >>> It doesn't.
> >>>
> >>> One of many problems on the "known errors" list from an incomplete
> >>> original attempt to get acceleration working.
> >>>
> >>> There's no good reason to cache those disables in the first place (both
> >>> are both trivially available from other positions in memory), and
> >>> correctness reasons not to.
> >>>
> >>>>  And the neighboring (to where I'm adding
> >>>> the new code) pt_may_unmask_irq() call then also wouldn't occur.
> >>>>
> >>>> I'm actually pretty sure we do too much in this case - in particular none
> >>>> of the vlapic_set_reg() should be necessary. But we certainly can't get
> >>>> away with doing nothing, and hence we depend on that VM exit to actually
> >>>> occur.
> >>>
> >>> We must do exactly and only what real hardware does, so that the state
> >>> changes emulated by Xen are identical to those accelerated by microcode.
> >>>
> >>> Other than that, I really wouldn't make any presumptions about the
> >>> existing vLAPIC logic being correct.
> >>>
> >>> It is, at best, enough of an approximation to the spec for major OSes to
> >>> function, with multiple known bugs and no coherent testing.
> >>
> >> But can we leave resolving of the wider issue then separate, and leave
> >> the change here as it presently is? Yes, mimic-ing the same behavior
> >> later may be "interesting", but if we can't achieve consistent behavior
> >> with yet more advanced acceleration, maybe we simply can't use that
> >> (perhaps until a complete overhaul of everything involved in LAPIC
> >> handling, possibly including a guest side indicator that they're happy
> >> without the extra signaling, at which point that yet-more-advanced
> >> acceleration could then be enabled for that guest).
> >>
> >> Otherwise - do you have any suggestion as to alternative logic which I
> >> might use in this patch?
> > 
> > Maybe the underlying issue is that we allow executing
> > HVMOP_set_evtchn_upcall_vector against remote vCPU.  This could be
> > solved by only allowing HVMOP_set_evtchn_upcall_vector against the
> > current vCPU and with the LAPIC enabled, but I guess we are too late
> > for that.
> 
> Allowing things like this ahead of bringing a vCPU online can be
> helpful for the OS side implementation, I think.

I thinks it's more natural to do the vector callback setup as part of
the CPU bringup path, like any other CPU related setting that need to
be applied, but I guess that's a question of taste.

> > Actually, what about only injecting the spurious event if the vCPU is
> > online, ie:
> > 
> > diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> > index ae4368ec4b..4b84706579 100644
> > --- a/xen/arch/x86/hvm/hvm.c
> > +++ b/xen/arch/x86/hvm/hvm.c
> > @@ -4105,7 +4105,8 @@ static int hvmop_set_evtchn_upcall_vector(
> >      printk(XENLOG_G_INFO "%pv: upcall vector %02x\n", v, op.vector);
> >  
> >      v->arch.hvm.evtchn_upcall_vector = op.vector;
> > -    hvm_assert_evtchn_irq(v);
> > +    if ( is_vcpu_online(v) )
> > +        hvm_assert_evtchn_irq(v);
> 
> While this would match what hvm_set_callback_via() does, see my post-
> commit-message remark suggesting to key this to evtchn_upcall_pending.
> Tying the call to the vCPU being online looks pretty arbitrary to me,
> the more that this would continue to be
> - racy with the vCPU coming online, and perhaps already being past
>   VCPUOP_initialise - after all VCPUOP_up is little more than clearing
>   VPF_down,

If the OS attempts to setup the callback at the same time the CPU is
being brought online all bets are off I think, and the OS gets to keep
the pieces.

> - problematic wrt evtchn_upcall_pending, once set, preventing event
>   injection later on.
> As you may have inferred already, I'm inclined to suggest to drop the
> the is_vcpu_online() check from hvm_set_callback_via().
> 
> One related question here is whether vlapic_do_init() shouldn't have
> the non-architectural side effect of clearing evtchn_upcall_pending.
> While this again violates the principle of the hypervisor only ever
> setting that bit, it would deal with the risk of no further event
> injection once the flag is set, considering that vlapic_do_init()
> clears IRR (and ISR).

That would seem sensible to me, and was kind of what I was suggesting
in:

https://lore.kernel.org/xen-devel/Y3eO0bMKRPYJc2yQ@Air-de-Roger/

Thanks, Roger.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-24  8:42                 ` Roger Pau Monné
@ 2022-11-24  9:06                   ` Roger Pau Monné
  2022-11-24  9:11                     ` Jan Beulich
  2022-11-24  9:06                   ` Jan Beulich
  1 sibling, 1 reply; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-24  9:06 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On Thu, Nov 24, 2022 at 09:42:40AM +0100, Roger Pau Monné wrote:
> On Thu, Nov 24, 2022 at 08:59:00AM +0100, Jan Beulich wrote:
> > - problematic wrt evtchn_upcall_pending, once set, preventing event
> >   injection later on.
> > As you may have inferred already, I'm inclined to suggest to drop the
> > the is_vcpu_online() check from hvm_set_callback_via().
> > 
> > One related question here is whether vlapic_do_init() shouldn't have
> > the non-architectural side effect of clearing evtchn_upcall_pending.
> > While this again violates the principle of the hypervisor only ever
> > setting that bit, it would deal with the risk of no further event
> > injection once the flag is set, considering that vlapic_do_init()
> > clears IRR (and ISR).
> 
> That would seem sensible to me, and was kind of what I was suggesting
> in:
> 
> https://lore.kernel.org/xen-devel/Y3eO0bMKRPYJc2yQ@Air-de-Roger/

Another option would be for vcpu_mark_events_pending() to
unconditionally call hvm_assert_evtchn_irq() regardless of the state
of evtchn_upcall_pending.  This will create some spurious events.

Regards, Roger.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-24  8:42                 ` Roger Pau Monné
  2022-11-24  9:06                   ` Roger Pau Monné
@ 2022-11-24  9:06                   ` Jan Beulich
  1 sibling, 0 replies; 30+ messages in thread
From: Jan Beulich @ 2022-11-24  9:06 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On 24.11.2022 09:42, Roger Pau Monné wrote:
> On Thu, Nov 24, 2022 at 08:59:00AM +0100, Jan Beulich wrote:
>> One related question here is whether vlapic_do_init() shouldn't have
>> the non-architectural side effect of clearing evtchn_upcall_pending.
>> While this again violates the principle of the hypervisor only ever
>> setting that bit, it would deal with the risk of no further event
>> injection once the flag is set, considering that vlapic_do_init()
>> clears IRR (and ISR).
> 
> That would seem sensible to me, and was kind of what I was suggesting
> in:
> 
> https://lore.kernel.org/xen-devel/Y3eO0bMKRPYJc2yQ@Air-de-Roger/

Oh, I didn't read it that way, as there you said "when it is enabled",
whereas here I'm suggesting to do so when it is being (re)initialized.
But, as said both above and in the reply, we'd need to be sure of the
resulting behavioral change (kind of an ABI one) being acceptable.

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-24  9:06                   ` Roger Pau Monné
@ 2022-11-24  9:11                     ` Jan Beulich
  2022-11-24  9:33                       ` Roger Pau Monné
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2022-11-24  9:11 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On 24.11.2022 10:06, Roger Pau Monné wrote:
> On Thu, Nov 24, 2022 at 09:42:40AM +0100, Roger Pau Monné wrote:
>> On Thu, Nov 24, 2022 at 08:59:00AM +0100, Jan Beulich wrote:
>>> - problematic wrt evtchn_upcall_pending, once set, preventing event
>>>   injection later on.
>>> As you may have inferred already, I'm inclined to suggest to drop the
>>> the is_vcpu_online() check from hvm_set_callback_via().
>>>
>>> One related question here is whether vlapic_do_init() shouldn't have
>>> the non-architectural side effect of clearing evtchn_upcall_pending.
>>> While this again violates the principle of the hypervisor only ever
>>> setting that bit, it would deal with the risk of no further event
>>> injection once the flag is set, considering that vlapic_do_init()
>>> clears IRR (and ISR).
>>
>> That would seem sensible to me, and was kind of what I was suggesting
>> in:
>>
>> https://lore.kernel.org/xen-devel/Y3eO0bMKRPYJc2yQ@Air-de-Roger/
> 
> Another option would be for vcpu_mark_events_pending() to
> unconditionally call hvm_assert_evtchn_irq() regardless of the state
> of evtchn_upcall_pending.

I think you said so before, and ...

>  This will create some spurious events.

... I continue to be afraid of s/some/many/. This event delivery is meant
to be kind of edge triggered, and I think it is a reasonable model to treat
the flag going from 0 to 1 as the "edge".

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-24  9:11                     ` Jan Beulich
@ 2022-11-24  9:33                       ` Roger Pau Monné
  2022-11-24 11:16                         ` Jan Beulich
  0 siblings, 1 reply; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-24  9:33 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On Thu, Nov 24, 2022 at 10:11:05AM +0100, Jan Beulich wrote:
> On 24.11.2022 10:06, Roger Pau Monné wrote:
> > On Thu, Nov 24, 2022 at 09:42:40AM +0100, Roger Pau Monné wrote:
> >> On Thu, Nov 24, 2022 at 08:59:00AM +0100, Jan Beulich wrote:
> >>> - problematic wrt evtchn_upcall_pending, once set, preventing event
> >>>   injection later on.
> >>> As you may have inferred already, I'm inclined to suggest to drop the
> >>> the is_vcpu_online() check from hvm_set_callback_via().
> >>>
> >>> One related question here is whether vlapic_do_init() shouldn't have
> >>> the non-architectural side effect of clearing evtchn_upcall_pending.
> >>> While this again violates the principle of the hypervisor only ever
> >>> setting that bit, it would deal with the risk of no further event
> >>> injection once the flag is set, considering that vlapic_do_init()
> >>> clears IRR (and ISR).
> >>
> >> That would seem sensible to me, and was kind of what I was suggesting
> >> in:
> >>
> >> https://lore.kernel.org/xen-devel/Y3eO0bMKRPYJc2yQ@Air-de-Roger/
> > 
> > Another option would be for vcpu_mark_events_pending() to
> > unconditionally call hvm_assert_evtchn_irq() regardless of the state
> > of evtchn_upcall_pending.
> 
> I think you said so before, and ...
> 
> >  This will create some spurious events.
> 
> ... I continue to be afraid of s/some/many/.

Not _that_ many I think, as we can only queue one pending interrupt in
IRR.

> This event delivery is meant
> to be kind of edge triggered, and I think it is a reasonable model to treat
> the flag going from 0 to 1 as the "edge".

Hm, it's a weird interrupt model I would say.  In some aspects it's
similar to level (as the line stays asserted until it's cleared), but
we don't get new interrupts injected into the APIC.

Maybe the right mode would be to treat evtchn_upcall_pending as a
level triggered line and keep injecting interrupts until the line is
deasserted (ie: evtchn_upcall_pending == 0)?

Sorry, I feel like I'm asking more questions that providing answers.

Roger.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-24  9:33                       ` Roger Pau Monné
@ 2022-11-24 11:16                         ` Jan Beulich
  2022-11-24 15:12                           ` Roger Pau Monné
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2022-11-24 11:16 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On 24.11.2022 10:33, Roger Pau Monné wrote:
> On Thu, Nov 24, 2022 at 10:11:05AM +0100, Jan Beulich wrote:
>> On 24.11.2022 10:06, Roger Pau Monné wrote:
>>> On Thu, Nov 24, 2022 at 09:42:40AM +0100, Roger Pau Monné wrote:
>>>> On Thu, Nov 24, 2022 at 08:59:00AM +0100, Jan Beulich wrote:
>>>>> - problematic wrt evtchn_upcall_pending, once set, preventing event
>>>>>   injection later on.
>>>>> As you may have inferred already, I'm inclined to suggest to drop the
>>>>> the is_vcpu_online() check from hvm_set_callback_via().
>>>>>
>>>>> One related question here is whether vlapic_do_init() shouldn't have
>>>>> the non-architectural side effect of clearing evtchn_upcall_pending.
>>>>> While this again violates the principle of the hypervisor only ever
>>>>> setting that bit, it would deal with the risk of no further event
>>>>> injection once the flag is set, considering that vlapic_do_init()
>>>>> clears IRR (and ISR).
>>>>
>>>> That would seem sensible to me, and was kind of what I was suggesting
>>>> in:
>>>>
>>>> https://lore.kernel.org/xen-devel/Y3eO0bMKRPYJc2yQ@Air-de-Roger/
>>>
>>> Another option would be for vcpu_mark_events_pending() to
>>> unconditionally call hvm_assert_evtchn_irq() regardless of the state
>>> of evtchn_upcall_pending.
>>
>> I think you said so before, and ...
>>
>>>  This will create some spurious events.
>>
>> ... I continue to be afraid of s/some/many/.
> 
> Not _that_ many I think, as we can only queue one pending interrupt in
> IRR.

We need to be careful here - the kernel treating it as "edge" (like
any other interrupt coming directly from the LAPIC), it ack-s it
before calling the handler, i.e. before evtchn_upcall_pending would
have a chance to be cleared. See Linux'es sysvec_xen_hvm_callback().

>> This event delivery is meant
>> to be kind of edge triggered, and I think it is a reasonable model to treat
>> the flag going from 0 to 1 as the "edge".
> 
> Hm, it's a weird interrupt model I would say.  In some aspects it's
> similar to level (as the line stays asserted until it's cleared), but
> we don't get new interrupts injected into the APIC.
> 
> Maybe the right mode would be to treat evtchn_upcall_pending as a
> level triggered line and keep injecting interrupts until the line is
> deasserted (ie: evtchn_upcall_pending == 0)?

As said above, and as also pointed out by Andrew on another sub-
thread when discussing the (dis)similarity with IO-APIC connected
interrupts, at the LAPIC there's no edge/level distinction anymore,
as we're not dealing with "asserted" signals there, but just with
messages sent on the bus.

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-24 11:16                         ` Jan Beulich
@ 2022-11-24 15:12                           ` Roger Pau Monné
  2022-11-25  8:43                             ` Jan Beulich
  0 siblings, 1 reply; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-24 15:12 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On Thu, Nov 24, 2022 at 12:16:13PM +0100, Jan Beulich wrote:
> On 24.11.2022 10:33, Roger Pau Monné wrote:
> > On Thu, Nov 24, 2022 at 10:11:05AM +0100, Jan Beulich wrote:
> >> On 24.11.2022 10:06, Roger Pau Monné wrote:
> >>> On Thu, Nov 24, 2022 at 09:42:40AM +0100, Roger Pau Monné wrote:
> >>>> On Thu, Nov 24, 2022 at 08:59:00AM +0100, Jan Beulich wrote:
> >>>>> - problematic wrt evtchn_upcall_pending, once set, preventing event
> >>>>>   injection later on.
> >>>>> As you may have inferred already, I'm inclined to suggest to drop the
> >>>>> the is_vcpu_online() check from hvm_set_callback_via().
> >>>>>
> >>>>> One related question here is whether vlapic_do_init() shouldn't have
> >>>>> the non-architectural side effect of clearing evtchn_upcall_pending.
> >>>>> While this again violates the principle of the hypervisor only ever
> >>>>> setting that bit, it would deal with the risk of no further event
> >>>>> injection once the flag is set, considering that vlapic_do_init()
> >>>>> clears IRR (and ISR).
> >>>>
> >>>> That would seem sensible to me, and was kind of what I was suggesting
> >>>> in:
> >>>>
> >>>> https://lore.kernel.org/xen-devel/Y3eO0bMKRPYJc2yQ@Air-de-Roger/
> >>>
> >>> Another option would be for vcpu_mark_events_pending() to
> >>> unconditionally call hvm_assert_evtchn_irq() regardless of the state
> >>> of evtchn_upcall_pending.
> >>
> >> I think you said so before, and ...
> >>
> >>>  This will create some spurious events.
> >>
> >> ... I continue to be afraid of s/some/many/.
> > 
> > Not _that_ many I think, as we can only queue one pending interrupt in
> > IRR.
> 
> We need to be careful here - the kernel treating it as "edge" (like
> any other interrupt coming directly from the LAPIC), it ack-s it
> before calling the handler, i.e. before evtchn_upcall_pending would
> have a chance to be cleared. See Linux'es sysvec_xen_hvm_callback().

Hm, that's not how I handle it on FreeBSD, where the vector is acked
after calling the handler (evtchn_upcall_pending gets cleared before
the EOI).  Maybe there's some corner case I'm missing that requires
the EOI to be performed before clearing evtchn_upcall_pending?

> >> This event delivery is meant
> >> to be kind of edge triggered, and I think it is a reasonable model to treat
> >> the flag going from 0 to 1 as the "edge".
> > 
> > Hm, it's a weird interrupt model I would say.  In some aspects it's
> > similar to level (as the line stays asserted until it's cleared), but
> > we don't get new interrupts injected into the APIC.
> > 
> > Maybe the right mode would be to treat evtchn_upcall_pending as a
> > level triggered line and keep injecting interrupts until the line is
> > deasserted (ie: evtchn_upcall_pending == 0)?
> 
> As said above, and as also pointed out by Andrew on another sub-
> thread when discussing the (dis)similarity with IO-APIC connected
> interrupts, at the LAPIC there's no edge/level distinction anymore,
> as we're not dealing with "asserted" signals there, but just with
> messages sent on the bus.

Right, we could likely fake the behavior I've listed above, but not
sure it's worth it.

We should likely have some of this documented in xen.h next to the
declaration of evtchn_upcall_pending, at least to note that once
evtchn_upcall_pending is set no further vector callbacks will get
injected until the field is cleared.

Roger.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-24 15:12                           ` Roger Pau Monné
@ 2022-11-25  8:43                             ` Jan Beulich
  2022-11-25  9:00                               ` Roger Pau Monné
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2022-11-25  8:43 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On 24.11.2022 16:12, Roger Pau Monné wrote:
> On Thu, Nov 24, 2022 at 12:16:13PM +0100, Jan Beulich wrote:
>> On 24.11.2022 10:33, Roger Pau Monné wrote:
>>> On Thu, Nov 24, 2022 at 10:11:05AM +0100, Jan Beulich wrote:
>>>> On 24.11.2022 10:06, Roger Pau Monné wrote:
>>>>> On Thu, Nov 24, 2022 at 09:42:40AM +0100, Roger Pau Monné wrote:
>>>>>> On Thu, Nov 24, 2022 at 08:59:00AM +0100, Jan Beulich wrote:
>>>>>>> - problematic wrt evtchn_upcall_pending, once set, preventing event
>>>>>>>   injection later on.
>>>>>>> As you may have inferred already, I'm inclined to suggest to drop the
>>>>>>> the is_vcpu_online() check from hvm_set_callback_via().
>>>>>>>
>>>>>>> One related question here is whether vlapic_do_init() shouldn't have
>>>>>>> the non-architectural side effect of clearing evtchn_upcall_pending.
>>>>>>> While this again violates the principle of the hypervisor only ever
>>>>>>> setting that bit, it would deal with the risk of no further event
>>>>>>> injection once the flag is set, considering that vlapic_do_init()
>>>>>>> clears IRR (and ISR).
>>>>>>
>>>>>> That would seem sensible to me, and was kind of what I was suggesting
>>>>>> in:
>>>>>>
>>>>>> https://lore.kernel.org/xen-devel/Y3eO0bMKRPYJc2yQ@Air-de-Roger/
>>>>>
>>>>> Another option would be for vcpu_mark_events_pending() to
>>>>> unconditionally call hvm_assert_evtchn_irq() regardless of the state
>>>>> of evtchn_upcall_pending.
>>>>
>>>> I think you said so before, and ...
>>>>
>>>>>  This will create some spurious events.
>>>>
>>>> ... I continue to be afraid of s/some/many/.
>>>
>>> Not _that_ many I think, as we can only queue one pending interrupt in
>>> IRR.
>>
>> We need to be careful here - the kernel treating it as "edge" (like
>> any other interrupt coming directly from the LAPIC), it ack-s it
>> before calling the handler, i.e. before evtchn_upcall_pending would
>> have a chance to be cleared. See Linux'es sysvec_xen_hvm_callback().
> 
> Hm, that's not how I handle it on FreeBSD, where the vector is acked
> after calling the handler (evtchn_upcall_pending gets cleared before
> the EOI).  Maybe there's some corner case I'm missing that requires
> the EOI to be performed before clearing evtchn_upcall_pending?

I think for the purpose of the one vector doing the EOI late is okay,
but aiui the goal of doing it early for edge triggered interrupts in
general (and yet more generally as early as possible) is to unmask
lower priority vectors as well. Of course that's useful only if IRQs
as a whole are unmasked during (part of) the handling.

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-25  8:43                             ` Jan Beulich
@ 2022-11-25  9:00                               ` Roger Pau Monné
  2022-11-25  9:09                                 ` Jan Beulich
  0 siblings, 1 reply; 30+ messages in thread
From: Roger Pau Monné @ 2022-11-25  9:00 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On Fri, Nov 25, 2022 at 09:43:59AM +0100, Jan Beulich wrote:
> On 24.11.2022 16:12, Roger Pau Monné wrote:
> > On Thu, Nov 24, 2022 at 12:16:13PM +0100, Jan Beulich wrote:
> >> On 24.11.2022 10:33, Roger Pau Monné wrote:
> >>> On Thu, Nov 24, 2022 at 10:11:05AM +0100, Jan Beulich wrote:
> >>>> On 24.11.2022 10:06, Roger Pau Monné wrote:
> >>>>> On Thu, Nov 24, 2022 at 09:42:40AM +0100, Roger Pau Monné wrote:
> >>>>>> On Thu, Nov 24, 2022 at 08:59:00AM +0100, Jan Beulich wrote:
> >>>>>>> - problematic wrt evtchn_upcall_pending, once set, preventing event
> >>>>>>>   injection later on.
> >>>>>>> As you may have inferred already, I'm inclined to suggest to drop the
> >>>>>>> the is_vcpu_online() check from hvm_set_callback_via().
> >>>>>>>
> >>>>>>> One related question here is whether vlapic_do_init() shouldn't have
> >>>>>>> the non-architectural side effect of clearing evtchn_upcall_pending.
> >>>>>>> While this again violates the principle of the hypervisor only ever
> >>>>>>> setting that bit, it would deal with the risk of no further event
> >>>>>>> injection once the flag is set, considering that vlapic_do_init()
> >>>>>>> clears IRR (and ISR).
> >>>>>>
> >>>>>> That would seem sensible to me, and was kind of what I was suggesting
> >>>>>> in:
> >>>>>>
> >>>>>> https://lore.kernel.org/xen-devel/Y3eO0bMKRPYJc2yQ@Air-de-Roger/
> >>>>>
> >>>>> Another option would be for vcpu_mark_events_pending() to
> >>>>> unconditionally call hvm_assert_evtchn_irq() regardless of the state
> >>>>> of evtchn_upcall_pending.
> >>>>
> >>>> I think you said so before, and ...
> >>>>
> >>>>>  This will create some spurious events.
> >>>>
> >>>> ... I continue to be afraid of s/some/many/.
> >>>
> >>> Not _that_ many I think, as we can only queue one pending interrupt in
> >>> IRR.
> >>
> >> We need to be careful here - the kernel treating it as "edge" (like
> >> any other interrupt coming directly from the LAPIC), it ack-s it
> >> before calling the handler, i.e. before evtchn_upcall_pending would
> >> have a chance to be cleared. See Linux'es sysvec_xen_hvm_callback().
> > 
> > Hm, that's not how I handle it on FreeBSD, where the vector is acked
> > after calling the handler (evtchn_upcall_pending gets cleared before
> > the EOI).  Maybe there's some corner case I'm missing that requires
> > the EOI to be performed before clearing evtchn_upcall_pending?
> 
> I think for the purpose of the one vector doing the EOI late is okay,
> but aiui the goal of doing it early for edge triggered interrupts in
> general (and yet more generally as early as possible) is to unmask
> lower priority vectors as well.

My reasoning for doing it late was in order to avoid adding extra
latency to things like the timer handling, as the EOI will likely
trigger a vmexit.

> Of course that's useful only if IRQs
> as a whole are unmasked during (part of) the handling.

What do you mean with IRQs as a whole?  Are you referring to setting
the interrupt flag?

Thanks for the input, it's appreciated, and sorry for diverging the
conversation so much.

Roger.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-25  9:00                               ` Roger Pau Monné
@ 2022-11-25  9:09                                 ` Jan Beulich
  0 siblings, 0 replies; 30+ messages in thread
From: Jan Beulich @ 2022-11-25  9:09 UTC (permalink / raw)
  To: Roger Pau Monné; +Cc: Andrew Cooper, Wei Liu, Paul Durrant, xen-devel

On 25.11.2022 10:00, Roger Pau Monné wrote:
> On Fri, Nov 25, 2022 at 09:43:59AM +0100, Jan Beulich wrote:
>> On 24.11.2022 16:12, Roger Pau Monné wrote:
>>> On Thu, Nov 24, 2022 at 12:16:13PM +0100, Jan Beulich wrote:
>>>> We need to be careful here - the kernel treating it as "edge" (like
>>>> any other interrupt coming directly from the LAPIC), it ack-s it
>>>> before calling the handler, i.e. before evtchn_upcall_pending would
>>>> have a chance to be cleared. See Linux'es sysvec_xen_hvm_callback().
>>>
>>> Hm, that's not how I handle it on FreeBSD, where the vector is acked
>>> after calling the handler (evtchn_upcall_pending gets cleared before
>>> the EOI).  Maybe there's some corner case I'm missing that requires
>>> the EOI to be performed before clearing evtchn_upcall_pending?
>>
>> I think for the purpose of the one vector doing the EOI late is okay,
>> but aiui the goal of doing it early for edge triggered interrupts in
>> general (and yet more generally as early as possible) is to unmask
>> lower priority vectors as well.
> 
> My reasoning for doing it late was in order to avoid adding extra
> latency to things like the timer handling, as the EOI will likely
> trigger a vmexit.
> 
>> Of course that's useful only if IRQs
>> as a whole are unmasked during (part of) the handling.
> 
> What do you mean with IRQs as a whole?  Are you referring to setting
> the interrupt flag?

Yes (it being cleared).

> Thanks for the input, it's appreciated, and sorry for diverging the
> conversation so much.

I think that's quite fine, because aspects like the one still in context
are at least potentially relevant. Especially since here we're not
dealing with architectural behavior, but with an extrapolation thereof.
And views may (and apparently do) differ as to what the correct
extrapolation would be, even if just for corner aspects.

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled
  2022-11-21 12:23         ` Andrew Cooper
  2022-11-21 12:34           ` Jan Beulich
@ 2022-12-05 13:44           ` Jan Beulich
  1 sibling, 0 replies; 30+ messages in thread
From: Jan Beulich @ 2022-12-05 13:44 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Wei Liu, Roger Pau Monne, Paul Durrant, xen-devel

On 21.11.2022 13:23, Andrew Cooper wrote:
> On 21/11/2022 08:56, Jan Beulich wrote:
>> On 18.11.2022 15:27, Andrew Cooper wrote:
>>> On 18/11/2022 12:54, Jan Beulich wrote:
>>>> On 18.11.2022 13:33, Andrew Cooper wrote:
>>>>> On 18/11/2022 10:31, Jan Beulich wrote:
>>>>>> Linux'es relatively new use of HVMOP_set_evtchn_upcall_vector has
>>>>>> exposed a problem with the marking of the respective vector as
>>>>>> pending: For quite some time Linux has been checking whether any stale
>>>>>> ISR or IRR bits would still be set while preparing the LAPIC for use.
>>>>>> This check is now triggering on the upcall vector, as the registration,
>>>>>> at least for APs, happens before the LAPIC is actually enabled.
>>>>>>
>>>>>> In software-disabled state an LAPIC would not accept any interrupt
>>>>>> requests and hence no IRR bit would newly become set while in this
>>>>>> state. As a result it is also wrong for us to mark the upcall vector as
>>>>>> having a pending request when the vLAPIC is in this state.
>>>>> I agree with this.
>>>>>
>>>>>> To compensate for the "enabled" check added to the assertion logic, add
>>>>>> logic to (conditionally) mark the upcall vector as having a request
>>>>>> pending at the time the LAPIC is being software-enabled by the guest.
>>>>> But this, I don't think is appropriate.
>>>>>
>>>>> The point of raising on enable is allegedly to work around setup race
>>>>> conditions.  I'm unconvinced by this reasoning, but it is what it is,
>>>>> and the stated behaviour is to raise there and then.
>>>>>
>>>>> If a guest enables evtchn while the LAPIC is disabled, then the
>>>>> interrupt is lost.  Like every other interrupt in an x86 system.
>>>> Edge triggered ones you mean, I suppose, but yes.
>>> For IO-APIC systems, you mostly lose line interrupts too, don't you?
>>>
>>> The line will remain pending at the IO-APIC, but nothing in the system
>>> will unwedge until someone polls the IO-APIC.
>>>
>>> Either way...
>>>
>>>>> I don't think there is any credible way a guest kernel author can expect
>>>>> the weird evtchn edgecase to wait for an arbitrary point in the future,
>>>>> and it's a corner case that I think is worth not keeping.
>>>> Well - did you look at 7b5b8ca7dffd ("x86/upcall: inject a spurious event
>>>> after setting upcall vector"), referenced by the Fixes: tag? The issue is
>>>> that with evtchn_upcall_pending once set, there would never again be a
>>>> notification.
>>> Ok, so we do need to do something.
>>>
>>>>  So if what you say is to be the model we follow, then that
>>>> earlier change was perhaps wrong as well. Instead it should then have
>>>> been a guest change (as also implicit from your reply) to clear
>>>> evtchn_upcall_pending after vCPU info registration (there) or LAPIC
>>>> enabling (here), perhaps by way of "manually" invoking the handling of
>>>> that pending event, or by issuing a self-IPI with that vector.
>>>> Especially the LAPIC enabling case would then be yet another Xen-specific
>>>> on a guest code path which better wouldn't have to be aware of Xen. 
>>> Without trying to prescribe how to fix this specific issue, wherever
>>> possible we should be trying to limit the Xen-isms from non-Xen areas. 
>>> There's a whole lot of poorly described and surprising behaviours which
>>> have not stood the test of time.
>>>
>>> In this case, it seems that we have yet another x86 PV-ism which hasn't
>>> translated well x86 HVM.  Specifically, we're trying to overlay an
>>> entirely shared-memory (and delayed return-to-guest) interrupt
>>> controller onto one which is properly constructed to handle events in
>>> realtime.
>>>
>>>
>>> I even got as far as writing that maybe leaving it as-is was the best
>>> option (principle of least surprise for Xen developers), but our
>>> "friend" apic acceleration strikes again.
>>>
>>> Xen doesn't always get a VMExit when the guest clears SW_DISABLE,
>>> because microcode may have accelerated it.
>> But as per "APIC-Write Emulation" in the SDM we'd still get an APIC-write
>> VM exit.
> 
> Intel isn't the only accelerated implementation, and there future
> details not in the public docs.
> 
> There will be an implementation we will want to support where Xen
> doesn't get a vmexit for a write to SPIV.

To cover for that, as just discussed, I've added

"Note however that, like for the pt_may_unmask_irq() we already have
 there, long term we may need to find a different solution. This will be
 especially relevant in case yet better LAPIC acceleration would
 eliminate notifications of guest writes to this and other registers."

to the last paragraph of the commit message.

Jan


^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2022-12-05 13:44 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-18 10:31 [PATCH] x86/HVM: don't mark evtchn upcall vector as pending when vLAPIC is disabled Jan Beulich
2022-11-18 12:31 ` Juergen Gross
2022-11-18 12:33 ` Andrew Cooper
2022-11-18 12:51   ` Roger Pau Monné
2022-11-18 12:54   ` Jan Beulich
2022-11-18 13:55     ` Roger Pau Monné
2022-11-18 13:58       ` Jan Beulich
2022-11-18 14:09         ` Roger Pau Monné
2022-11-18 14:27     ` Andrew Cooper
2022-11-21  8:56       ` Jan Beulich
2022-11-21 12:23         ` Andrew Cooper
2022-11-21 12:34           ` Jan Beulich
2022-11-23 12:03             ` Roger Pau Monné
2022-11-24  7:59               ` Jan Beulich
2022-11-24  8:42                 ` Roger Pau Monné
2022-11-24  9:06                   ` Roger Pau Monné
2022-11-24  9:11                     ` Jan Beulich
2022-11-24  9:33                       ` Roger Pau Monné
2022-11-24 11:16                         ` Jan Beulich
2022-11-24 15:12                           ` Roger Pau Monné
2022-11-25  8:43                             ` Jan Beulich
2022-11-25  9:00                               ` Roger Pau Monné
2022-11-25  9:09                                 ` Jan Beulich
2022-11-24  9:06                   ` Jan Beulich
2022-12-05 13:44           ` Jan Beulich
2022-11-18 14:26 ` Roger Pau Monné
2022-11-21  8:33   ` Jan Beulich
2022-11-21 10:53     ` Roger Pau Monné
2022-11-21 11:14       ` Jan Beulich
2022-11-21 12:06     ` Jan Beulich

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.