From patchwork Sat May 21 16:19:49 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Aviv B.D." X-Patchwork-Id: 9130615 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 17A7660221 for ; Sat, 21 May 2016 16:23:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 098792807B for ; Sat, 21 May 2016 16:23:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F26DB28156; Sat, 21 May 2016 16:23:49 +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.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID 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 35DF52807B for ; Sat, 21 May 2016 16:23:49 +0000 (UTC) Received: from localhost ([::1]:40707 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b49gq-0008R0-As for patchwork-qemu-devel@patchwork.kernel.org; Sat, 21 May 2016 12:23:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34021) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b49dx-0006Ta-AZ for qemu-devel@nongnu.org; Sat, 21 May 2016 12:20:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b49do-0002zt-4y for qemu-devel@nongnu.org; Sat, 21 May 2016 12:20:49 -0400 Received: from mail-wm0-x243.google.com ([2a00:1450:400c:c09::243]:34401) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b49dn-0002zp-Hz for qemu-devel@nongnu.org; Sat, 21 May 2016 12:20:40 -0400 Received: by mail-wm0-x243.google.com with SMTP id n129so4249579wmn.1 for ; Sat, 21 May 2016 09:20:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=C1r/4mIxE1p1hlZr5AgxWmz3Q1+9yhOuExR2ARHoes0=; b=s+VGCw3tk0aq5mEFsPAjZvvU0Jdv94Hcy2GjrdeDVPhXixmhjT8p3WwBQvj8MXFodH cWx7IpmrdMpb0RJ4rrqz8P9YfQx7iCaFidoca81WYKMFeyS4OjoUHdrbz4mu1XehGfcy aFMEzcFkr0VajdHXNVIvDYDTTdL6BPJDcvRnyrVTlg+NOKZgRuaZHoJZw57zAnmxUMGb ob81xvxZlmnf3MY7ogoSIHVDflmZ8teZqN1jtlmxyNP9Z0EQEF6wTwUin+NrqJlVFqTi E4fHf/ufIvZ+s3rlHzKM/gNKnqwnH0TaTOJ7pxjMFnPRhu8wwlH0v9ZEM/3M8VT4LVaw cwLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=C1r/4mIxE1p1hlZr5AgxWmz3Q1+9yhOuExR2ARHoes0=; b=Jvi0XnZTQ48VIrOeHONSkHrIVxXyaIbQ5vlAK0QS6/pZKHlM/7KmA19anRDKwWxMF+ nwCzG1zNwJ/nEnuAYl2OviLDKO8GEtAsGsRNTkOPc6cnWdDgqP2vlGvixVbZmXte9/g+ emuRtVUgI4/9VCEBzqQmwIt/0hNwmb8TIiSuWg0NvZcJGF5nveGRHrQ3/k/ZvbjFzK/V iVL4I09zAwTdluce3NoMQ9YRjZhAndsvctfODBpsH+/0x/K5ysHKvf+YCIev/qDw2zPZ Ar3REjGaG08Z9TCii2WSYgF2hla4IJ4NIa9l690a9kOid/qAlRxOll8gitt+FN7Sf2rW ndTg== X-Gm-Message-State: AOPr4FVBhQyBblNLPBW/5auuotuUtkjDoZ8VMikmSTTgGFhL+iEqyZxbju2HIIjp1XFn+w== X-Received: by 10.194.62.99 with SMTP id x3mr8604095wjr.128.1463847638811; Sat, 21 May 2016 09:20:38 -0700 (PDT) Received: from tapuz2.cslcs.technion.ac.il (tapuz2.cslcs.technion.ac.il. [132.68.206.212]) by smtp.gmail.com with ESMTPSA id e8sm4087838wma.2.2016.05.21.09.20.36 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 21 May 2016 09:20:37 -0700 (PDT) From: "Aviv B.D" To: qemu-devel@nongnu.org Date: Sat, 21 May 2016 19:19:49 +0300 Message-Id: <1463847590-22782-3-git-send-email-bd.aviv@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1463847590-22782-1-git-send-email-bd.aviv@gmail.com> References: <1463847590-22782-1-git-send-email-bd.aviv@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::243 Subject: [Qemu-devel] [PATCH v3 2/3] IOMMU: change iommu_op->translate's is_write to flags, add support to NO_FAIL flag mode 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: Jan Kiszka , Alex Williamson , Aviv Ben-David , Peter Xu , "Michael S. Tsirkin" Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: "Aviv Ben-David" Supports translation trials without reporting error to guest on translation failures. Signed-off-by: Aviv Ben-David --- exec.c | 2 +- hw/i386/intel_iommu.c | 65 ++++++++++++++++++++++++++++++++------------------- include/exec/memory.h | 4 ++-- memory.c | 2 +- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/exec.c b/exec.c index 2e363f0..028c8e0 100644 --- a/exec.c +++ b/exec.c @@ -431,7 +431,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, break; } - iotlb = mr->iommu_ops->translate(mr, addr, is_write); + iotlb = mr->iommu_ops->translate(mr, addr, is_write ? IOMMU_WO : IOMMU_RO); addr = ((iotlb.translated_addr & ~iotlb.addr_mask) | (addr & iotlb.addr_mask)); *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 1af8da8..410f810 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -356,7 +356,7 @@ static void vtd_set_frcd_and_update_ppf(IntelIOMMUState *s, uint16_t index) /* Must not update F field now, should be done later */ static void vtd_record_frcd(IntelIOMMUState *s, uint16_t index, uint16_t source_id, hwaddr addr, - VTDFaultReason fault, bool is_write) + VTDFaultReason fault, IOMMUAccessFlags flags) { uint64_t hi = 0, lo; hwaddr frcd_reg_addr = DMAR_FRCD_REG_OFFSET + (((uint64_t)index) << 4); @@ -365,7 +365,7 @@ static void vtd_record_frcd(IntelIOMMUState *s, uint16_t index, lo = VTD_FRCD_FI(addr); hi = VTD_FRCD_SID(source_id) | VTD_FRCD_FR(fault); - if (!is_write) { + if (!(flags == IOMMU_WO || flags == IOMMU_RW)) { hi |= VTD_FRCD_T; } vtd_set_quad_raw(s, frcd_reg_addr, lo); @@ -396,7 +396,7 @@ static bool vtd_try_collapse_fault(IntelIOMMUState *s, uint16_t source_id) /* Log and report an DMAR (address translation) fault to software */ static void vtd_report_dmar_fault(IntelIOMMUState *s, uint16_t source_id, hwaddr addr, VTDFaultReason fault, - bool is_write) + IOMMUAccessFlags flags) { uint32_t fsts_reg = vtd_get_long_raw(s, DMAR_FSTS_REG); @@ -407,7 +407,7 @@ static void vtd_report_dmar_fault(IntelIOMMUState *s, uint16_t source_id, return; } VTD_DPRINTF(FLOG, "sid 0x%"PRIx16 ", fault %d, addr 0x%"PRIx64 - ", is_write %d", source_id, fault, addr, is_write); + ", flags %d", source_id, fault, addr, flags); if (fsts_reg & VTD_FSTS_PFO) { VTD_DPRINTF(FLOG, "new fault is not recorded due to " "Primary Fault Overflow"); @@ -425,7 +425,7 @@ static void vtd_report_dmar_fault(IntelIOMMUState *s, uint16_t source_id, return; } - vtd_record_frcd(s, s->next_frcd_reg, source_id, addr, fault, is_write); + vtd_record_frcd(s, s->next_frcd_reg, source_id, addr, fault, flags); if (fsts_reg & VTD_FSTS_PPF) { VTD_DPRINTF(FLOG, "there are pending faults already, " @@ -621,7 +621,7 @@ static bool vtd_slpte_nonzero_rsvd(uint64_t slpte, uint32_t level) /* Given the @gpa, get relevant @slptep. @slpte_level will be the last level * of the translation, can be used for deciding the size of large page. */ -static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t gpa, bool is_write, +static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t gpa, IOMMUAccessFlags flags, uint64_t *slptep, uint32_t *slpte_level, bool *reads, bool *writes) { @@ -641,7 +641,20 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t gpa, bool is_write, } /* FIXME: what is the Atomics request here? */ - access_right_check = is_write ? VTD_SL_W : VTD_SL_R; + switch(flags){ + case IOMMU_WO: + access_right_check = VTD_SL_W; + break; + case IOMMU_RO: + access_right_check = VTD_SL_R; + break; + case IOMMU_RW: /* passthrow */ + case IOMMU_NO_FAIL: + access_right_check = VTD_SL_R | VTD_SL_W; + break; + default: + assert(0); + } while (true) { offset = vtd_gpa_level_offset(gpa, level); @@ -663,8 +676,8 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t gpa, bool is_write, if (!(slpte & access_right_check)) { VTD_DPRINTF(GENERAL, "error: lack of %s permission for " "gpa 0x%"PRIx64 " slpte 0x%"PRIx64, - (is_write ? "write" : "read"), gpa, slpte); - return is_write ? -VTD_FR_WRITE : -VTD_FR_READ; + (flags == IOMMU_WO ? "write" : "read"), gpa, slpte); + return (flags == IOMMU_RW || flags == IOMMU_WO) ? -VTD_FR_WRITE : -VTD_FR_READ; } if (vtd_slpte_nonzero_rsvd(slpte, level)) { VTD_DPRINTF(GENERAL, "error: non-zero reserved field in second " @@ -781,11 +794,11 @@ static inline bool vtd_is_interrupt_addr(hwaddr addr) * * @bus_num: The bus number * @devfn: The devfn, which is the combined of device and function number - * @is_write: The access is a write operation + * @flags: The access is a write operation * @entry: IOMMUTLBEntry that contain the addr to be translated and result */ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus, - uint8_t devfn, hwaddr addr, bool is_write, + uint8_t devfn, hwaddr addr, IOMMUAccessFlags flags, IOMMUTLBEntry *entry) { IntelIOMMUState *s = vtd_as->iommu_state; @@ -803,7 +816,7 @@ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus, /* Check if the request is in interrupt address range */ if (vtd_is_interrupt_addr(addr)) { - if (is_write) { + if (flags == IOMMU_WO || flags == IOMMU_RW) { /* FIXME: since we don't know the length of the access here, we * treat Non-DWORD length write requests without PASID as * interrupt requests, too. Withoud interrupt remapping support, @@ -819,7 +832,7 @@ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus, } else { VTD_DPRINTF(GENERAL, "error: read request from interrupt address " "gpa 0x%"PRIx64, addr); - vtd_report_dmar_fault(s, source_id, addr, VTD_FR_READ, is_write); + vtd_report_dmar_fault(s, source_id, addr, VTD_FR_READ, flags); return; } } @@ -848,12 +861,14 @@ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus, is_fpd_set = ce.lo & VTD_CONTEXT_ENTRY_FPD; if (ret_fr) { ret_fr = -ret_fr; - if (is_fpd_set && vtd_is_qualified_fault(ret_fr)) { - VTD_DPRINTF(FLOG, "fault processing is disabled for DMA " + if (flags != IOMMU_NO_FAIL){ + if (is_fpd_set && vtd_is_qualified_fault(ret_fr)) { + VTD_DPRINTF(FLOG, "fault processing is disabled for DMA " "requests through this context-entry " "(with FPD Set)"); - } else { - vtd_report_dmar_fault(s, source_id, addr, ret_fr, is_write); + } else { + vtd_report_dmar_fault(s, source_id, addr, ret_fr, flags); + } } return; } @@ -866,15 +881,17 @@ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus, cc_entry->context_cache_gen = s->context_cache_gen; } - ret_fr = vtd_gpa_to_slpte(&ce, addr, is_write, &slpte, &level, + ret_fr = vtd_gpa_to_slpte(&ce, addr, flags, &slpte, &level, &reads, &writes); if (ret_fr) { ret_fr = -ret_fr; - if (is_fpd_set && vtd_is_qualified_fault(ret_fr)) { - VTD_DPRINTF(FLOG, "fault processing is disabled for DMA requests " + if (flags != IOMMU_NO_FAIL){ + if (is_fpd_set && vtd_is_qualified_fault(ret_fr)) { + VTD_DPRINTF(FLOG, "fault processing is disabled for DMA requests " "through this context-entry (with FPD Set)"); - } else { - vtd_report_dmar_fault(s, source_id, addr, ret_fr, is_write); + } else { + vtd_report_dmar_fault(s, source_id, addr, ret_fr, flags); + } } return; } @@ -1840,7 +1857,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr, } static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr, - bool is_write) + IOMMUAccessFlags flags) { VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu); IntelIOMMUState *s = vtd_as->iommu_state; @@ -1862,7 +1879,7 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr, } vtd_do_iommu_translate(vtd_as, vtd_as->bus, vtd_as->devfn, addr, - is_write, &ret); + flags, &ret); VTD_DPRINTF(MMU, "bus %"PRIu8 " slot %"PRIu8 " func %"PRIu8 " devfn %"PRIu8 " gpa 0x%"PRIx64 " hpa 0x%"PRIx64, pci_bus_num(vtd_as->bus), diff --git a/include/exec/memory.h b/include/exec/memory.h index 7fb9188..755a026 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -55,6 +55,7 @@ typedef enum { IOMMU_RO = 1, IOMMU_WO = 2, IOMMU_RW = 3, + IOMMU_NO_FAIL = 4, /* may not be present, don't repport error to guest */ } IOMMUAccessFlags; struct IOMMUTLBEntry { @@ -145,10 +146,9 @@ struct MemoryRegionOps { }; typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps; - struct MemoryRegionIOMMUOps { /* Return a TLB entry that contains a given address. */ - IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, bool is_write); + IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, IOMMUAccessFlags flags); }; typedef struct CoalescedMemoryRange CoalescedMemoryRange; diff --git a/memory.c b/memory.c index a8ef852..ba46cbb 100644 --- a/memory.c +++ b/memory.c @@ -1522,7 +1522,7 @@ void memory_region_iommu_replay(MemoryRegion *mr, Notifier *n, IOMMUTLBEntry iotlb; for (addr = 0; addr < memory_region_size(mr); addr += granularity) { - iotlb = mr->iommu_ops->translate(mr, addr, is_write); + iotlb = mr->iommu_ops->translate(mr, addr, is_write ? IOMMU_WO : IOMMU_RO); if (iotlb.perm != IOMMU_NONE) { n->notify(n, &iotlb); }