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 + -
显示快捷键?