From: "Aviv B.D" <bd.aviv@gmail.com>
To: qemu-devel@nongnu.org
Cc: "Michael S. Tsirkin" <mst@redhat.com>,
Alex Williamson <alex.williamson@redhat.com>,
Peter Xu <peterx@redhat.com>, Jan Kiszka <jan.kiszka@siemens.com>,
Aviv Ben-David <bd.aviv@gmail.com>
Subject: [Qemu-devel] [PATCH v5 2/3] IOMMU: change iommu_op->translate's is_write to flags, add support to NO_FAIL flag mode
Date: Fri, 21 Oct 2016 00:07:20 +0300 [thread overview]
Message-ID: <1476997641-29648-3-git-send-email-bd.aviv@gmail.com> (raw)
In-Reply-To: <1476997641-29648-1-git-send-email-bd.aviv@gmail.com>
From: "Aviv Ben-David" <bd.aviv@gmail.com>
Supports translation trials without reporting error to guest on
translation failure.
Signed-off-by: Aviv Ben-David <bd.aviv@gmail.com>
---
exec.c | 3 ++-
hw/i386/amd_iommu.c | 4 ++--
hw/i386/intel_iommu.c | 59 +++++++++++++++++++++++++++++++++------------------
hw/ppc/spapr_iommu.c | 2 +-
include/exec/memory.h | 6 ++++--
memory.c | 3 ++-
6 files changed, 49 insertions(+), 28 deletions(-)
diff --git a/exec.c b/exec.c
index e63c5a1..9e2e5ca 100644
--- a/exec.c
+++ b/exec.c
@@ -432,7 +432,8 @@ 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/amd_iommu.c b/hw/i386/amd_iommu.c
index 47b79d9..1f0d76b 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -988,7 +988,7 @@ static inline bool amdvi_is_interrupt_addr(hwaddr addr)
}
static IOMMUTLBEntry amdvi_translate(MemoryRegion *iommu, hwaddr addr,
- bool is_write)
+ IOMMUAccessFlags flags)
{
AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
AMDVIState *s = as->iommu_state;
@@ -1017,7 +1017,7 @@ static IOMMUTLBEntry amdvi_translate(MemoryRegion *iommu, hwaddr addr,
return ret;
}
- amdvi_do_translate(as, addr, is_write, &ret);
+ amdvi_do_translate(as, addr, flags & IOMMU_WO, &ret);
trace_amdvi_translation_result(as->bus_num, PCI_SLOT(as->devfn),
PCI_FUNC(as->devfn), addr, ret.translated_addr);
return ret;
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 834887f..0821079 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -631,7 +631,8 @@ 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)
{
@@ -640,7 +641,7 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t gpa, bool is_write,
uint32_t offset;
uint64_t slpte;
uint32_t ce_agaw = vtd_get_agaw_from_context_entry(ce);
- uint64_t access_right_check;
+ uint64_t access_right_check = 0;
/* Check if @gpa is above 2^X-1, where X is the minimum of MGAW in CAP_REG
* and AW in context-entry.
@@ -651,7 +652,15 @@ 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;
+ if (flags & IOMMU_WO) {
+ access_right_check |= VTD_SL_W;
+ }
+ if (flags & IOMMU_RO) {
+ access_right_check |= VTD_SL_R;
+ }
+ if (flags & IOMMU_NO_FAIL) {
+ access_right_check |= VTD_SL_R | VTD_SL_W;
+ }
while (true) {
offset = vtd_gpa_level_offset(gpa, level);
@@ -673,8 +682,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_WO) ? -VTD_FR_WRITE : -VTD_FR_READ;
}
if (vtd_slpte_nonzero_rsvd(slpte, level)) {
VTD_DPRINTF(GENERAL, "error: non-zero reserved field in second "
@@ -791,11 +800,13 @@ 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 permission of the operation, use IOMMU_NO_FAIL to
+ * suppress translation errors (e.g. no mapping present)
* @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;
@@ -813,7 +824,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) {
/* 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,
@@ -829,7 +840,8 @@ 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 & IOMMU_WO);
return;
}
}
@@ -858,12 +870,15 @@ 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 & IOMMU_WO);
+ }
}
return;
}
@@ -876,15 +891,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 "
- "through this context-entry (with FPD Set)");
- } else {
- vtd_report_dmar_fault(s, source_id, addr, ret_fr, is_write);
+ 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, flags);
+ }
}
return;
}
@@ -1946,7 +1963,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;
@@ -1968,7 +1985,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/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index ae30bbe..d19c3ff 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -110,7 +110,7 @@ static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table)
/* Called from RCU critical section */
static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
- bool is_write)
+ IOMMUAccessFlags flags)
{
sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
uint64_t tce;
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 10d7eac..0d4acb9 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -57,6 +57,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 {
@@ -168,10 +169,11 @@ 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);
/* Returns minimum supported page size */
uint64_t (*get_min_page_size)(MemoryRegion *iommu);
/* Called when IOMMU Notifier flag changed */
diff --git a/memory.c b/memory.c
index 58f9269..dfbb9a0 100644
--- a/memory.c
+++ b/memory.c
@@ -1563,7 +1563,8 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n,
granularity = memory_region_iommu_get_min_page_size(mr);
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);
}
--
1.9.1
next prev parent reply other threads:[~2016-10-20 21:07 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-20 21:07 [Qemu-devel] [PATCH v5 0/3] IOMMU: intel_iommu support map and unmap notifications Aviv B.D
2016-10-20 21:07 ` [Qemu-devel] [PATCH v5 1/3] IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest Aviv B.D
2016-10-20 21:07 ` Aviv B.D [this message]
2016-10-20 21:07 ` [Qemu-devel] [PATCH v5 3/3] IOMMU: enable intel_iommu map and unmap notifiers Aviv B.D
2016-10-26 16:37 ` [Qemu-devel] [PATCH v5 0/3] IOMMU: intel_iommu support map and unmap notifications Chao Gao
2016-10-30 10:18 ` Aviv B.D.
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1476997641-29648-3-git-send-email-bd.aviv@gmail.com \
--to=bd.aviv@gmail.com \
--cc=alex.williamson@redhat.com \
--cc=jan.kiszka@siemens.com \
--cc=mst@redhat.com \
--cc=peterx@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.