From patchwork Fri Feb 14 18:55:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11383131 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D82961820 for ; Fri, 14 Feb 2020 18:57:17 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B3742206CC for ; Fri, 14 Feb 2020 18:57:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="gZX8WNvG" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B3742206CC Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1j2g7t-0001eM-PQ; Fri, 14 Feb 2020 18:55:45 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1j2g7t-0001eH-4X for xen-devel@lists.xenproject.org; Fri, 14 Feb 2020 18:55:45 +0000 X-Inumbo-ID: 99d2d2f2-4f5b-11ea-baf6-12813bfff9fa Received: from esa6.hc3370-68.iphmx.com (unknown [216.71.155.175]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 99d2d2f2-4f5b-11ea-baf6-12813bfff9fa; Fri, 14 Feb 2020 18:55:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1581706543; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=nGISS6YL1u/XQT1xtWBRSPKszQ3ibsMfn3hLKKCTKNQ=; b=gZX8WNvGGPK5TLOpdQk3xMd0knFNYtblLiJZxbXRfFJdN9eOOyuPKBHt SC3SUiMb35+wkiHOkQE1I12beuRLGWyJucnBd+s9fZjDWlyYEtGDDdxC8 B6MFpZjFZsn/lqnPNoUgMcPi2t3GHzmYfeWT4YAroZw7AfwSp55sadgPh w=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa6.hc3370-68.iphmx.com: domain of Andrew.Cooper3@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ip4:168.245.78.127 ~all" Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: Q+FMqG4uQMOnfLrAWxV+LhgnDl9U9cAlShIRxgOF9SHHjnyjqh6aY1sW3g0w2xMjjpGgBVE46m n/pK2NgZrL6HG81iiz1amda/7ohA+qzMpE2x6r9tjDYVkSsAOs1YBuYp94dzouSo73rtzN3McF 6jayzbXNZyczIju1wMCzaBK1jk4GO6QWwlcudt9s5c+/fDL0ZlbdjLjLL/Y5HY8WkjO39zwv0i r/SbfvTqn+jflYtTxeYWlcie8i6sFW7tzSy1meJM41yrbVlS2MXDwuMEXVF2ROO8hkIQG8zkvk 6ug= X-SBRS: 2.7 X-MesageID: 12916363 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.70,441,1574139600"; d="scan'208";a="12916363" From: Andrew Cooper To: Xen-devel Date: Fri, 14 Feb 2020 18:55:39 +0000 Message-ID: <20200214185539.7444-1-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 MIME-Version: 1.0 Subject: [Xen-devel] [PATCH] AMD/IOMMU: Common the #732/#733 errata handling in iommu_read_log() X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Wei Liu , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" There is no need to have both helpers implement the same workaround. The size and layout of the the Event and PPR logs (and others for that matter) share a lot of commonality. Use MASK_EXTR() to locate the code field, and use ACCESS_ONCE() rather than barrier() to prevent hoisting of the repeated read. Avoid unnecessary zeroing by only clobbering the 'code' field - this alone is sufficient to spot the errata when the rings wrap. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné --- xen/drivers/passthrough/amd/iommu_init.c | 80 ++++++++++++-------------------- 1 file changed, 29 insertions(+), 51 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index c42b608f07..5de5315d8b 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -300,7 +300,7 @@ static int iommu_read_log(struct amd_iommu *iommu, unsigned int entry_size, void (*parse_func)(struct amd_iommu *, u32 *)) { - u32 tail, *entry, tail_offest, head_offset; + unsigned int tail, tail_offest, head_offset; BUG_ON(!iommu || ((log != &iommu->event_log) && (log != &iommu->ppr_log))); @@ -319,11 +319,36 @@ static int iommu_read_log(struct amd_iommu *iommu, while ( tail != log->head ) { - /* read event log entry */ - entry = log->buffer + log->head; + uint32_t *entry = log->buffer + log->head; + unsigned int count = 0; + + /* Event and PPR logs have their code field in the same position. */ + unsigned int code = MASK_EXTR(entry[1], IOMMU_EVENT_CODE_MASK); + + /* + * Workaround for errata #732, #733: + * + * It can happen that the tail pointer is updated before the actual + * entry got written. As suggested by RevGuide, we initialize the + * buffer to all zeros and clear entries after processing them. + */ + while ( unlikely(code == 0) ) + { + if ( unlikely(++count == IOMMU_LOG_ENTRY_TIMEOUT) ) + { + AMD_IOMMU_DEBUG("AMD-Vi: No entry written to %s Log\n", + log == &iommu->event_log ? "Event" : "PPR"); + return 0; + } + udelay(1); + code = MASK_EXTR(ACCESS_ONCE(entry[1]), IOMMU_EVENT_CODE_MASK); + } parse_func(iommu, entry); + /* Clear 'code' to be able to spot the erratum when the ring wraps. */ + ACCESS_ONCE(entry[1]) = 0; + log->head += entry_size; if ( log->head == log->size ) log->head = 0; @@ -503,7 +528,6 @@ static hw_irq_controller iommu_x2apic_type = { static void parse_event_log_entry(struct amd_iommu *iommu, u32 entry[]) { u32 code; - int count = 0; static const char *const event_str[] = { #define EVENT_STR(name) [IOMMU_EVENT_##name - 1] = #name EVENT_STR(ILLEGAL_DEV_TABLE_ENTRY), @@ -521,25 +545,6 @@ static void parse_event_log_entry(struct amd_iommu *iommu, u32 entry[]) code = get_field_from_reg_u32(entry[1], IOMMU_EVENT_CODE_MASK, IOMMU_EVENT_CODE_SHIFT); - /* - * Workaround for erratum 732: - * It can happen that the tail pointer is updated before the actual entry - * got written. As suggested by RevGuide, we initialize the event log - * buffer to all zeros and clear event log entries after processing them. - */ - while ( code == 0 ) - { - if ( unlikely(++count == IOMMU_LOG_ENTRY_TIMEOUT) ) - { - AMD_IOMMU_DEBUG("AMD-Vi: No event written to log\n"); - return; - } - udelay(1); - barrier(); /* Prevent hoisting of the entry[] read. */ - code = get_field_from_reg_u32(entry[1], IOMMU_EVENT_CODE_MASK, - IOMMU_EVENT_CODE_SHIFT); - } - /* Look up the symbolic name for code. */ if ( code <= ARRAY_SIZE(event_str) ) code_str = event_str[code - 1]; @@ -575,8 +580,6 @@ static void parse_event_log_entry(struct amd_iommu *iommu, u32 entry[]) else printk(XENLOG_ERR "%s %08x %08x %08x %08x\n", code_str, entry[0], entry[1], entry[2], entry[3]); - - memset(entry, 0, IOMMU_EVENT_LOG_ENTRY_SIZE); } static void iommu_check_event_log(struct amd_iommu *iommu) @@ -627,31 +630,8 @@ void parse_ppr_log_entry(struct amd_iommu *iommu, u32 entry[]) { u16 device_id; - u8 bus, devfn, code; + u8 bus, devfn; struct pci_dev *pdev; - int count = 0; - - code = get_field_from_reg_u32(entry[1], IOMMU_PPR_LOG_CODE_MASK, - IOMMU_PPR_LOG_CODE_SHIFT); - - /* - * Workaround for erratum 733: - * It can happen that the tail pointer is updated before the actual entry - * got written. As suggested by RevGuide, we initialize the event log - * buffer to all zeros and clear ppr log entries after processing them. - */ - while ( code == 0 ) - { - if ( unlikely(++count == IOMMU_LOG_ENTRY_TIMEOUT) ) - { - AMD_IOMMU_DEBUG("AMD-Vi: No ppr written to log\n"); - return; - } - udelay(1); - barrier(); /* Prevent hoisting of the entry[] read. */ - code = get_field_from_reg_u32(entry[1], IOMMU_PPR_LOG_CODE_MASK, - IOMMU_PPR_LOG_CODE_SHIFT); - } /* here device_id is physical value */ device_id = iommu_get_devid_from_cmd(entry[0]); @@ -664,8 +644,6 @@ void parse_ppr_log_entry(struct amd_iommu *iommu, u32 entry[]) if ( pdev ) guest_iommu_add_ppr_log(pdev->domain, entry); - - memset(entry, 0, IOMMU_PPR_LOG_ENTRY_SIZE); } static void iommu_check_ppr_log(struct amd_iommu *iommu)