From 68931738e1f555c929cc77d9338043dc38f4610e Mon Sep 17 00:00:00 2001 From: George Dunlap Date: Wed, 21 Jun 2017 16:08:31 +0100 Subject: [PATCH] x86/p2m-pt: simplify p2m_next_level() [Insert description here] Signed-off-by: George Dunlap --- xen/arch/x86/mm/p2m-pt.c | 77 +++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 44 deletions(-) diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c index 06e64b8..4e1028e 100644 --- a/xen/arch/x86/mm/p2m-pt.c +++ b/xen/arch/x86/mm/p2m-pt.c @@ -195,7 +195,7 @@ p2m_next_level(struct p2m_domain *p2m, void **table, l1_pgentry_t *p2m_entry; l1_pgentry_t new_entry; void *next; - int i; + unsigned int i; if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn, shift, max)) ) @@ -232,12 +232,10 @@ p2m_next_level(struct p2m_domain *p2m, void **table, } } - ASSERT(l1e_get_flags(*p2m_entry) & (_PAGE_PRESENT|_PAGE_PSE)); - /* split 1GB pages into 2MB pages */ - if ( type == PGT_l2_page_table && (l1e_get_flags(*p2m_entry) & _PAGE_PSE) ) + if ( l1e_get_flags(*p2m_entry) & _PAGE_PSE ) { - unsigned long flags, pfn; + unsigned long flags, pfn, level; struct page_info *pg; pg = p2m_alloc_ptp(p2m, PGT_l2_page_table); @@ -247,54 +245,45 @@ p2m_next_level(struct p2m_domain *p2m, void **table, flags = l1e_get_flags(*p2m_entry); pfn = l1e_get_pfn(*p2m_entry); - l1_entry = __map_domain_page(pg); - for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ ) + if ( type == PGT_l2_page_table ) { - 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, new_entry, 2); + l1_entry = __map_domain_page(pg); + 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, new_entry, 2); + } + level = 2; } - unmap_domain_page(l1_entry); - new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)), - P2M_BASE_FLAGS | _PAGE_RW); /* disable PSE */ - p2m_add_iommu_flags(&new_entry, 2, IOMMUF_readable|IOMMUF_writable); - p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, 3); - } - - - /* split single 2MB large page into 4KB page in P2M table */ - if ( type == PGT_l1_page_table && (l1e_get_flags(*p2m_entry) & _PAGE_PSE) ) - { - unsigned long flags, pfn; - struct page_info *pg; - - pg = p2m_alloc_ptp(p2m, PGT_l1_page_table); - if ( pg == NULL ) - return -ENOMEM; - - /* New splintered mappings inherit the flags of the old superpage, - * with a little reorganisation for the _PAGE_PSE_PAT bit. */ - flags = l1e_get_flags(*p2m_entry); - pfn = l1e_get_pfn(*p2m_entry); - if ( pfn & 1 ) /* ==> _PAGE_PSE_PAT was set */ - pfn -= 1; /* Clear it; _PAGE_PSE becomes _PAGE_PAT */ else - flags &= ~_PAGE_PSE; /* Clear _PAGE_PSE (== _PAGE_PAT) */ - - l1_entry = __map_domain_page(pg); - 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, new_entry, 1); + /* New splintered mappings inherit the flags of the old superpage, + * with a little reorganisation for the _PAGE_PSE_PAT bit. */ + if ( pfn & 1 ) /* ==> _PAGE_PSE_PAT was set */ + pfn -= 1; /* Clear it; _PAGE_PSE becomes _PAGE_PAT */ + else + flags &= ~_PAGE_PSE; /* Clear _PAGE_PSE (== _PAGE_PAT) */ + + l1_entry = __map_domain_page(pg); + 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, new_entry, 1); + } + level = 1; } - unmap_domain_page(l1_entry); + unmap_domain_page(l1_entry); + new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)), P2M_BASE_FLAGS | _PAGE_RW); - p2m_add_iommu_flags(&new_entry, 1, IOMMUF_readable|IOMMUF_writable); - p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, 2); + p2m_add_iommu_flags(&new_entry, level, IOMMUF_readable|IOMMUF_writable); + p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level+1); } + else + ASSERT(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT); next = map_domain_page(_mfn(l1e_get_pfn(*p2m_entry))); if ( unmap ) -- 2.1.4