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

📄 domain_build.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
    {        l1_pgentry_t gdt_l1e;        d->arch.is_32bit_pv = d->arch.has_32bit_shinfo = 1;        v->vcpu_info = (void *)&d->shared_info->compat.vcpu_info[0];        if ( nr_pages != (unsigned int)nr_pages )            nr_pages = UINT_MAX;        /*         * Map compatibility Xen segments into every VCPU's GDT. See         * arch_domain_create() for further comments.         */        gdt_l1e = l1e_from_page(virt_to_page(compat_gdt_table),                                PAGE_HYPERVISOR);        for ( i = 0; i < MAX_VIRT_CPUS; i++ )            d->arch.mm_perdomain_pt[((i << GDT_LDT_VCPU_SHIFT) +                                     FIRST_RESERVED_GDT_PAGE)] = gdt_l1e;        flush_tlb_one_local(GDT_LDT_VIRT_START + FIRST_RESERVED_GDT_BYTE);    }#endif    if ( parms.pae == PAEKERN_extended_cr3 )            set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist);    if ( (parms.virt_hv_start_low != UNSET_ADDR) && elf_32bit(&elf) )    {        unsigned long mask = (1UL << L2_PAGETABLE_SHIFT) - 1;        value = (parms.virt_hv_start_low + mask) & ~mask;        BUG_ON(!is_pv_32bit_domain(d));#if defined(__i386__)        if ( value > HYPERVISOR_VIRT_START )            panic("Domain 0 expects too high a hypervisor start address.\n");#else        if ( value > __HYPERVISOR_COMPAT_VIRT_START )            panic("Domain 0 expects too high a hypervisor start address.\n");        HYPERVISOR_COMPAT_VIRT_START(d) =            max_t(unsigned int, m2p_compat_vstart, value);#endif    }    domain_set_alloc_bitsize(d);    /*     * Why do we need this? The number of page-table frames depends on the      * size of the bootstrap address space. But the size of the address space      * depends on the number of page-table frames (since each one is mapped      * read-only). We have a pair of simultaneous equations in two unknowns,      * which we solve by exhaustive search.     */    v_start          = parms.virt_base;    vkern_start      = parms.virt_kstart;    vkern_end        = parms.virt_kend;    vinitrd_start    = round_pgup(vkern_end);    vinitrd_end      = vinitrd_start + initrd_len;    vphysmap_start   = round_pgup(vinitrd_end);    vphysmap_end     = vphysmap_start + (nr_pages * (!is_pv_32on64_domain(d) ?                                                     sizeof(unsigned long) :                                                     sizeof(unsigned int)));    vstartinfo_start = round_pgup(vphysmap_end);    vstartinfo_end   = (vstartinfo_start +                        sizeof(struct start_info) +                        sizeof(struct dom0_vga_console_info));    vpt_start        = round_pgup(vstartinfo_end);    for ( nr_pt_pages = 2; ; nr_pt_pages++ )    {        vpt_end          = vpt_start + (nr_pt_pages * PAGE_SIZE);        vstack_start     = vpt_end;        vstack_end       = vstack_start + PAGE_SIZE;        v_end            = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1);        if ( (v_end - vstack_end) < (512UL << 10) )            v_end += 1UL << 22; /* Add extra 4MB to get >= 512kB padding. */#if defined(__i386__)        /* 5 pages: 1x 3rd + 4x 2nd level */        if ( (((v_end - v_start + ((1UL<<L2_PAGETABLE_SHIFT)-1)) >>               L2_PAGETABLE_SHIFT) + 5) <= nr_pt_pages )            break;#elif defined(__x86_64__)#define NR(_l,_h,_s) \    (((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \       ((_l) & ~((1UL<<(_s))-1))) >> (_s))        if ( (1 + /* # L4 */              NR(v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */              (!is_pv_32on64_domain(d) ?               NR(v_start, v_end, L3_PAGETABLE_SHIFT) : /* # L2 */               4) + /* # compat L2 */              NR(v_start, v_end, L2_PAGETABLE_SHIFT))  /* # L1 */             <= nr_pt_pages )            break;#endif    }    order = get_order_from_bytes(v_end - v_start);    if ( (1UL << order) > nr_pages )        panic("Domain 0 allocation is too small for kernel image.\n");#ifdef __i386__    /* Ensure that our low-memory 1:1 mapping covers the allocation. */    page = alloc_domheap_pages(d, order, MEMF_bits(30));#else    page = alloc_domheap_pages(d, order, 0);#endif    if ( page == NULL )        panic("Not enough RAM for domain 0 allocation.\n");    alloc_spfn = page_to_mfn(page);    alloc_epfn = alloc_spfn + d->tot_pages;    printk("PHYSICAL MEMORY ARRANGEMENT:\n"           " Dom0 alloc.:   %"PRIpaddr"->%"PRIpaddr,           pfn_to_paddr(alloc_spfn), pfn_to_paddr(alloc_epfn));    if ( d->tot_pages < nr_pages )        printk(" (%lu pages to be allocated)",               nr_pages - d->tot_pages);    printk("\nVIRTUAL MEMORY ARRANGEMENT:\n"           " Loaded kernel: %p->%p\n"           " Init. ramdisk: %p->%p\n"           " Phys-Mach map: %p->%p\n"           " Start info:    %p->%p\n"           " Page tables:   %p->%p\n"           " Boot stack:    %p->%p\n"           " TOTAL:         %p->%p\n",           _p(vkern_start), _p(vkern_end),           _p(vinitrd_start), _p(vinitrd_end),           _p(vphysmap_start), _p(vphysmap_end),           _p(vstartinfo_start), _p(vstartinfo_end),           _p(vpt_start), _p(vpt_end),           _p(vstack_start), _p(vstack_end),           _p(v_start), _p(v_end));    printk(" ENTRY ADDRESS: %p\n", _p(parms.virt_entry));    if ( ((v_end - v_start)>>PAGE_SHIFT) > nr_pages )    {        printk("Initial guest OS requires too much space\n"               "(%luMB is greater than %luMB limit)\n",               (v_end-v_start)>>20, nr_pages>>(20-PAGE_SHIFT));        return -ENOMEM;    }    mpt_alloc = (vpt_start - v_start) +        (unsigned long)pfn_to_paddr(alloc_spfn);#if defined(__i386__)    /*     * Protect the lowest 1GB of memory. We use a temporary mapping there     * from which we copy the kernel and ramdisk images.     */    if ( v_start < (1UL<<30) )    {        printk("Initial loading isn't allowed to lowest 1GB of memory.\n");        return -EINVAL;    }    /* WARNING: The new domain must have its 'processor' field filled in! */    l3start = l3tab = (l3_pgentry_t *)mpt_alloc; mpt_alloc += PAGE_SIZE;    l2start = l2tab = (l2_pgentry_t *)mpt_alloc; mpt_alloc += 4*PAGE_SIZE;    memcpy(l2tab, idle_pg_table_l2, 4*PAGE_SIZE);    for (i = 0; i < 4; i++) {        l3tab[i] = l3e_from_paddr((u32)l2tab + i*PAGE_SIZE, L3_PROT);        l2tab[(LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT)+i] =            l2e_from_paddr((u32)l2tab + i*PAGE_SIZE, __PAGE_HYPERVISOR);    }    v->arch.guest_table = pagetable_from_paddr((unsigned long)l3start);    for ( i = 0; i < PDPT_L2_ENTRIES; i++ )        l2tab[l2_linear_offset(PERDOMAIN_VIRT_START) + i] =            l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt) + i,                          __PAGE_HYPERVISOR);    l2tab += l2_linear_offset(v_start);    mfn = alloc_spfn;    for ( count = 0; count < ((v_end-v_start)>>PAGE_SHIFT); count++ )    {        if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) )        {            l1start = l1tab = (l1_pgentry_t *)mpt_alloc;            mpt_alloc += PAGE_SIZE;            *l2tab = l2e_from_paddr((unsigned long)l1start, L2_PROT);            l2tab++;            clear_page(l1tab);            if ( count == 0 )                l1tab += l1_table_offset(v_start);        }        *l1tab = l1e_from_pfn(mfn, L1_PROT);        l1tab++;                page = mfn_to_page(mfn);        if ( !get_page_and_type(page, d, PGT_writable_page) )            BUG();        mfn++;    }    /* Pages that are part of page tables must be read only. */    l2tab = l2start + l2_linear_offset(vpt_start);    l1start = l1tab = (l1_pgentry_t *)(u32)l2e_get_paddr(*l2tab);    l1tab += l1_table_offset(vpt_start);    for ( count = 0; count < nr_pt_pages; count++ )     {        page = mfn_to_page(l1e_get_pfn(*l1tab));        if ( !opt_dom0_shadow )            l1e_remove_flags(*l1tab, _PAGE_RW);        else            if ( !get_page_type(page, PGT_writable_page) )                BUG();        switch ( count )        {        case 0:            page->u.inuse.type_info &= ~PGT_type_mask;            page->u.inuse.type_info |= PGT_l3_page_table;            get_page(page, d); /* an extra ref because of readable mapping */            /* Get another ref to L3 page so that it can be pinned. */            page->u.inuse.type_info++;            page->count_info++;            set_bit(_PGT_pinned, &page->u.inuse.type_info);            break;        case 1 ... 4:            page->u.inuse.type_info &= ~PGT_type_mask;            page->u.inuse.type_info |= PGT_l2_page_table;            if ( count == 4 )                page->u.inuse.type_info |= PGT_pae_xen_l2;            get_page(page, d); /* an extra ref because of readable mapping */            break;        default:            page->u.inuse.type_info &= ~PGT_type_mask;            page->u.inuse.type_info |= PGT_l1_page_table;            get_page(page, d); /* an extra ref because of readable mapping */            break;        }        if ( !((unsigned long)++l1tab & (PAGE_SIZE - 1)) )            l1start = l1tab = (l1_pgentry_t *)(u32)l2e_get_paddr(*++l2tab);    }#elif defined(__x86_64__)    /* Overlap with Xen protected area? */    if ( !is_pv_32on64_domain(d) ?         ((v_start < HYPERVISOR_VIRT_END) &&          (v_end > HYPERVISOR_VIRT_START)) :         (v_end > HYPERVISOR_COMPAT_VIRT_START(d)) )    {        printk("DOM0 image overlaps with Xen private area.\n");        return -EINVAL;    }    if ( is_pv_32on64_domain(d) )    {        v->arch.guest_context.failsafe_callback_cs = FLAT_COMPAT_KERNEL_CS;        v->arch.guest_context.event_callback_cs    = FLAT_COMPAT_KERNEL_CS;    }    /* WARNING: The new domain must have its 'processor' field filled in! */    if ( !is_pv_32on64_domain(d) )    {        maddr_to_page(mpt_alloc)->u.inuse.type_info = PGT_l4_page_table;        l4start = l4tab = __va(mpt_alloc); mpt_alloc += PAGE_SIZE;    }    else    {        page = alloc_domheap_page(NULL, 0);        if ( !page )            panic("Not enough RAM for domain 0 PML4.\n");        page->u.inuse.type_info = PGT_l4_page_table|PGT_validated|1;        l4start = l4tab = page_to_virt(page);    }    copy_page(l4tab, idle_pg_table);    l4tab[0] = l4e_empty(); /* zap trampoline mapping */    l4tab[l4_table_offset(LINEAR_PT_VIRT_START)] =        l4e_from_paddr(__pa(l4start), __PAGE_HYPERVISOR);    l4tab[l4_table_offset(PERDOMAIN_VIRT_START)] =        l4e_from_paddr(__pa(d->arch.mm_perdomain_l3), __PAGE_HYPERVISOR);    v->arch.guest_table = pagetable_from_paddr(__pa(l4start));    if ( is_pv_32on64_domain(d) )        v->arch.guest_table_user = v->arch.guest_table;    l4tab += l4_table_offset(v_start);    mfn = alloc_spfn;    for ( count = 0; count < ((v_end-v_start)>>PAGE_SHIFT); count++ )    {        if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) )        {            maddr_to_page(mpt_alloc)->u.inuse.type_info = PGT_l1_page_table;            l1start = l1tab = __va(mpt_alloc); mpt_alloc += PAGE_SIZE;            clear_page(l1tab);            if ( count == 0 )                l1tab += l1_table_offset(v_start);            if ( !((unsigned long)l2tab & (PAGE_SIZE-1)) )            {                maddr_to_page(mpt_alloc)->u.inuse.type_info = PGT_l2_page_table;                l2start = l2tab = __va(mpt_alloc); mpt_alloc += PAGE_SIZE;                clear_page(l2tab);                if ( count == 0 )                    l2tab += l2_table_offset(v_start);                if ( !((unsigned long)l3tab & (PAGE_SIZE-1)) )                {                    maddr_to_page(mpt_alloc)->u.inuse.type_info =                        PGT_l3_page_table;                    l3start = l3tab = __va(mpt_alloc); mpt_alloc += PAGE_SIZE;                    clear_page(l3tab);                    if ( count == 0 )                        l3tab += l3_table_offset(v_start);                    *l4tab = l4e_from_paddr(__pa(l3start), L4_PROT);                    l4tab++;                }                *l3tab = l3e_from_paddr(__pa(l2start), L3_PROT);                l3tab++;            }            *l2tab = l2e_from_paddr(__pa(l1start), L2_PROT);            l2tab++;        }        *l1tab = l1e_from_pfn(mfn, (!is_pv_32on64_domain(d) ?                                    L1_PROT : COMPAT_L1_PROT));        l1tab++;

⌨️ 快捷键说明

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