From patchwork Fri Mar 25 02:13:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wang X-Patchwork-Id: 8667931 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id ACAC09F326 for ; Fri, 25 Mar 2016 02:17:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DE081203AE for ; Fri, 25 Mar 2016 02:17:20 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E1AAF20383 for ; Fri, 25 Mar 2016 02:17:19 +0000 (UTC) Received: from localhost ([::1]:53738 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ajHJP-0002jp-6z for patchwork-qemu-devel@patchwork.kernel.org; Thu, 24 Mar 2016 22:17:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50524) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ajHG4-0005On-8w for qemu-devel@nongnu.org; Thu, 24 Mar 2016 22:13:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ajHG2-0008FM-TE for qemu-devel@nongnu.org; Thu, 24 Mar 2016 22:13:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38944) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ajHG2-0008FA-LS for qemu-devel@nongnu.org; Thu, 24 Mar 2016 22:13:50 -0400 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id 5EA34627C5; Fri, 25 Mar 2016 02:13:50 +0000 (UTC) Received: from jason-ThinkPad-T430s.redhat.com (vpn1-7-152.pek2.redhat.com [10.72.7.152]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u2P2DUX5032064; Thu, 24 Mar 2016 22:13:47 -0400 From: Jason Wang To: mst@redhat.com, qemu-devel@nongnu.org Date: Fri, 25 Mar 2016 10:13:27 +0800 Message-Id: <1458872009-13342-7-git-send-email-jasowang@redhat.com> In-Reply-To: <1458872009-13342-1-git-send-email-jasowang@redhat.com> References: <1458872009-13342-1-git-send-email-jasowang@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 25 Mar 2016 02:13:50 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Cc: Eduardo Habkost , Jason Wang , peterx@redhat.com, cornelia.huck@de.ibm.com, pbonzini@redhat.com, Richard Henderson Subject: [Qemu-devel] [RFC PATCH 6/8] intel_iommu: support device iotlb descriptor X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch enables device IOTLB support for intel iommu. The major work is to implement QI device IOTLB descriptor processing and notify the device through iommu notifier. Cc: Paolo Bonzini Cc: Richard Henderson Cc: Eduardo Habkost Cc: Michael S. Tsirkin Signed-off-by: Jason Wang --- hw/i386/intel_iommu.c | 81 ++++++++++++++++++++++++++++++++++++++---- hw/i386/intel_iommu_internal.h | 13 +++++-- 2 files changed, 86 insertions(+), 8 deletions(-) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 36b2072..e23bf2c 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -728,11 +728,18 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num, "context-entry hi 0x%"PRIx64 " lo 0x%"PRIx64, ce->hi, ce->lo); return -VTD_FR_CONTEXT_ENTRY_INV; - } else if (ce->lo & VTD_CONTEXT_ENTRY_TT) { - VTD_DPRINTF(GENERAL, "error: unsupported Translation Type in " - "context-entry hi 0x%"PRIx64 " lo 0x%"PRIx64, - ce->hi, ce->lo); - return -VTD_FR_CONTEXT_ENTRY_INV; + } else { + switch (ce->lo & VTD_CONTEXT_ENTRY_TT) { + case VTD_CONTEXT_TT_MULTI_LEVEL: + /* fall through */ + case VTD_CONTEXT_TT_DEV_IOTLB: + break; + default: + VTD_DPRINTF(GENERAL, "error: unsupported Translation Type in " + "context-entry hi 0x%"PRIx64 " lo 0x%"PRIx64, + ce->hi, ce->lo); + return -VTD_FR_CONTEXT_ENTRY_INV; + } } return 0; } @@ -1361,6 +1368,60 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc) return true; } +static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s, + VTDInvDesc *inv_desc) +{ + VTDAddressSpace *vtd_dev_as; + IOMMUTLBEntry entry; + struct VTDBus *vtd_bus; + hwaddr addr; + uint64_t sz; + uint16_t sid; + uint8_t devfn; + bool size; + uint8_t bus_num; + + addr = VTD_INV_DESC_DEVICE_IOTLB_ADDR(inv_desc->hi); + sid = VTD_INV_DESC_DEVICE_IOTLB_SID(inv_desc->lo); + devfn = sid & 0xff; + bus_num = sid >> 8; + size = VTD_INV_DESC_DEVICE_IOTLB_SIZE(inv_desc->hi); + + if ((inv_desc->lo & VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO) || + (inv_desc->hi & VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI)) { + VTD_DPRINTF(GENERAL, "error: non-zero reserved field in Device " + "IOTLB Invalidate Descriptor hi 0x%"PRIx64 " lo 0x%"PRIx64, + inv_desc->hi, inv_desc->lo); + return false; + } + + vtd_bus = vtd_find_as_from_bus_num(s, bus_num); + if (!vtd_bus) { + goto done; + } + + vtd_dev_as = vtd_bus->dev_as[devfn]; + if (!vtd_dev_as) { + goto done; + } + + if (size) { + sz = ffsll(~(addr >> VTD_PAGE_SHIFT)); + addr = addr & ~((1 << (sz + VTD_PAGE_SHIFT)) - 1); + sz = VTD_PAGE_SIZE << sz; + } else { + sz = VTD_PAGE_SIZE; + } + + entry.target_as = &vtd_dev_as->as; + entry.addr_mask = sz - 1; + entry.iova = addr; + memory_region_notify_iommu(entry.target_as->root, entry); + +done: + return true; +} + static bool vtd_process_inv_desc(IntelIOMMUState *s) { VTDInvDesc inv_desc; @@ -1400,6 +1461,14 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s) } break; + case VTD_INV_DESC_DEVICE: + VTD_DPRINTF(INV, "Device IOTLB Invalidation Descriptor hi 0x%"PRIx64 + " lo 0x%"PRIx64, inv_desc.hi, inv_desc.lo); + if (!vtd_process_device_iotlb_desc(s, &inv_desc)) { + return false; + } + break; + default: VTD_DPRINTF(GENERAL, "error: unkonw Invalidation Descriptor type " "hi 0x%"PRIx64 " lo 0x%"PRIx64 " type %"PRIu8, @@ -1953,7 +2022,7 @@ static void vtd_init(IntelIOMMUState *s) s->next_frcd_reg = 0; s->cap = VTD_CAP_FRO | VTD_CAP_NFR | VTD_CAP_ND | VTD_CAP_MGAW | VTD_CAP_SAGAW | VTD_CAP_MAMV | VTD_CAP_PSI | VTD_CAP_SLLPS; - s->ecap = VTD_ECAP_QI | VTD_ECAP_IRO; + s->ecap = VTD_ECAP_QI | VTD_ECAP_DT | VTD_ECAP_IRO; vtd_reset_context_cache(s); vtd_reset_iotlb(s); diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index e5f514c..5b803d5 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -176,6 +176,7 @@ /* (offset >> 4) << 8 */ #define VTD_ECAP_IRO (DMAR_IOTLB_REG_OFFSET << 4) #define VTD_ECAP_QI (1ULL << 1) +#define VTD_ECAP_DT (1ULL << 2) /* CAP_REG */ /* (offset >> 4) << 24 */ @@ -286,6 +287,7 @@ typedef struct VTDInvDesc VTDInvDesc; #define VTD_INV_DESC_TYPE 0xf #define VTD_INV_DESC_CC 0x1 /* Context-cache Invalidate Desc */ #define VTD_INV_DESC_IOTLB 0x2 +#define VTD_INV_DESC_DEVICE 0x3 #define VTD_INV_DESC_WAIT 0x5 /* Invalidation Wait Descriptor */ #define VTD_INV_DESC_NONE 0 /* Not an Invalidate Descriptor */ @@ -319,6 +321,13 @@ typedef struct VTDInvDesc VTDInvDesc; #define VTD_INV_DESC_IOTLB_RSVD_LO 0xffffffff0000ff00ULL #define VTD_INV_DESC_IOTLB_RSVD_HI 0xf80ULL +/* Mask for Device IOTLB Invalidate Descriptor */ +#define VTD_INV_DESC_DEVICE_IOTLB_ADDR(val) ((val) & 0xfffffffffffff000ULL) +#define VTD_INV_DESC_DEVICE_IOTLB_SIZE(val) ((val) & 0x1) +#define VTD_INV_DESC_DEVICE_IOTLB_SID(val) (((val) >> 32) & 0xFFFFULL) +#define VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI 0xffeULL +#define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8 + /* Information about page-selective IOTLB invalidate */ struct VTDIOTLBPageInvInfo { uint16_t domain_id; @@ -357,8 +366,8 @@ typedef struct VTDRootEntry VTDRootEntry; #define VTD_CONTEXT_ENTRY_FPD (1ULL << 1) /* Fault Processing Disable */ #define VTD_CONTEXT_ENTRY_TT (3ULL << 2) /* Translation Type */ #define VTD_CONTEXT_TT_MULTI_LEVEL 0 -#define VTD_CONTEXT_TT_DEV_IOTLB 1 -#define VTD_CONTEXT_TT_PASS_THROUGH 2 +#define VTD_CONTEXT_TT_DEV_IOTLB (1ULL << 2) +#define VTD_CONTEXT_TT_PASS_THROUGH (2ULL << 2) /* Second Level Page Translation Pointer*/ #define VTD_CONTEXT_ENTRY_SLPTPTR (~0xfffULL) #define VTD_CONTEXT_ENTRY_RSVD_LO (0xff0ULL | ~VTD_HAW_MASK)