[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 2 of 2] Move IOMMU faults handling into softirq for AMD-Vi.
On Monday 19 December 2011 19:53:32 Dario Faggioli wrote: > Dealing with interrupts from AMD-Vi IOMMU is deferred to a softirq-tasklet, > raised by the actual IRQ handler. To avoid more interrupts being generated > (because of further faults), they must be masked in the IOMMU within the > low level IRQ handler and enabled back in the tasklet body. Notice that > this may cause the log to overflow, but none of the existing entry will > be overwritten. > > Signed-off-by: Dario Faggioli <dario.faggioli@xxxxxxxxxx> > > diff -r 12cc8fc9a908 xen/drivers/passthrough/amd/iommu_init.c > --- a/xen/drivers/passthrough/amd/iommu_init.c Mon Dec 19 16:46:14 2011 > +0000 +++ b/xen/drivers/passthrough/amd/iommu_init.c Mon Dec 19 16:46:39 > 2011 +0000 @@ -32,6 +32,8 @@ > > static int __initdata nr_amd_iommus; > > +static struct tasklet amd_iommu_fault_tasklet; > + > unsigned short ivrs_bdf_entries; > static struct radix_tree_root ivrs_maps; > struct list_head amd_iommu_head; > @@ -522,12 +524,10 @@ static void parse_event_log_entry(struct > } > } > > -static void amd_iommu_page_fault(int irq, void *dev_id, > - struct cpu_user_regs *regs) > +static void __do_amd_iommu_page_fault(struct amd_iommu *iommu) > { > u32 entry; > unsigned long flags; > - struct amd_iommu *iommu = dev_id; > > spin_lock_irqsave(&iommu->lock, flags); > amd_iommu_read_event_log(iommu); > @@ -546,6 +546,43 @@ static void amd_iommu_page_fault(int irq > spin_unlock_irqrestore(&iommu->lock, flags); > } > > +static void do_amd_iommu_page_fault(unsigned long data) > +{ > + struct amd_iommu *iommu; > + > + if ( list_empty(&amd_iommu_head) ) Here you could use iommu_found(). Rest part of this patch looks good to me. Thanks, Wei > + { > + AMD_IOMMU_DEBUG("no device found, something must be very > wrong!\n"); + return; > + } > + > + /* No matter from whom the interrupt came from, check all the > + * IOMMUs present in the system. This allows for having just one > + * tasklet (instead of one per each IOMMU) and should be more than > + * fine, considering how rare the event of a fault should be. */ > +for_each_amd_iommu ( iommu ) > + __do_amd_iommu_page_fault(iommu); > +} > + > +static void amd_iommu_page_fault(int irq, void *dev_id, > + struct cpu_user_regs *regs) > +{ > + u32 entry; > + unsigned long flags; > + struct amd_iommu *iommu = dev_id; > + > + /* silence interrupts. The tasklet will enable them back */ > + spin_lock_irqsave(&iommu->lock, flags); > + entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); > + iommu_clear_bit(&entry, IOMMU_STATUS_EVENT_LOG_INT_SHIFT); > + writel(entry, iommu->mmio_base+IOMMU_STATUS_MMIO_OFFSET); > + spin_unlock_irqrestore(&iommu->lock, flags); > + > + /* Flag the tasklet as runnable so that it can execute, clear > + * the log and re-enable interrupts. */ > + tasklet_schedule(&amd_iommu_fault_tasklet); > +} > + > static int __init set_iommu_interrupt_handler(struct amd_iommu *iommu) > { > int irq, ret; > @@ -884,6 +921,8 @@ int __init amd_iommu_init(void) > if ( amd_iommu_init_one(iommu) != 0 ) > goto error_out; > > + softirq_tasklet_init(&amd_iommu_fault_tasklet, > do_amd_iommu_page_fault, 0); + > return 0; > > error_out: _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |