[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-3.4-testing] AMD IOMMU: Reset event logging when event overflows
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1262596167 0 # Node ID a7b2d4e03a1f4d0b4796378aa1cfc8e2908d4624 # Parent a5b0c000a9d90d949fc4f47d4ba3424ee1258dea AMD IOMMU: Reset event logging when event overflows Restart iommu event logging if EventOverFlow bit is set to prevent event logging from being disabled after event overflows. Signed-off-by: Wei Wang <wei.wang2@xxxxxxx> xen-unstable changeset: 20653:84de9733e3ee xen-unstable date: Wed Dec 16 16:47:31 2009 +0000 --- xen/drivers/passthrough/amd/iommu_init.c | 92 ++++++++++++++++++++++--------- 1 files changed, 68 insertions(+), 24 deletions(-) diff -r a5b0c000a9d9 -r a7b2d4e03a1f xen/drivers/passthrough/amd/iommu_init.c --- a/xen/drivers/passthrough/amd/iommu_init.c Wed Dec 30 13:21:41 2009 +0000 +++ b/xen/drivers/passthrough/amd/iommu_init.c Mon Jan 04 09:09:27 2010 +0000 @@ -270,26 +270,65 @@ static void set_iommu_event_log_control( writel(entry, iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); } -static int amd_iommu_read_event_log(struct amd_iommu *iommu, u32 event[]) +static void amd_iommu_reset_event_log(struct amd_iommu *iommu) +{ + u32 entry; + int log_run; + int loop_count = 1000; + + /* wait until EventLogRun bit = 0 */ + do { + entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); + log_run = get_field_from_reg_u32(entry, + IOMMU_STATUS_EVENT_LOG_RUN_MASK, + IOMMU_STATUS_EVENT_LOG_RUN_SHIFT); + loop_count--; + } while ( log_run && loop_count ); + + if ( log_run ) + { + AMD_IOMMU_DEBUG("Warning: EventLogRun bit is not cleared" + "before reset!\n"); + return; + } + + set_iommu_event_log_control(iommu, IOMMU_CONTROL_DISABLED); + + /*clear overflow bit */ + set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, entry, + IOMMU_STATUS_EVENT_OVERFLOW_MASK, + IOMMU_STATUS_EVENT_OVERFLOW_SHIFT, &entry); + writel(entry, iommu->mmio_base+IOMMU_STATUS_MMIO_OFFSET); + + /*reset event log base address */ + iommu->event_log_head = 0; + + set_iommu_event_log_control(iommu, IOMMU_CONTROL_ENABLED); +} + +static void parse_event_log_entry(u32 entry[]); + +static int amd_iommu_read_event_log(struct amd_iommu *iommu) { u32 tail, head, *event_log; - int i; - - BUG_ON( !iommu || !event ); + + BUG_ON( !iommu ); /* make sure there's an entry in the log */ - tail = get_field_from_reg_u32( - readl(iommu->mmio_base + IOMMU_EVENT_LOG_TAIL_OFFSET), - IOMMU_EVENT_LOG_TAIL_MASK, - IOMMU_EVENT_LOG_TAIL_SHIFT); - if ( tail != iommu->event_log_head ) + tail = readl(iommu->mmio_base + IOMMU_EVENT_LOG_TAIL_OFFSET); + tail = get_field_from_reg_u32(tail, + IOMMU_EVENT_LOG_TAIL_MASK, + IOMMU_EVENT_LOG_TAIL_SHIFT); + + while ( tail != iommu->event_log_head ) { /* read event log entry */ event_log = (u32 *)(iommu->event_log.buffer + - (iommu->event_log_head * - IOMMU_EVENT_LOG_ENTRY_SIZE)); - for ( i = 0; i < IOMMU_EVENT_LOG_U32_PER_ENTRY; i++ ) - event[i] = event_log[i]; + (iommu->event_log_head * + IOMMU_EVENT_LOG_ENTRY_SIZE)); + + parse_event_log_entry(event_log); + if ( ++iommu->event_log_head == iommu->event_log.entries ) iommu->event_log_head = 0; @@ -298,10 +337,9 @@ static int amd_iommu_read_event_log(stru IOMMU_EVENT_LOG_HEAD_MASK, IOMMU_EVENT_LOG_HEAD_SHIFT, &head); writel(head, iommu->mmio_base + IOMMU_EVENT_LOG_HEAD_OFFSET); - return 0; - } - - return -EFAULT; + } + + return 0; } static void amd_iommu_msi_data_init(struct amd_iommu *iommu) @@ -455,14 +493,24 @@ static void amd_iommu_page_fault(int vec static void amd_iommu_page_fault(int vector, void *dev_id, struct cpu_user_regs *regs) { - u32 event[4]; u32 entry; unsigned long flags; - int ret = 0; + int of; struct amd_iommu *iommu = dev_id; spin_lock_irqsave(&iommu->lock, flags); - ret = amd_iommu_read_event_log(iommu, event); + amd_iommu_read_event_log(iommu); + + /*check event overflow */ + entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); + of = get_field_from_reg_u32(entry, + IOMMU_STATUS_EVENT_OVERFLOW_MASK, + IOMMU_STATUS_EVENT_OVERFLOW_SHIFT); + + /* reset event log if event overflow */ + if ( of ) + amd_iommu_reset_event_log(iommu); + /* reset interrupt status bit */ entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, @@ -470,10 +518,6 @@ static void amd_iommu_page_fault(int vec IOMMU_STATUS_EVENT_LOG_INT_SHIFT, &entry); writel(entry, iommu->mmio_base+IOMMU_STATUS_MMIO_OFFSET); spin_unlock_irqrestore(&iommu->lock, flags); - - if ( ret != 0 ) - return; - parse_event_log_entry(event); } static int set_iommu_interrupt_handler(struct amd_iommu *iommu) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |