* [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications
@ 2016-10-15 10:12 Aviv B.D
2016-10-15 10:12 ` [Qemu-devel] [PATCH v4 1/3] IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest Aviv B.D
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Aviv B.D @ 2016-10-15 10:12 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Alex Williamson, Peter Xu, Jan Kiszka,
Aviv Ben-David
From: "Aviv Ben-David" <bd.aviv@gmail.com>
* Advertize Cache Mode capability in iommu cap register.
This capability is controlled by "cache-mode" property of intel-iommu device.
To enable this option call QEMU with "-device intel-iommu,cache-mode=true".
* On page cache invalidation in intel vIOMMU, check if the domain belong to
registered notifier, and notify accordingly.
Currently this patch still doesn't enabling VFIO devices support with vIOMMU
present. Current problems:
* vfio_iommu_map_notify is not aware about memory range belong to specific
VFIOGuestIOMMU.
* memory_region_iommu_replay hangs QEMU on start up while it itterate over
64bit address space. Commenting out the call to this function enables
workable VFIO device while vIOMMU present.
Changes from v1 to v2:
* remove assumption that the cache do not clears
* fix lockup on high load.
Changes from v2 to v3:
* remove debug leftovers
* split to sepearate commits
* change is_write to flags in vtd_do_iommu_translate, add IOMMU_NO_FAIL
to suppress error propagating to guest.
Changes from v3 to v4:
* Add property to intel_iommu device to control the CM capability,
default to False.
* Use s->iommu_ops.notify_flag_changed to register notifiers.
Aviv Ben-David (3):
IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to
guest
IOMMU: change iommu_op->translate's is_write to flags, add support to
NO_FAIL flag mode
IOMMU: enable intel_iommu map and unmap notifiers
exec.c | 2 +-
hw/i386/amd_iommu.c | 4 +-
hw/i386/intel_iommu.c | 170 +++++++++++++++++++++++++++++++++--------
hw/i386/intel_iommu_internal.h | 3 +
include/exec/memory.h | 4 +-
include/hw/i386/intel_iommu.h | 10 +++
memory.c | 2 +-
7 files changed, 159 insertions(+), 36 deletions(-)
--
1.9.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v4 1/3] IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest
2016-10-15 10:12 [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications Aviv B.D
@ 2016-10-15 10:12 ` Aviv B.D
2016-10-15 10:12 ` [Qemu-devel] [PATCH v4 2/3] IOMMU: change iommu_op->translate's is_write to flags, add support to NO_FAIL flag mode Aviv B.D
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Aviv B.D @ 2016-10-15 10:12 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Alex Williamson, Peter Xu, Jan Kiszka,
Aviv Ben-David
From: "Aviv Ben-David" <bd.aviv@gmail.com>
This capability asks the guest to invalidate cache before each map operation.
We can use this invalidation to trap map operations in the hypervisor.
This capability only enabled when cache-mode property of the device is true.
Signed-off-by: Aviv Ben-David <bd.aviv@gmail.com>
---
hw/i386/intel_iommu.c | 5 +++++
hw/i386/intel_iommu_internal.h | 1 +
include/hw/i386/intel_iommu.h | 2 ++
3 files changed, 8 insertions(+)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 2efd69b..6e5ad7b 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2012,6 +2012,7 @@ static const MemoryRegionOps vtd_mem_ops = {
static Property vtd_properties[] = {
DEFINE_PROP_UINT32("version", IntelIOMMUState, version, 0),
+ DEFINE_PROP_BOOL("cache-mode", IntelIOMMUState, cache_mode_enabled, FALSE),
DEFINE_PROP_END_OF_LIST(),
};
@@ -2385,6 +2386,10 @@ static void vtd_init(IntelIOMMUState *s)
s->ecap |= VTD_ECAP_IR | VTD_ECAP_EIM | VTD_ECAP_MHMV;
}
+ if (s->cache_mode_enabled){
+ s->cap |= VTD_CAP_CM;
+ }
+
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 0829a50..35d9f3a 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -201,6 +201,7 @@
#define VTD_CAP_MAMV (VTD_MAMV << 48)
#define VTD_CAP_PSI (1ULL << 39)
#define VTD_CAP_SLLPS ((1ULL << 34) | (1ULL << 35))
+#define VTD_CAP_CM (1ULL << 7)
/* Supported Adjusted Guest Address Widths */
#define VTD_CAP_SAGAW_SHIFT 8
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index a42dbd7..7a94f16 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -258,6 +258,8 @@ struct IntelIOMMUState {
uint8_t womask[DMAR_REG_SIZE]; /* WO (write only - read returns 0) */
uint32_t version;
+ bool cache_mode_enabled; /* RO - is cap CM enabled? */
+
dma_addr_t root; /* Current root table pointer */
bool root_extended; /* Type of root table (extended or not) */
bool dmar_enabled; /* Set if DMA remapping is enabled */
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v4 2/3] IOMMU: change iommu_op->translate's is_write to flags, add support to NO_FAIL flag mode
2016-10-15 10:12 [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications Aviv B.D
2016-10-15 10:12 ` [Qemu-devel] [PATCH v4 1/3] IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest Aviv B.D
@ 2016-10-15 10:12 ` Aviv B.D
2016-10-15 10:12 ` [Qemu-devel] [PATCH v4 3/3] IOMMU: enable intel_iommu map and unmap notifiers Aviv B.D
2016-10-15 10:28 ` [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications no-reply
3 siblings, 0 replies; 5+ messages in thread
From: Aviv B.D @ 2016-10-15 10:12 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Alex Williamson, Peter Xu, Jan Kiszka,
Aviv Ben-David
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 | 2 +-
hw/i386/amd_iommu.c | 4 ++--
hw/i386/intel_iommu.c | 65 ++++++++++++++++++++++++++++++++-------------------
include/exec/memory.h | 4 ++--
memory.c | 2 +-
5 files changed, 47 insertions(+), 30 deletions(-)
diff --git a/exec.c b/exec.c
index 374c364..1b16fe4 100644
--- a/exec.c
+++ b/exec.c
@@ -432,7 +432,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/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 6e5ad7b..9ffa45f 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -364,7 +364,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);
@@ -373,7 +373,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);
@@ -404,7 +404,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);
@@ -415,7 +415,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");
@@ -433,7 +433,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, "
@@ -629,7 +629,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)
{
@@ -649,7 +649,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);
@@ -671,8 +684,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 "
@@ -789,11 +802,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;
@@ -811,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 || 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,
@@ -827,7 +840,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;
}
}
@@ -856,12 +869,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;
}
@@ -874,15 +889,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;
}
@@ -1944,7 +1961,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;
@@ -1966,7 +1983,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 10d7eac..01c9b2d 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,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);
/* 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..98d896da 100644
--- a/memory.c
+++ b/memory.c
@@ -1563,7 +1563,7 @@ 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
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v4 3/3] IOMMU: enable intel_iommu map and unmap notifiers
2016-10-15 10:12 [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications Aviv B.D
2016-10-15 10:12 ` [Qemu-devel] [PATCH v4 1/3] IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest Aviv B.D
2016-10-15 10:12 ` [Qemu-devel] [PATCH v4 2/3] IOMMU: change iommu_op->translate's is_write to flags, add support to NO_FAIL flag mode Aviv B.D
@ 2016-10-15 10:12 ` Aviv B.D
2016-10-15 10:28 ` [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications no-reply
3 siblings, 0 replies; 5+ messages in thread
From: Aviv B.D @ 2016-10-15 10:12 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, Alex Williamson, Peter Xu, Jan Kiszka,
Aviv Ben-David
From: "Aviv Ben-David" <bd.aviv@gmail.com>
* register notifiers when vtd_iommu_notify_flag_changed is called.
* Notify on IOTLB page invalidation about unmap and map operations.
Adds a list of registered vtd_as's to intel iommu state to save
iterations over each PCI device in a search of the corrosponding domain.
Signed-off-by: Aviv Ben-David <bd.aviv@gmail.com>
---
hw/i386/intel_iommu.c | 102 ++++++++++++++++++++++++++++++++++++++---
hw/i386/intel_iommu_internal.h | 2 +
include/hw/i386/intel_iommu.h | 8 ++++
3 files changed, 105 insertions(+), 7 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 9ffa45f..0560e3c 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -51,6 +51,9 @@ static int vtd_dbgflags = VTD_DBGBIT(GENERAL) | VTD_DBGBIT(CSR);
#define VTD_DPRINTF(what, fmt, ...) do {} while (0)
#endif
+static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
+ uint8_t devfn, VTDContextEntry *ce);
+
static void vtd_define_quad(IntelIOMMUState *s, hwaddr addr, uint64_t val,
uint64_t wmask, uint64_t w1cmask)
{
@@ -142,6 +145,23 @@ static uint64_t vtd_set_clear_mask_quad(IntelIOMMUState *s, hwaddr addr,
return new_val;
}
+static int vtd_get_did_dev(IntelIOMMUState *s, uint8_t bus_num, uint8_t devfn,
+ uint16_t * domain_id)
+{
+ VTDContextEntry ce;
+ int ret_fr;
+
+ assert(domain_id);
+
+ ret_fr = vtd_dev_to_context_entry(s, bus_num, devfn, &ce);
+ if (ret_fr){
+ return -1;
+ }
+
+ *domain_id = VTD_CONTEXT_ENTRY_DID(ce.hi);
+ return 0;
+}
+
/* GHashTable functions */
static gboolean vtd_uint64_equal(gconstpointer v1, gconstpointer v2)
{
@@ -682,9 +702,6 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t gpa, IOMMUAccessFlags
*reads = (*reads) && (slpte & VTD_SL_R);
*writes = (*writes) && (slpte & VTD_SL_W);
if (!(slpte & access_right_check)) {
- VTD_DPRINTF(GENERAL, "error: lack of %s permission for "
- "gpa 0x%"PRIx64 " slpte 0x%"PRIx64,
- (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)) {
@@ -732,9 +749,6 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
}
if (!vtd_context_entry_present(ce)) {
- VTD_DPRINTF(GENERAL,
- "error: context-entry #%"PRIu8 "(bus #%"PRIu8 ") "
- "is not present", devfn, bus_num);
return -VTD_FR_CONTEXT_ENTRY_P;
} else if ((ce->hi & VTD_CONTEXT_ENTRY_RSVD_HI) ||
(ce->lo & VTD_CONTEXT_ENTRY_RSVD_LO)) {
@@ -1062,6 +1076,55 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)
&domain_id);
}
+static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,
+ uint16_t domain_id, hwaddr addr,
+ uint8_t am)
+{
+ IntelIOMMUNotifierNode * node;
+
+ QLIST_FOREACH(node, &(s->notifiers_list), next){
+ VTDAddressSpace *vtd_as = node->vtd_as;
+ uint16_t vfio_domain_id;
+ int ret = vtd_get_did_dev(s, pci_bus_num(vtd_as->bus), vtd_as->devfn,
+ &vfio_domain_id);
+ //int i=0;
+ if (!ret && domain_id == vfio_domain_id){
+ IOMMUTLBEntry entry;
+
+ /* notify unmap */
+ if (node->notifier_flag & IOMMU_NOTIFIER_UNMAP){
+ VTD_DPRINTF(GENERAL, "Remove addr 0x%"PRIx64 " mask %d", addr, am);
+ entry.target_as = &address_space_memory;
+ entry.iova = addr & VTD_PAGE_MASK_4K;
+ entry.translated_addr = 0;
+ entry.addr_mask = ~VTD_PAGE_MASK(VTD_PAGE_SHIFT_4K + am);
+ entry.perm = IOMMU_NONE;
+ memory_region_notify_iommu(&node->vtd_as->iommu, entry);
+ }
+
+ /* notify map */
+ if (node->notifier_flag & IOMMU_NOTIFIER_MAP){
+ hwaddr original_addr = addr;
+ VTD_DPRINTF(GENERAL, "add addr 0x%"PRIx64 " mask %d", addr, am);
+ while (addr < original_addr + (1<<am) * VTD_PAGE_SIZE){
+ /* call to vtd_iommu_translate */
+ IOMMUTLBEntry entry = s->iommu_ops.translate(
+ &node->vtd_as->iommu,
+ addr,
+ IOMMU_NO_FAIL);
+ if (entry.perm != IOMMU_NONE){
+ addr += entry.addr_mask + 1;
+ memory_region_notify_iommu(&node->vtd_as->iommu, entry);
+ } else {
+ addr += VTD_PAGE_SIZE;
+ }
+ }
+ }
+ }
+ }
+}
+
+
static void vtd_iotlb_page_invalidate(IntelIOMMUState *s, uint16_t domain_id,
hwaddr addr, uint8_t am)
{
@@ -1072,6 +1135,8 @@ static void vtd_iotlb_page_invalidate(IntelIOMMUState *s, uint16_t domain_id,
info.addr = addr;
info.mask = ~((1 << am) - 1);
g_hash_table_foreach_remove(s->iotlb, vtd_hash_remove_by_page, &info);
+
+ vtd_iotlb_page_invalidate_notify(s, domain_id, addr, am);
}
/* Flush IOTLB
@@ -1997,8 +2062,10 @@ static void vtd_iommu_notify_flag_changed(MemoryRegion *iommu,
IOMMUNotifierFlag new)
{
VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
+ IntelIOMMUState *s = vtd_as->iommu_state;
+ IntelIOMMUNotifierNode * node = NULL;
- if (new & IOMMU_NOTIFIER_MAP) {
+ if (!s->cache_mode_enabled && new & IOMMU_NOTIFIER_MAP) {
error_report("Device at bus %s addr %02x.%d requires iommu "
"notifier which is currently not supported by "
"intel-iommu emulation",
@@ -2006,6 +2073,27 @@ static void vtd_iommu_notify_flag_changed(MemoryRegion *iommu,
PCI_FUNC(vtd_as->devfn));
exit(1);
}
+
+ /* Add new ndoe if no mapping was exising before this call */
+ if (old == IOMMU_NOTIFIER_NONE){
+ node = g_malloc0(sizeof(*node));
+ node->vtd_as = vtd_as;
+ node->notifier_flag = new;
+ QLIST_INSERT_HEAD(&s->notifiers_list, node, next);
+ return;
+ }
+
+ /* update notifier node with new flags */
+ QLIST_FOREACH(node, &s->notifiers_list, next){
+ if (node->vtd_as == vtd_as){
+ if (new == IOMMU_NOTIFIER_NONE){
+ QLIST_REMOVE(node, next);
+ } else {
+ node->notifier_flag = new;
+ }
+ return;
+ }
+ }
}
static const VMStateDescription vtd_vmstate = {
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 35d9f3a..96df4ae 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -381,6 +381,8 @@ typedef struct VTDIOTLBPageInvInfo VTDIOTLBPageInvInfo;
#define VTD_PAGE_SHIFT_1G 30
#define VTD_PAGE_MASK_1G (~((1ULL << VTD_PAGE_SHIFT_1G) - 1))
+#define VTD_PAGE_MASK(shift) (~((1ULL << (shift)) - 1))
+
struct VTDRootEntry {
uint64_t val;
uint64_t rsvd;
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 7a94f16..3083608 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -63,6 +63,7 @@ typedef union VTD_IR_TableEntry VTD_IR_TableEntry;
typedef union VTD_IR_MSIAddress VTD_IR_MSIAddress;
typedef struct VTDIrq VTDIrq;
typedef struct VTD_MSIMessage VTD_MSIMessage;
+typedef struct IntelIOMMUNotifierNode IntelIOMMUNotifierNode;
/* Context-Entry */
struct VTDContextEntry {
@@ -248,6 +249,12 @@ struct VTD_MSIMessage {
/* When IR is enabled, all MSI/MSI-X data bits should be zero */
#define VTD_IR_MSI_DATA (0)
+struct IntelIOMMUNotifierNode {
+ VTDAddressSpace * vtd_as;
+ IOMMUNotifierFlag notifier_flag;
+ QLIST_ENTRY(IntelIOMMUNotifierNode) next;
+};
+
/* The iommu (DMAR) device state struct */
struct IntelIOMMUState {
X86IOMMUState x86_iommu;
@@ -285,6 +292,7 @@ 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 */
+ QLIST_HEAD(, IntelIOMMUNotifierNode) notifiers_list; /* list of registered notifiers */
/* interrupt remapping */
bool intr_enabled; /* Whether guest enabled IR */
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications
2016-10-15 10:12 [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications Aviv B.D
` (2 preceding siblings ...)
2016-10-15 10:12 ` [Qemu-devel] [PATCH v4 3/3] IOMMU: enable intel_iommu map and unmap notifiers Aviv B.D
@ 2016-10-15 10:28 ` no-reply
3 siblings, 0 replies; 5+ messages in thread
From: no-reply @ 2016-10-15 10:28 UTC (permalink / raw)
To: bd.aviv; +Cc: famz, qemu-devel, jan.kiszka, alex.williamson, peterx, mst
Hi,
Your series seems to have some coding style problems. See output below for
more information:
Type: series
Message-id: 1476526326-32363-1-git-send-email-bd.aviv@gmail.com
Subject: [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications
=== TEST SCRIPT BEGIN ===
#!/bin/bash
BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0
# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True
commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git show --no-patch --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done
exit $failed
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
2bf1af5 IOMMU: enable intel_iommu map and unmap notifiers
859d070 IOMMU: change iommu_op->translate's is_write to flags, add support to NO_FAIL flag mode
45f4bb2 IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest
=== OUTPUT BEGIN ===
Checking PATCH 1/3: IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest...
ERROR: space required before the open brace '{'
#31: FILE: hw/i386/intel_iommu.c:2389:
+ if (s->cache_mode_enabled){
total: 1 errors, 0 warnings, 32 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 2/3: IOMMU: change iommu_op->translate's is_write to flags, add support to NO_FAIL flag mode...
WARNING: line over 80 characters
#22: FILE: exec.c:435:
+ iotlb = mr->iommu_ops->translate(mr, addr, is_write ? IOMMU_WO : IOMMU_RO);
WARNING: line over 80 characters
#102: FILE: hw/i386/intel_iommu.c:632:
+static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t gpa, IOMMUAccessFlags flags,
ERROR: switch and case should be at the same indent
#111: FILE: hw/i386/intel_iommu.c:652:
+ switch(flags){
+ case IOMMU_WO:
[...]
+ case IOMMU_RO:
[...]
+ case IOMMU_RW: /* passthrow */
+ case IOMMU_NO_FAIL:
[...]
+ default:
ERROR: space required before the open brace '{'
#111: FILE: hw/i386/intel_iommu.c:652:
+ switch(flags){
ERROR: space required before the open parenthesis '('
#111: FILE: hw/i386/intel_iommu.c:652:
+ switch(flags){
ERROR: line over 90 characters
#135: FILE: hw/i386/intel_iommu.c:688:
+ return (flags == IOMMU_RW || flags == IOMMU_WO) ? -VTD_FR_WRITE : -VTD_FR_READ;
WARNING: line over 80 characters
#149: FILE: hw/i386/intel_iommu.c:809:
+ uint8_t devfn, hwaddr addr, IOMMUAccessFlags flags,
ERROR: space required before the open brace '{'
#177: FILE: hw/i386/intel_iommu.c:872:
+ if (flags != IOMMU_NO_FAIL){
ERROR: space required before the open brace '{'
#201: FILE: hw/i386/intel_iommu.c:896:
+ if (flags != IOMMU_NO_FAIL){
WARNING: line over 80 characters
#203: FILE: hw/i386/intel_iommu.c:898:
+ VTD_DPRINTF(FLOG, "fault processing is disabled for DMA requests "
WARNING: line over 80 characters
#251: FILE: include/exec/memory.h:174:
+ IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, IOMMUAccessFlags flags);
WARNING: line over 80 characters
#264: FILE: memory.c:1566:
+ iotlb = mr->iommu_ops->translate(mr, addr, is_write ? IOMMU_WO : IOMMU_RO);
total: 6 errors, 6 warnings, 214 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 3/3: IOMMU: enable intel_iommu map and unmap notifiers...
ERROR: trailing whitespace
#33: FILE: hw/i386/intel_iommu.c:148:
+static int vtd_get_did_dev(IntelIOMMUState *s, uint8_t bus_num, uint8_t devfn, $
ERROR: "foo * bar" should be "foo *bar"
#34: FILE: hw/i386/intel_iommu.c:149:
+ uint16_t * domain_id)
ERROR: space required before the open brace '{'
#42: FILE: hw/i386/intel_iommu.c:157:
+ if (ret_fr){
ERROR: trailing whitespace
#77: FILE: hw/i386/intel_iommu.c:1079:
+static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s, $
ERROR: trailing whitespace
#78: FILE: hw/i386/intel_iommu.c:1080:
+ uint16_t domain_id, hwaddr addr, $
ERROR: "foo * bar" should be "foo *bar"
#81: FILE: hw/i386/intel_iommu.c:1083:
+ IntelIOMMUNotifierNode * node;
ERROR: space required before the open brace '{'
#83: FILE: hw/i386/intel_iommu.c:1085:
+ QLIST_FOREACH(node, &(s->notifiers_list), next){
ERROR: trailing whitespace
#84: FILE: hw/i386/intel_iommu.c:1086:
+ VTDAddressSpace *vtd_as = node->vtd_as; $
ERROR: trailing whitespace
#85: FILE: hw/i386/intel_iommu.c:1087:
+ uint16_t vfio_domain_id; $
ERROR: trailing whitespace
#86: FILE: hw/i386/intel_iommu.c:1088:
+ int ret = vtd_get_did_dev(s, pci_bus_num(vtd_as->bus), vtd_as->devfn, $
ERROR: do not use C99 // comments
#88: FILE: hw/i386/intel_iommu.c:1090:
+ //int i=0;
ERROR: space required before the open brace '{'
#89: FILE: hw/i386/intel_iommu.c:1091:
+ if (!ret && domain_id == vfio_domain_id){
ERROR: trailing whitespace
#90: FILE: hw/i386/intel_iommu.c:1092:
+ IOMMUTLBEntry entry; $
ERROR: trailing whitespace
#91: FILE: hw/i386/intel_iommu.c:1093:
+ $
ERROR: space required before the open brace '{'
#93: FILE: hw/i386/intel_iommu.c:1095:
+ if (node->notifier_flag & IOMMU_NOTIFIER_UNMAP){
WARNING: line over 80 characters
#94: FILE: hw/i386/intel_iommu.c:1096:
+ VTD_DPRINTF(GENERAL, "Remove addr 0x%"PRIx64 " mask %d", addr, am);
ERROR: trailing whitespace
#102: FILE: hw/i386/intel_iommu.c:1104:
+ $
ERROR: space required before the open brace '{'
#104: FILE: hw/i386/intel_iommu.c:1106:
+ if (node->notifier_flag & IOMMU_NOTIFIER_MAP){
ERROR: spaces required around that '<<' (ctx:VxV)
#107: FILE: hw/i386/intel_iommu.c:1109:
+ while (addr < original_addr + (1<<am) * VTD_PAGE_SIZE){
^
ERROR: space required before the open brace '{'
#107: FILE: hw/i386/intel_iommu.c:1109:
+ while (addr < original_addr + (1<<am) * VTD_PAGE_SIZE){
WARNING: line over 80 characters
#110: FILE: hw/i386/intel_iommu.c:1112:
+ &node->vtd_as->iommu,
ERROR: trailing whitespace
#111: FILE: hw/i386/intel_iommu.c:1113:
+ addr, $
ERROR: trailing whitespace
#112: FILE: hw/i386/intel_iommu.c:1114:
+ IOMMU_NO_FAIL); $
ERROR: space required before the open brace '{'
#113: FILE: hw/i386/intel_iommu.c:1115:
+ if (entry.perm != IOMMU_NONE){
ERROR: trailing whitespace
#114: FILE: hw/i386/intel_iommu.c:1116:
+ addr += entry.addr_mask + 1; $
ERROR: "foo * bar" should be "foo *bar"
#143: FILE: hw/i386/intel_iommu.c:2066:
+ IntelIOMMUNotifierNode * node = NULL;
ERROR: space required before the open brace '{'
#156: FILE: hw/i386/intel_iommu.c:2078:
+ if (old == IOMMU_NOTIFIER_NONE){
ERROR: space required before the open brace '{'
#165: FILE: hw/i386/intel_iommu.c:2087:
+ QLIST_FOREACH(node, &s->notifiers_list, next){
ERROR: space required before the open brace '{'
#166: FILE: hw/i386/intel_iommu.c:2088:
+ if (node->vtd_as == vtd_as){
ERROR: space required before the open brace '{'
#167: FILE: hw/i386/intel_iommu.c:2089:
+ if (new == IOMMU_NOTIFIER_NONE){
ERROR: trailing whitespace
#199: FILE: include/hw/i386/intel_iommu.h:66:
+typedef struct IntelIOMMUNotifierNode IntelIOMMUNotifierNode; $
ERROR: "foo * bar" should be "foo *bar"
#208: FILE: include/hw/i386/intel_iommu.h:253:
+ VTDAddressSpace * vtd_as;
ERROR: line over 90 characters
#220: FILE: include/hw/i386/intel_iommu.h:295:
+ QLIST_HEAD(, IntelIOMMUNotifierNode) notifiers_list; /* list of registered notifiers */
total: 31 errors, 2 warnings, 185 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===
Test command exited with code: 1
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-10-15 10:28 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-10-15 10:12 [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications Aviv B.D
2016-10-15 10:12 ` [Qemu-devel] [PATCH v4 1/3] IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest Aviv B.D
2016-10-15 10:12 ` [Qemu-devel] [PATCH v4 2/3] IOMMU: change iommu_op->translate's is_write to flags, add support to NO_FAIL flag mode Aviv B.D
2016-10-15 10:12 ` [Qemu-devel] [PATCH v4 3/3] IOMMU: enable intel_iommu map and unmap notifiers Aviv B.D
2016-10-15 10:28 ` [Qemu-devel] [PATCH v4 0/3] IOMMU: intel_iommu support map and unmap notifications no-reply
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).