From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Wang2 Subject: [PATCH] AMD IOMMU: Reset event logging when event overflows Date: Wed, 16 Dec 2009 16:50:58 +0100 Message-ID: <200912161650.59394.wei.wang2@amd.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary-00=_jHQKLtLv5Uz+EmR" Return-path: Content-Disposition: inline List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org --Boundary-00=_jHQKLtLv5Uz+EmR Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Attached patch restarts iommu event logging if EventOverFlow bit is set to= =20 prevent event logging from being disabled after event overflows. Thanks, Wei Signed-off-by: Wei Wang =2D- Legal Information: Advanced Micro Devices GmbH Karl-Hammerschmidt-Str. 34 85609 Dornach b. M=FCnchen Gesch=E4ftsf=FChrer: Andrew Bowd, Thomas M. McCoy, Giuliano Meroni Sitz: Dornach, Gemeinde Aschheim, Landkreis M=FCnchen Registergericht M=FCnchen, HRB Nr. 43632 --Boundary-00=_jHQKLtLv5Uz+EmR Content-Type: text/x-diff; charset="us-ascii"; name="reset.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="reset.patch" diff -r 0f332e986bae xen/drivers/passthrough/amd/iommu_init.c --- a/xen/drivers/passthrough/amd/iommu_init.c Wed Dec 16 15:50:35 2009 +0100 +++ b/xen/drivers/passthrough/amd/iommu_init.c Wed Dec 16 15:58:09 2009 +0100 @@ -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 iommu_msi_set_affinity(unsigned int irq, cpumask_t mask) @@ -459,14 +497,24 @@ static void amd_iommu_page_fault(int irq static void amd_iommu_page_fault(int irq, 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, @@ -474,10 +522,6 @@ static void amd_iommu_page_fault(int irq 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) --Boundary-00=_jHQKLtLv5Uz+EmR Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --Boundary-00=_jHQKLtLv5Uz+EmR--