From patchwork Mon Jun 13 13:09:25 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Xu X-Patchwork-Id: 9172963 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2ECEF60573 for ; Mon, 13 Jun 2016 13:29:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1FEF020410 for ; Mon, 13 Jun 2016 13:29:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1414B262AE; Mon, 13 Jun 2016 13:29:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 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.wl.linuxfoundation.org (Postfix) with ESMTPS id 8583A20410 for ; Mon, 13 Jun 2016 13:29:41 +0000 (UTC) Received: from localhost ([::1]:56494 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCRvw-00006b-59 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jun 2016 09:29:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48503) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCRdk-0008I0-Tt for qemu-devel@nongnu.org; Mon, 13 Jun 2016 09:10:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bCRde-000053-LA for qemu-devel@nongnu.org; Mon, 13 Jun 2016 09:10:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50962) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCRde-00004z-D7 for qemu-devel@nongnu.org; Mon, 13 Jun 2016 09:10:46 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 15B93C049E17; Mon, 13 Jun 2016 13:10:46 +0000 (UTC) Received: from pxdev.xzpeter.org (vpn1-6-63.pek2.redhat.com [10.72.6.63]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5DD9iRM025046; Mon, 13 Jun 2016 09:10:40 -0400 From: Peter Xu To: qemu-devel@nongnu.org Date: Mon, 13 Jun 2016 21:09:25 +0800 Message-Id: <1465823381-23602-10-git-send-email-peterx@redhat.com> In-Reply-To: <1465823381-23602-1-git-send-email-peterx@redhat.com> References: <1465823381-23602-1-git-send-email-peterx@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 13 Jun 2016 13:10:46 +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 Subject: [Qemu-devel] [PATCH v9 09/25] intel_iommu: define interrupt remap table addr register X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: ehabkost@redhat.com, mst@redhat.com, jasowang@redhat.com, rkrcmar@redhat.com, peterx@redhat.com, alex.williamson@redhat.com, jan.kiszka@web.de, wexu@redhat.com, pbonzini@redhat.com, marcel@redhat.com, imammedo@redhat.com, davidkiarie4@gmail.com, rth@twiddle.net Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Defined Interrupt Remap Table Address register to store IR table pointer. Also, do proper handling on global command register writes to store table pointer and its size. One more debug flag "DEBUG_IR" is added for interrupt remapping. Signed-off-by: Peter Xu --- hw/i386/intel_iommu.c | 52 +++++++++++++++++++++++++++++++++++++++++- hw/i386/intel_iommu_internal.h | 4 ++++ include/hw/i386/intel_iommu.h | 5 ++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index e216fd3..26ef17a3 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -33,7 +33,7 @@ #ifdef DEBUG_INTEL_IOMMU enum { DEBUG_GENERAL, DEBUG_CSR, DEBUG_INV, DEBUG_MMU, DEBUG_FLOG, - DEBUG_CACHE, + DEBUG_CACHE, DEBUG_IR, }; #define VTD_DBGBIT(x) (1 << DEBUG_##x) static int vtd_dbgflags = VTD_DBGBIT(GENERAL) | VTD_DBGBIT(CSR); @@ -903,6 +903,19 @@ static void vtd_root_table_setup(IntelIOMMUState *s) (s->root_extended ? "(extended)" : "")); } +static void vtd_interrupt_remap_table_setup(IntelIOMMUState *s) +{ + uint64_t value = 0; + value = vtd_get_quad_raw(s, DMAR_IRTA_REG); + s->intr_size = 1UL << ((value & VTD_IRTA_SIZE_MASK) + 1); + s->intr_root = value & VTD_IRTA_ADDR_MASK; + + /* TODO: invalidate interrupt entry cache */ + + VTD_DPRINTF(CSR, "int remap table addr 0x%"PRIx64 " size %"PRIu32, + s->intr_root, s->intr_size); +} + static void vtd_context_global_invalidate(IntelIOMMUState *s) { s->context_cache_gen++; @@ -1141,6 +1154,16 @@ static void vtd_handle_gcmd_srtp(IntelIOMMUState *s) vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_RTPS); } +/* Set Interrupt Remap Table Pointer */ +static void vtd_handle_gcmd_sirtp(IntelIOMMUState *s) +{ + VTD_DPRINTF(CSR, "set Interrupt Remap Table Pointer"); + + vtd_interrupt_remap_table_setup(s); + /* Ok - report back to driver */ + vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_IRTPS); +} + /* Handle Translation Enable/Disable */ static void vtd_handle_gcmd_te(IntelIOMMUState *s, bool en) { @@ -1180,6 +1203,10 @@ static void vtd_handle_gcmd_write(IntelIOMMUState *s) /* Queued Invalidation Enable */ vtd_handle_gcmd_qie(s, val & VTD_GCMD_QIE); } + if (val & VTD_GCMD_SIRTP) { + /* Set/update the interrupt remapping root-table pointer */ + vtd_handle_gcmd_sirtp(s); + } } /* Handle write to Context Command Register */ @@ -1841,6 +1868,23 @@ static void vtd_mem_write(void *opaque, hwaddr addr, vtd_update_fsts_ppf(s); break; + case DMAR_IRTA_REG: + VTD_DPRINTF(IR, "DMAR_IRTA_REG write addr 0x%"PRIx64 + ", size %d, val 0x%"PRIx64, addr, size, val); + if (size == 4) { + vtd_set_long(s, addr, val); + } else { + vtd_set_quad(s, addr, val); + } + break; + + case DMAR_IRTA_REG_HI: + VTD_DPRINTF(IR, "DMAR_IRTA_REG_HI write addr 0x%"PRIx64 + ", size %d, val 0x%"PRIx64, addr, size, val); + assert(size == 4); + vtd_set_long(s, addr, val); + break; + default: VTD_DPRINTF(GENERAL, "error: unhandled reg write addr 0x%"PRIx64 ", size %d, val 0x%"PRIx64, addr, size, val); @@ -2023,6 +2067,12 @@ static void vtd_init(IntelIOMMUState *s) /* Fault Recording Registers, 128-bit */ vtd_define_quad(s, DMAR_FRCD_REG_0_0, 0, 0, 0); vtd_define_quad(s, DMAR_FRCD_REG_0_2, 0, 0, 0x8000000000000000ULL); + + /* + * Interrupt remapping registers, not support extended interrupt + * mode for now. + */ + vtd_define_quad(s, DMAR_IRTA_REG, 0, 0xfffffffffffff00fULL, 0); } /* Should not reset address_spaces when reset because devices will still use diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index 5b98a11..309833f 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -172,6 +172,10 @@ #define VTD_RTADDR_RTT (1ULL << 11) #define VTD_RTADDR_ADDR_MASK (VTD_HAW_MASK ^ 0xfffULL) +/* IRTA_REG */ +#define VTD_IRTA_ADDR_MASK (VTD_HAW_MASK ^ 0xfffULL) +#define VTD_IRTA_SIZE_MASK (0xfULL) + /* ECAP_REG */ /* (offset >> 4) << 8 */ #define VTD_ECAP_IRO (DMAR_IOTLB_REG_OFFSET << 4) diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 638d77f..83d1905 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -125,6 +125,11 @@ struct IntelIOMMUState { MemoryRegionIOMMUOps iommu_ops; GHashTable *vtd_as_by_busptr; /* VTDBus objects indexed by PCIBus* reference */ VTDBus *vtd_as_by_bus_num[VTD_PCI_BUS_MAX]; /* VTDBus objects indexed by bus number */ + + /* interrupt remapping */ + bool intr_enabled; /* Whether guest enabled IR */ + dma_addr_t intr_root; /* Interrupt remapping table pointer */ + uint32_t intr_size; /* Number of IR table entries */ }; #endif