qemu-devel
[Top][All Lists]
Advanced

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

Re: [RFC PATCH] intel-iommu: Report interrupt remapping faults


From: David Woodhouse
Subject: Re: [RFC PATCH] intel-iommu: Report interrupt remapping faults
Date: Sat, 11 Mar 2023 10:30:02 +0000
User-agent: Evolution 3.44.4-0ubuntu1

On Fri, 2023-03-10 at 15:57 -0500, Peter Xu wrote:
> On Fri, Mar 10, 2023 at 05:49:38PM +0000, David Woodhouse wrote:
> > From: David Woodhouse <dwmw@amazon.co.uk>
> > 
> > +}
> > +
> > +#define log_irte_fault(f, sid, i) vtd_report_ir_fault(iommu, sid, f, i)
> 
> This one seems not used.

Oops yes, that was supposed to be temporary until I did the
search/replace.

> > +
> >  /* Handle Invalidation Queue Errors of queued invalidation interface error
> >   * conditions.
> >   */
> > @@ -3300,7 +3320,8 @@ static Property vtd_properties[] = {
> >  
> >  /* Read IRTE entry with specific index */
> >  static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
> > -                        VTD_IR_TableEntry *entry, uint16_t sid)
> > +                        VTD_IR_TableEntry *entry, uint16_t sid,
> > +                        bool do_fault)
> >  {
> >      static const uint16_t vtd_svt_mask[VTD_SQ_MAX] = \
> >          {0xffff, 0xfffb, 0xfff9, 0xfff8};
> > @@ -3311,6 +3332,9 @@ static int vtd_irte_get(IntelIOMMUState *iommu, 
> > uint16_t index,
> >      if (index >= iommu->intr_size) {
> >          error_report_once("%s: index too large: ind=0x%x",
> >                            __func__, index);
> > +        if (do_fault) {
> > +            vtd_report_ir_fault(iommu, sid, VTD_FR_IR_INDEX_OVER, index);
> > +        }
> 
> IIUC it's only the fault reason to report, then I am thinking if it's
> easier to let the caller taking care of that?
> 
> Though we'll need conditions for fault disabled, e.g....
> 
> >          return -VTD_FR_IR_INDEX_OVER;

Well, remember I want to kill that *return* of the VTD_FR_xxx error, so
although it looks like duplication now, it won't be.


> >      }
> >  
> > @@ -3319,17 +3343,33 @@ static int vtd_irte_get(IntelIOMMUState *iommu, 
> > uint16_t index,
> >                          entry, sizeof(*entry), MEMTXATTRS_UNSPECIFIED)) {
> >          error_report_once("%s: read failed: ind=0x%x addr=0x%" PRIx64,
> >                            __func__, index, addr);
> > +        if (do_fault) {
> > +            vtd_report_ir_fault(iommu, sid, VTD_FR_IR_ROOT_INVAL, index);
> > +        }
> >          return -VTD_FR_IR_ROOT_INVAL;
> >      }
> >  
> >      trace_vtd_ir_irte_get(index, le64_to_cpu(entry->data[1]),
> >                            le64_to_cpu(entry->data[0]));
> >  
> > +       /*
> > +        * The remaining potential fault conditions are "qualified" by the
> > +        * Fault Processing Disable bit in the IRTE. Even "not present".
> > +        * So just clear the do_fault flag if PFD is set, which will
> > +        * prevent faults being raised.
> > +        */
> > +       if (entry->irte.fault_disable) {
> > +               do_fault = false;
> > +    }
> > +
> >      if (!entry->irte.present) {
> >          error_report_once("%s: detected non-present IRTE "
> >                            "(index=%u, high=0x%" PRIx64 ", low=0x%" PRIx64 
> > ")",
> >                            __func__, index, le64_to_cpu(entry->data[1]),
> >                            le64_to_cpu(entry->data[0]));
> > +        if (do_fault) {
> > +            vtd_report_ir_fault(iommu, sid, VTD_FR_IR_ENTRY_P, index);
> > +        }
> >          return -VTD_FR_IR_ENTRY_P;
> 
> ... here IIUC we can do:
> 
>   if (entry->irte.fault_disable)
>         return 0;
>   else
>         return -VTD_FR_IR_ENTRY_P;
>         
> Hence when error occurs we always keep the error report above, and let the
> caller report IR fault when <0.  It seems this will at least avoid plenty
> of same calls within vtd_irte_get().
> 
> I do see a few others outside vtd_irte_get().  In short, it'll be nice to
> avoid calling this same pattern in multiple places somehow.

I suppose we could pass the do_fault *into* vtd_report_ir_fault(). It's
a similar pattern to vtd_report_fault() which also takes an is_fpd_set
argument.

(Note: If I could tolerate just passing VTD_FRCD_IR_IDX(index) I think
I could actually just *call* the existing vtd_report_fault() without
having to touch any of the fault reporting functions at all. The bits
do all end up in the right place. It just seemed a bit icky.)

I did briefly ponder just returning the value and then letting the
caller do the report, but then we'd *also* have to make the return code
distinguish between "failed, but do not report a fault" and "succeeded,
and your translation is valid" cases. I figured I preferred it this
way.


> > --- a/hw/i386/intel_iommu_internal.h
> > +++ b/hw/i386/intel_iommu_internal.h
> > @@ -268,6 +268,7 @@
> >  #define VTD_FRCD_FI(val)        ((val) & ~0xfffULL)
> >  #define VTD_FRCD_PV(val)        (((val) & 0xffffULL) << 40)
> >  #define VTD_FRCD_PP(val)        (((val) & 0x1) << 31)
> > +#define VTD_FRCD_IR_IDX(val)    (((val) & 0xffffULL) << 48)


Think 'val' probably needs casting to a (uint64_t) before the shift there.

Attachment: smime.p7s
Description: S/MIME cryptographic signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]