⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mm.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#define adjust_guest_l2e(_p, _d) ((void)(_d))#define adjust_guest_l3e(_p, _d) ((void)(_d))#endif#ifdef CONFIG_COMPAT#define unadjust_guest_l3e(pl3e, d)                                         \    do {                                                                    \        if ( unlikely(is_pv_32on64_domain(d)) &&                            \             likely(l3e_get_flags((pl3e)) & _PAGE_PRESENT) )                \            l3e_remove_flags((pl3e), _PAGE_USER|_PAGE_RW|_PAGE_ACCESSED);   \    } while ( 0 )#else#define unadjust_guest_l3e(_p, _d) ((void)(_d))#endifvoid put_page_from_l1e(l1_pgentry_t l1e, struct domain *d){    unsigned long     pfn = l1e_get_pfn(l1e);    struct page_info *page;    struct domain    *e;    struct vcpu      *v;    if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) || is_iomem_page(pfn) )        return;    page = mfn_to_page(pfn);    e = page_get_owner(page);    /*     * Check if this is a mapping that was established via a grant reference.     * If it was then we should not be here: we require that such mappings are     * explicitly destroyed via the grant-table interface.     *      * The upshot of this is that the guest can end up with active grants that     * it cannot destroy (because it no longer has a PTE to present to the     * grant-table interface). This can lead to subtle hard-to-catch bugs,     * hence a special grant PTE flag can be enabled to catch the bug early.     *      * (Note that the undestroyable active grants are not a security hole in     * Xen. All active grants can safely be cleaned up when the domain dies.)     */    if ( (l1e_get_flags(l1e) & _PAGE_GNTTAB) &&         !d->is_shutting_down && !d->is_dying )    {        MEM_LOG("Attempt to implicitly unmap a granted PTE %" PRIpte,                l1e_get_intpte(l1e));        domain_crash(d);    }    /* Remember we didn't take a type-count of foreign writable mappings     * to paging-external domains */    if ( (l1e_get_flags(l1e) & _PAGE_RW) &&          !(unlikely((e != d) && paging_mode_external(e))) )    {        put_page_and_type(page);    }    else    {        /* We expect this is rare so we blow the entire shadow LDT. */        if ( unlikely(((page->u.inuse.type_info & PGT_type_mask) ==                        PGT_ldt_page)) &&             unlikely(((page->u.inuse.type_info & PGT_count_mask) != 0)) &&             (d == e) )        {            for_each_vcpu ( d, v )                invalidate_shadow_ldt(v);        }        put_page(page);    }}/* * NB. Virtual address 'l2e' maps to a machine address within frame 'pfn'. * Note also that this automatically deals correctly with linear p.t.'s. */static void put_page_from_l2e(l2_pgentry_t l2e, unsigned long pfn){    if ( (l2e_get_flags(l2e) & _PAGE_PRESENT) &&          (l2e_get_pfn(l2e) != pfn) )        put_page_and_type(l2e_get_page(l2e));}#if CONFIG_PAGING_LEVELS >= 3static void put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn){    if ( (l3e_get_flags(l3e) & _PAGE_PRESENT) &&          (l3e_get_pfn(l3e) != pfn) )        put_page_and_type(l3e_get_page(l3e));}#endif#if CONFIG_PAGING_LEVELS >= 4static void put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn){    if ( (l4e_get_flags(l4e) & _PAGE_PRESENT) &&          (l4e_get_pfn(l4e) != pfn) )        put_page_and_type(l4e_get_page(l4e));}#endifstatic int alloc_l1_table(struct page_info *page){    struct domain *d = page_get_owner(page);    unsigned long  pfn = page_to_mfn(page);    l1_pgentry_t  *pl1e;    int            i;    pl1e = map_domain_page(pfn);    for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )    {        if ( is_guest_l1_slot(i) &&             unlikely(!get_page_from_l1e(pl1e[i], d)) )            goto fail;        adjust_guest_l1e(pl1e[i], d);    }    unmap_domain_page(pl1e);    return 1; fail:    MEM_LOG("Failure in alloc_l1_table: entry %d", i);    while ( i-- > 0 )        if ( is_guest_l1_slot(i) )            put_page_from_l1e(pl1e[i], d);    unmap_domain_page(pl1e);    return 0;}#if defined(CONFIG_X86_PAE) || defined(CONFIG_COMPAT)static int create_pae_xen_mappings(struct domain *d, l3_pgentry_t *pl3e){    struct page_info *page;    l2_pgentry_t    *pl2e;    l3_pgentry_t     l3e3;#ifndef CONFIG_COMPAT    l2_pgentry_t     l2e;    int              i;#endif    if ( !is_pv_32bit_domain(d) )        return 1;    pl3e = (l3_pgentry_t *)((unsigned long)pl3e & PAGE_MASK);    /* 3rd L3 slot contains L2 with Xen-private mappings. It *must* exist. */    l3e3 = pl3e[3];    if ( !(l3e_get_flags(l3e3) & _PAGE_PRESENT) )    {        MEM_LOG("PAE L3 3rd slot is empty");        return 0;    }    /*     * The Xen-private mappings include linear mappings. The L2 thus cannot     * be shared by multiple L3 tables. The test here is adequate because:     *  1. Cannot appear in slots != 3 because get_page_type() checks the     *     PGT_pae_xen_l2 flag, which is asserted iff the L2 appears in slot 3     *  2. Cannot appear in another page table's L3:     *     a. alloc_l3_table() calls this function and this check will fail     *     b. mod_l3_entry() disallows updates to slot 3 in an existing table     */    page = l3e_get_page(l3e3);    BUG_ON(page->u.inuse.type_info & PGT_pinned);    BUG_ON((page->u.inuse.type_info & PGT_count_mask) == 0);    BUG_ON(!(page->u.inuse.type_info & PGT_pae_xen_l2));    if ( (page->u.inuse.type_info & PGT_count_mask) != 1 )    {        MEM_LOG("PAE L3 3rd slot is shared");        return 0;    }    /* Xen private mappings. */    pl2e = map_domain_page(l3e_get_pfn(l3e3));#ifndef CONFIG_COMPAT    memcpy(&pl2e[L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1)],           &idle_pg_table_l2[L2_PAGETABLE_FIRST_XEN_SLOT],           L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));    for ( i = 0; i < PDPT_L2_ENTRIES; i++ )    {        l2e = l2e_from_page(            virt_to_page(page_get_owner(page)->arch.mm_perdomain_pt) + i,            __PAGE_HYPERVISOR);        l2e_write(&pl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i], l2e);    }    for ( i = 0; i < (LINEARPT_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )    {        l2e = l2e_empty();        if ( l3e_get_flags(pl3e[i]) & _PAGE_PRESENT )            l2e = l2e_from_pfn(l3e_get_pfn(pl3e[i]), __PAGE_HYPERVISOR);        l2e_write(&pl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i], l2e);    }#else    memcpy(&pl2e[COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d)],           &compat_idle_pg_table_l2[               l2_table_offset(HIRO_COMPAT_MPT_VIRT_START)],           COMPAT_L2_PAGETABLE_XEN_SLOTS(d) * sizeof(*pl2e));#endif    unmap_domain_page(pl2e);    return 1;}#else# define create_pae_xen_mappings(d, pl3e) (1)#endif#ifdef CONFIG_X86_PAE/* Flush a pgdir update into low-memory caches. */static void pae_flush_pgd(    unsigned long mfn, unsigned int idx, l3_pgentry_t nl3e){    struct domain *d = page_get_owner(mfn_to_page(mfn));    struct vcpu   *v;    intpte_t       _ol3e, _nl3e, _pl3e;    l3_pgentry_t  *l3tab_ptr;    struct pae_l3_cache *cache;    if ( unlikely(shadow_mode_enabled(d)) )    {        cpumask_t m = CPU_MASK_NONE;        /* Re-shadow this l3 table on any vcpus that are using it */        for_each_vcpu ( d, v )            if ( pagetable_get_pfn(v->arch.guest_table) == mfn )            {                paging_update_cr3(v);                cpus_or(m, m, v->vcpu_dirty_cpumask);            }        flush_tlb_mask(m);    }    /* If below 4GB then the pgdir is not shadowed in low memory. */    if ( !l3tab_needs_shadow(mfn) )        return;    for_each_vcpu ( d, v )    {        cache = &v->arch.pae_l3_cache;        spin_lock(&cache->lock);        if ( cache->high_mfn == mfn )        {            l3tab_ptr = &cache->table[cache->inuse_idx][idx];            _ol3e = l3e_get_intpte(*l3tab_ptr);            _nl3e = l3e_get_intpte(nl3e);            _pl3e = cmpxchg(&l3e_get_intpte(*l3tab_ptr), _ol3e, _nl3e);            BUG_ON(_pl3e != _ol3e);        }        spin_unlock(&cache->lock);    }    flush_tlb_mask(d->domain_dirty_cpumask);}#else# define pae_flush_pgd(mfn, idx, nl3e) ((void)0)#endifstatic int alloc_l2_table(struct page_info *page, unsigned long type){    struct domain *d = page_get_owner(page);    unsigned long  pfn = page_to_mfn(page);    l2_pgentry_t  *pl2e;    int            i;    pl2e = map_domain_page(pfn);    for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )    {        if ( is_guest_l2_slot(d, type, i) &&             unlikely(!get_page_from_l2e(pl2e[i], pfn, d)) )            goto fail;                adjust_guest_l2e(pl2e[i], d);    }#if CONFIG_PAGING_LEVELS == 2    /* Xen private mappings. */    memcpy(&pl2e[L2_PAGETABLE_FIRST_XEN_SLOT],           &idle_pg_table[L2_PAGETABLE_FIRST_XEN_SLOT],           L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));    pl2e[l2_table_offset(LINEAR_PT_VIRT_START)] =        l2e_from_pfn(pfn, __PAGE_HYPERVISOR);    for ( i = 0; i < PDPT_L2_ENTRIES; i++ )        pl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =            l2e_from_page(                virt_to_page(page_get_owner(page)->arch.mm_perdomain_pt) + i,                __PAGE_HYPERVISOR);#endif    unmap_domain_page(pl2e);    return 1; fail:    MEM_LOG("Failure in alloc_l2_table: entry %d", i);    while ( i-- > 0 )        if ( is_guest_l2_slot(d, type, i) )            put_page_from_l2e(pl2e[i], pfn);    unmap_domain_page(pl2e);    return 0;}#if CONFIG_PAGING_LEVELS >= 3static int alloc_l3_table(struct page_info *page){    struct domain *d = page_get_owner(page);    unsigned long  pfn = page_to_mfn(page);    l3_pgentry_t  *pl3e;    int            i;#ifdef CONFIG_X86_PAE    /*     * PAE pgdirs above 4GB are unacceptable if the guest does not understand     * the weird 'extended cr3' format for dealing with high-order address     * bits. We cut some slack for control tools (before vcpu0 is initialised).     */    if ( (pfn >= 0x100000) &&         unlikely(!VM_ASSIST(d, VMASST_TYPE_pae_extended_cr3)) &&         d->vcpu[0] && d->vcpu[0]->is_initialised )    {        MEM_LOG("PAE pgd must be below 4GB (0x%lx >= 0x100000)", pfn);        return 0;    }#endif    pl3e = map_domain_page(pfn);    /*     * PAE guests allocate full pages, but aren't required to initialize     * more than the first four entries; when running in compatibility     * mode, however, the full page is visible to the MMU, and hence all     * 512 entries must be valid/verified, which is most easily achieved     * by clearing them out.     */    if ( is_pv_32on64_domain(d) )        memset(pl3e + 4, 0, (L3_PAGETABLE_ENTRIES - 4) * sizeof(*pl3e));    for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ )    {#if defined(CONFIG_X86_PAE) || defined(CONFIG_COMPAT)        if ( is_pv_32bit_domain(d) && (i == 3) )        {            if ( !(l3e_get_flags(pl3e[i]) & _PAGE_PRESENT) ||                 (l3e_get_flags(pl3e[i]) & l3_disallow_mask(d)) ||                 !get_page_and_type_from_pagenr(l3e_get_pfn(pl3e[i]),                                                PGT_l2_page_table |                                                PGT_pae_xen_l2,                                                d) )                goto fail;        }        else#endif        if ( is_guest_l3_slot(i) &&             unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) )            goto fail;                adjust_guest_l3e(pl3e[i], d);    }    if ( !create_pae_xen_mappings(d, pl3e) )        goto fail;    unmap_domain_page(pl3e);    return 1; fail:    MEM_LOG("Failure in alloc_l3_table: entry %d", i);    while ( i-- > 0 )        if ( is_guest_l3_slot(i) )            put_page_from_l3e(pl3e[i], pfn);    unmap_domain_page(pl3e);    return 0;}#else#define alloc_l3_table(page) (0)#endif#if CONFIG_PAGING_LEVELS >= 4static int alloc_l4_table(struct page_info *page){    struct domain *d = page_get_owner(page);    unsigned long  pfn = page_to_mfn(page);    l4_pgentry_t  *pl4e = page_to_virt(page);    int            i;    for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ )    {        if ( is_guest_l4_slot(d, i) &&             unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) )            goto fail;        adjust_guest_l4e(pl4e[i], d);    }    /* Xen private mappings. */    memcpy(&pl4e[ROOT_PAGETABLE_FIRST_XEN_SLOT],           &idle_pg_table[ROOT_PAGETABLE_FIRST_XEN_SLOT],           ROOT_PAGETABLE_XEN_SLOTS * sizeof(l4_pgentry_t));    pl4e[l4_table_offset(LINEAR_PT_VIRT_START)] =        l4e_from_pfn(pfn, __PAGE_HYPERVISOR);    pl4e[l4_table_offset(PERDOMAIN_VIRT_START)] =        l4e_from_page(virt_to_page(d->arch.mm_perdomain_l3),                      __PAGE_HYPERVISOR);    if ( is_pv_32on64_domain(d) )        pl4e[l4_table_offset(COMPAT_ARG_XLAT_VIRT_BASE)] =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -