common.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,973 行 · 第 1/5 页

C
1,973
字号
 * sl3 size         -    -    -    -    4k * sl4 size         -    -    -    -    4k * * We allocate memory from xen in four-page units and break them down * with a simple buddy allocator.  Can't use the xen allocator to handle * this as it only works for contiguous zones, and a domain's shadow * pool is made of fragments. * * In HVM guests, the p2m table is built out of shadow pages, and we provide  * a function for the p2m management to steal pages, in max-order chunks, from  * the free pool.  We don't provide for giving them back, yet. *//* Figure out the least acceptable quantity of shadow memory. * The minimum memory requirement for always being able to free up a * chunk of memory is very small -- only three max-order chunks per * vcpu to hold the top level shadows and pages with Xen mappings in them.   * * But for a guest to be guaranteed to successfully execute a single * instruction, we must be able to map a large number (about thirty) VAs * at the same time, which means that to guarantee progress, we must * allow for more than ninety allocated pages per vcpu.  We round that * up to 128 pages, or half a megabyte per vcpu. */static unsigned int shadow_min_acceptable_pages(struct domain *d) {    u32 vcpu_count = 0;    struct vcpu *v;    for_each_vcpu(d, v)        vcpu_count++;    return (vcpu_count * 128);} /* Figure out the order of allocation needed for a given shadow type */static inline u32shadow_order(unsigned int shadow_type) {    static const u32 type_to_order[SH_type_unused] = {        0, /* SH_type_none           */        1, /* SH_type_l1_32_shadow   */        1, /* SH_type_fl1_32_shadow  */        2, /* SH_type_l2_32_shadow   */        0, /* SH_type_l1_pae_shadow  */        0, /* SH_type_fl1_pae_shadow */        0, /* SH_type_l2_pae_shadow  */        0, /* SH_type_l2h_pae_shadow */        0, /* SH_type_l1_64_shadow   */        0, /* SH_type_fl1_64_shadow  */        0, /* SH_type_l2_64_shadow   */        0, /* SH_type_l2h_64_shadow  */        0, /* SH_type_l3_64_shadow   */        0, /* SH_type_l4_64_shadow   */        2, /* SH_type_p2m_table      */        0, /* SH_type_monitor_table  */        0  /* SH_type_oos_snapshot   */        };    ASSERT(shadow_type < SH_type_unused);    return type_to_order[shadow_type];}static inline unsigned intshadow_max_order(struct domain *d){    return is_hvm_domain(d) ? SHADOW_MAX_ORDER : 0;}/* Do we have at total of count pages of the requested order free? */static inline int space_is_available(    struct domain *d,    unsigned int order,    unsigned int count){    for ( ; order <= shadow_max_order(d); ++order )    {        unsigned int n = count;        const struct list_head *p;        list_for_each ( p, &d->arch.paging.shadow.freelists[order] )            if ( --n == 0 )                return 1;        count = (count + 1) >> 1;    }    return 0;}/* Dispatcher function: call the per-mode function that will unhook the * non-Xen mappings in this top-level shadow mfn */static void shadow_unhook_mappings(struct vcpu *v, mfn_t smfn){    struct shadow_page_info *sp = mfn_to_shadow_page(smfn);    switch ( sp->type )    {    case SH_type_l2_32_shadow:        SHADOW_INTERNAL_NAME(sh_unhook_32b_mappings, 2)(v,smfn);        break;    case SH_type_l2_pae_shadow:    case SH_type_l2h_pae_shadow:        SHADOW_INTERNAL_NAME(sh_unhook_pae_mappings, 3)(v,smfn);        break;#if CONFIG_PAGING_LEVELS >= 4    case SH_type_l4_64_shadow:        SHADOW_INTERNAL_NAME(sh_unhook_64b_mappings, 4)(v,smfn);        break;#endif    default:        SHADOW_ERROR("top-level shadow has bad type %08x\n", sp->type);        BUG();    }}/* Make sure there are at least count order-sized pages * available in the shadow page pool. */static void _shadow_prealloc(    struct domain *d,    unsigned int order,    unsigned int count){    /* Need a vpcu for calling unpins; for now, since we don't have     * per-vcpu shadows, any will do */    struct vcpu *v, *v2;    struct list_head *l, *t;    struct shadow_page_info *sp;    mfn_t smfn;    int i;    ASSERT(order <= shadow_max_order(d));    if ( space_is_available(d, order, count) ) return;        v = current;    if ( v->domain != d )        v = d->vcpu[0];    ASSERT(v != NULL); /* Shouldn't have enabled shadows if we've no vcpus  */    /* Stage one: walk the list of pinned pages, unpinning them */    perfc_incr(shadow_prealloc_1);    list_for_each_backwards_safe(l, t, &d->arch.paging.shadow.pinned_shadows)    {        sp = list_entry(l, struct shadow_page_info, list);        smfn = shadow_page_to_mfn(sp);        /* Unpin this top-level shadow */        sh_unpin(v, smfn);        /* See if that freed up enough space */        if ( space_is_available(d, order, count) ) return;    }    /* Stage two: all shadow pages are in use in hierarchies that are     * loaded in cr3 on some vcpu.  Walk them, unhooking the non-Xen     * mappings. */    perfc_incr(shadow_prealloc_2);    for_each_vcpu(d, v2)         for ( i = 0 ; i < 4 ; i++ )        {            if ( !pagetable_is_null(v2->arch.shadow_table[i]) )            {                shadow_unhook_mappings(v,                                pagetable_get_mfn(v2->arch.shadow_table[i]));                /* See if that freed up enough space */                if ( space_is_available(d, order, count) )                {                    flush_tlb_mask(d->domain_dirty_cpumask);                    return;                }            }        }        /* Nothing more we can do: all remaining shadows are of pages that     * hold Xen mappings for some vcpu.  This can never happen. */    SHADOW_ERROR("Can't pre-allocate %u order-%u shadow pages!\n"                 "  shadow pages total = %u, free = %u, p2m=%u\n",                 count, order,                 d->arch.paging.shadow.total_pages,                 d->arch.paging.shadow.free_pages,                 d->arch.paging.shadow.p2m_pages);    BUG();}/* Make sure there are at least count pages of the order according to * type available in the shadow page pool. * This must be called before any calls to shadow_alloc().  Since this * will free existing shadows to make room, it must be called early enough * to avoid freeing shadows that the caller is currently working on. */void shadow_prealloc(struct domain *d, u32 type, unsigned int count){    ASSERT(type != SH_type_p2m_table);    return _shadow_prealloc(d, shadow_order(type), count);}/* Deliberately free all the memory we can: this will tear down all of * this domain's shadows */static void shadow_blow_tables(struct domain *d) {    struct list_head *l, *t;    struct shadow_page_info *sp;    struct vcpu *v = d->vcpu[0];    mfn_t smfn;    int i;    ASSERT(v != NULL);    /* Pass one: unpin all pinned pages */    list_for_each_backwards_safe(l,t, &d->arch.paging.shadow.pinned_shadows)    {        sp = list_entry(l, struct shadow_page_info, list);        smfn = shadow_page_to_mfn(sp);        sh_unpin(v, smfn);    }            /* Second pass: unhook entries of in-use shadows */    for_each_vcpu(d, v)         for ( i = 0 ; i < 4 ; i++ )            if ( !pagetable_is_null(v->arch.shadow_table[i]) )                shadow_unhook_mappings(v,                                pagetable_get_mfn(v->arch.shadow_table[i]));    /* Make sure everyone sees the unshadowings */    flush_tlb_mask(d->domain_dirty_cpumask);}void shadow_blow_tables_per_domain(struct domain *d){    if ( shadow_mode_enabled(d) && d->vcpu[0] != NULL ) {        shadow_lock(d);        shadow_blow_tables(d);        shadow_unlock(d);    }}#ifndef NDEBUG/* Blow all shadows of all shadowed domains: this can be used to cause the * guest's pagetables to be re-shadowed if we suspect that the shadows * have somehow got out of sync */static void shadow_blow_all_tables(unsigned char c){    struct domain *d;    printk("'%c' pressed -> blowing all shadow tables\n", c);    rcu_read_lock(&domlist_read_lock);    for_each_domain(d)    {        if ( shadow_mode_enabled(d) && d->vcpu[0] != NULL )        {            shadow_lock(d);            shadow_blow_tables(d);            shadow_unlock(d);        }    }    rcu_read_unlock(&domlist_read_lock);}/* Register this function in the Xen console keypress table */static __init int shadow_blow_tables_keyhandler_init(void){    register_keyhandler('S', shadow_blow_all_tables,"reset shadow pagetables");    return 0;}__initcall(shadow_blow_tables_keyhandler_init);#endif /* !NDEBUG *//* Allocate another shadow's worth of (contiguous, aligned) pages, * and fill in the type and backpointer fields of their page_infos.  * Never fails to allocate. */mfn_t shadow_alloc(struct domain *d,                      u32 shadow_type,                    unsigned long backpointer){    struct shadow_page_info *sp = NULL;    unsigned int order = shadow_order(shadow_type);    cpumask_t mask;    void *p;    int i;    ASSERT(shadow_locked_by_me(d));    if (shadow_type == SH_type_p2m_table && order > shadow_max_order(d))        order = shadow_max_order(d);    ASSERT(order <= shadow_max_order(d));    ASSERT(shadow_type != SH_type_none);    perfc_incr(shadow_alloc);    /* Find smallest order which can satisfy the request. */    for ( i = order; i <= SHADOW_MAX_ORDER; i++ )        if ( !list_empty(&d->arch.paging.shadow.freelists[i]) )            goto found;        /* If we get here, we failed to allocate. This should never happen.     * It means that we didn't call shadow_prealloc() correctly before     * we allocated.  We can't recover by calling prealloc here, because     * we might free up higher-level pages that the caller is working on. */    SHADOW_ERROR("Can't allocate %i shadow pages!\n", 1 << order);    BUG(); found:    sp = list_entry(d->arch.paging.shadow.freelists[i].next,                     struct shadow_page_info, list);    list_del(&sp->list);                /* We may have to halve the chunk a number of times. */    while ( i != order )    {        i--;        sp->order = i;        list_add_tail(&sp->list, &d->arch.paging.shadow.freelists[i]);        sp += 1 << i;    }    d->arch.paging.shadow.free_pages -= 1 << order;    /* Init page info fields and clear the pages */    for ( i = 0; i < 1<<order ; i++ )     {        /* Before we overwrite the old contents of this page,          * we need to be sure that no TLB holds a pointer to it. */        mask = d->domain_dirty_cpumask;        tlbflush_filter(mask, sp[i].tlbflush_timestamp);        if ( unlikely(!cpus_empty(mask)) )        {            perfc_incr(shadow_alloc_tlbflush);            flush_tlb_mask(mask);        }        /* Now safe to clear the page for reuse */        p = sh_map_domain_page(shadow_page_to_mfn(sp+i));        ASSERT(p != NULL);        clear_page(p);        sh_unmap_domain_page(p);        INIT_LIST_HEAD(&sp[i].list);        sp[i].type = shadow_type;        sp[i].pinned = 0;        sp[i].count = 0;        sp[i].backpointer = backpointer;        sp[i].next_shadow = NULL;        perfc_incr(shadow_alloc_count);    }    return shadow_page_to_mfn(sp);}/* Return some shadow pages to the pool. */void shadow_free(struct domain *d, mfn_t smfn){    struct shadow_page_info *sp = mfn_to_shadow_page(smfn);     u32 shadow_type;    unsigned long order;    unsigned long mask;    int i;    ASSERT(shadow_locked_by_me(d));    perfc_incr(shadow_free);    shadow_type = sp->type;    ASSERT(shadow_type != SH_type_none);    ASSERT(shadow_type != SH_type_p2m_table);    order = shadow_order(shadow_type);    d->arch.paging.shadow.free_pages += 1 << order;    for ( i = 0; i < 1<<order; i++ )     {#if SHADOW_OPTIMIZATIONS & (SHOPT_WRITABLE_HEURISTIC | SHOPT_FAST_EMULATION)        struct vcpu *v;        for_each_vcpu(d, v)         {#if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC            /* No longer safe to look for a writeable mapping in this shadow */            if ( v->arch.paging.shadow.last_writeable_pte_smfn == mfn_x(smfn) + i )                 v->arch.paging.shadow.last_writeable_pte_smfn = 0;#endif#if SHADOW_OPTIMIZATIONS & SHOPT_FAST_EMULATION            v->arch.paging.last_write_emul_ok = 0;#endif        }#endif        /* Strip out the type: this is now a free shadow page */        sp[i].type = 0;        /* Remember the TLB timestamp so we will know whether to flush          * TLBs when we reuse the page.  Because the destructors leave the         * contents of the pages in place, we can delay TLB flushes until         * just before the allocator hands the page out again. */        sp[i].tlbflush_timestamp = tlbflush_current_time();        perfc_decr(shadow_alloc_count);    }    /* Merge chunks as far as possible. */    for ( ; order < shadow_max_order(d); ++order )    {        mask = 1 << order;        if ( (mfn_x(shadow_page_to_mfn(sp)) & mask) ) {            /* Merge with predecessor block? */            if ( ((sp-mask)->type != PGT_none) || ((sp-mask)->order != order) )                break;            list_del(&(sp-mask)->list);            sp -= mask;

⌨️ 快捷键说明

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