|
[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 |