|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC 07/10] passthrough/amd: split out hvm code from iommu_map.c
Move and rename update_paging_mode. Create a local header file for
this and other functions that need exporting.
Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx>
---
Cc: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>
---
xen/drivers/passthrough/x86/amd/Makefile | 1 +
xen/drivers/passthrough/x86/amd/hvm.c | 108 ++++++++++++++++++++++++++++
xen/drivers/passthrough/x86/amd/iommu.h | 32 +++++++++
xen/drivers/passthrough/x86/amd/iommu_map.c | 103 ++------------------------
4 files changed, 148 insertions(+), 96 deletions(-)
create mode 100644 xen/drivers/passthrough/x86/amd/hvm.c
create mode 100644 xen/drivers/passthrough/x86/amd/iommu.h
diff --git a/xen/drivers/passthrough/x86/amd/Makefile
b/xen/drivers/passthrough/x86/amd/Makefile
index 415146fcdb..ed28fdb660 100644
--- a/xen/drivers/passthrough/x86/amd/Makefile
+++ b/xen/drivers/passthrough/x86/amd/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_HVM) += hvm.o
obj-bin-y += iommu_detect.init.o
obj-y += iommu_init.o
obj-y += iommu_map.o
diff --git a/xen/drivers/passthrough/x86/amd/hvm.c
b/xen/drivers/passthrough/x86/amd/hvm.c
new file mode 100644
index 0000000000..35c76c2545
--- /dev/null
+++ b/xen/drivers/passthrough/x86/amd/hvm.c
@@ -0,0 +1,108 @@
+#include <xen/sched.h>
+#include <asm/amd-iommu.h>
+#include <asm/hvm/svm/amd-iommu-proto.h>
+#include "../../ats.h"
+#include <xen/pci.h>
+
+#include "iommu.h"
+
+int hvm_update_paging_mode(struct domain *d, unsigned long gfn)
+{
+ u16 bdf;
+ void *device_entry;
+ unsigned int req_id, level, offset;
+ unsigned long flags;
+ struct pci_dev *pdev;
+ struct amd_iommu *iommu = NULL;
+ struct page_info *new_root = NULL;
+ struct page_info *old_root = NULL;
+ void *new_root_vaddr;
+ unsigned long old_root_mfn;
+ struct domain_iommu *hd = dom_iommu(d);
+
+ if ( gfn == gfn_x(INVALID_GFN) )
+ return -EADDRNOTAVAIL;
+ ASSERT(!(gfn >> DEFAULT_DOMAIN_ADDRESS_WIDTH));
+
+ level = hd->arch.paging_mode;
+ old_root = hd->arch.root_table;
+ offset = gfn >> (PTE_PER_TABLE_SHIFT * (level - 1));
+
+ ASSERT(spin_is_locked(&hd->arch.mapping_lock) && is_hvm_domain(d));
+
+ while ( offset >= PTE_PER_TABLE_SIZE )
+ {
+ /* Allocate and install a new root table.
+ * Only upper I/O page table grows, no need to fix next level bits */
+ new_root = alloc_amd_iommu_pgtable();
+ if ( new_root == NULL )
+ {
+ AMD_IOMMU_DEBUG("%s Cannot allocate I/O page table\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ new_root_vaddr = __map_domain_page(new_root);
+ old_root_mfn = page_to_mfn(old_root);
+ set_iommu_pde_present(new_root_vaddr, old_root_mfn, level,
+ !!IOMMUF_writable, !!IOMMUF_readable);
+ level++;
+ old_root = new_root;
+ offset >>= PTE_PER_TABLE_SHIFT;
+ unmap_domain_page(new_root_vaddr);
+ }
+
+ if ( new_root != NULL )
+ {
+ hd->arch.paging_mode = level;
+ hd->arch.root_table = new_root;
+
+ if ( !pcidevs_locked() )
+ AMD_IOMMU_DEBUG("%s Try to access pdev_list "
+ "without aquiring pcidevs_lock.\n", __func__);
+
+ /* Update device table entries using new root table and paging mode */
+ for_each_pdev( d, pdev )
+ {
+ bdf = PCI_BDF2(pdev->bus, pdev->devfn);
+ iommu = find_iommu_for_device(pdev->seg, bdf);
+ if ( !iommu )
+ {
+ AMD_IOMMU_DEBUG("%s Fail to find iommu.\n", __func__);
+ return -ENODEV;
+ }
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ do {
+ req_id = get_dma_requestor_id(pdev->seg, bdf);
+ device_entry = iommu->dev_table.buffer +
+ (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
+
+ /* valid = 0 only works for dom0 passthrough mode */
+ amd_iommu_set_root_page_table((u32 *)device_entry,
+
page_to_maddr(hd->arch.root_table),
+ d->domain_id,
+ hd->arch.paging_mode, 1);
+
+ amd_iommu_flush_device(iommu, req_id);
+ bdf += pdev->phantom_stride;
+ } while ( PCI_DEVFN2(bdf) != pdev->devfn &&
+ PCI_SLOT(bdf) == PCI_SLOT(pdev->devfn) );
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ }
+
+ /* For safety, invalidate all entries */
+ amd_iommu_flush_all_pages(d);
+ }
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/drivers/passthrough/x86/amd/iommu.h
b/xen/drivers/passthrough/x86/amd/iommu.h
new file mode 100644
index 0000000000..bb31de61ae
--- /dev/null
+++ b/xen/drivers/passthrough/x86/amd/iommu.h
@@ -0,0 +1,32 @@
+#ifndef _X86_AMD_IOMMU_H_
+#define _X86_AMD_IOMMU_H_
+
+bool_t set_iommu_pde_present(u32 *pde, unsigned long next_mfn,
+ unsigned int next_level,
+ bool_t iw, bool_t ir);
+
+#ifdef CONFIG_HVM
+
+int hvm_update_paging_mode(struct domain *d, unsigned long gfn);
+
+#else
+
+static inline int hvm_update_paging_mode(struct domain *d, unsigned long gfn)
+{
+ ASSERT_UNREACHABLE();
+ return -EINVAL;
+}
+
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/drivers/passthrough/x86/amd/iommu_map.c
b/xen/drivers/passthrough/x86/amd/iommu_map.c
index 0f9bd538af..e51a5c5ffe 100644
--- a/xen/drivers/passthrough/x86/amd/iommu_map.c
+++ b/xen/drivers/passthrough/x86/amd/iommu_map.c
@@ -25,6 +25,8 @@
#include "../../ats.h"
#include <xen/pci.h>
+#include "iommu.h"
+
/* Given pfn and page table level, return pde index */
static unsigned int pfn_to_pde_idx(unsigned long pfn, unsigned int level)
{
@@ -45,9 +47,9 @@ void clear_iommu_pte_present(unsigned long l1_mfn, unsigned
long gfn)
unmap_domain_page(table);
}
-static bool_t set_iommu_pde_present(u32 *pde, unsigned long next_mfn,
- unsigned int next_level,
- bool_t iw, bool_t ir)
+bool_t set_iommu_pde_present(u32 *pde, unsigned long next_mfn,
+ unsigned int next_level,
+ bool_t iw, bool_t ir)
{
u64 addr_lo, addr_hi, maddr_old, maddr_next;
u32 entry;
@@ -540,97 +542,6 @@ static int iommu_pde_from_gfn(struct domain *d, unsigned
long pfn,
return 0;
}
-static int update_paging_mode(struct domain *d, unsigned long gfn)
-{
- u16 bdf;
- void *device_entry;
- unsigned int req_id, level, offset;
- unsigned long flags;
- struct pci_dev *pdev;
- struct amd_iommu *iommu = NULL;
- struct page_info *new_root = NULL;
- struct page_info *old_root = NULL;
- void *new_root_vaddr;
- unsigned long old_root_mfn;
- struct domain_iommu *hd = dom_iommu(d);
-
- if ( gfn == gfn_x(INVALID_GFN) )
- return -EADDRNOTAVAIL;
- ASSERT(!(gfn >> DEFAULT_DOMAIN_ADDRESS_WIDTH));
-
- level = hd->arch.paging_mode;
- old_root = hd->arch.root_table;
- offset = gfn >> (PTE_PER_TABLE_SHIFT * (level - 1));
-
- ASSERT(spin_is_locked(&hd->arch.mapping_lock) && is_hvm_domain(d));
-
- while ( offset >= PTE_PER_TABLE_SIZE )
- {
- /* Allocate and install a new root table.
- * Only upper I/O page table grows, no need to fix next level bits */
- new_root = alloc_amd_iommu_pgtable();
- if ( new_root == NULL )
- {
- AMD_IOMMU_DEBUG("%s Cannot allocate I/O page table\n",
- __func__);
- return -ENOMEM;
- }
-
- new_root_vaddr = __map_domain_page(new_root);
- old_root_mfn = page_to_mfn(old_root);
- set_iommu_pde_present(new_root_vaddr, old_root_mfn, level,
- !!IOMMUF_writable, !!IOMMUF_readable);
- level++;
- old_root = new_root;
- offset >>= PTE_PER_TABLE_SHIFT;
- unmap_domain_page(new_root_vaddr);
- }
-
- if ( new_root != NULL )
- {
- hd->arch.paging_mode = level;
- hd->arch.root_table = new_root;
-
- if ( !pcidevs_locked() )
- AMD_IOMMU_DEBUG("%s Try to access pdev_list "
- "without aquiring pcidevs_lock.\n", __func__);
-
- /* Update device table entries using new root table and paging mode */
- for_each_pdev( d, pdev )
- {
- bdf = PCI_BDF2(pdev->bus, pdev->devfn);
- iommu = find_iommu_for_device(pdev->seg, bdf);
- if ( !iommu )
- {
- AMD_IOMMU_DEBUG("%s Fail to find iommu.\n", __func__);
- return -ENODEV;
- }
-
- spin_lock_irqsave(&iommu->lock, flags);
- do {
- req_id = get_dma_requestor_id(pdev->seg, bdf);
- device_entry = iommu->dev_table.buffer +
- (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
-
- /* valid = 0 only works for dom0 passthrough mode */
- amd_iommu_set_root_page_table((u32 *)device_entry,
-
page_to_maddr(hd->arch.root_table),
- d->domain_id,
- hd->arch.paging_mode, 1);
-
- amd_iommu_flush_device(iommu, req_id);
- bdf += pdev->phantom_stride;
- } while ( PCI_DEVFN2(bdf) != pdev->devfn &&
- PCI_SLOT(bdf) == PCI_SLOT(pdev->devfn) );
- spin_unlock_irqrestore(&iommu->lock, flags);
- }
-
- /* For safety, invalidate all entries */
- amd_iommu_flush_all_pages(d);
- }
- return 0;
-}
-
int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn,
unsigned int flags)
{
@@ -660,7 +571,7 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn,
unsigned long mfn,
* we might need a deeper page table for lager gfn now */
if ( is_hvm_domain(d) )
{
- if ( update_paging_mode(d, gfn) )
+ if ( hvm_update_paging_mode(d, gfn) )
{
spin_unlock(&hd->arch.mapping_lock);
AMD_IOMMU_DEBUG("Update page mode failed gfn = %lx\n", gfn);
@@ -742,7 +653,7 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long
gfn)
* we might need a deeper page table for lager gfn now */
if ( is_hvm_domain(d) )
{
- int rc = update_paging_mode(d, gfn);
+ int rc = hvm_update_paging_mode(d, gfn);
if ( rc )
{
--
2.11.0
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |