diff mbox

[5/5] x86/vioapic: bind interrupts to PVH Dom0

Message ID 20170327104429.99992-6-roger.pau@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Roger Pau Monné March 27, 2017, 10:44 a.m. UTC
Add the glue in order to bind the PVH Dom0 GSI from bare metal. This is done
when Dom0 unmasks the vIO APIC pins, by fetching the current pin settings and
setting up the PIRQ, which will then be bound to Dom0 using the newly
introduced PT_IRQ_TYPE_GSI bind type.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
---
 xen/arch/x86/hvm/vioapic.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

Comments

Jan Beulich April 18, 2017, 12:35 p.m. UTC | #1
>>> On 27.03.17 at 12:44, <roger.pau@citrix.com> wrote:
> --- a/xen/arch/x86/hvm/vioapic.c
> +++ b/xen/arch/x86/hvm/vioapic.c
> @@ -199,6 +199,34 @@ static void vioapic_write_redirent(
>          unmasked = unmasked && !ent.fields.mask;
>      }
>  
> +    if ( is_hardware_domain(d) && unmasked )
> +    {
> +        xen_domctl_bind_pt_irq_t pt_irq_bind = {
> +            .irq_type = PT_IRQ_TYPE_GSI,
> +            .machine_irq = gsi,
> +            .u.gsi.gsi = gsi,
> +            .hvm_domid = DOMID_SELF,
> +        };
> +        int ret, pirq = gsi;
> +
> +        /* Interrupt has been unmasked, bind it now. */
> +        ret = mp_register_gsi(gsi, ent.fields.trig_mode, ent.fields.polarity);
> +        if ( ret && ret != -EEXIST )
> +        {
> +            gdprintk(XENLOG_WARNING,
> +                     "%s: error registering GSI %u: %d\n", __func__, gsi, ret);
> +        }
> +        if ( !ret )
> +        {
> +            ret = physdev_map_pirq(DOMID_SELF, MAP_PIRQ_TYPE_GSI, &pirq, &pirq,
> +                                   NULL);

With this call you basically admit that PVH can't really do without
physdev ops, just that you hide it behind IO-APIC RTE writes.
Along the lines of the comment on the previous patch I wonder
though whether you really need to use this function, i.e.
whether you can't instead get away with little more than the
call to map_domain_pirq() which that function does.

> +            BUG_ON(ret);

You absolutely don't want to bring down the entire system if a
failure occurs here or ...

> +            ret = pt_irq_create_bind(d, &pt_irq_bind);
> +            BUG_ON(ret);

... here. Probably the best you can do besides issuing a log
message is to mask the RTE.

Jan
Roger Pau Monné April 18, 2017, 1:44 p.m. UTC | #2
On Tue, Apr 18, 2017 at 06:35:57AM -0600, Jan Beulich wrote:
> >>> On 27.03.17 at 12:44, <roger.pau@citrix.com> wrote:
> > --- a/xen/arch/x86/hvm/vioapic.c
> > +++ b/xen/arch/x86/hvm/vioapic.c
> > @@ -199,6 +199,34 @@ static void vioapic_write_redirent(
> >          unmasked = unmasked && !ent.fields.mask;
> >      }
> >  
> > +    if ( is_hardware_domain(d) && unmasked )
> > +    {
> > +        xen_domctl_bind_pt_irq_t pt_irq_bind = {
> > +            .irq_type = PT_IRQ_TYPE_GSI,
> > +            .machine_irq = gsi,
> > +            .u.gsi.gsi = gsi,
> > +            .hvm_domid = DOMID_SELF,
> > +        };
> > +        int ret, pirq = gsi;
> > +
> > +        /* Interrupt has been unmasked, bind it now. */
> > +        ret = mp_register_gsi(gsi, ent.fields.trig_mode, ent.fields.polarity);
> > +        if ( ret && ret != -EEXIST )
> > +        {
> > +            gdprintk(XENLOG_WARNING,
> > +                     "%s: error registering GSI %u: %d\n", __func__, gsi, ret);
> > +        }
> > +        if ( !ret )
> > +        {
> > +            ret = physdev_map_pirq(DOMID_SELF, MAP_PIRQ_TYPE_GSI, &pirq, &pirq,
> > +                                   NULL);
> 
> With this call you basically admit that PVH can't really do without
> physdev ops, just that you hide it behind IO-APIC RTE writes.

Yes, I just want to get rid of the physdev hypercalls for PVH Dom0, not the
physdev ops inside of Xen.

> Along the lines of the comment on the previous patch I wonder
> though whether you really need to use this function, i.e.
> whether you can't instead get away with little more than the
> call to map_domain_pirq() which that function does.

Well, I could certainly open-code part of physdev_map_pirq here, AFAICT I just
need to make sure the GSI is not used, and bind it to Dom0, but that's just
duplicating the code inside of physdev_map_pirq.

For MSI/MSI-X I certainly need to use physdev_map_pirq, because the logic in
that case is more complex, so I will have to end up making physdev_map_pirq
available to external callers in any case.

> 
> > +            BUG_ON(ret);
> 
> You absolutely don't want to bring down the entire system if a
> failure occurs here or ...
> 
> > +            ret = pt_irq_create_bind(d, &pt_irq_bind);
> > +            BUG_ON(ret);
> 
> ... here. Probably the best you can do besides issuing a log
> message is to mask the RTE.

Right, those are leftovers from when I was still debugging this.

Thanks, Roger.
Jan Beulich April 18, 2017, 2:17 p.m. UTC | #3
>>> On 18.04.17 at 15:44, <roger.pau@citrix.com> wrote:
> On Tue, Apr 18, 2017 at 06:35:57AM -0600, Jan Beulich wrote:
>> >>> On 27.03.17 at 12:44, <roger.pau@citrix.com> wrote:
>> > --- a/xen/arch/x86/hvm/vioapic.c
>> > +++ b/xen/arch/x86/hvm/vioapic.c
>> > @@ -199,6 +199,34 @@ static void vioapic_write_redirent(
>> >          unmasked = unmasked && !ent.fields.mask;
>> >      }
>> >  
>> > +    if ( is_hardware_domain(d) && unmasked )
>> > +    {
>> > +        xen_domctl_bind_pt_irq_t pt_irq_bind = {
>> > +            .irq_type = PT_IRQ_TYPE_GSI,
>> > +            .machine_irq = gsi,
>> > +            .u.gsi.gsi = gsi,
>> > +            .hvm_domid = DOMID_SELF,
>> > +        };
>> > +        int ret, pirq = gsi;
>> > +
>> > +        /* Interrupt has been unmasked, bind it now. */
>> > +        ret = mp_register_gsi(gsi, ent.fields.trig_mode, ent.fields.polarity);
>> > +        if ( ret && ret != -EEXIST )
>> > +        {
>> > +            gdprintk(XENLOG_WARNING,
>> > +                     "%s: error registering GSI %u: %d\n", __func__, gsi, ret);
>> > +        }
>> > +        if ( !ret )
>> > +        {
>> > +            ret = physdev_map_pirq(DOMID_SELF, MAP_PIRQ_TYPE_GSI, &pirq, &pirq,
>> > +                                   NULL);
>> 
>> With this call you basically admit that PVH can't really do without
>> physdev ops, just that you hide it behind IO-APIC RTE writes.
> 
> Yes, I just want to get rid of the physdev hypercalls for PVH Dom0, not the
> physdev ops inside of Xen.
> 
>> Along the lines of the comment on the previous patch I wonder
>> though whether you really need to use this function, i.e.
>> whether you can't instead get away with little more than the
>> call to map_domain_pirq() which that function does.
> 
> Well, I could certainly open-code part of physdev_map_pirq here, AFAICT I just
> need to make sure the GSI is not used, and bind it to Dom0, but that's just
> duplicating the code inside of physdev_map_pirq.
> 
> For MSI/MSI-X I certainly need to use physdev_map_pirq, because the logic in
> that case is more complex, so I will have to end up making physdev_map_pirq
> available to external callers in any case.

Hmm, ugly. I'd really like to keep them local as they are - as their
name says - physdev-op specific. Would it perhaps be possible to
split out GSI and MSI specific helpers from it (which you could
then call from here and from the MSI code you're going to add),
or would that still leave too much code duplication?

Jan
diff mbox

Patch

diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index c349a3ee61..ca3aab16ef 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -199,6 +199,34 @@  static void vioapic_write_redirent(
         unmasked = unmasked && !ent.fields.mask;
     }
 
+    if ( is_hardware_domain(d) && unmasked )
+    {
+        xen_domctl_bind_pt_irq_t pt_irq_bind = {
+            .irq_type = PT_IRQ_TYPE_GSI,
+            .machine_irq = gsi,
+            .u.gsi.gsi = gsi,
+            .hvm_domid = DOMID_SELF,
+        };
+        int ret, pirq = gsi;
+
+        /* Interrupt has been unmasked, bind it now. */
+        ret = mp_register_gsi(gsi, ent.fields.trig_mode, ent.fields.polarity);
+        if ( ret && ret != -EEXIST )
+        {
+            gdprintk(XENLOG_WARNING,
+                     "%s: error registering GSI %u: %d\n", __func__, gsi, ret);
+        }
+        if ( !ret )
+        {
+            ret = physdev_map_pirq(DOMID_SELF, MAP_PIRQ_TYPE_GSI, &pirq, &pirq,
+                                   NULL);
+            BUG_ON(ret);
+
+            ret = pt_irq_create_bind(d, &pt_irq_bind);
+            BUG_ON(ret);
+        }
+    }
+
     *pent = ent;
 
     if ( gsi == 0 )