diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c
index 4686813..c0c7576 100644
--- a/xen/drivers/passthrough/amd/iommu_init.c
+++ b/xen/drivers/passthrough/amd/iommu_init.c
@@ -27,6 +27,7 @@
 #include <asm/amd-iommu.h>
 #include <asm/msi.h>
 #include <asm/hvm/svm/amd-iommu-proto.h>
+#include <asm/p2m.h>
 #include <asm-x86/fixmap.h>
 #include <mach_apic.h>
 #include <xen/delay.h>
@@ -522,6 +523,28 @@ static hw_irq_controller iommu_maskable_msi_type = {
     .set_affinity = set_msi_affinity,
 };
 
+typedef union {
+    struct {
+        u64 r       :   1,  /* bit 0 - Read permission */
+        w           :   1,  /* bit 1 - Write permission */
+        x           :   1,  /* bit 2 - Execute permission */
+        emt         :   3,  /* bits 5:3 - EPT Memory type */
+        ipat        :   1,  /* bit 6 - Ignore PAT memory type */
+        sp          :   1,  /* bit 7 - Is this a superpage? */
+        rsvd1       :   2,  /* bits 9:8 - Reserved for future use */
+        avail1      :   1,  /* bit 10 - Software available 1 */
+        rsvd2_snp   :   1,  /* bit 11 - Used for VT-d snoop control
+                               in shared EPT/VT-d usage */
+        mfn         :   40, /* bits 51:12 - Machine physical frame number */
+        sa_p2mt     :   6,  /* bits 57:52 - Software available 2 */
+        access      :   4,  /* bits 61:58 - p2m_access_t */
+        rsvd3_tm    :   1,  /* bit 62 - Used for VT-d transient-mapping
+                               hint in shared EPT/VT-d usage */
+        avail3      :   1;  /* bit 63 - Software available 3 */
+    };
+    u64 epte;
+} ept_entry_t;
+
 static void parse_event_log_entry(struct amd_iommu *iommu, u32 entry[])
 {
     u16 domain_id, device_id, flags;
@@ -566,6 +589,13 @@ static void parse_event_log_entry(struct amd_iommu *iommu, u32 entry[])
 
     if ( code == IOMMU_EVENT_IO_PAGE_FAULT )
     {
+        struct domain *d;
+        struct p2m_domain *p2m;
+        struct ept_data *ept;
+        ept_entry_t *table;
+        int i;
+        unsigned long gfn_remainder;
+
         device_id = iommu_get_devid_from_event(entry[0]);
         domain_id = get_field_from_reg_u32(entry[1],
                                            IOMMU_EVENT_DOMAIN_ID_MASK,
@@ -579,6 +609,48 @@ static void parse_event_log_entry(struct amd_iommu *iommu, u32 entry[])
                "fault address = %#"PRIx64", flags = %#x\n",
                event_str[code-1], domain_id, device_id, *addr, flags);
 
+        for_each_domain(d)
+        {
+            p2m = d->arch.p2m;
+            ept = &p2m->ept;
+            gfn_remainder = *addr >> PAGE_SHIFT;
+            table = map_domain_page(pagetable_get_pfn((p2m)->phys_table));
+
+            if ( d->domain_id != domain_id )
+                continue;
+
+            printk("domain %d, fault gfn %lx\n", d->domain_id, gfn_remainder);
+            for ( i = ept_get_wl(ept); i >= 0; i-- )
+            {
+                ept_entry_t *ept_entry, *next;
+                u32 index;
+
+                #define EPT_TABLE_ORDER         9
+                /* Stolen from ept_next_level */
+                index = gfn_remainder >> (i*EPT_TABLE_ORDER);
+                ept_entry = table + index;
+
+                printk("l%d: epte %"PRIx64"\n", i + 1, ept_entry->epte);
+
+                #define is_epte_present(ept_entry)      ((ept_entry)->epte & 0x7)
+                #define is_epte_superpage(ept_entry)    ((ept_entry)->sp)
+                if ( (i == 0) || !is_epte_present(ept_entry) ||
+                        is_epte_superpage(ept_entry) ) {
+                    break;
+                }
+                else
+                {
+                    gfn_remainder &= (1UL << (i*EPT_TABLE_ORDER)) - 1;
+
+                    next = map_domain_page(ept_entry->mfn);
+
+                    unmap_domain_page(table);
+
+                    table = next;
+                }
+            }
+
+        }
         for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
             if ( get_dma_requestor_id(iommu->seg, bdf) == device_id )
                 pci_check_disable_device(iommu->seg, PCI_BUS(bdf),
