|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] IOMMU/x86: avoid pages without GFN in page table creation/updating
commit 7349efc695852c70b8c5e24d9ecf208757e8b471
Author: Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Wed May 13 16:35:54 2015 +0200
Commit: Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Wed May 13 16:35:54 2015 +0200
IOMMU/x86: avoid pages without GFN in page table creation/updating
Handing INVALID_GFN to functions like hd->platform_ops->map_page()
just can't do any good, and the ioreq server code results in such pages
being on the list of ones owned by a guest.
While - as suggested by Tim - we should use get_gfn()/put_gfn() there
to eliminate races, we really can't due to holding the domain's page
alloc lock. Ultimately arch_iommu_populate_page_table() may need to be
switched to be GFN based. Here is what Tim said in this regard:
"Ideally this loop would be iterating over all gfns in the p2m rather
than over all owned MFNs. As long as needs_iommu gets set first,
such a loop could safely be paused and restarted without worrying
about concurrent updates. The code sould even stay in this file,
though exposing an iterator from the p2m code would be a lot more
efficient."
Original by Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, using further
suggestions from Tim Deegan <tim@xxxxxxx>.
Reported-by: Sander Eikelenboom <linux@xxxxxxxxxxxxxx>
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
Tested-by: Sander Eikelenboom <linux@xxxxxxxxxxxxxx>
Acked-by: Tim Deegan <tim@xxxxxxx>
Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Acked-by: Yang Zhang <yang.z.zhang@xxxxxxxxx>
Acked-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@xxxxxxx>
---
xen/drivers/passthrough/amd/iommu_map.c | 13 ++++++++++---
xen/drivers/passthrough/vtd/iommu.h | 1 -
xen/drivers/passthrough/x86/iommu.c | 15 +++++++++++----
xen/include/asm-x86/hvm/iommu.h | 2 ++
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h | 2 --
5 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/xen/drivers/passthrough/amd/iommu_map.c
b/xen/drivers/passthrough/amd/iommu_map.c
index 495ff5c..64c5225 100644
--- a/xen/drivers/passthrough/amd/iommu_map.c
+++ b/xen/drivers/passthrough/amd/iommu_map.c
@@ -557,6 +557,10 @@ static int update_paging_mode(struct domain *d, unsigned
long gfn)
unsigned long old_root_mfn;
struct hvm_iommu *hd = domain_hvm_iommu(d);
+ if ( gfn == INVALID_MFN )
+ 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));
@@ -729,12 +733,15 @@ 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) )
{
- if ( update_paging_mode(d, gfn) )
+ int rc = update_paging_mode(d, gfn);
+
+ if ( rc )
{
spin_unlock(&hd->arch.mapping_lock);
AMD_IOMMU_DEBUG("Update page mode failed gfn = %lx\n", gfn);
- domain_crash(d);
- return -EFAULT;
+ if ( rc != -EADDRNOTAVAIL )
+ domain_crash(d);
+ return rc;
}
}
diff --git a/xen/drivers/passthrough/vtd/iommu.h
b/xen/drivers/passthrough/vtd/iommu.h
index d6e6520..80f8830 100644
--- a/xen/drivers/passthrough/vtd/iommu.h
+++ b/xen/drivers/passthrough/vtd/iommu.h
@@ -482,7 +482,6 @@ struct qinval_entry {
#define VTD_PAGE_TABLE_LEVEL_3 3
#define VTD_PAGE_TABLE_LEVEL_4 4
-#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
#define MAX_IOMMU_REGS 0xc0
extern struct list_head acpi_drhd_units;
diff --git a/xen/drivers/passthrough/x86/iommu.c
b/xen/drivers/passthrough/x86/iommu.c
index 9eb8d33..90b78d0 100644
--- a/xen/drivers/passthrough/x86/iommu.c
+++ b/xen/drivers/passthrough/x86/iommu.c
@@ -59,10 +59,17 @@ int arch_iommu_populate_page_table(struct domain *d)
if ( has_hvm_container_domain(d) ||
(page->u.inuse.type_info & PGT_type_mask) == PGT_writable_page )
{
- BUG_ON(SHARED_M2P(mfn_to_gmfn(d, page_to_mfn(page))));
- rc = hd->platform_ops->map_page(
- d, mfn_to_gmfn(d, page_to_mfn(page)), page_to_mfn(page),
- IOMMUF_readable|IOMMUF_writable);
+ unsigned long mfn = page_to_mfn(page);
+ unsigned long gfn = mfn_to_gmfn(d, mfn);
+
+ if ( gfn != INVALID_MFN )
+ {
+ ASSERT(!(gfn >> DEFAULT_DOMAIN_ADDRESS_WIDTH));
+ BUG_ON(SHARED_M2P(gfn));
+ rc = hd->platform_ops->map_page(d, gfn, mfn,
+ IOMMUF_readable |
+ IOMMUF_writable);
+ }
if ( rc )
{
page_list_add(page, &d->page_list);
diff --git a/xen/include/asm-x86/hvm/iommu.h b/xen/include/asm-x86/hvm/iommu.h
index 46cb126..3a4c68a 100644
--- a/xen/include/asm-x86/hvm/iommu.h
+++ b/xen/include/asm-x86/hvm/iommu.h
@@ -46,6 +46,8 @@ struct g2m_ioport {
unsigned int np;
};
+#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
+
struct arch_hvm_iommu
{
u64 pgd_maddr; /* io page directory machine address */
diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
index 2ac6f75..44a2fd9 100644
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
@@ -464,8 +464,6 @@
#define IOMMU_CONTROL_DISABLED 0
#define IOMMU_CONTROL_ENABLED 1
-#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
-
/* interrupt remapping table */
#define INT_REMAP_ENTRY_REMAPEN_MASK 0x00000001
#define INT_REMAP_ENTRY_REMAPEN_SHIFT 0
--
generated by git-patchbot for /home/xen/git/xen.git#master
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |