p2m.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,188 行 · 第 1/3 页
C
1,188 行
i3++ ) { if ( !(l3e_get_flags(l3e[i3]) & _PAGE_PRESENT) ) { gfn += 1 << (L3_PAGETABLE_SHIFT - PAGE_SHIFT); continue; } l2e = map_domain_page(mfn_x(_mfn(l3e_get_pfn(l3e[i3])))); for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; i2++ ) { if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) ) { gfn += 1 << (L2_PAGETABLE_SHIFT - PAGE_SHIFT); continue; } /* check for super page */ if ( l2e_get_flags(l2e[i2]) & _PAGE_PSE ) { mfn = l2e_get_pfn(l2e[i2]); ASSERT(mfn_valid(_mfn(mfn))); for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++) { m2pfn = get_gpfn_from_mfn(mfn+i1); if ( m2pfn != (gfn + i) ) { pmbad++; P2M_PRINTK("mismatch: gfn %#lx -> mfn %#lx" " -> gfn %#lx\n", gfn+i, mfn+i, m2pfn); BUG(); } } gfn += 1 << (L2_PAGETABLE_SHIFT - PAGE_SHIFT); continue; } l1e = map_domain_page(mfn_x(_mfn(l2e_get_pfn(l2e[i2])))); for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ ) { if ( !(l1e_get_flags(l1e[i1]) & _PAGE_PRESENT) ) continue; mfn = l1e_get_pfn(l1e[i1]); ASSERT(mfn_valid(_mfn(mfn))); m2pfn = get_gpfn_from_mfn(mfn); if ( m2pfn != gfn ) { pmbad++; P2M_PRINTK("mismatch: gfn %#lx -> mfn %#lx" " -> gfn %#lx\n", gfn, mfn, m2pfn); BUG(); } } unmap_domain_page(l1e); } unmap_domain_page(l2e); }#if CONFIG_PAGING_LEVELS >= 4 unmap_domain_page(l3e); }#endif#if CONFIG_PAGING_LEVELS == 4 unmap_domain_page(l4e);#else /* CONFIG_PAGING_LEVELS == 3 */ unmap_domain_page(l3e);#endif } //P2M_PRINTK("p2m audit complete\n"); //if ( orphans_i | orphans_d | mpbad | pmbad ) // P2M_PRINTK("p2m audit found %lu orphans (%lu inval %lu debug)\n", // orphans_i + orphans_d, orphans_i, orphans_d, if ( mpbad | pmbad ) P2M_PRINTK("p2m audit found %lu odd p2m, %lu bad m2p entries\n", pmbad, mpbad);}#else#define audit_p2m(_d) do { (void)(_d); } while(0)#endif /* P2M_AUDIT */static voidp2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn, unsigned int page_order){ unsigned long i; if ( !paging_mode_translate(d) ) { if ( need_iommu(d) ) for ( i = 0; i < (1 << page_order); i++ ) iommu_unmap_page(d, mfn + i); return; } P2M_DEBUG("removing gfn=%#lx mfn=%#lx\n", gfn, mfn); set_p2m_entry(d, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid); for ( i = 0; i < (1UL << page_order); i++ ) set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY);}voidguest_physmap_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn, unsigned int page_order){ p2m_lock(d->arch.p2m); audit_p2m(d); p2m_remove_page(d, gfn, mfn, page_order); audit_p2m(d); p2m_unlock(d->arch.p2m);}intguest_physmap_add_entry(struct domain *d, unsigned long gfn, unsigned long mfn, unsigned int page_order, p2m_type_t t){ unsigned long i, ogfn; p2m_type_t ot; mfn_t omfn; int rc = 0; if ( !paging_mode_translate(d) ) { if ( need_iommu(d) && t == p2m_ram_rw ) { for ( i = 0; i < (1 << page_order); i++ ) if ( (rc = iommu_map_page(d, mfn + i, mfn + i)) != 0 ) { while ( i-- > 0 ) iommu_unmap_page(d, mfn + i); return rc; } } return 0; }#if CONFIG_PAGING_LEVELS == 3 /* * 32bit PAE nested paging does not support over 4GB guest due to * hardware translation limit. This limitation is checked by comparing * gfn with 0xfffffUL. */ if ( paging_mode_hap(d) && (gfn > 0xfffffUL) ) { if ( !test_and_set_bool(d->arch.hvm_domain.svm.npt_4gb_warning) ) dprintk(XENLOG_WARNING, "Dom%d failed to populate memory beyond" " 4GB: specify 'hap=0' domain config option.\n", d->domain_id); return -EINVAL; }#endif p2m_lock(d->arch.p2m); audit_p2m(d); P2M_DEBUG("adding gfn=%#lx mfn=%#lx\n", gfn, mfn); omfn = gfn_to_mfn(d, gfn, &ot); if ( p2m_is_ram(ot) ) { ASSERT(mfn_valid(omfn)); for ( i = 0; i < (1UL << page_order); i++ ) set_gpfn_from_mfn(mfn_x(omfn)+i, INVALID_M2P_ENTRY); } ogfn = mfn_to_gfn(d, _mfn(mfn)); if (#ifdef __x86_64__ (ogfn != 0x5555555555555555L)#else (ogfn != 0x55555555L)#endif && (ogfn != INVALID_M2P_ENTRY) && (ogfn != gfn) ) { /* This machine frame is already mapped at another physical address */ P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n", mfn, ogfn, gfn); omfn = gfn_to_mfn(d, ogfn, &ot); if ( p2m_is_ram(ot) ) { ASSERT(mfn_valid(omfn)); P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n", ogfn , mfn_x(omfn)); if ( mfn_x(omfn) == mfn ) p2m_remove_page(d, ogfn, mfn, page_order); } } if ( mfn_valid(_mfn(mfn)) ) { if ( !set_p2m_entry(d, gfn, _mfn(mfn), page_order, t) ) rc = -EINVAL; for ( i = 0; i < (1UL << page_order); i++ ) set_gpfn_from_mfn(mfn+i, gfn+i); } else { gdprintk(XENLOG_WARNING, "Adding bad mfn to p2m map (%#lx -> %#lx)\n", gfn, mfn); if ( !set_p2m_entry(d, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid) ) rc = -EINVAL; } audit_p2m(d); p2m_unlock(d->arch.p2m); return rc;}/* Walk the whole p2m table, changing any entries of the old type * to the new type. This is used in hardware-assisted paging to * quickly enable or diable log-dirty tracking */void p2m_change_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt){ unsigned long mfn, gfn, flags; l1_pgentry_t l1e_content; l1_pgentry_t *l1e; l2_pgentry_t *l2e; mfn_t l1mfn, l2mfn; int i1, i2; l3_pgentry_t *l3e; int i3;#if CONFIG_PAGING_LEVELS == 4 l4_pgentry_t *l4e; int i4;#endif /* CONFIG_PAGING_LEVELS == 4 */ if ( !paging_mode_translate(d) ) return; if ( pagetable_get_pfn(d->arch.phys_table) == 0 ) return; ASSERT(p2m_locked_by_me(d->arch.p2m));#if CONFIG_PAGING_LEVELS == 4 l4e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));#else /* CONFIG_PAGING_LEVELS == 3 */ l3e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));#endif#if CONFIG_PAGING_LEVELS >= 4 for ( i4 = 0; i4 < L4_PAGETABLE_ENTRIES; i4++ ) { if ( !(l4e_get_flags(l4e[i4]) & _PAGE_PRESENT) ) { continue; } l3e = map_domain_page(l4e_get_pfn(l4e[i4]));#endif for ( i3 = 0; i3 < ((CONFIG_PAGING_LEVELS==4) ? L3_PAGETABLE_ENTRIES : 8); i3++ ) { if ( !(l3e_get_flags(l3e[i3]) & _PAGE_PRESENT) ) { continue; } l2mfn = _mfn(l3e_get_pfn(l3e[i3])); l2e = map_domain_page(l3e_get_pfn(l3e[i3])); for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; i2++ ) { if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) ) { continue; } if ( (l2e_get_flags(l2e[i2]) & _PAGE_PSE) ) { flags = l2e_get_flags(l2e[i2]); if ( p2m_flags_to_type(flags) != ot ) continue; mfn = l2e_get_pfn(l2e[i2]); gfn = get_gpfn_from_mfn(mfn); flags = p2m_type_to_flags(nt); l1e_content = l1e_from_pfn(mfn, flags | _PAGE_PSE); paging_write_p2m_entry(d, gfn, (l1_pgentry_t *)&l2e[i2], l2mfn, l1e_content, 2); continue; } l1mfn = _mfn(l2e_get_pfn(l2e[i2])); l1e = map_domain_page(mfn_x(l1mfn)); for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ ) { flags = l1e_get_flags(l1e[i1]); if ( p2m_flags_to_type(flags) != ot ) continue; mfn = l1e_get_pfn(l1e[i1]); gfn = get_gpfn_from_mfn(mfn); /* create a new 1le entry with the new type */ flags = p2m_type_to_flags(nt); l1e_content = l1e_from_pfn(mfn, flags); paging_write_p2m_entry(d, gfn, &l1e[i1], l1mfn, l1e_content, 1); } unmap_domain_page(l1e); } unmap_domain_page(l2e); }#if CONFIG_PAGING_LEVELS >= 4 unmap_domain_page(l3e); }#endif#if CONFIG_PAGING_LEVELS == 4 unmap_domain_page(l4e);#else /* CONFIG_PAGING_LEVELS == 3 */ unmap_domain_page(l3e);#endif}/* Modify the p2m type of a single gfn from ot to nt, returning the * entry's previous type */p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn, p2m_type_t ot, p2m_type_t nt){ p2m_type_t pt; mfn_t mfn; p2m_lock(d->arch.p2m); mfn = gfn_to_mfn(d, gfn, &pt); if ( pt == ot ) set_p2m_entry(d, gfn, mfn, 0, nt); p2m_unlock(d->arch.p2m); return pt;}intset_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn){ int rc = 0; p2m_type_t ot; mfn_t omfn; if ( !paging_mode_translate(d) ) return 0; omfn = gfn_to_mfn(d, gfn, &ot); if ( p2m_is_ram(ot) ) { ASSERT(mfn_valid(omfn)); set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY); } rc = set_p2m_entry(d, gfn, mfn, 0, p2m_mmio_direct); if ( 0 == rc ) gdprintk(XENLOG_ERR, "set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n", gmfn_to_mfn(d, gfn)); return rc;}intclear_mmio_p2m_entry(struct domain *d, unsigned long gfn){ int rc = 0; unsigned long mfn; if ( !paging_mode_translate(d) ) return 0; mfn = gmfn_to_mfn(d, gfn); if ( INVALID_MFN == mfn ) { gdprintk(XENLOG_ERR, "clear_mmio_p2m_entry: gfn_to_mfn failed! gfn=%08lx\n", gfn); return 0; } rc = set_p2m_entry(d, gfn, _mfn(INVALID_MFN), 0, 0); return rc;}/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?