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

📄 domain_page.c

📁 xen虚拟机源代码安装包
💻 C
字号:
/****************************************************************************** * domain_page.h *  * Allow temporary mapping of domain pages. *  * Copyright (c) 2003-2006, Keir Fraser <keir@xensource.com> */#include <xen/config.h>#include <xen/sched.h>#include <xen/mm.h>#include <xen/perfc.h>#include <xen/domain_page.h>#include <asm/current.h>#include <asm/flushtlb.h>#include <asm/hardirq.h>#include <asm/hvm/support.h>static inline struct vcpu *mapcache_current_vcpu(void){    struct vcpu *v;    /* In the common case we use the mapcache of the running VCPU. */    v = current;    /*     * If guest_table is NULL, and we are running a paravirtualised guest,     * then it means we are running on the idle domain's page table and must     * therefore use its mapcache.     */    if ( unlikely(!pagetable_get_pfn(v->arch.guest_table)) && !is_hvm_vcpu(v) )    {        /* If we really are idling, perform lazy context switch now. */        if ( (v = idle_vcpu[smp_processor_id()]) == current )            __sync_lazy_execstate();        /* We must now be running on the idle page table. */        ASSERT(read_cr3() == __pa(idle_pg_table));    }    return v;}void *map_domain_page(unsigned long mfn){    unsigned long va;    unsigned int idx, i;    struct vcpu *v;    struct mapcache_domain *dcache;    struct mapcache_vcpu *vcache;    struct vcpu_maphash_entry *hashent;    ASSERT(!in_irq());    perfc_incr(map_domain_page_count);    v = mapcache_current_vcpu();    dcache = &v->domain->arch.mapcache;    vcache = &v->arch.mapcache;    hashent = &vcache->hash[MAPHASH_HASHFN(mfn)];    if ( hashent->mfn == mfn )    {        idx = hashent->idx;        hashent->refcnt++;        ASSERT(idx < MAPCACHE_ENTRIES);        ASSERT(hashent->refcnt != 0);        ASSERT(l1e_get_pfn(dcache->l1tab[idx]) == mfn);        goto out;    }    spin_lock(&dcache->lock);    /* Has some other CPU caused a wrap? We must flush if so. */    if ( unlikely(dcache->epoch != vcache->shadow_epoch) )    {        vcache->shadow_epoch = dcache->epoch;        if ( NEED_FLUSH(this_cpu(tlbflush_time), dcache->tlbflush_timestamp) )        {            perfc_incr(domain_page_tlb_flush);            flush_tlb_local();        }    }    idx = find_next_zero_bit(dcache->inuse, MAPCACHE_ENTRIES, dcache->cursor);    if ( unlikely(idx >= MAPCACHE_ENTRIES) )    {        /* /First/, clean the garbage map and update the inuse list. */        for ( i = 0; i < ARRAY_SIZE(dcache->garbage); i++ )        {            unsigned long x = xchg(&dcache->garbage[i], 0);            dcache->inuse[i] &= ~x;        }        /* /Second/, flush TLBs. */        perfc_incr(domain_page_tlb_flush);        flush_tlb_local();        vcache->shadow_epoch = ++dcache->epoch;        dcache->tlbflush_timestamp = tlbflush_current_time();        idx = find_first_zero_bit(dcache->inuse, MAPCACHE_ENTRIES);        BUG_ON(idx >= MAPCACHE_ENTRIES);    }    set_bit(idx, dcache->inuse);    dcache->cursor = idx + 1;    spin_unlock(&dcache->lock);    l1e_write(&dcache->l1tab[idx], l1e_from_pfn(mfn, __PAGE_HYPERVISOR)); out:    va = MAPCACHE_VIRT_START + (idx << PAGE_SHIFT);    return (void *)va;}void unmap_domain_page(void *va){    unsigned int idx;    struct vcpu *v;    struct mapcache_domain *dcache;    unsigned long mfn;    struct vcpu_maphash_entry *hashent;    ASSERT(!in_irq());    ASSERT((void *)MAPCACHE_VIRT_START <= va);    ASSERT(va < (void *)MAPCACHE_VIRT_END);    v = mapcache_current_vcpu();    dcache = &v->domain->arch.mapcache;    idx = ((unsigned long)va - MAPCACHE_VIRT_START) >> PAGE_SHIFT;    mfn = l1e_get_pfn(dcache->l1tab[idx]);    hashent = &v->arch.mapcache.hash[MAPHASH_HASHFN(mfn)];    if ( hashent->idx == idx )    {        ASSERT(hashent->mfn == mfn);        ASSERT(hashent->refcnt != 0);        hashent->refcnt--;    }    else if ( hashent->refcnt == 0 )    {        if ( hashent->idx != MAPHASHENT_NOTINUSE )        {            /* /First/, zap the PTE. */            ASSERT(l1e_get_pfn(dcache->l1tab[hashent->idx]) == hashent->mfn);            l1e_write(&dcache->l1tab[hashent->idx], l1e_empty());            /* /Second/, mark as garbage. */            set_bit(hashent->idx, dcache->garbage);        }        /* Add newly-freed mapping to the maphash. */        hashent->mfn = mfn;        hashent->idx = idx;    }    else    {        /* /First/, zap the PTE. */        l1e_write(&dcache->l1tab[idx], l1e_empty());        /* /Second/, mark as garbage. */        set_bit(idx, dcache->garbage);    }}void mapcache_domain_init(struct domain *d){    d->arch.mapcache.l1tab = d->arch.mm_perdomain_pt +        (GDT_LDT_MBYTES << (20 - PAGE_SHIFT));    spin_lock_init(&d->arch.mapcache.lock);}void mapcache_vcpu_init(struct vcpu *v){    unsigned int i;    struct vcpu_maphash_entry *hashent;    /* Mark all maphash entries as not in use. */    for ( i = 0; i < MAPHASH_ENTRIES; i++ )    {        hashent = &v->arch.mapcache.hash[i];        hashent->mfn = ~0UL; /* never valid to map */        hashent->idx = MAPHASHENT_NOTINUSE;    }}#define GLOBALMAP_BITS (IOREMAP_MBYTES << (20 - PAGE_SHIFT))static unsigned long inuse[BITS_TO_LONGS(GLOBALMAP_BITS)];static unsigned long garbage[BITS_TO_LONGS(GLOBALMAP_BITS)];static unsigned int inuse_cursor;static DEFINE_SPINLOCK(globalmap_lock);void *map_domain_page_global(unsigned long mfn){    l2_pgentry_t *pl2e;    l1_pgentry_t *pl1e;    unsigned int idx, i;    unsigned long va;    ASSERT(!in_irq() && local_irq_is_enabled());    spin_lock(&globalmap_lock);    idx = find_next_zero_bit(inuse, GLOBALMAP_BITS, inuse_cursor);    va = IOREMAP_VIRT_START + (idx << PAGE_SHIFT);    if ( unlikely(va >= FIXADDR_START) )    {        /* /First/, clean the garbage map and update the inuse list. */        for ( i = 0; i < ARRAY_SIZE(garbage); i++ )        {            unsigned long x = xchg(&garbage[i], 0);            inuse[i] &= ~x;        }        /* /Second/, flush all TLBs to get rid of stale garbage mappings. */        flush_tlb_all();        idx = find_first_zero_bit(inuse, GLOBALMAP_BITS);        va = IOREMAP_VIRT_START + (idx << PAGE_SHIFT);        if ( unlikely(va >= FIXADDR_START) )        {            spin_unlock(&globalmap_lock);            return NULL;        }    }    set_bit(idx, inuse);    inuse_cursor = idx + 1;    spin_unlock(&globalmap_lock);    pl2e = virt_to_xen_l2e(va);    pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(va);    l1e_write(pl1e, l1e_from_pfn(mfn, __PAGE_HYPERVISOR));    return (void *)va;}void unmap_domain_page_global(void *va){    unsigned long __va = (unsigned long)va;    l2_pgentry_t *pl2e;    l1_pgentry_t *pl1e;    unsigned int idx;    ASSERT(__va >= IOREMAP_VIRT_START);    /* /First/, we zap the PTE. */    pl2e = virt_to_xen_l2e(__va);    pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(__va);    l1e_write(pl1e, l1e_empty());    /* /Second/, we add to the garbage map. */    idx = (__va - IOREMAP_VIRT_START) >> PAGE_SHIFT;    set_bit(idx, garbage);}

⌨️ 快捷键说明

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