|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH v7 10/14] amd/iommu: Introduce lookup implementation
PV-IOMMU requires a lookup implementation to behave properly, provide one.
Signed-off-by: Teddy Astie <teddy.astie@xxxxxxxxxx>
---
v7: introduced
---
xen/drivers/passthrough/amd/iommu.h | 2 +
xen/drivers/passthrough/amd/iommu_map.c | 90 +++++++++++++++++++++
xen/drivers/passthrough/amd/pci_amd_iommu.c | 1 +
3 files changed, 93 insertions(+)
diff --git a/xen/drivers/passthrough/amd/iommu.h
b/xen/drivers/passthrough/amd/iommu.h
index 0bd0f15a72..de1442af1b 100644
--- a/xen/drivers/passthrough/amd/iommu.h
+++ b/xen/drivers/passthrough/amd/iommu.h
@@ -202,6 +202,8 @@ int __must_check cf_check amd_iommu_map_page(
int __must_check cf_check amd_iommu_unmap_page(
struct domain *d, dfn_t dfn, unsigned int order,
unsigned int *flush_flags, struct iommu_context *ctx);
+int cf_check amd_iommu_lookup_page(struct domain *d, dfn_t dfn, mfn_t *mfn,
+ unsigned int *flags, struct iommu_context
*ctx);
int amd_iommu_reserve_domain_unity_map(struct domain *d, struct iommu_context
*ctx,
const struct ivrs_unity_map *map,
unsigned int flag);
diff --git a/xen/drivers/passthrough/amd/iommu_map.c
b/xen/drivers/passthrough/amd/iommu_map.c
index 01b36fdf4f..82f8eb85c8 100644
--- a/xen/drivers/passthrough/amd/iommu_map.c
+++ b/xen/drivers/passthrough/amd/iommu_map.c
@@ -622,6 +622,96 @@ int cf_check amd_iommu_flush_iotlb_pages(
return 0;
}
+static int lookup_pagewalk(struct page_info *table, dfn_t dfn, unsigned long
level,
+ mfn_t *mfn, unsigned int *flags)
+{
+ int rc = 0;
+ union amd_iommu_pte entry, *pagetable;
+
+ pagetable = __map_domain_page(table);
+ if ( !pagetable )
+ return -ENOMEM;
+
+ entry = pagetable[pfn_to_pde_idx(dfn_x(dfn), level)];
+
+ if ( !entry.pr || WARN_ON(!entry.mfn) )
+ {
+ /* Missing mapping has no flag. */
+ *flags = 0;
+ rc = -ENOENT;
+ goto out;
+ }
+
+ /*
+ * AMD-Vi Specification, 2.2.3 I/O Page Tables for Host Translations
+ *
+ * Effective write permission is calculated using the IW(resp IR) bits in
the DTE,
+ * the I/O PDEs, and the I/O PTE. At each step of the translation process,
+ * I/O write permission (IW) bits (resp IR) from fetched page table
entries are
+ * logically ANDed into cumulative I/O write permissions for the
translation
+ * including the IW (resp IR) bit in the DTE.
+ */
+
+ if ( !entry.ir )
+ *flags &= ~IOMMUF_readable;
+
+ if ( !entry.iw )
+ *flags &= ~IOMMUF_writable;
+
+ if ( entry.next_level )
+ {
+ /* Go to the next mapping */
+ if ( WARN_ON(entry.next_level >= level) )
+ {
+ rc = -EILSEQ;
+ goto out;
+ }
+
+ unmap_domain_page(pagetable);
+ return lookup_pagewalk(mfn_to_page(_mfn(entry.mfn)), dfn,
entry.next_level,
+ mfn, flags);
+ }
+ else
+ {
+ /*
+ * Terminal mapping (either superpage or PTE). Compute that by
combining entry
+ * address with dfn (for taking account of sub-entry frames in case of
a superpage).
+ */
+ *mfn = _mfn(entry.mfn |
+ (dfn_x(dfn) & ((1ULL << ((level - 1) * PTE_PER_TABLE_SHIFT)) -
1)));
+ }
+
+out:
+ unmap_domain_page(pagetable);
+ return rc;
+}
+
+int cf_check amd_iommu_lookup_page(struct domain *d, dfn_t dfn, mfn_t *mfn,
+ unsigned int *flags, struct iommu_context
*ctx)
+{
+ struct page_info *root_table;
+ unsigned long level;
+
+ if ( ctx->opaque )
+ return -EOPNOTSUPP;
+
+ if ( !ctx->arch.amd.root_table )
+ return -ENOENT;
+
+ root_table = ctx->arch.amd.root_table;
+ level = dom_iommu(d)->arch.amd.paging_mode;
+
+ if ( dfn_x(dfn) >> (PTE_PER_TABLE_SHIFT * level) )
+ return -ENOENT;
+
+ /*
+ * We initially consider the page writable and readable, lookup_pagewalk
will
+ * remove these flags if it is not actually the case.
+ */
+ *flags |= IOMMUF_writable | IOMMUF_readable;
+ return lookup_pagewalk(root_table, dfn, level, mfn, flags);
+}
+
int amd_iommu_reserve_domain_unity_map(struct domain *d, struct iommu_context
*ctx,
const struct ivrs_unity_map *map,
unsigned int flag)
diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c
b/xen/drivers/passthrough/amd/pci_amd_iommu.c
index 3c17d78caf..3d08a925d6 100644
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c
@@ -732,6 +732,7 @@ static const struct iommu_ops __initconst_cf_clobber
_iommu_ops = {
.suspend = amd_iommu_suspend,
.resume = amd_iommu_resume,
.crash_shutdown = amd_iommu_crash_shutdown,
+ .lookup_page = amd_iommu_lookup_page,
.get_reserved_device_memory = amd_iommu_get_reserved_device_memory,
.dump_page_tables = amd_dump_page_tables,
.quiesce = amd_iommu_quiesce,
--
2.51.2
--
Teddy Astie | Vates XCP-ng Developer
XCP-ng & Xen Orchestra - Vates solutions
web: https://vates.tech
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |