[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [Patch RFC 02/13] vt-d: Register MSI for async invalidation completion interrupt.



>> >>> On 29.09.2015 at 16:57 <JBeulich@xxxxxxxx> wrote:
> >>> On 16.09.15 at 15:23, <quan.xu@xxxxxxxxx> wrote:
> > +/* IOMMU Queued Invalidation(QI). */
> > +static void _qi_msi_unmask(struct iommu *iommu) {
> > +    u32 sts;
> > +    unsigned long flags;
> > +
> > +    /* Clear IM bit of DMAR_IECTL_REG. */
> > +    spin_lock_irqsave(&iommu->register_lock, flags);
> > +    sts = dmar_readl(iommu->reg, DMAR_IECTL_REG);
> > +    sts &= ~DMA_IECTL_IM;
> > +    dmar_writel(iommu->reg, DMAR_IECTL_REG, sts);
> > +    spin_unlock_irqrestore(&iommu->register_lock, flags); }
> 
> I think rather than duplicating all this code from the fault interrupt you 
> should
> instead re-factor to make the original usable for both purposes. Afaics the
> differences really are just the register and bit locations.
> 

hw_irq_controller is a common data structure for arm/amd/x86.
For reusing these function, I should redefine the function pointers 
.set_affinity / . startup .etc.
It takes much effort to modify the other arm/amd/x86 code.


> > +static void _do_iommu_qi(struct iommu *iommu) { }
> 
> ???
> 

Now it still has no knowledge about ATS.


> > +static void qi_msi_unmask(struct irq_desc *desc) {
> > +    _qi_msi_unmask(desc->action->dev_id);
> > +}
> > +
> > +static void qi_msi_mask(struct irq_desc *desc) {
> > +    _qi_msi_mask(desc->action->dev_id);
> > +}
> 
> These wrappers look pretty pointless.
> 

I will modify it in next version.


> > +static void qi_msi_end(struct irq_desc *desc, u8 vector) {
> > +    ack_APIC_irq();
> > +}
> 
> Why is there, other than for its fault counterpart, no unmask operation here?
> 


 In my design: I try to optimize it in interrupt handler(or associated tasklet):
Check the IP field at the end of interrupt handler, if it is Set, try to scan 
the domain list again, instead of clear IM to cause another Interrupt.
For the logic of IWC/IP/IM as below:

                       Interrupt condition (An invalidation wait descriptor 
with Interrupt Flag(IF) field Set completed.)
                            ||
                             v
           ----------------------(IWC) ----------------------
           (IWC is Set)                     (IWC is not Set)
               ||                              ||
               V                              ||
(Not treated as an new interrupt condition)         ||
                                               ||
                                               V
                                             (Set IWC / IP)
                                               ||
                                               V
                         ------------------------------(IM)---------------------
                       (IM is Set)                               (IM not Set)
                        ||                                        ||
                        ||                                        V
                        ||                    (cause Interrupt message / then 
hardware clear IP)
                        ||
                        V
   (interrupt is held pending, clearing IM to cause interrupt message)
  

And, If you clear IWC, the IP is cleared.


> > @@ -1123,6 +1243,7 @@ int __init iommu_alloc(struct acpi_drhd_unit *drhd)
> >          return -ENOMEM;
> >
> >      iommu->msi.irq = -1; /* No irq assigned yet. */
> > +    iommu->qi_msi.irq = -1; /* No irq assigned yet. */
> 
> Which suggests that (perhaps in patch 1) the existing field should be renamed 
> to
> e.g. fe_msi.
> 

I'd better rename the existing in next patch set. otherwise it is confusing.



> > @@ -1985,6 +2109,9 @@ static void adjust_irq_affinity(struct acpi_drhd_unit
> *drhd)
> >           cpumask_intersects(&node_to_cpumask(node), cpumask) )
> >          cpumask = &node_to_cpumask(node);
> >      dma_msi_set_affinity(irq_to_desc(drhd->iommu->msi.irq), cpumask);
> > +
> > +    if ( ats_enabled )
> > +        qi_msi_set_affinity(irq_to_desc(drhd->iommu->qi_msi.irq),
> > + cpumask);
> >  }
> >
> >  int adjust_vtd_irq_affinities(void)
> > @@ -2183,6 +2310,11 @@ int __init intel_vtd_setup(void)
> >
> >          ret = iommu_set_interrupt(drhd, &dma_msi_type, "dmar",
> &drhd->iommu->msi,
> >                                    iommu_page_fault);
> > +        if ( ats_enabled )
> > +            ret = iommu_set_interrupt(drhd, &qi_msi_type, "qi",
> > +                                      &drhd->iommu->qi_msi,
> > +                                      iommu_qi_completion);
> > +
> 
> Would there be any harm from leaving out most/all of these ats_enabled
> conditionals, despite right now that code only intended to be used for ATS
> invalidations? I.e. wouldn't it just be that the interrupt never triggers?
> 

No harm.
It is no use if the ATS is not enabled now.
It is only be triggered when an invalidation wait descriptor with Interrupt 
Flag(IF) field Set completed


> > --- a/xen/drivers/passthrough/vtd/iommu.h
> > +++ b/xen/drivers/passthrough/vtd/iommu.h
> > @@ -47,6 +47,11 @@
> >  #define    DMAR_IQH_REG    0x80    /* invalidation queue head */
> >  #define    DMAR_IQT_REG    0x88    /* invalidation queue tail */
> >  #define    DMAR_IQA_REG    0x90    /* invalidation queue addr */
> > +#define    DMAR_IECTL_REG  0xA0    /* invalidation event contrl register
> */
> > +#define    DMAR_IEDATA_REG 0xA4    /* invalidation event data register
> */
> > +#define    DMAR_IEADDR_REG 0xA8    /* invalidation event address
> register */
> > +#define    DMAR_IEUADDR_REG 0xAC   /* invalidation event upper
> address register */
> > +#define    DMAR_ICS_REG    0x9C    /* invalidation completion status
> register */
> 
> Numerically ordered please.
> 

Got it.


Quan






_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.