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 v3 2/3] IOMMU: change iommu_op->translate's is_write to flags, add support to NO_FAIL flag mode
Date: Sat, 21 May 2016 19:19:49 +0300 [thread overview]
Message-ID: <1463847590-22782-3-git-send-email-bd.aviv@gmail.com> (raw)
In-Reply-To: <1463847590-22782-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
failures.
Signed-off-by: Aviv Ben-David <bd.aviv@gmail.com>
---
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);
}
--
1.9.1
next prev parent reply other threads:[~2016-05-21 16:20 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-21 16:19 [Qemu-devel] [PATCH v3 0/3] IOMMU: Add Support to VFIO devices with vIOMMU present Aviv B.D
2016-05-21 16:19 ` [Qemu-devel] [PATCH v3 1/3] IOMMU: add VTD_CAP_CM to vIOMMU capability exposed to guest Aviv B.D
2016-05-21 16:42 ` Jan Kiszka
2016-06-02 8:44 ` Peter Xu
2016-06-02 13:00 ` Alex Williamson
2016-06-02 13:14 ` Jan Kiszka
2016-06-02 13:17 ` Jan Kiszka
2016-06-02 16:15 ` Michael S. Tsirkin
2016-06-06 5:04 ` Peter Xu
2016-06-06 13:11 ` Alex Williamson
2016-06-06 13:43 ` Peter Xu
2016-06-06 17:02 ` Alex Williamson
2016-06-07 3:20 ` Peter Xu
2016-06-07 3:58 ` Alex Williamson
2016-06-07 5:00 ` Peter Xu
2016-06-07 5:21 ` Huang, Kai
2016-06-07 18:46 ` Alex Williamson
2016-06-07 22:39 ` Huang, Kai
2016-05-24 8:14 ` Jason Wang
2016-05-24 9:25 ` Jan Kiszka
2016-05-28 16:12 ` Aviv B.D.
2016-05-28 16:34 ` Kiszka, Jan
2016-05-21 16:19 ` Aviv B.D [this message]
2016-06-06 5:04 ` [Qemu-devel] [PATCH v3 2/3] IOMMU: change iommu_op->translate's is_write to flags, add support to NO_FAIL flag mode Peter Xu
2016-05-21 16:19 ` [Qemu-devel] [PATCH v3 3/3] IOMMU: Integrate between VFIO and vIOMMU to support device assignment Aviv B.D
2016-05-23 17:53 ` Alex Williamson
2016-05-26 20:58 ` Alex Williamson
2016-05-28 10:52 ` Aviv B.D.
2016-05-28 16:02 ` Alex Williamson
2016-05-28 16:10 ` Aviv B.D.
2016-05-28 17:39 ` Alex Williamson
2016-05-28 18:14 ` Aviv B.D.
2016-05-28 19:48 ` Alex Williamson
2016-06-02 13:09 ` Aviv B.D.
2016-06-02 13:34 ` Alex Williamson
2016-06-06 8:09 ` Peter Xu
2016-06-06 18:21 ` Alex Williamson
2016-06-07 13:20 ` Peter Xu
2016-06-06 7:38 ` Peter Xu
2016-06-06 17:30 ` Alex Williamson
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=1463847590-22782-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).