Skip to contentSkip to conversation

amd iommu: add iommu next level bits into p2m entries

PATCH In review Wei Wang2 1 participant 1 message Apr 15, 2011

lore
Share & tools
lore

Wei Wang2

author
#0 lore raw

PATCH v2 2/4 amd iommu: add iommu next level bits into p2m entries

--
Advanced Micro Devices GmbH
Sitz: Dornach, Gemeinde Aschheim,
Landkreis München Registergericht München,
HRB Nr. 43632
WEEE-Reg-Nr: DE 12919551
Geschäftsführer:
Alberto Bozzo, Andrew Bowd

# HG changeset patch
# User Wei Wang <[email protected]>
# Node ID 435b2e64ad501c40b8bb65622eb5e387c59f8f93
# Parent f7c0e6e6d629b7e195337bc5f6aaca0d7e989fd7
This patch adds next levels bit into bit 9 - bit 11 of p2m entries and adds r/w permission bits into bit 61- bit 62 of p2m entries.

xen/arch/x86/mm/p2m.c +35 -1
diff -r f7c0e6e6d629 -r 435b2e64ad50 xen/arch/x86/mm/p2m.c
@@ -201,6 +201,19 @@ p2m_free_entry(struct p2m_domain *p2m, l
 // Walk one level of the P2M table, allocating a new table if required.
 // Returns 0 on error.
 //
+
+/* AMD IOMMU: Convert next level bits and r/w bits into 24 bits p2m flags */
+#define iommu_nlevel_to_flags(nl, f) ((((nl) & 0x7) << 9 )|(((f) & 0x3) << 21))
+
+static void p2m_add_iommu_flags(l1_pgentry_t *p2m_entry,
+                                unsigned int nlevel, unsigned int flags)
+{
+#if CONFIG_PAGING_LEVELS == 4
+    if ( iommu_hap_pt_share )
+        l1e_add_flags(*p2m_entry, iommu_nlevel_to_flags(nlevel, flags));
+#endif
+}
+
 static int
 p2m_next_level(struct p2m_domain *p2m, mfn_t *table_mfn, void **table,
                unsigned long *gfn_remainder, unsigned long gfn, u32 shift,
@@ -230,6 +243,7 @@ p2m_next_level(struct p2m_domain *p2m, m
 
         switch ( type ) {
         case PGT_l3_page_table:
+            p2m_add_iommu_flags(&new_entry, 3, IOMMUF_readable|IOMMUF_writable);
             p2m->write_p2m_entry(p2m, gfn, p2m_entry, *table_mfn, new_entry, 4);
             break;
         case PGT_l2_page_table:
@@ -237,9 +251,11 @@ p2m_next_level(struct p2m_domain *p2m, m
             /* for PAE mode, PDPE only has PCD/PWT/P bits available */
             new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)), _PAGE_PRESENT);
 #endif
+            p2m_add_iommu_flags(&new_entry, 2, IOMMUF_readable|IOMMUF_writable);
             p2m->write_p2m_entry(p2m, gfn, p2m_entry, *table_mfn, new_entry, 3);
             break;
         case PGT_l1_page_table:
+            p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
             p2m->write_p2m_entry(p2m, gfn, p2m_entry, *table_mfn, new_entry, 2);
             break;
         default:
@@ -267,12 +283,14 @@ p2m_next_level(struct p2m_domain *p2m, m
         for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
         {
             new_entry = l1e_from_pfn(pfn + (i * L1_PAGETABLE_ENTRIES), flags);
+            p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
             p2m->write_p2m_entry(p2m, gfn,
                 l1_entry+i, *table_mfn, new_entry, 2);
         }
         unmap_domain_page(l1_entry);
         new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                  __PAGE_HYPERVISOR|_PAGE_USER); //disable PSE
+        p2m_add_iommu_flags(&new_entry, 2, IOMMUF_readable|IOMMUF_writable);
         p2m->write_p2m_entry(p2m, gfn, p2m_entry, *table_mfn, new_entry, 3);
     }
 
@@ -300,6 +318,7 @@ p2m_next_level(struct p2m_domain *p2m, m
         for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
         {
             new_entry = l1e_from_pfn(pfn + i, flags);
+            p2m_add_iommu_flags(&new_entry, 0, 0);
             p2m->write_p2m_entry(p2m, gfn,
                 l1_entry+i, *table_mfn, new_entry, 1);
         }
@@ -307,6 +326,7 @@ p2m_next_level(struct p2m_domain *p2m, m
         
         new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                  __PAGE_HYPERVISOR|_PAGE_USER);
+        p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable);
         p2m->write_p2m_entry(p2m, gfn,
             p2m_entry, *table_mfn, new_entry, 2);
     }
@@ -1395,6 +1415,9 @@ p2m_set_entry(struct p2m_domain *p2m, un
     l2_pgentry_t l2e_content;
     l3_pgentry_t l3e_content;
     int rv=0;
+    unsigned int iommu_pte_flags = (p2mt == p2m_ram_rw) ?
+                                   IOMMUF_readable|IOMMUF_writable:
+                                   0; 
 
     if ( tb_init_done )
     {
@@ -1443,6 +1466,10 @@ p2m_set_entry(struct p2m_domain *p2m, un
                            p2m_type_to_flags(p2mt, mfn) | _PAGE_PSE)
             : l3e_empty();
         entry_content.l1 = l3e_content.l3;
+
+        if ( entry_content.l1 != 0 )
+            p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
+
         p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 3);
         /* NB: paging_write_p2m_entry() handles tlb flushes properly */
 
@@ -1481,7 +1508,10 @@ p2m_set_entry(struct p2m_domain *p2m, un
                                          p2m_type_to_flags(p2mt, mfn));
         else
             entry_content = l1e_empty();
-        
+
+        if ( entry_content.l1 != 0 )
+            p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
+
         /* level 1 entry */
         p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 1);
         /* NB: paging_write_p2m_entry() handles tlb flushes properly */
@@ -1512,6 +1542,10 @@ p2m_set_entry(struct p2m_domain *p2m, un
             l2e_content = l2e_empty();
         
         entry_content.l1 = l2e_content.l2;
+
+        if ( entry_content.l1 != 0 )
+            p2m_add_iommu_flags(&entry_content, 0, iommu_pte_flags);
+
         p2m->write_p2m_entry(p2m, gfn, p2m_entry, table_mfn, entry_content, 2);
         /* NB: paging_write_p2m_entry() handles tlb flushes properly */
 

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel