xen/vtd-fix.patch

81 lines
2.6 KiB
Diff

Index: xen-3.2.1-testing/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
===================================================================
--- xen-3.2.1-testing.orig/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
+++ xen-3.2.1-testing/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
@@ -28,6 +28,7 @@
#include <asm/delay.h>
#include <asm/string.h>
#include <asm/mm.h>
+#include <asm/paging.h>
#include <asm/iommu.h>
#include <asm/hvm/vmx/intel-iommu.h>
#include "dmar.h"
@@ -1900,6 +1901,45 @@ void iommu_set_pgd(struct domain *d)
}
p2m_table = mfn_x(pagetable_get_mfn(d->arch.phys_table));
+ if ( paging_mode_hap(d) )
+ {
+ if ( !hd->pgd )
+ {
+ int level = agaw_to_level(hd->agaw);
+ struct dma_pte *dpte = NULL;
+ mfn_t pgd_mfn;
+
+ switch ( level )
+ {
+ case VTD_PAGE_TABLE_LEVEL_3:
+ dpte = map_domain_page(p2m_table);
+ if ( !dma_pte_present(*dpte) )
+ {
+ gdprintk(XENLOG_ERR VTDPREFIX,
+ "iommu_set_pgd: second level wasn't there\n");
+ unmap_domain_page(dpte);
+ return;
+ }
+ pgd_mfn = _mfn(dma_pte_addr(*dpte) >> PAGE_SHIFT_4K);
+ unmap_domain_page(dpte);
+ hd->pgd = maddr_to_virt(pagetable_get_paddr(
+ pagetable_from_mfn(pgd_mfn)));
+ break;
+
+ case VTD_PAGE_TABLE_LEVEL_4:
+ pgd_mfn = _mfn(p2m_table);
+ hd->pgd = maddr_to_virt(pagetable_get_paddr(
+ pagetable_from_mfn(pgd_mfn)));
+ break;
+ default:
+ gdprintk(XENLOG_ERR VTDPREFIX,
+ "iommu_set_pgd:Unsupported p2m table sharing level!\n");
+ break;
+ }
+ }
+ }
+ else
+ {
#if CONFIG_PAGING_LEVELS == 3
if ( !hd->pgd )
{
@@ -2005,6 +2045,7 @@ void iommu_set_pgd(struct domain *d)
}
}
#endif
+ }
gdprintk(XENLOG_INFO VTDPREFIX,
"iommu_set_pgd: hd->pgd = %p\n", hd->pgd);
}
Index: xen-3.2.1-testing/xen/arch/x86/mm/p2m-ept.c
===================================================================
--- xen-3.2.1-testing.orig/xen/arch/x86/mm/p2m-ept.c
+++ xen-3.2.1-testing/xen/arch/x86/mm/p2m-ept.c
@@ -157,6 +157,9 @@ ept_set_entry(struct domain *d, unsigned
else
ept_entry->epte = 0;
+ if ( vtd_enabled && (p2mt == p2m_mmio_direct) && is_hvm_domain(d) )
+ iommu_flush(d, gfn, (u64 *)ept_entry);
+
/* Success */
rv = 1;