* [Qemu-devel] [PATCH RFC v2 01/17] IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 02/17] memory: handle alias for iommu notifier Peter Xu
` (17 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
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.
Signed-off-by: Aviv Ben-David <bd.aviv@gmail.com>
Signed-off-by: Peter Xu <peterx@redhat.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 5f3e351..6c7362a 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2018,6 +2018,7 @@ static Property vtd_properties[] = {
DEFINE_PROP_ON_OFF_AUTO("eim", IntelIOMMUState, intr_eim,
ON_OFF_AUTO_AUTO),
DEFINE_PROP_BOOL("x-buggy-eim", IntelIOMMUState, buggy_eim, false),
+ DEFINE_PROP_BOOL("cache-mode", IntelIOMMUState, cache_mode_enabled, FALSE),
DEFINE_PROP_END_OF_LIST(),
};
@@ -2392,6 +2393,10 @@ static void vtd_init(IntelIOMMUState *s)
assert(s->intr_eim != ON_OFF_AUTO_AUTO);
}
+ 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 11abfa2..00cbe0d 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 405c9d1..749eef9 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -257,6 +257,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 */
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 02/17] memory: handle alias for iommu notifier
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 01/17] IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 03/17] memory: handle alias in memory_region_is_iommu() Peter Xu
` (16 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
From: Jason Wang <jasowang@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
memory.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/memory.c b/memory.c
index 33110e9..2bfc37f 100644
--- a/memory.c
+++ b/memory.c
@@ -1603,6 +1603,11 @@ static void memory_region_update_iommu_notify_flags(MemoryRegion *mr)
void memory_region_register_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n)
{
+ if (mr->alias) {
+ memory_region_register_iommu_notifier(mr->alias, n);
+ return;
+ }
+
/* We need to register for at least one bitfield */
assert(n->notifier_flags != IOMMU_NOTIFIER_NONE);
QLIST_INSERT_HEAD(&mr->iommu_notify, n, node);
@@ -1643,6 +1648,10 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n,
void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n)
{
+ if (mr->alias) {
+ memory_region_unregister_iommu_notifier(mr->alias, n);
+ return;
+ }
QLIST_REMOVE(n, node);
memory_region_update_iommu_notify_flags(mr);
}
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 03/17] memory: handle alias in memory_region_is_iommu()
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 01/17] IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 02/17] memory: handle alias for iommu notifier Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 04/17] intel_iommu: allocate new key when creating new address space Peter Xu
` (15 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
From: Jason Wang <jasowang@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
include/exec/memory.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 64560f6..958f4b2 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -628,6 +628,9 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
*/
static inline bool memory_region_is_iommu(MemoryRegion *mr)
{
+ if (mr->alias) {
+ return memory_region_is_iommu(mr->alias);
+ }
return mr->iommu_ops;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 04/17] intel_iommu: allocate new key when creating new address space
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (2 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 03/17] memory: handle alias in memory_region_is_iommu() Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 05/17] intel_iommu: simplify irq region translation Peter Xu
` (14 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
From: Jason Wang <jasowang@redhat.com>
We use the pointer to stack for key for new address space, this will
break hash table searching, fixing by g_malloc() a new key instead.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Acked-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 6c7362a..f4d3cce 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2327,12 +2327,13 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
VTDAddressSpace *vtd_dev_as;
if (!vtd_bus) {
+ uintptr_t *new_key = g_malloc(sizeof(*new_key));
+ *new_key = (uintptr_t)bus;
/* No corresponding free() */
vtd_bus = g_malloc0(sizeof(VTDBus) + sizeof(VTDAddressSpace *) * \
X86_IOMMU_PCI_DEVFN_MAX);
vtd_bus->bus = bus;
- key = (uintptr_t)bus;
- g_hash_table_insert(s->vtd_as_by_busptr, &key, vtd_bus);
+ g_hash_table_insert(s->vtd_as_by_busptr, new_key, vtd_bus);
}
vtd_dev_as = vtd_bus->dev_as[devfn];
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 05/17] intel_iommu: simplify irq region translation
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (3 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 04/17] intel_iommu: allocate new key when creating new address space Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 06/17] intel_iommu: renaming gpa to iova where proper Peter Xu
` (13 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
Before we have int-remap, we need to bypass interrupt write requests.
That's not necessary now - we have supported int-remap, and all the irq
region requests should be redirected there. Cleaning up the block with
an assertion instead.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 28 ++++++----------------------
1 file changed, 6 insertions(+), 22 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index f4d3cce..74243b5 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -811,28 +811,12 @@ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
bool writes = true;
VTDIOTLBEntry *iotlb_entry;
- /* Check if the request is in interrupt address range */
- if (vtd_is_interrupt_addr(addr)) {
- if (is_write) {
- /* 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,
- * we just use 1:1 mapping.
- */
- VTD_DPRINTF(MMU, "write request to interrupt address "
- "gpa 0x%"PRIx64, addr);
- entry->iova = addr & VTD_PAGE_MASK_4K;
- entry->translated_addr = addr & VTD_PAGE_MASK_4K;
- entry->addr_mask = ~VTD_PAGE_MASK_4K;
- entry->perm = IOMMU_WO;
- return;
- } 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);
- return;
- }
- }
+ /*
+ * We have standalone memory region for interrupt addresses, we
+ * should never receive translation requests in this region.
+ */
+ assert(!vtd_is_interrupt_addr(addr));
+
/* Try to fetch slpte form IOTLB */
iotlb_entry = vtd_lookup_iotlb(s, source_id, addr);
if (iotlb_entry) {
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 06/17] intel_iommu: renaming gpa to iova where proper
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (4 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 05/17] intel_iommu: simplify irq region translation Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 07/17] intel_iommu: fix trace for inv desc handling Peter Xu
` (12 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
There are lots of places in current intel_iommu.c codes that named
"iova" as "gpa". It is really confusing to use a name "gpa" in these
places (which is very easily to be understood as "Guest Physical
Address", while it's not). To make the codes (much) easier to be read, I
decided to do this once and for all.
No functional change is made. Only literal ones.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 74243b5..6009091 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -259,7 +259,7 @@ static void vtd_update_iotlb(IntelIOMMUState *s, uint16_t source_id,
uint64_t *key = g_malloc(sizeof(*key));
uint64_t gfn = vtd_get_iotlb_gfn(addr, level);
- VTD_DPRINTF(CACHE, "update iotlb sid 0x%"PRIx16 " gpa 0x%"PRIx64
+ VTD_DPRINTF(CACHE, "update iotlb sid 0x%"PRIx16 " iova 0x%"PRIx64
" slpte 0x%"PRIx64 " did 0x%"PRIx16, source_id, addr, slpte,
domain_id);
if (g_hash_table_size(s->iotlb) >= VTD_IOTLB_MAX_SIZE) {
@@ -575,12 +575,12 @@ static uint64_t vtd_get_slpte(dma_addr_t base_addr, uint32_t index)
return slpte;
}
-/* Given a gpa and the level of paging structure, return the offset of current
- * level.
+/* Given an iova and the level of paging structure, return the offset
+ * of current level.
*/
-static inline uint32_t vtd_gpa_level_offset(uint64_t gpa, uint32_t level)
+static inline uint32_t vtd_iova_level_offset(uint64_t iova, uint32_t level)
{
- return (gpa >> vtd_slpt_level_shift(level)) &
+ return (iova >> vtd_slpt_level_shift(level)) &
((1ULL << VTD_SL_LEVEL_BITS) - 1);
}
@@ -628,10 +628,10 @@ 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
+/* Given the @iova, 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 iova, bool is_write,
uint64_t *slptep, uint32_t *slpte_level,
bool *reads, bool *writes)
{
@@ -642,11 +642,11 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t gpa, bool is_write,
uint32_t ce_agaw = vtd_get_agaw_from_context_entry(ce);
uint64_t access_right_check;
- /* Check if @gpa is above 2^X-1, where X is the minimum of MGAW in CAP_REG
- * and AW in context-entry.
+ /* Check if @iova is above 2^X-1, where X is the minimum of MGAW
+ * in CAP_REG and AW in context-entry.
*/
- if (gpa & ~((1ULL << MIN(ce_agaw, VTD_MGAW)) - 1)) {
- VTD_DPRINTF(GENERAL, "error: gpa 0x%"PRIx64 " exceeds limits", gpa);
+ if (iova & ~((1ULL << MIN(ce_agaw, VTD_MGAW)) - 1)) {
+ VTD_DPRINTF(GENERAL, "error: iova 0x%"PRIx64 " exceeds limits", iova);
return -VTD_FR_ADDR_BEYOND_MGAW;
}
@@ -654,13 +654,13 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t gpa, bool is_write,
access_right_check = is_write ? VTD_SL_W : VTD_SL_R;
while (true) {
- offset = vtd_gpa_level_offset(gpa, level);
+ offset = vtd_iova_level_offset(iova, level);
slpte = vtd_get_slpte(addr, offset);
if (slpte == (uint64_t)-1) {
VTD_DPRINTF(GENERAL, "error: fail to access second-level paging "
- "entry at level %"PRIu32 " for gpa 0x%"PRIx64,
- level, gpa);
+ "entry at level %"PRIu32 " for iova 0x%"PRIx64,
+ level, iova);
if (level == vtd_get_level_from_context_entry(ce)) {
/* Invalid programming of context-entry */
return -VTD_FR_CONTEXT_ENTRY_INV;
@@ -672,8 +672,8 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t gpa, bool is_write,
*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,
- (is_write ? "write" : "read"), gpa, slpte);
+ "iova 0x%"PRIx64 " slpte 0x%"PRIx64,
+ (is_write ? "write" : "read"), iova, slpte);
return is_write ? -VTD_FR_WRITE : -VTD_FR_READ;
}
if (vtd_slpte_nonzero_rsvd(slpte, level)) {
@@ -820,7 +820,7 @@ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
/* Try to fetch slpte form IOTLB */
iotlb_entry = vtd_lookup_iotlb(s, source_id, addr);
if (iotlb_entry) {
- VTD_DPRINTF(CACHE, "hit iotlb sid 0x%"PRIx16 " gpa 0x%"PRIx64
+ VTD_DPRINTF(CACHE, "hit iotlb sid 0x%"PRIx16 " iova 0x%"PRIx64
" slpte 0x%"PRIx64 " did 0x%"PRIx16, source_id, addr,
iotlb_entry->slpte, iotlb_entry->domain_id);
slpte = iotlb_entry->slpte;
@@ -1956,7 +1956,7 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
is_write, &ret);
VTD_DPRINTF(MMU,
"bus %"PRIu8 " slot %"PRIu8 " func %"PRIu8 " devfn %"PRIu8
- " gpa 0x%"PRIx64 " hpa 0x%"PRIx64, pci_bus_num(vtd_as->bus),
+ " iova 0x%"PRIx64 " hpa 0x%"PRIx64, pci_bus_num(vtd_as->bus),
VTD_PCI_SLOT(vtd_as->devfn), VTD_PCI_FUNC(vtd_as->devfn),
vtd_as->devfn, addr, ret.translated_addr);
return ret;
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 07/17] intel_iommu: fix trace for inv desc handling
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (5 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 06/17] intel_iommu: renaming gpa to iova where proper Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 08/17] intel_iommu: fix trace for addr translation Peter Xu
` (11 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
VT-d codes are still using static DEBUG_INTEL_IOMMU macro. That's not
good, and we should end the day when we need to recompile the code
before getting useful debugging information for vt-d. Time to switch to
the trace system.
This is the first patch to do it.
Generally, the rule of mine is:
- for the old GENERAL typed message, I use error_report() directly if
apply. Those are something shouldn't happen, and we should print those
errors in all cases, even without enabling debug and tracing.
- for the non-GENERAL typed messages, remove those VTD_PRINTF()s that
looks hardly used, and convert the rest lines into trace_*().
- for useless DPRINTFs, I removed them.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 98 ++++++++++++++++++++++++---------------------------
hw/i386/trace-events | 13 +++++++
2 files changed, 59 insertions(+), 52 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 6009091..36ea90f 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -35,6 +35,7 @@
#include "sysemu/kvm.h"
#include "hw/i386/apic_internal.h"
#include "kvm_i386.h"
+#include "trace.h"
/*#define DEBUG_INTEL_IOMMU*/
#ifdef DEBUG_INTEL_IOMMU
@@ -474,22 +475,19 @@ static void vtd_handle_inv_queue_error(IntelIOMMUState *s)
/* Set the IWC field and try to generate an invalidation completion interrupt */
static void vtd_generate_completion_event(IntelIOMMUState *s)
{
- VTD_DPRINTF(INV, "completes an invalidation wait command with "
- "Interrupt Flag");
if (vtd_get_long_raw(s, DMAR_ICS_REG) & VTD_ICS_IWC) {
- VTD_DPRINTF(INV, "there is a previous interrupt condition to be "
- "serviced by software, "
- "new invalidation event is not generated");
+ trace_vtd_inv_desc_wait_irq("One pending, skip current");
return;
}
vtd_set_clear_mask_long(s, DMAR_ICS_REG, 0, VTD_ICS_IWC);
vtd_set_clear_mask_long(s, DMAR_IECTL_REG, 0, VTD_IECTL_IP);
if (vtd_get_long_raw(s, DMAR_IECTL_REG) & VTD_IECTL_IM) {
- VTD_DPRINTF(INV, "IM filed in IECTL_REG is set, new invalidation "
- "event is not generated");
+ trace_vtd_inv_desc_wait_irq("IM in IECTL_REG is set, "
+ "new event not generated");
return;
} else {
/* Generate the interrupt event */
+ trace_vtd_inv_desc_wait_irq("Generating complete event");
vtd_generate_interrupt(s, DMAR_IEADDR_REG, DMAR_IEDATA_REG);
vtd_set_clear_mask_long(s, DMAR_IECTL_REG, VTD_IECTL_IP, 0);
}
@@ -916,6 +914,7 @@ static void vtd_interrupt_remap_table_setup(IntelIOMMUState *s)
static void vtd_context_global_invalidate(IntelIOMMUState *s)
{
+ trace_vtd_inv_desc_cc_global();
s->context_cache_gen++;
if (s->context_cache_gen == VTD_CONTEXT_CACHE_GEN_MAX) {
vtd_reset_context_cache(s);
@@ -955,9 +954,11 @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
uint16_t mask;
VTDBus *vtd_bus;
VTDAddressSpace *vtd_as;
- uint16_t devfn;
+ uint8_t bus_n, devfn;
uint16_t devfn_it;
+ trace_vtd_inv_desc_cc_devices(source_id, func_mask);
+
switch (func_mask & 3) {
case 0:
mask = 0; /* No bits in the SID field masked */
@@ -973,16 +974,16 @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
break;
}
mask = ~mask;
- VTD_DPRINTF(INV, "device-selective invalidation source 0x%"PRIx16
- " mask %"PRIu16, source_id, mask);
- vtd_bus = vtd_find_as_from_bus_num(s, VTD_SID_TO_BUS(source_id));
+
+ bus_n = VTD_SID_TO_BUS(source_id);
+ vtd_bus = vtd_find_as_from_bus_num(s, bus_n);
if (vtd_bus) {
devfn = VTD_SID_TO_DEVFN(source_id);
for (devfn_it = 0; devfn_it < X86_IOMMU_PCI_DEVFN_MAX; ++devfn_it) {
vtd_as = vtd_bus->dev_as[devfn_it];
if (vtd_as && ((devfn_it & mask) == (devfn & mask))) {
- VTD_DPRINTF(INV, "invalidate context-cahce of devfn 0x%"PRIx16,
- devfn_it);
+ trace_vtd_inv_desc_cc_device(bus_n, (devfn_it >> 3) & 0x1f,
+ devfn_it & 3);
vtd_as->context_cache_entry.context_cache_gen = 0;
}
}
@@ -1295,7 +1296,7 @@ static bool vtd_process_wait_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
{
if ((inv_desc->hi & VTD_INV_DESC_WAIT_RSVD_HI) ||
(inv_desc->lo & VTD_INV_DESC_WAIT_RSVD_LO)) {
- VTD_DPRINTF(GENERAL, "error: non-zero reserved field in Invalidation "
+ error_report("Non-zero reserved field in Invalidation "
"Wait Descriptor hi 0x%"PRIx64 " lo 0x%"PRIx64,
inv_desc->hi, inv_desc->lo);
return false;
@@ -1309,21 +1310,20 @@ static bool vtd_process_wait_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
/* FIXME: need to be masked with HAW? */
dma_addr_t status_addr = inv_desc->hi;
- VTD_DPRINTF(INV, "status data 0x%x, status addr 0x%"PRIx64,
- status_data, status_addr);
+ trace_vtd_inv_desc_wait_sw(status_addr, status_data);
status_data = cpu_to_le32(status_data);
if (dma_memory_write(&address_space_memory, status_addr, &status_data,
sizeof(status_data))) {
- VTD_DPRINTF(GENERAL, "error: fail to perform a coherent write");
+ error_report("Invalidate Desc Wait status write failed");
return false;
}
} else if (inv_desc->lo & VTD_INV_DESC_WAIT_IF) {
/* Interrupt flag */
- VTD_DPRINTF(INV, "Invalidation Wait Descriptor interrupt completion");
vtd_generate_completion_event(s);
} else {
- VTD_DPRINTF(GENERAL, "error: invalid Invalidation Wait Descriptor: "
- "hi 0x%"PRIx64 " lo 0x%"PRIx64, inv_desc->hi, inv_desc->lo);
+ error_report("invalid Invalidation Wait Descriptor: "
+ "hi 0x%"PRIx64 " lo 0x%"PRIx64,
+ inv_desc->hi, inv_desc->lo);
return false;
}
return true;
@@ -1332,30 +1332,32 @@ static bool vtd_process_wait_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
static bool vtd_process_context_cache_desc(IntelIOMMUState *s,
VTDInvDesc *inv_desc)
{
+ uint16_t sid, fmask;
+
if ((inv_desc->lo & VTD_INV_DESC_CC_RSVD) || inv_desc->hi) {
- VTD_DPRINTF(GENERAL, "error: non-zero reserved field in Context-cache "
- "Invalidate Descriptor");
+ error_report("non-zero reserved field in Context-cache "
+ "Invalidate Descriptor");
return false;
}
switch (inv_desc->lo & VTD_INV_DESC_CC_G) {
case VTD_INV_DESC_CC_DOMAIN:
- VTD_DPRINTF(INV, "domain-selective invalidation domain 0x%"PRIx16,
- (uint16_t)VTD_INV_DESC_CC_DID(inv_desc->lo));
+ trace_vtd_inv_desc_cc_domain(
+ (uint16_t)VTD_INV_DESC_CC_DID(inv_desc->lo));
/* Fall through */
case VTD_INV_DESC_CC_GLOBAL:
- VTD_DPRINTF(INV, "global invalidation");
vtd_context_global_invalidate(s);
break;
case VTD_INV_DESC_CC_DEVICE:
- vtd_context_device_invalidate(s, VTD_INV_DESC_CC_SID(inv_desc->lo),
- VTD_INV_DESC_CC_FM(inv_desc->lo));
+ sid = VTD_INV_DESC_CC_SID(inv_desc->lo);
+ fmask = VTD_INV_DESC_CC_FM(inv_desc->lo);
+ vtd_context_device_invalidate(s, sid, fmask);
break;
default:
- VTD_DPRINTF(GENERAL, "error: invalid granularity in Context-cache "
- "Invalidate Descriptor hi 0x%"PRIx64 " lo 0x%"PRIx64,
- inv_desc->hi, inv_desc->lo);
+ error_report("invalid granularity in Context-cache "
+ "Invalidate Descriptor hi 0x%"PRIx64" lo 0x%"PRIx64,
+ inv_desc->hi, inv_desc->lo);
return false;
}
return true;
@@ -1369,7 +1371,7 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
if ((inv_desc->lo & VTD_INV_DESC_IOTLB_RSVD_LO) ||
(inv_desc->hi & VTD_INV_DESC_IOTLB_RSVD_HI)) {
- VTD_DPRINTF(GENERAL, "error: non-zero reserved field in IOTLB "
+ error_report("non-zero reserved field in IOTLB "
"Invalidate Descriptor hi 0x%"PRIx64 " lo 0x%"PRIx64,
inv_desc->hi, inv_desc->lo);
return false;
@@ -1377,14 +1379,13 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
switch (inv_desc->lo & VTD_INV_DESC_IOTLB_G) {
case VTD_INV_DESC_IOTLB_GLOBAL:
- VTD_DPRINTF(INV, "global invalidation");
+ trace_vtd_inv_desc_iotlb_global();
vtd_iotlb_global_invalidate(s);
break;
case VTD_INV_DESC_IOTLB_DOMAIN:
domain_id = VTD_INV_DESC_IOTLB_DID(inv_desc->lo);
- VTD_DPRINTF(INV, "domain-selective invalidation domain 0x%"PRIx16,
- domain_id);
+ trace_vtd_inv_desc_iotlb_domain(domain_id);
vtd_iotlb_domain_invalidate(s, domain_id);
break;
@@ -1392,18 +1393,17 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
domain_id = VTD_INV_DESC_IOTLB_DID(inv_desc->lo);
addr = VTD_INV_DESC_IOTLB_ADDR(inv_desc->hi);
am = VTD_INV_DESC_IOTLB_AM(inv_desc->hi);
- VTD_DPRINTF(INV, "page-selective invalidation domain 0x%"PRIx16
- " addr 0x%"PRIx64 " mask %"PRIu8, domain_id, addr, am);
+ trace_vtd_inv_desc_iotlb_pages(domain_id, addr, am);
if (am > VTD_MAMV) {
- VTD_DPRINTF(GENERAL, "error: supported max address mask value is "
- "%"PRIu8, (uint8_t)VTD_MAMV);
+ error_report("supported max address mask value is %"PRIu8,
+ (uint8_t)VTD_MAMV);
return false;
}
vtd_iotlb_page_invalidate(s, domain_id, addr, am);
break;
default:
- VTD_DPRINTF(GENERAL, "error: invalid granularity in IOTLB Invalidate "
+ error_report("invalid granularity in IOTLB Invalidate "
"Descriptor hi 0x%"PRIx64 " lo 0x%"PRIx64,
inv_desc->hi, inv_desc->lo);
return false;
@@ -1431,7 +1431,6 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
VTDInvDesc inv_desc;
uint8_t desc_type;
- VTD_DPRINTF(INV, "iq head %"PRIu16, s->iq_head);
if (!vtd_get_inv_desc(s->iq, s->iq_head, &inv_desc)) {
s->iq_last_desc_type = VTD_INV_DESC_NONE;
return false;
@@ -1442,42 +1441,37 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
switch (desc_type) {
case VTD_INV_DESC_CC:
- VTD_DPRINTF(INV, "Context-cache Invalidate Descriptor hi 0x%"PRIx64
- " lo 0x%"PRIx64, inv_desc.hi, inv_desc.lo);
+ trace_vtd_inv_desc("context-cache", inv_desc.hi, inv_desc.lo);
if (!vtd_process_context_cache_desc(s, &inv_desc)) {
return false;
}
break;
case VTD_INV_DESC_IOTLB:
- VTD_DPRINTF(INV, "IOTLB Invalidate Descriptor hi 0x%"PRIx64
- " lo 0x%"PRIx64, inv_desc.hi, inv_desc.lo);
+ trace_vtd_inv_desc("iotlb", inv_desc.hi, inv_desc.lo);
if (!vtd_process_iotlb_desc(s, &inv_desc)) {
return false;
}
break;
case VTD_INV_DESC_WAIT:
- VTD_DPRINTF(INV, "Invalidation Wait Descriptor hi 0x%"PRIx64
- " lo 0x%"PRIx64, inv_desc.hi, inv_desc.lo);
+ trace_vtd_inv_desc("wait", inv_desc.hi, inv_desc.lo);
if (!vtd_process_wait_desc(s, &inv_desc)) {
return false;
}
break;
case VTD_INV_DESC_IEC:
- VTD_DPRINTF(INV, "Invalidation Interrupt Entry Cache "
- "Descriptor hi 0x%"PRIx64 " lo 0x%"PRIx64,
- inv_desc.hi, inv_desc.lo);
+ trace_vtd_inv_desc("iec", inv_desc.hi, inv_desc.lo);
if (!vtd_process_inv_iec_desc(s, &inv_desc)) {
return false;
}
break;
default:
- VTD_DPRINTF(GENERAL, "error: unkonw Invalidation Descriptor type "
- "hi 0x%"PRIx64 " lo 0x%"PRIx64 " type %"PRIu8,
- inv_desc.hi, inv_desc.lo, desc_type);
+ error_report("Unkonw Invalidation Descriptor type "
+ "hi 0x%"PRIx64" lo 0x%"PRIx64" type %"PRIu8,
+ inv_desc.hi, inv_desc.lo, desc_type);
return false;
}
s->iq_head++;
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index d2b4973..fba81f4 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -10,6 +10,19 @@ xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space (ad
# hw/i386/x86-iommu.c
x86_iommu_iec_notify(bool global, uint32_t index, uint32_t mask) "Notify IEC invalidation: global=%d index=%" PRIu32 " mask=%" PRIu32
+# hw/i386/intel_iommu.c
+vtd_switch_address_space(uint8_t bus, uint8_t slot, uint8_t fn, bool on) "Device %02x:%02x.%x switching address space (iommu enabled=%d)"
+vtd_inv_desc(const char *type, uint64_t hi, uint64_t lo) "invalidate desc type %s high 0x%"PRIx64" low 0x%"PRIx64
+vtd_inv_desc_cc_domain(uint16_t domain) "context invalidate domain 0x%"PRIx16
+vtd_inv_desc_cc_global(void) "context invalidate globally"
+vtd_inv_desc_cc_device(uint8_t bus, uint8_t dev, uint8_t fn) "context invalidate device %02"PRIx8":%02"PRIx8".%02"PRIx8
+vtd_inv_desc_cc_devices(uint16_t sid, uint16_t fmask) "context invalidate devices sid 0x%"PRIx16" fmask 0x%"PRIx16
+vtd_inv_desc_iotlb_global(void) "iotlb invalidate global"
+vtd_inv_desc_iotlb_domain(uint16_t domain) "iotlb invalidate whole domain 0x%"PRIx16
+vtd_inv_desc_iotlb_pages(uint16_t domain, uint64_t addr, uint8_t mask) "iotlb invalidate domain 0x%"PRIx16" addr 0x%"PRIx64" mask 0x%"PRIx8
+vtd_inv_desc_wait_sw(uint64_t addr, uint32_t data) "wait invalidate status write addr 0x%"PRIx64" data 0x%"PRIx32
+vtd_inv_desc_wait_irq(const char *msg) "%s"
+
# hw/i386/amd_iommu.c
amdvi_evntlog_fail(uint64_t addr, uint32_t head) "error: fail to write at addr 0x%"PRIx64" + offset 0x%"PRIx32
amdvi_cache_update(uint16_t domid, uint8_t bus, uint8_t slot, uint8_t func, uint64_t gpa, uint64_t txaddr) " update iotlb domid 0x%"PRIx16" devid: %02x:%02x.%x gpa 0x%"PRIx64" hpa 0x%"PRIx64
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 08/17] intel_iommu: fix trace for addr translation
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (6 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 07/17] intel_iommu: fix trace for inv desc handling Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 09/17] intel_iommu: vtd_slpt_level_shift check level Peter Xu
` (10 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
Another patch to convert the DPRINTF() stuffs. This patch focuses on the
address translation path and caching.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 87 ++++++++++++++++++++++++---------------------------
hw/i386/trace-events | 7 +++++
2 files changed, 48 insertions(+), 46 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 36ea90f..f1118dd 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -260,11 +260,9 @@ static void vtd_update_iotlb(IntelIOMMUState *s, uint16_t source_id,
uint64_t *key = g_malloc(sizeof(*key));
uint64_t gfn = vtd_get_iotlb_gfn(addr, level);
- VTD_DPRINTF(CACHE, "update iotlb sid 0x%"PRIx16 " iova 0x%"PRIx64
- " slpte 0x%"PRIx64 " did 0x%"PRIx16, source_id, addr, slpte,
- domain_id);
+ trace_vtd_iotlb_page_update(source_id, addr, slpte, domain_id);
if (g_hash_table_size(s->iotlb) >= VTD_IOTLB_MAX_SIZE) {
- VTD_DPRINTF(CACHE, "iotlb exceeds size limit, forced to reset");
+ trace_vtd_iotlb_reset("iotlb exceeds size limit");
vtd_reset_iotlb(s);
}
@@ -505,8 +503,8 @@ static int vtd_get_root_entry(IntelIOMMUState *s, uint8_t index,
addr = s->root + index * sizeof(*re);
if (dma_memory_read(&address_space_memory, addr, re, sizeof(*re))) {
- VTD_DPRINTF(GENERAL, "error: fail to access root-entry at 0x%"PRIx64
- " + %"PRIu8, s->root, index);
+ error_report("Fail to access root-entry at 0x%"PRIx64
+ " index %"PRIu8, s->root, index);
re->val = 0;
return -VTD_FR_ROOT_TABLE_INV;
}
@@ -525,13 +523,12 @@ static int vtd_get_context_entry_from_root(VTDRootEntry *root, uint8_t index,
dma_addr_t addr;
if (!vtd_root_entry_present(root)) {
- VTD_DPRINTF(GENERAL, "error: root-entry is not present");
+ error_report("Root-entry is not present");
return -VTD_FR_ROOT_ENTRY_P;
}
addr = (root->val & VTD_ROOT_ENTRY_CTP) + index * sizeof(*ce);
if (dma_memory_read(&address_space_memory, addr, ce, sizeof(*ce))) {
- VTD_DPRINTF(GENERAL, "error: fail to access context-entry at 0x%"PRIx64
- " + %"PRIu8,
+ error_report("Fail to access context-entry at 0x%"PRIx64" ind %"PRIu8,
(uint64_t)(root->val & VTD_ROOT_ENTRY_CTP), index);
return -VTD_FR_CONTEXT_TABLE_INV;
}
@@ -644,7 +641,7 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t iova, bool is_write,
* in CAP_REG and AW in context-entry.
*/
if (iova & ~((1ULL << MIN(ce_agaw, VTD_MGAW)) - 1)) {
- VTD_DPRINTF(GENERAL, "error: iova 0x%"PRIx64 " exceeds limits", iova);
+ error_report("IOVA 0x%"PRIx64 " exceeds limits", iova);
return -VTD_FR_ADDR_BEYOND_MGAW;
}
@@ -656,7 +653,7 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t iova, bool is_write,
slpte = vtd_get_slpte(addr, offset);
if (slpte == (uint64_t)-1) {
- VTD_DPRINTF(GENERAL, "error: fail to access second-level paging "
+ error_report("Fail to access second-level paging "
"entry at level %"PRIu32 " for iova 0x%"PRIx64,
level, iova);
if (level == vtd_get_level_from_context_entry(ce)) {
@@ -669,13 +666,13 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t iova, bool is_write,
*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 "
- "iova 0x%"PRIx64 " slpte 0x%"PRIx64,
- (is_write ? "write" : "read"), iova, slpte);
+ error_report("Lack of %s permission for iova 0x%"PRIx64
+ " slpte 0x%"PRIx64,
+ (is_write ? "write" : "read"), iova, slpte);
return is_write ? -VTD_FR_WRITE : -VTD_FR_READ;
}
if (vtd_slpte_nonzero_rsvd(slpte, level)) {
- VTD_DPRINTF(GENERAL, "error: non-zero reserved field in second "
+ error_report("Non-zero reserved field in second "
"level paging entry level %"PRIu32 " slpte 0x%"PRIx64,
level, slpte);
return -VTD_FR_PAGING_ENTRY_RSVD;
@@ -704,12 +701,13 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
}
if (!vtd_root_entry_present(&re)) {
- VTD_DPRINTF(GENERAL, "error: root-entry #%"PRIu8 " is not present",
- bus_num);
+ /* Not error - it's okay we don't have root entry. */
+ trace_vtd_re_not_present(bus_num);
return -VTD_FR_ROOT_ENTRY_P;
} else if (re.rsvd || (re.val & VTD_ROOT_ENTRY_RSVD)) {
- VTD_DPRINTF(GENERAL, "error: non-zero reserved field in root-entry "
- "hi 0x%"PRIx64 " lo 0x%"PRIx64, re.rsvd, re.val);
+ error_report("Non-zero reserved field in root-entry bus_num %d "
+ "hi 0x%"PRIx64 " lo 0x%"PRIx64,
+ bus_num, re.rsvd, re.val);
return -VTD_FR_ROOT_ENTRY_RSVD;
}
@@ -719,27 +717,25 @@ 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);
+ /* Not error - it's okay we don't have context entry. */
+ trace_vtd_ce_not_present(bus_num, devfn);
return -VTD_FR_CONTEXT_ENTRY_P;
} else if ((ce->hi & VTD_CONTEXT_ENTRY_RSVD_HI) ||
(ce->lo & VTD_CONTEXT_ENTRY_RSVD_LO)) {
- VTD_DPRINTF(GENERAL,
- "error: non-zero reserved field in context-entry "
+ error_report("Non-zero reserved field in context-entry"
"hi 0x%"PRIx64 " lo 0x%"PRIx64, ce->hi, ce->lo);
return -VTD_FR_CONTEXT_ENTRY_RSVD;
}
/* Check if the programming of context-entry is valid */
if (!vtd_is_level_supported(s, vtd_get_level_from_context_entry(ce))) {
- VTD_DPRINTF(GENERAL, "error: unsupported Address Width value in "
- "context-entry hi 0x%"PRIx64 " lo 0x%"PRIx64,
- ce->hi, ce->lo);
+ error_report("Unsupported Address Width value in "
+ "context-entry hi 0x%"PRIx64 " lo 0x%"PRIx64,
+ ce->hi, ce->lo);
return -VTD_FR_CONTEXT_ENTRY_INV;
} else if (ce->lo & VTD_CONTEXT_ENTRY_TT) {
- VTD_DPRINTF(GENERAL, "error: unsupported Translation Type in "
- "context-entry hi 0x%"PRIx64 " lo 0x%"PRIx64,
- ce->hi, ce->lo);
+ error_report("Unsupported Translation Type in "
+ "context-entry hi 0x%"PRIx64 " lo 0x%"PRIx64,
+ ce->hi, ce->lo);
return -VTD_FR_CONTEXT_ENTRY_INV;
}
return 0;
@@ -818,9 +814,8 @@ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
/* Try to fetch slpte form IOTLB */
iotlb_entry = vtd_lookup_iotlb(s, source_id, addr);
if (iotlb_entry) {
- VTD_DPRINTF(CACHE, "hit iotlb sid 0x%"PRIx16 " iova 0x%"PRIx64
- " slpte 0x%"PRIx64 " did 0x%"PRIx16, source_id, addr,
- iotlb_entry->slpte, iotlb_entry->domain_id);
+ trace_vtd_iotlb_page_hit(source_id, addr, iotlb_entry->slpte,
+ iotlb_entry->domain_id);
slpte = iotlb_entry->slpte;
reads = iotlb_entry->read_flags;
writes = iotlb_entry->write_flags;
@@ -829,10 +824,9 @@ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
}
/* Try to fetch context-entry from cache first */
if (cc_entry->context_cache_gen == s->context_cache_gen) {
- VTD_DPRINTF(CACHE, "hit context-cache bus %d devfn %d "
- "(hi %"PRIx64 " lo %"PRIx64 " gen %"PRIu32 ")",
- bus_num, devfn, cc_entry->context_entry.hi,
- cc_entry->context_entry.lo, cc_entry->context_cache_gen);
+ trace_vtd_iotlb_cc_hit(bus_num, devfn, cc_entry->context_entry.hi,
+ cc_entry->context_entry.lo,
+ cc_entry->context_cache_gen);
ce = cc_entry->context_entry;
is_fpd_set = ce.lo & VTD_CONTEXT_ENTRY_FPD;
} else {
@@ -841,19 +835,18 @@ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
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)");
+ error_report("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);
}
return;
}
/* Update context-cache */
- VTD_DPRINTF(CACHE, "update context-cache bus %d devfn %d "
- "(hi %"PRIx64 " lo %"PRIx64 " gen %"PRIu32 "->%"PRIu32 ")",
- bus_num, devfn, ce.hi, ce.lo,
- cc_entry->context_cache_gen, s->context_cache_gen);
+ trace_vtd_iotlb_cc_update(bus_num, devfn, ce.hi, ce.lo,
+ cc_entry->context_cache_gen,
+ s->context_cache_gen);
cc_entry->context_entry = ce;
cc_entry->context_cache_gen = s->context_cache_gen;
}
@@ -863,8 +856,9 @@ static void vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus,
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)");
+ error_report("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);
}
@@ -1024,6 +1018,7 @@ static uint64_t vtd_context_cache_invalidate(IntelIOMMUState *s, uint64_t val)
static void vtd_iotlb_global_invalidate(IntelIOMMUState *s)
{
+ trace_vtd_iotlb_reset("global invalidation recved");
vtd_reset_iotlb(s);
}
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index fba81f4..eba9bf2 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -22,6 +22,13 @@ vtd_inv_desc_iotlb_domain(uint16_t domain) "iotlb invalidate whole domain 0x%"PR
vtd_inv_desc_iotlb_pages(uint16_t domain, uint64_t addr, uint8_t mask) "iotlb invalidate domain 0x%"PRIx16" addr 0x%"PRIx64" mask 0x%"PRIx8
vtd_inv_desc_wait_sw(uint64_t addr, uint32_t data) "wait invalidate status write addr 0x%"PRIx64" data 0x%"PRIx32
vtd_inv_desc_wait_irq(const char *msg) "%s"
+vtd_re_not_present(uint8_t bus) "Root entry bus %"PRIu8" not present"
+vtd_ce_not_present(uint8_t bus, uint8_t devfn) "Context entry bus %"PRIu8" devfn %"PRIu8" not present"
+vtd_iotlb_page_hit(uint16_t sid, uint64_t addr, uint64_t slpte, uint16_t domain) "IOTLB page hit sid 0x%"PRIx16" iova 0x%"PRIx64" slpte 0x%"PRIx64" domain 0x%"PRIx16
+vtd_iotlb_page_update(uint16_t sid, uint64_t addr, uint64_t slpte, uint16_t domain) "IOTLB page update sid 0x%"PRIx16" iova 0x%"PRIx64" slpte 0x%"PRIx64" domain 0x%"PRIx16
+vtd_iotlb_cc_hit(uint8_t bus, uint8_t devfn, uint64_t high, uint64_t low, uint32_t gen) "IOTLB context hit bus 0x%"PRIx8" devfn 0x%"PRIx8" high 0x%"PRIx64" low 0x%"PRIx64" gen %"PRIu32
+vtd_iotlb_cc_update(uint8_t bus, uint8_t devfn, uint64_t high, uint64_t low, uint32_t gen1, uint32_t gen2) "IOTLB context update bus 0x%"PRIx8" devfn 0x%"PRIx8" high 0x%"PRIx64" low 0x%"PRIx64" gen %"PRIu32" -> gen %"PRIu32
+vtd_iotlb_reset(const char *reason) "IOTLB reset (reason: %s)"
# hw/i386/amd_iommu.c
amdvi_evntlog_fail(uint64_t addr, uint32_t head) "error: fail to write at addr 0x%"PRIx64" + offset 0x%"PRIx32
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 09/17] intel_iommu: vtd_slpt_level_shift check level
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (7 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 08/17] intel_iommu: fix trace for addr translation Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 10/17] memory: add section range info for IOMMU notifier Peter Xu
` (9 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
This helps in debugging incorrect level passed in.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index f1118dd..abb9d2e 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -168,6 +168,7 @@ static gboolean vtd_hash_remove_by_domain(gpointer key, gpointer value,
/* The shift of an addr for a certain level of paging structure */
static inline uint32_t vtd_slpt_level_shift(uint32_t level)
{
+ assert(level != 0);
return VTD_PAGE_SHIFT_4K + (level - 1) * VTD_SL_LEVEL_BITS;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 10/17] memory: add section range info for IOMMU notifier
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (8 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 09/17] intel_iommu: vtd_slpt_level_shift check level Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 11/17] memory: provide iommu_replay_all() Peter Xu
` (8 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
In this patch, IOMMUNotifier.{start|end} are introduced to store section
information for a specific notifier. When notification occurs, we not
only check the notification type (MAP|UNMAP), but also check whether the
notified iova is in the range of specific IOMMU notifier, and skip those
notifiers if not in the listened range.
When removing an region, we need to make sure we removed the correct
VFIOGuestIOMMU by checking the IOMMUNotifier.start address as well.
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/vfio/common.c | 7 ++++++-
include/exec/memory.h | 3 +++
memory.c | 4 +++-
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 801578b..6f648da 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -455,6 +455,10 @@ static void vfio_listener_region_add(MemoryListener *listener,
giommu->container = container;
giommu->n.notify = vfio_iommu_map_notify;
giommu->n.notifier_flags = IOMMU_NOTIFIER_ALL;
+ giommu->n.start = section->offset_within_region;
+ llend = int128_add(int128_make64(giommu->n.start), section->size);
+ llend = int128_sub(llend, int128_one());
+ giommu->n.end = int128_get64(llend);
QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);
@@ -525,7 +529,8 @@ static void vfio_listener_region_del(MemoryListener *listener,
VFIOGuestIOMMU *giommu;
QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
- if (giommu->iommu == section->mr) {
+ if (giommu->iommu == section->mr &&
+ giommu->n.start == section->offset_within_region) {
memory_region_unregister_iommu_notifier(giommu->iommu,
&giommu->n);
QLIST_REMOVE(giommu, giommu_next);
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 958f4b2..cecfed1 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -84,6 +84,9 @@ typedef enum {
struct IOMMUNotifier {
void (*notify)(struct IOMMUNotifier *notifier, IOMMUTLBEntry *data);
IOMMUNotifierFlag notifier_flags;
+ /* Notify for address space range start <= addr <= end */
+ hwaddr start;
+ hwaddr end;
QLIST_ENTRY(IOMMUNotifier) node;
};
typedef struct IOMMUNotifier IOMMUNotifier;
diff --git a/memory.c b/memory.c
index 2bfc37f..e88bb54 100644
--- a/memory.c
+++ b/memory.c
@@ -1671,7 +1671,9 @@ void memory_region_notify_iommu(MemoryRegion *mr,
}
QLIST_FOREACH(iommu_notifier, &mr->iommu_notify, node) {
- if (iommu_notifier->notifier_flags & request_flags) {
+ if (iommu_notifier->notifier_flags & request_flags &&
+ iommu_notifier->start <= entry.iova &&
+ iommu_notifier->end >= entry.iova) {
iommu_notifier->notify(iommu_notifier, &entry);
}
}
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 11/17] memory: provide iommu_replay_all()
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (9 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 10/17] memory: add section range info for IOMMU notifier Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 12/17] memory: introduce memory_region_notify_one() Peter Xu
` (7 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
This is an "global" version of exising memory_region_iommu_replay() - we
announce the translations to all the registered notifiers, instead of a
specific one.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
include/exec/memory.h | 8 ++++++++
memory.c | 9 +++++++++
2 files changed, 17 insertions(+)
diff --git a/include/exec/memory.h b/include/exec/memory.h
index cecfed1..d8363a0 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -694,6 +694,14 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n,
bool is_write);
/**
+ * memory_region_iommu_replay_all: replay existing IOMMU translations
+ * to all the notifiers registered.
+ *
+ * @mr: the memory region to observe
+ */
+void memory_region_iommu_replay_all(MemoryRegion *mr);
+
+/**
* memory_region_unregister_iommu_notifier: unregister a notifier for
* changes to IOMMU translation entries.
*
diff --git a/memory.c b/memory.c
index e88bb54..df62bd1 100644
--- a/memory.c
+++ b/memory.c
@@ -1645,6 +1645,15 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n,
}
}
+void memory_region_iommu_replay_all(MemoryRegion *mr)
+{
+ IOMMUNotifier *notifier;
+
+ QLIST_FOREACH(notifier, &mr->iommu_notify, node) {
+ memory_region_iommu_replay(mr, notifier, false);
+ }
+}
+
void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n)
{
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 12/17] memory: introduce memory_region_notify_one()
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (10 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 11/17] memory: provide iommu_replay_all() Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 13/17] memory: add MemoryRegionIOMMUOps.replay() callback Peter Xu
` (6 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
Generalizing the notify logic in memory_region_notify_iommu() into a
single function. This can be further used in customized replay()
functions for IOMMUs.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
include/exec/memory.h | 15 +++++++++++++++
memory.c | 29 ++++++++++++++++++-----------
2 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/include/exec/memory.h b/include/exec/memory.h
index d8363a0..afe150c 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -669,6 +669,21 @@ void memory_region_notify_iommu(MemoryRegion *mr,
IOMMUTLBEntry entry);
/**
+ * memory_region_notify_one: notify a change in an IOMMU translation
+ * entry to a single notifier
+ *
+ * This works just like memory_region_notify_iommu(), but it only
+ * notifies a specific notifier, not all of them.
+ *
+ * @notifier: the notifier to be notified
+ * @entry: the new entry in the IOMMU translation table. The entry
+ * replaces all old entries for the same virtual I/O address range.
+ * Deleted entries have .@perm == 0.
+ */
+void memory_region_notify_one(IOMMUNotifier *notifier,
+ IOMMUTLBEntry *entry);
+
+/**
* memory_region_register_iommu_notifier: register a notifier for changes to
* IOMMU translation entries.
*
diff --git a/memory.c b/memory.c
index df62bd1..6e4c872 100644
--- a/memory.c
+++ b/memory.c
@@ -1665,26 +1665,33 @@ void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
memory_region_update_iommu_notify_flags(mr);
}
-void memory_region_notify_iommu(MemoryRegion *mr,
- IOMMUTLBEntry entry)
+void memory_region_notify_one(IOMMUNotifier *notifier,
+ IOMMUTLBEntry *entry)
{
- IOMMUNotifier *iommu_notifier;
IOMMUNotifierFlag request_flags;
- assert(memory_region_is_iommu(mr));
-
- if (entry.perm & IOMMU_RW) {
+ if (entry->perm & IOMMU_RW) {
request_flags = IOMMU_NOTIFIER_MAP;
} else {
request_flags = IOMMU_NOTIFIER_UNMAP;
}
+ if (notifier->notifier_flags & request_flags &&
+ notifier->start <= entry->iova &&
+ notifier->end >= entry->iova) {
+ notifier->notify(notifier, entry);
+ }
+}
+
+void memory_region_notify_iommu(MemoryRegion *mr,
+ IOMMUTLBEntry entry)
+{
+ IOMMUNotifier *iommu_notifier;
+
+ assert(memory_region_is_iommu(mr));
+
QLIST_FOREACH(iommu_notifier, &mr->iommu_notify, node) {
- if (iommu_notifier->notifier_flags & request_flags &&
- iommu_notifier->start <= entry.iova &&
- iommu_notifier->end >= entry.iova) {
- iommu_notifier->notify(iommu_notifier, &entry);
- }
+ memory_region_notify_one(iommu_notifier, &entry);
}
}
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 13/17] memory: add MemoryRegionIOMMUOps.replay() callback
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (11 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 12/17] memory: introduce memory_region_notify_one() Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 14/17] intel_iommu: provide its own replay() callback Peter Xu
` (5 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
Originally we have one memory_region_iommu_replay() function, which is
the default behavior to replay the translations of the whole IOMMU
region. However, on some platform like x86, we may want our own replay
logic for IOMMU regions. This patch add one more hook for IOMMUOps for
the callback, and it'll override the default if set.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
include/exec/memory.h | 2 ++
memory.c | 6 ++++++
2 files changed, 8 insertions(+)
diff --git a/include/exec/memory.h b/include/exec/memory.h
index afe150c..a26763f 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -181,6 +181,8 @@ struct MemoryRegionIOMMUOps {
void (*notify_flag_changed)(MemoryRegion *iommu,
IOMMUNotifierFlag old_flags,
IOMMUNotifierFlag new_flags);
+ /* Set this up to provide customized IOMMU replay function */
+ void (*replay)(MemoryRegion *iommu, IOMMUNotifier *notifier);
};
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
diff --git a/memory.c b/memory.c
index 6e4c872..609ac67 100644
--- a/memory.c
+++ b/memory.c
@@ -1629,6 +1629,12 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n,
hwaddr addr, granularity;
IOMMUTLBEntry iotlb;
+ /* If the IOMMU has its own replay callback, override */
+ if (mr->iommu_ops->replay) {
+ mr->iommu_ops->replay(mr, n);
+ return;
+ }
+
granularity = memory_region_iommu_get_min_page_size(mr);
for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 14/17] intel_iommu: provide its own replay() callback
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (12 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 13/17] memory: add MemoryRegionIOMMUOps.replay() callback Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 15/17] intel_iommu: do replay when context invalidate Peter Xu
` (4 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
The default replay() don't work for VT-d since vt-d will have a huge
default memory region which covers address range 0-(2^64-1). This will
normally bring a dead loop when guest starts.
The solution is simple - we don't walk over all the regions. Instead, we
jump over the regions when we found that the page directories are empty.
It'll greatly reduce the time to walk the whole region.
To achieve this, we provided a page walk helper to do that, invoking
corresponding hook function when we found an page we are interested in.
vtd_page_walk_level() is the core logic for the page walking. It's
interface is designed to suite further use case, e.g., to invalidate a
range of addresses.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++--
hw/i386/trace-events | 8 ++
include/exec/memory.h | 2 +
3 files changed, 217 insertions(+), 5 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index abb9d2e..6f26bcb 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -600,6 +600,22 @@ static inline uint32_t vtd_get_agaw_from_context_entry(VTDContextEntry *ce)
return 30 + (ce->hi & VTD_CONTEXT_ENTRY_AW) * 9;
}
+static inline uint64_t vtd_iova_limit(VTDContextEntry *ce)
+{
+ uint32_t ce_agaw = vtd_get_agaw_from_context_entry(ce);
+ return 1ULL << MIN(ce_agaw, VTD_MGAW);
+}
+
+/* Return true if IOVA passes range check, otherwise false. */
+static inline bool vtd_iova_range_check(uint64_t iova, VTDContextEntry *ce)
+{
+ /*
+ * Check if @iova is above 2^X-1, where X is the minimum of MGAW
+ * in CAP_REG and AW in context-entry.
+ */
+ return !(iova & ~(vtd_iova_limit(ce) - 1));
+}
+
static const uint64_t vtd_paging_entry_rsvd_field[] = {
[0] = ~0ULL,
/* For not large page */
@@ -635,13 +651,9 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t iova, bool is_write,
uint32_t level = vtd_get_level_from_context_entry(ce);
uint32_t offset;
uint64_t slpte;
- uint32_t ce_agaw = vtd_get_agaw_from_context_entry(ce);
uint64_t access_right_check;
- /* Check if @iova is above 2^X-1, where X is the minimum of MGAW
- * in CAP_REG and AW in context-entry.
- */
- if (iova & ~((1ULL << MIN(ce_agaw, VTD_MGAW)) - 1)) {
+ if (!vtd_iova_range_check(iova, ce)) {
error_report("IOVA 0x%"PRIx64 " exceeds limits", iova);
return -VTD_FR_ADDR_BEYOND_MGAW;
}
@@ -689,6 +701,166 @@ static int vtd_gpa_to_slpte(VTDContextEntry *ce, uint64_t iova, bool is_write,
}
}
+typedef int (*vtd_page_walk_hook)(IOMMUTLBEntry *entry, void *private);
+
+/**
+ * vtd_page_walk_level - walk over specific level for IOVA range
+ *
+ * @addr: base GPA addr to start the walk
+ * @start: IOVA range start address
+ * @end: IOVA range end address (start <= addr < end)
+ * @hook_fn: hook func to be called when detected page
+ * @private: private data to be passed into hook func
+ * @read: whether parent level has read permission
+ * @write: whether parent level has write permission
+ * @skipped: accumulated skipped ranges
+ * @notify_unmap: whether we should notify invalid entries
+ */
+static int vtd_page_walk_level(dma_addr_t addr, uint64_t start,
+ uint64_t end, vtd_page_walk_hook hook_fn,
+ void *private, uint32_t level,
+ bool read, bool write, uint64_t *skipped,
+ bool notify_unmap)
+{
+ bool read_cur, write_cur, entry_valid;
+ uint32_t offset;
+ uint64_t slpte;
+ uint64_t subpage_size, subpage_mask;
+ IOMMUTLBEntry entry;
+ uint64_t iova = start;
+ uint64_t iova_next;
+ uint64_t skipped_local = 0;
+ int ret = 0;
+
+ trace_vtd_page_walk_level(addr, level, start, end);
+
+ subpage_size = 1ULL << vtd_slpt_level_shift(level);
+ subpage_mask = vtd_slpt_level_page_mask(level);
+
+ while (iova < end) {
+ iova_next = (iova & subpage_mask) + subpage_size;
+
+ offset = vtd_iova_level_offset(iova, level);
+ slpte = vtd_get_slpte(addr, offset);
+
+ /*
+ * When one of the following case happens, we assume the whole
+ * range is invalid:
+ *
+ * 1. read block failed
+ * 3. reserved area non-zero
+ * 2. both read & write flag are not set
+ */
+
+ if (slpte == (uint64_t)-1) {
+ trace_vtd_page_walk_skip_read(iova, iova_next);
+ skipped_local++;
+ goto next;
+ }
+
+ if (vtd_slpte_nonzero_rsvd(slpte, level)) {
+ trace_vtd_page_walk_skip_reserve(iova, iova_next);
+ skipped_local++;
+ goto next;
+ }
+
+ /* Permissions are stacked with parents' */
+ read_cur = read && (slpte & VTD_SL_R);
+ write_cur = write && (slpte & VTD_SL_W);
+
+ /*
+ * As long as we have either read/write permission, this is
+ * a valid entry. The rule works for both page or page tables.
+ */
+ entry_valid = read_cur | write_cur;
+
+ if (vtd_is_last_slpte(slpte, level)) {
+ entry.target_as = &address_space_memory;
+ entry.iova = iova & subpage_mask;
+ /*
+ * This might be meaningless addr if (!read_cur &&
+ * !write_cur), but after all this field will be
+ * meaningless in that case, so let's share the code to
+ * generate the IOTLBs no matter it's an MAP or UNMAP
+ */
+ entry.translated_addr = vtd_get_slpte_addr(slpte);
+ entry.addr_mask = ~subpage_mask;
+ entry.perm = IOMMU_ACCESS_FLAG(read_cur, write_cur);
+ if (!entry_valid && !notify_unmap) {
+ trace_vtd_page_walk_skip_perm(iova, iova_next);
+ skipped_local++;
+ goto next;
+ }
+ trace_vtd_page_walk_one(level, entry.iova, entry.translated_addr,
+ entry.addr_mask, entry.perm);
+ if (hook_fn) {
+ ret = hook_fn(&entry, private);
+ if (ret < 0) {
+ error_report("Detected error in page walk hook "
+ "function, stop walk.");
+ return ret;
+ }
+ }
+ } else {
+ if (!entry_valid) {
+ trace_vtd_page_walk_skip_perm(iova, iova_next);
+ skipped_local++;
+ goto next;
+ }
+ ret = vtd_page_walk_level(vtd_get_slpte_addr(slpte), iova,
+ MIN(iova_next, end), hook_fn, private,
+ level - 1, read_cur, write_cur,
+ &skipped_local, notify_unmap);
+ if (ret < 0) {
+ error_report("Detected page walk error on addr 0x%"PRIx64
+ " level %"PRIu32", stop walk.", addr, level - 1);
+ return ret;
+ }
+ }
+
+next:
+ iova = iova_next;
+ }
+
+ if (skipped) {
+ *skipped += skipped_local;
+ }
+
+ return 0;
+}
+
+/**
+ * vtd_page_walk - walk specific IOVA range, and call the hook
+ *
+ * @ce: context entry to walk upon
+ * @start: IOVA address to start the walk
+ * @end: IOVA range end address (start <= addr < end)
+ * @hook_fn: the hook that to be called for each detected area
+ * @private: private data for the hook function
+ */
+static int vtd_page_walk(VTDContextEntry *ce, uint64_t start, uint64_t end,
+ vtd_page_walk_hook hook_fn, void *private)
+{
+ dma_addr_t addr = vtd_get_slpt_base_from_context(ce);
+ uint32_t level = vtd_get_level_from_context_entry(ce);
+
+ if (!vtd_iova_range_check(start, ce)) {
+ error_report("IOVA start 0x%"PRIx64 " end 0x%"PRIx64" exceeds limits",
+ start, end);
+ return -VTD_FR_ADDR_BEYOND_MGAW;
+ }
+
+ if (!vtd_iova_range_check(end, ce)) {
+ /* Fix end so that it reaches the maximum */
+ end = vtd_iova_limit(ce);
+ }
+
+ trace_vtd_page_walk(ce->hi, ce->lo, start, end);
+
+ return vtd_page_walk_level(addr, start, end, hook_fn, private,
+ level, true, true, NULL, false);
+}
+
/* Map a device to its corresponding domain (context-entry) */
static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
uint8_t devfn, VTDContextEntry *ce)
@@ -2332,6 +2504,35 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
return vtd_dev_as;
}
+static int vtd_replay_hook(IOMMUTLBEntry *entry, void *private)
+{
+ memory_region_notify_one((IOMMUNotifier *)private, entry);
+ return 0;
+}
+
+static void vtd_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
+{
+ VTDAddressSpace *vtd_as = container_of(mr, VTDAddressSpace, iommu);
+ IntelIOMMUState *s = vtd_as->iommu_state;
+ uint8_t bus_n = pci_bus_num(vtd_as->bus);
+ VTDContextEntry ce;
+
+ if (vtd_dev_to_context_entry(s, bus_n, vtd_as->devfn, &ce) == 0) {
+ /*
+ * Scanned a valid context entry, walk over the pages and
+ * notify when needed.
+ */
+ trace_vtd_replay_ce_valid(bus_n, PCI_SLOT(vtd_as->devfn),
+ PCI_FUNC(vtd_as->devfn), ce.hi, ce.lo);
+ vtd_page_walk(&ce, 0, ~0, vtd_replay_hook, (void *)n);
+ } else {
+ trace_vtd_replay_ce_invalid(bus_n, PCI_SLOT(vtd_as->devfn),
+ PCI_FUNC(vtd_as->devfn));
+ }
+
+ return;
+}
+
/* Do the initialization. It will also be called when reset, so pay
* attention when adding new initialization stuff.
*/
@@ -2346,6 +2547,7 @@ static void vtd_init(IntelIOMMUState *s)
s->iommu_ops.translate = vtd_iommu_translate;
s->iommu_ops.notify_flag_changed = vtd_iommu_notify_flag_changed;
+ s->iommu_ops.replay = vtd_iommu_replay;
s->root = 0;
s->root_extended = false;
s->dmar_enabled = false;
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index eba9bf2..92d210d 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -29,6 +29,14 @@ vtd_iotlb_page_update(uint16_t sid, uint64_t addr, uint64_t slpte, uint16_t doma
vtd_iotlb_cc_hit(uint8_t bus, uint8_t devfn, uint64_t high, uint64_t low, uint32_t gen) "IOTLB context hit bus 0x%"PRIx8" devfn 0x%"PRIx8" high 0x%"PRIx64" low 0x%"PRIx64" gen %"PRIu32
vtd_iotlb_cc_update(uint8_t bus, uint8_t devfn, uint64_t high, uint64_t low, uint32_t gen1, uint32_t gen2) "IOTLB context update bus 0x%"PRIx8" devfn 0x%"PRIx8" high 0x%"PRIx64" low 0x%"PRIx64" gen %"PRIu32" -> gen %"PRIu32
vtd_iotlb_reset(const char *reason) "IOTLB reset (reason: %s)"
+vtd_replay_ce_valid(uint8_t bus, uint8_t dev, uint8_t fn, uint64_t hi, uint64_t lo) "replay valid context device %02"PRIx8":%02"PRIx8".%02"PRIx8" hi 0x%"PRIx64" lo 0x%"PRIx64
+vtd_replay_ce_invalid(uint8_t bus, uint8_t dev, uint8_t fn) "replay invalid context device %02"PRIx8":%02"PRIx8".%02"PRIx8
+vtd_page_walk(uint64_t hi, uint64_t lo, uint64_t start, uint64_t end) "Page walk for ce (0x%"PRIx64", 0x%"PRIx64") iova range 0x%"PRIx64" - 0x%"PRIx64
+vtd_page_walk_level(uint64_t addr, uint32_t level, uint64_t start, uint64_t end) "Page walk (base=0x%"PRIx64", level=%"PRIu32") iova range 0x%"PRIx64" - 0x%"PRIx64
+vtd_page_walk_one(uint32_t level, uint64_t iova, uint64_t gpa, uint64_t mask, int perm) "Page walk detected map level 0x%"PRIx32" iova 0x%"PRIx64" -> gpa 0x%"PRIx64" mask 0x%"PRIx64" perm %d"
+vtd_page_walk_skip_read(uint64_t iova, uint64_t next) "Page walk skip iova 0x%"PRIx64" - 0x%"PRIx64" due to unable to read"
+vtd_page_walk_skip_perm(uint64_t iova, uint64_t next) "Page walk skip iova 0x%"PRIx64" - 0x%"PRIx64" due to perm empty"
+vtd_page_walk_skip_reserve(uint64_t iova, uint64_t next) "Page walk skip iova 0x%"PRIx64" - 0x%"PRIx64" due to rsrv set"
# hw/i386/amd_iommu.c
amdvi_evntlog_fail(uint64_t addr, uint32_t head) "error: fail to write at addr 0x%"PRIx64" + offset 0x%"PRIx32
diff --git a/include/exec/memory.h b/include/exec/memory.h
index a26763f..89c63ba 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -59,6 +59,8 @@ typedef enum {
IOMMU_RW = 3,
} IOMMUAccessFlags;
+#define IOMMU_ACCESS_FLAG(r, w) ((r) ? IOMMU_RO : 0) | ((w) ? IOMMU_WO : 0)
+
struct IOMMUTLBEntry {
AddressSpace *target_as;
hwaddr iova;
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 15/17] intel_iommu: do replay when context invalidate
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (13 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 14/17] intel_iommu: provide its own replay() callback Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 16/17] intel_iommu: allow dynamic switch of IOMMU region Peter Xu
` (3 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
Before this one we only invalidate context cache when we receive context
entry invalidations. However it's possible that the invalidation also
contains a domain switch (only if cache-mode is enabled for vIOMMU). In
that case we need to notify all the registered components about the new
mapping.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 6f26bcb..ed60cfa 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -1152,6 +1152,7 @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
trace_vtd_inv_desc_cc_device(bus_n, (devfn_it >> 3) & 0x1f,
devfn_it & 3);
vtd_as->context_cache_entry.context_cache_gen = 0;
+ memory_region_iommu_replay_all(&vtd_as->iommu);
}
}
}
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 16/17] intel_iommu: allow dynamic switch of IOMMU region
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (14 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 15/17] intel_iommu: do replay when context invalidate Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 17/17] intel_iommu: enable vfio devices Peter Xu
` (2 subsequent siblings)
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
This is preparation work to finally enabled dynamic switching ON/OFF for
VT-d protection. The old VT-d codes is using static IOMMU region, and
that won't satisfy vfio-pci device listeners.
Let me explain.
vfio-pci devices depend on the memory region listener and IOMMU replay
mechanism to make sure the device mapping is coherent with the guest
even if there are domain switches. And there are two kinds of domain
switches:
(1) switch from domain A -> B
(2) switch from domain A -> no domain (e.g., turn DMAR off)
Case (1) is handled by the context entry invalidation handling by the
VT-d replay logic. What the replay function should do here is to replay
the existing page mappings in domain B.
However for case (2), we don't want to replay any domain mappings - we
just need the default GPA->HPA mappings (the address_space_memory
mapping). And this patch helps on case (2) to build up the mapping
automatically by leveraging the vfio-pci memory listeners.
Another important thing that this patch does is to seperate
IR (Interrupt Remapping) from DMAR (DMA Remapping). IR region should not
depend on the DMAR region (like before this patch). It should be a
standalone region, and it should be able to be activated without
DMAR (which is a common behavior of Linux kernel - by default it enables
IR while disabled DMAR).
Signed-off-by: Peter Xu <peterx@redhat.com>
---
v3:
- fix another trivial style issue patchew reported but I missed in v2
v2:
- fix issues reported by patchew
- switch domain by enable/disable memory regions [David]
- provide vtd_switch_address_space{_all}()
- provide a better comment on the memory regions
test done: with intel_iommu device, boot vm with/without
"intel_iommu=on" parameter.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 78 ++++++++++++++++++++++++++++++++++++++++---
hw/i386/trace-events | 2 +-
include/hw/i386/intel_iommu.h | 2 ++
3 files changed, 77 insertions(+), 5 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index ed60cfa..e66b823 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -1333,9 +1333,49 @@ static void vtd_handle_gcmd_sirtp(IntelIOMMUState *s)
vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_IRTPS);
}
+static void vtd_switch_address_space(VTDAddressSpace *as, bool iommu_enabled)
+{
+ assert(as);
+
+ trace_vtd_switch_address_space(pci_bus_num(as->bus),
+ VTD_PCI_SLOT(as->devfn),
+ VTD_PCI_FUNC(as->devfn),
+ iommu_enabled);
+
+ /* Turn off first then on the other */
+ if (iommu_enabled) {
+ memory_region_set_enabled(&as->sys_alias, false);
+ memory_region_set_enabled(&as->iommu, true);
+ } else {
+ memory_region_set_enabled(&as->iommu, false);
+ memory_region_set_enabled(&as->sys_alias, true);
+ }
+}
+
+static void vtd_switch_address_space_all(IntelIOMMUState *s, bool enabled)
+{
+ GHashTableIter iter;
+ VTDBus *vtd_bus;
+ int i;
+
+ g_hash_table_iter_init(&iter, s->vtd_as_by_busptr);
+ while (g_hash_table_iter_next(&iter, NULL, (void **)&vtd_bus)) {
+ for (i = 0; i < X86_IOMMU_PCI_DEVFN_MAX; i++) {
+ if (!vtd_bus->dev_as[i]) {
+ continue;
+ }
+ vtd_switch_address_space(vtd_bus->dev_as[i], enabled);
+ }
+ }
+}
+
/* Handle Translation Enable/Disable */
static void vtd_handle_gcmd_te(IntelIOMMUState *s, bool en)
{
+ if (s->dmar_enabled == en) {
+ return;
+ }
+
VTD_DPRINTF(CSR, "Translation Enable %s", (en ? "on" : "off"));
if (en) {
@@ -1350,6 +1390,8 @@ static void vtd_handle_gcmd_te(IntelIOMMUState *s, bool en)
/* Ok - report back to driver */
vtd_set_clear_mask_long(s, DMAR_GSTS_REG, VTD_GSTS_TES, 0);
}
+
+ vtd_switch_address_space_all(s, en);
}
/* Handle Interrupt Remap Enable/Disable */
@@ -2492,15 +2534,43 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
vtd_dev_as->devfn = (uint8_t)devfn;
vtd_dev_as->iommu_state = s;
vtd_dev_as->context_cache_entry.context_cache_gen = 0;
+
+ /*
+ * Memory region relationships looks like (Address range shows
+ * only lower 32 bits to make it short in length...):
+ *
+ * |-----------------+-------------------+----------|
+ * | Name | Address range | Priority |
+ * |-----------------+-------------------+----------+
+ * | vtd_root | 00000000-ffffffff | 0 |
+ * | intel_iommu | 00000000-ffffffff | 1 |
+ * | vtd_sys_alias | 00000000-ffffffff | 1 |
+ * | intel_iommu_ir | fee00000-feefffff | 64 |
+ * |-----------------+-------------------+----------|
+ *
+ * We enable/disable DMAR by switching enablement for
+ * vtd_sys_alias and intel_iommu regions. IR region is always
+ * enabled.
+ */
memory_region_init_iommu(&vtd_dev_as->iommu, OBJECT(s),
&s->iommu_ops, "intel_iommu", UINT64_MAX);
+ memory_region_init_alias(&vtd_dev_as->sys_alias, OBJECT(s),
+ "vtd_sys_alias", get_system_memory(),
+ 0, memory_region_size(get_system_memory()));
memory_region_init_io(&vtd_dev_as->iommu_ir, OBJECT(s),
&vtd_mem_ir_ops, s, "intel_iommu_ir",
VTD_INTERRUPT_ADDR_SIZE);
- memory_region_add_subregion(&vtd_dev_as->iommu, VTD_INTERRUPT_ADDR_FIRST,
- &vtd_dev_as->iommu_ir);
- address_space_init(&vtd_dev_as->as,
- &vtd_dev_as->iommu, "intel_iommu");
+ memory_region_init(&vtd_dev_as->root, OBJECT(s),
+ "vtd_root", UINT64_MAX);
+ memory_region_add_subregion_overlap(&vtd_dev_as->root,
+ VTD_INTERRUPT_ADDR_FIRST,
+ &vtd_dev_as->iommu_ir, 64);
+ address_space_init(&vtd_dev_as->as, &vtd_dev_as->root, "intel_iommu");
+ memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
+ &vtd_dev_as->sys_alias, 1);
+ memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
+ &vtd_dev_as->iommu, 1);
+ vtd_switch_address_space(vtd_dev_as, s->dmar_enabled);
}
return vtd_dev_as;
}
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index 92d210d..beaef61 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -11,7 +11,6 @@ xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space (ad
x86_iommu_iec_notify(bool global, uint32_t index, uint32_t mask) "Notify IEC invalidation: global=%d index=%" PRIu32 " mask=%" PRIu32
# hw/i386/intel_iommu.c
-vtd_switch_address_space(uint8_t bus, uint8_t slot, uint8_t fn, bool on) "Device %02x:%02x.%x switching address space (iommu enabled=%d)"
vtd_inv_desc(const char *type, uint64_t hi, uint64_t lo) "invalidate desc type %s high 0x%"PRIx64" low 0x%"PRIx64
vtd_inv_desc_cc_domain(uint16_t domain) "context invalidate domain 0x%"PRIx16
vtd_inv_desc_cc_global(void) "context invalidate globally"
@@ -37,6 +36,7 @@ vtd_page_walk_one(uint32_t level, uint64_t iova, uint64_t gpa, uint64_t mask, in
vtd_page_walk_skip_read(uint64_t iova, uint64_t next) "Page walk skip iova 0x%"PRIx64" - 0x%"PRIx64" due to unable to read"
vtd_page_walk_skip_perm(uint64_t iova, uint64_t next) "Page walk skip iova 0x%"PRIx64" - 0x%"PRIx64" due to perm empty"
vtd_page_walk_skip_reserve(uint64_t iova, uint64_t next) "Page walk skip iova 0x%"PRIx64" - 0x%"PRIx64" due to rsrv set"
+vtd_switch_address_space(uint8_t bus, uint8_t slot, uint8_t fn, bool on) "Device %02x:%02x.%x switching address space (iommu enabled=%d)"
# hw/i386/amd_iommu.c
amdvi_evntlog_fail(uint64_t addr, uint32_t head) "error: fail to write at addr 0x%"PRIx64" + offset 0x%"PRIx32
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 749eef9..9c3f6c0 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -83,6 +83,8 @@ struct VTDAddressSpace {
uint8_t devfn;
AddressSpace as;
MemoryRegion iommu;
+ MemoryRegion root;
+ MemoryRegion sys_alias;
MemoryRegion iommu_ir; /* Interrupt region: 0xfeeXXXXX */
IntelIOMMUState *iommu_state;
VTDContextCacheEntry context_cache_entry;
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [Qemu-devel] [PATCH RFC v2 17/17] intel_iommu: enable vfio devices
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (15 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 16/17] intel_iommu: allow dynamic switch of IOMMU region Peter Xu
@ 2017-01-03 7:29 ` Peter Xu
2017-01-03 7:52 ` [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances no-reply
2017-01-12 14:27 ` Michael S. Tsirkin
18 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-03 7:29 UTC (permalink / raw)
To: qemu-devel
Cc: tianyu.lan, kevin.tian, mst, jan.kiszka, jasowang, peterx,
alex.williamson, bd.aviv
This patch is based on Aviv Ben-David (<bd.aviv@gmail.com>)'s patch
upstream:
"IOMMU: enable intel_iommu map and unmap notifiers"
https://lists.gnu.org/archive/html/qemu-devel/2016-11/msg01453.html
However I removed/fixed some content, and added my own codes.
Instead of translate() every page for iotlb invalidations (which is
slower), we walk the pages when needed and notify in a hook function.
This patch enables vfio devices for VT-d emulation.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/i386/intel_iommu.c | 68 +++++++++++++++++++++++++++++++++++++------
include/hw/i386/intel_iommu.h | 8 +++++
2 files changed, 67 insertions(+), 9 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index e66b823..fa50230 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -839,7 +839,8 @@ next:
* @private: private data for the hook function
*/
static int vtd_page_walk(VTDContextEntry *ce, uint64_t start, uint64_t end,
- vtd_page_walk_hook hook_fn, void *private)
+ vtd_page_walk_hook hook_fn, void *private,
+ bool notify_unmap)
{
dma_addr_t addr = vtd_get_slpt_base_from_context(ce);
uint32_t level = vtd_get_level_from_context_entry(ce);
@@ -858,7 +859,7 @@ static int vtd_page_walk(VTDContextEntry *ce, uint64_t start, uint64_t end,
trace_vtd_page_walk(ce->hi, ce->lo, start, end);
return vtd_page_walk_level(addr, start, end, hook_fn, private,
- level, true, true, NULL, false);
+ level, true, true, NULL, notify_unmap);
}
/* Map a device to its corresponding domain (context-entry) */
@@ -1202,6 +1203,34 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)
&domain_id);
}
+static int vtd_page_invalidate_notify_hook(IOMMUTLBEntry *entry,
+ void *private)
+{
+ memory_region_notify_iommu((MemoryRegion *)private, *entry);
+ return 0;
+}
+
+static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,
+ uint16_t domain_id, hwaddr addr,
+ uint8_t am)
+{
+ IntelIOMMUNotifierNode *node;
+ VTDContextEntry ce;
+ int ret;
+
+ QLIST_FOREACH(node, &(s->notifiers_list), next) {
+ VTDAddressSpace *vtd_as = node->vtd_as;
+ ret = vtd_dev_to_context_entry(s, pci_bus_num(vtd_as->bus),
+ vtd_as->devfn, &ce);
+ if (!ret && domain_id == VTD_CONTEXT_ENTRY_DID(ce.hi)) {
+ vtd_page_walk(&ce, addr, addr + (1 << am) * VTD_PAGE_SIZE,
+ vtd_page_invalidate_notify_hook,
+ (void *)&vtd_as->iommu, true);
+ }
+ }
+}
+
+
static void vtd_iotlb_page_invalidate(IntelIOMMUState *s, uint16_t domain_id,
hwaddr addr, uint8_t am)
{
@@ -1212,6 +1241,7 @@ 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
@@ -2172,15 +2202,34 @@ 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;
+ IntelIOMMUNotifierNode *next_node = NULL;
- if (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",
- vtd_as->bus->qbus.name, PCI_SLOT(vtd_as->devfn),
- PCI_FUNC(vtd_as->devfn));
+ if (!s->cache_mode_enabled && new & IOMMU_NOTIFIER_MAP) {
+ error_report("We need to set cache_mode=1 for intel-iommu to enable "
+ "device assignment with IOMMU protection.");
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;
+ QLIST_INSERT_HEAD(&s->notifiers_list, node, next);
+ return;
+ }
+
+ /* update notifier node with new flags */
+ QLIST_FOREACH_SAFE(node, &s->notifiers_list, next, next_node) {
+ if (node->vtd_as == vtd_as) {
+ if (new == IOMMU_NOTIFIER_NONE) {
+ QLIST_REMOVE(node, next);
+ g_free(node);
+ }
+ return;
+ }
+ }
}
static const VMStateDescription vtd_vmstate = {
@@ -2595,7 +2644,7 @@ static void vtd_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
*/
trace_vtd_replay_ce_valid(bus_n, PCI_SLOT(vtd_as->devfn),
PCI_FUNC(vtd_as->devfn), ce.hi, ce.lo);
- vtd_page_walk(&ce, 0, ~0, vtd_replay_hook, (void *)n);
+ vtd_page_walk(&ce, 0, ~0, vtd_replay_hook, (void *)n, false);
} else {
trace_vtd_replay_ce_invalid(bus_n, PCI_SLOT(vtd_as->devfn),
PCI_FUNC(vtd_as->devfn));
@@ -2773,6 +2822,7 @@ static void vtd_realize(DeviceState *dev, Error **errp)
return;
}
+ QLIST_INIT(&s->notifiers_list);
memset(s->vtd_as_by_bus_num, 0, sizeof(s->vtd_as_by_bus_num));
memory_region_init_io(&s->csrmem, OBJECT(s), &vtd_mem_ops, s,
"intel_iommu", DMAR_REG_SIZE);
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 9c3f6c0..832cfc9 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 {
@@ -249,6 +250,11 @@ 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;
+ QLIST_ENTRY(IntelIOMMUNotifierNode) next;
+};
+
/* The iommu (DMAR) device state struct */
struct IntelIOMMUState {
X86IOMMUState x86_iommu;
@@ -286,6 +292,8 @@ 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 */
+ /* list of registered notifiers */
+ QLIST_HEAD(, IntelIOMMUNotifierNode) notifiers_list;
/* interrupt remapping */
bool intr_enabled; /* Whether guest enabled IR */
--
2.7.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (16 preceding siblings ...)
2017-01-03 7:29 ` [Qemu-devel] [PATCH RFC v2 17/17] intel_iommu: enable vfio devices Peter Xu
@ 2017-01-03 7:52 ` no-reply
2017-01-12 14:27 ` Michael S. Tsirkin
18 siblings, 0 replies; 22+ messages in thread
From: no-reply @ 2017-01-03 7:52 UTC (permalink / raw)
To: peterx
Cc: famz, qemu-devel, tianyu.lan, kevin.tian, mst, jan.kiszka,
jasowang, alex.williamson, bd.aviv
Hi,
Your series seems to have some coding style problems. See output below for
more information:
Subject: [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances
Type: series
Message-id: 1483428594-28880-1-git-send-email-peterx@redhat.com
=== 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 log -n 1 --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
From https://github.com/patchew-project/qemu
* [new tag] patchew/1483428594-28880-1-git-send-email-peterx@redhat.com -> patchew/1483428594-28880-1-git-send-email-peterx@redhat.com
Switched to a new branch 'test'
69863b6 intel_iommu: enable vfio devices
1a464bd intel_iommu: allow dynamic switch of IOMMU region
ad7aeef intel_iommu: do replay when context invalidate
dd43a17 intel_iommu: provide its own replay() callback
1fba488 memory: add MemoryRegionIOMMUOps.replay() callback
e408082 memory: introduce memory_region_notify_one()
a89c58b memory: provide iommu_replay_all()
3c6c972 memory: add section range info for IOMMU notifier
688ef82 intel_iommu: vtd_slpt_level_shift check level
d18a425 intel_iommu: fix trace for addr translation
04056c0 intel_iommu: fix trace for inv desc handling
692f398 intel_iommu: renaming gpa to iova where proper
ec8456f intel_iommu: simplify irq region translation
1ecd377 intel_iommu: allocate new key when creating new address space
4d509be memory: handle alias in memory_region_is_iommu()
06d183d memory: handle alias for iommu notifier
0905834 IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest
=== OUTPUT BEGIN ===
Checking PATCH 1/17: IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to guest...
Checking PATCH 2/17: memory: handle alias for iommu notifier...
Checking PATCH 3/17: memory: handle alias in memory_region_is_iommu()...
Checking PATCH 4/17: intel_iommu: allocate new key when creating new address space...
Checking PATCH 5/17: intel_iommu: simplify irq region translation...
Checking PATCH 6/17: intel_iommu: renaming gpa to iova where proper...
Checking PATCH 7/17: intel_iommu: fix trace for inv desc handling...
Checking PATCH 8/17: intel_iommu: fix trace for addr translation...
Checking PATCH 9/17: intel_iommu: vtd_slpt_level_shift check level...
Checking PATCH 10/17: memory: add section range info for IOMMU notifier...
Checking PATCH 11/17: memory: provide iommu_replay_all()...
Checking PATCH 12/17: memory: introduce memory_region_notify_one()...
Checking PATCH 13/17: memory: add MemoryRegionIOMMUOps.replay() callback...
Checking PATCH 14/17: intel_iommu: provide its own replay() callback...
ERROR: Macros with complex values should be enclosed in parenthesis
#303: FILE: include/exec/memory.h:62:
+#define IOMMU_ACCESS_FLAG(r, w) ((r) ? IOMMU_RO : 0) | ((w) ? IOMMU_WO : 0)
total: 1 errors, 0 warnings, 266 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 15/17: intel_iommu: do replay when context invalidate...
Checking PATCH 16/17: intel_iommu: allow dynamic switch of IOMMU region...
Checking PATCH 17/17: intel_iommu: enable vfio devices...
=== 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] 22+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances
2017-01-03 7:29 [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances Peter Xu
` (17 preceding siblings ...)
2017-01-03 7:52 ` [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances no-reply
@ 2017-01-12 14:27 ` Michael S. Tsirkin
2017-01-13 2:19 ` Peter Xu
18 siblings, 1 reply; 22+ messages in thread
From: Michael S. Tsirkin @ 2017-01-12 14:27 UTC (permalink / raw)
To: Peter Xu
Cc: qemu-devel, tianyu.lan, kevin.tian, jan.kiszka, jasowang,
alex.williamson, bd.aviv
On Tue, Jan 03, 2017 at 03:29:37PM +0800, Peter Xu wrote:
> (I renamed the title for this RFC v2, since starting from this version
> the series will be based on master, also I picked up some more fixes
> for vt-d into this series)
>
> v2:
> - change comment for "end" parameter in vtd_page_walk() [Tianyu]
> - change comment for "a iova" to "an iova" [Yi]
> - fix fault printed val for GPA address in vtd_page_walk_level (debug
> only)
> - rebased to master (rather than Aviv's v6 series) and merged Aviv's
> series v6: picked patch 1 (as patch 1 in this series), dropped patch
> 2, re-wrote patch 3 (as patch 17 of this series).
> - picked up two more bugfix patches from Jason's DMAR series
> - picked up the following patch as well:
> "[PATCH v3] intel_iommu: allow dynamic switch of IOMMU region"
>
> This RFC series is a re-work for Aviv B.D.'s vfio enablement series
> with vt-d:
>
> https://lists.gnu.org/archive/html/qemu-devel/2016-11/msg01452.html
>
> Aviv has done a great job there, and what we still lack there are
> mostly the following:
>
> (1) VFIO got duplicated IOTLB notifications due to splitted VT-d IOMMU
> memory region.
>
> (2) VT-d still haven't provide a correct replay() mechanism (e.g.,
> when IOMMU domain switches, things will broke).
>
> This series should have solved the above two issues.
>
> Online repo:
>
> https://github.com/xzpeter/qemu/tree/vtd-vfio-enablement-v2
>
> I would be glad to hear about any review comments for above patches.
This all looks good to me. The series needs to be
rebased on top of latest bits.
In particular, Jason made changes which conflict
with this.
> =========
> Test Done
> =========
>
> Build test passed for x86_64/arm/ppc64.
>
> Simply tested with x86_64, assigning two PCI devices to a single VM,
> boot the VM using:
>
> bin=x86_64-softmmu/qemu-system-x86_64
> $bin -M q35,accel=kvm,kernel-irqchip=split -m 1G \
> -device intel-iommu,intremap=on,eim=off,cache-mode=on \
> -netdev user,id=net0,hostfwd=tcp::5555-:22 \
> -device virtio-net-pci,netdev=net0 \
> -device vfio-pci,host=03:00.0 \
> -device vfio-pci,host=02:00.0 \
> -trace events=".trace.vfio" \
> /var/lib/libvirt/images/vm1.qcow2
>
> pxdev:bin [vtd-vfio-enablement]# cat .trace.vfio
> vtd_page_walk*
> vtd_replay*
> vtd_inv_desc*
>
> Then, in the guest, run the following tool:
>
> https://github.com/xzpeter/clibs/blob/master/gpl/userspace/vfio-bind-group/vfio-bind-group.c
>
> With parameter:
>
> ./vfio-bind-group 00:03.0 00:04.0
>
> Check host side trace log, I can see pages are replayed and mapped in
> 00:04.0 device address space, like:
>
> ...
> vtd_replay_ce_valid replay valid context device 00:04.00 hi 0x401 lo 0x38fe1001
> vtd_page_walk Page walk for ce (0x401, 0x38fe1001) iova range 0x0 - 0x8000000000
> vtd_page_walk_level Page walk (base=0x38fe1000, level=3) iova range 0x0 - 0x8000000000
> vtd_page_walk_level Page walk (base=0x35d31000, level=2) iova range 0x0 - 0x40000000
> vtd_page_walk_level Page walk (base=0x34979000, level=1) iova range 0x0 - 0x200000
> vtd_page_walk_one Page walk detected map level 0x1 iova 0x0 -> gpa 0x22dc3000 mask 0xfff perm 3
> vtd_page_walk_one Page walk detected map level 0x1 iova 0x1000 -> gpa 0x22e25000 mask 0xfff perm 3
> vtd_page_walk_one Page walk detected map level 0x1 iova 0x2000 -> gpa 0x22e12000 mask 0xfff perm 3
> vtd_page_walk_one Page walk detected map level 0x1 iova 0x3000 -> gpa 0x22e2d000 mask 0xfff perm 3
> vtd_page_walk_one Page walk detected map level 0x1 iova 0x4000 -> gpa 0x12a49000 mask 0xfff perm 3
> vtd_page_walk_one Page walk detected map level 0x1 iova 0x5000 -> gpa 0x129bb000 mask 0xfff perm 3
> vtd_page_walk_one Page walk detected map level 0x1 iova 0x6000 -> gpa 0x128db000 mask 0xfff perm 3
> vtd_page_walk_one Page walk detected map level 0x1 iova 0x7000 -> gpa 0x12a80000 mask 0xfff perm 3
> vtd_page_walk_one Page walk detected map level 0x1 iova 0x8000 -> gpa 0x12a7e000 mask 0xfff perm 3
> vtd_page_walk_one Page walk detected map level 0x1 iova 0x9000 -> gpa 0x12b22000 mask 0xfff perm 3
> vtd_page_walk_one Page walk detected map level 0x1 iova 0xa000 -> gpa 0x12b41000 mask 0xfff perm 3
> ...
>
> =========
> Todo List
> =========
>
> - error reporting for the assigned devices (as Tianyu has mentioned)
>
> - per-domain address-space: A better solution in the future may be -
> we maintain one address space per IOMMU domain in the guest (so
> multiple devices can share a same address space if they are sharing
> the same IOMMU domains in the guest), rather than one address space
> per device (which is current implementation of vt-d). However that's
> a step further than this series, and let's see whether we can first
> provide a workable version of device assignment with vt-d
> protection.
>
> - more to come...
>
> Thanks,
>
> Aviv Ben-David (1):
> IOMMU: add option to enable VTD_CAP_CM to vIOMMU capility exposoed to
> guest
>
> Jason Wang (3):
> memory: handle alias for iommu notifier
> memory: handle alias in memory_region_is_iommu()
> intel_iommu: allocate new key when creating new address space
>
> Peter Xu (13):
> intel_iommu: simplify irq region translation
> intel_iommu: renaming gpa to iova where proper
> intel_iommu: fix trace for inv desc handling
> intel_iommu: fix trace for addr translation
> intel_iommu: vtd_slpt_level_shift check level
> memory: add section range info for IOMMU notifier
> memory: provide iommu_replay_all()
> memory: introduce memory_region_notify_one()
> memory: add MemoryRegionIOMMUOps.replay() callback
> intel_iommu: provide its own replay() callback
> intel_iommu: do replay when context invalidate
> intel_iommu: allow dynamic switch of IOMMU region
> intel_iommu: enable vfio devices
>
> hw/i386/intel_iommu.c | 597 +++++++++++++++++++++++++++++++----------
> hw/i386/intel_iommu_internal.h | 1 +
> hw/i386/trace-events | 28 ++
> hw/vfio/common.c | 7 +-
> include/exec/memory.h | 33 +++
> include/hw/i386/intel_iommu.h | 12 +
> memory.c | 51 +++-
> 7 files changed, 572 insertions(+), 157 deletions(-)
>
> --
> 2.7.4
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances
2017-01-12 14:27 ` Michael S. Tsirkin
@ 2017-01-13 2:19 ` Peter Xu
2017-01-13 2:57 ` Peter Xu
0 siblings, 1 reply; 22+ messages in thread
From: Peter Xu @ 2017-01-13 2:19 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: qemu-devel, tianyu.lan, kevin.tian, jan.kiszka, jasowang,
alex.williamson, bd.aviv
On Thu, Jan 12, 2017 at 04:27:30PM +0200, Michael S. Tsirkin wrote:
> On Tue, Jan 03, 2017 at 03:29:37PM +0800, Peter Xu wrote:
> > (I renamed the title for this RFC v2, since starting from this version
> > the series will be based on master, also I picked up some more fixes
> > for vt-d into this series)
> >
> > v2:
> > - change comment for "end" parameter in vtd_page_walk() [Tianyu]
> > - change comment for "a iova" to "an iova" [Yi]
> > - fix fault printed val for GPA address in vtd_page_walk_level (debug
> > only)
> > - rebased to master (rather than Aviv's v6 series) and merged Aviv's
> > series v6: picked patch 1 (as patch 1 in this series), dropped patch
> > 2, re-wrote patch 3 (as patch 17 of this series).
> > - picked up two more bugfix patches from Jason's DMAR series
> > - picked up the following patch as well:
> > "[PATCH v3] intel_iommu: allow dynamic switch of IOMMU region"
> >
> > This RFC series is a re-work for Aviv B.D.'s vfio enablement series
> > with vt-d:
> >
> > https://lists.gnu.org/archive/html/qemu-devel/2016-11/msg01452.html
> >
> > Aviv has done a great job there, and what we still lack there are
> > mostly the following:
> >
> > (1) VFIO got duplicated IOTLB notifications due to splitted VT-d IOMMU
> > memory region.
> >
> > (2) VT-d still haven't provide a correct replay() mechanism (e.g.,
> > when IOMMU domain switches, things will broke).
> >
> > This series should have solved the above two issues.
> >
> > Online repo:
> >
> > https://github.com/xzpeter/qemu/tree/vtd-vfio-enablement-v2
> >
> > I would be glad to hear about any review comments for above patches.
>
> This all looks good to me. The series needs to be
> rebased on top of latest bits.
> In particular, Jason made changes which conflict
> with this.
Michael,
Thanks for your positive feedback.
Could you provide me a branch so that I can rebase this work on? I was
trying to find a good base point in your repo here:
git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git
but failed to find a suitable branch. Thanks,
-- peterx
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Qemu-devel] [PATCH RFC v2 00/17] VT-d: vfio enablement and misc enhances
2017-01-13 2:19 ` Peter Xu
@ 2017-01-13 2:57 ` Peter Xu
0 siblings, 0 replies; 22+ messages in thread
From: Peter Xu @ 2017-01-13 2:57 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: qemu-devel, tianyu.lan, kevin.tian, jan.kiszka, jasowang,
alex.williamson, bd.aviv
On Fri, Jan 13, 2017 at 10:19:27AM +0800, Peter Xu wrote:
[...]
> > This all looks good to me. The series needs to be
> > rebased on top of latest bits.
> > In particular, Jason made changes which conflict
> > with this.
>
> Michael,
>
> Thanks for your positive feedback.
>
> Could you provide me a branch so that I can rebase this work on? I was
> trying to find a good base point in your repo here:
>
> git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git
>
> but failed to find a suitable branch. Thanks,
Please don't bother. Just noticed that Jason's patches related to VT-d
have been merged. So will rebase to master and re-post.
Thanks,
-- peterx
^ permalink raw reply [flat|nested] 22+ messages in thread