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

📄 domain_build.c

📁 xen 3.2.2 源码
💻 C
字号:
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. * * Copyright IBM Corp. 2005, 2007 * * Authors: Jimi Xenidis <jimix@watson.ibm.com> *          Ryan Harper <ryanh@us.ibm.com> *          Hollis Blanchard <hollisb@us.ibm.com> */#include <xen/config.h>#include <xen/lib.h>#include <xen/sched.h>#include <xen/init.h>#include <xen/ctype.h>#include <xen/iocap.h>#include <xen/domain.h>#include <xen/version.h>#include <xen/paging.h>#include <asm/processor.h>#include <asm/platform.h>#include <asm/papr.h>#include <public/arch-powerpc.h>#include <public/libelf.h>#include "oftree.h"/* opt_dom0_mem: memory allocated to domain 0. */static unsigned int dom0_nrpages;static void parse_dom0_mem(char *s){    unsigned long long bytes;    bytes = parse_size_and_unit(s, NULL);    dom0_nrpages = bytes >> PAGE_SHIFT;}custom_param("dom0_mem", parse_dom0_mem);static unsigned int opt_dom0_max_vcpus;integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);static unsigned int opt_dom0_shadow;boolean_param("dom0_shadow", opt_dom0_shadow);/* adapted from common/elf.c */#define RM_MASK(a,l) ((a) & ((1UL << (l)) - 1))int construct_dom0(struct domain *d,                   unsigned long image_start, unsigned long image_len,                    unsigned long initrd_start, unsigned long initrd_len,                   char *cmdline){    struct elf_binary elf;    struct elf_dom_parms parms;    int rc;    struct vcpu *v;    ulong dst;    u64 *ofh_tree;    ulong firmware_base;    uint rma_nrpages = 1 << cpu_default_rma_order_pages();    ulong rma_sz;    ulong rma;    ulong eomem;    int preempt = 0;    int vcpu;    ulong mod_start = 0;    ulong mod_len = 0;    ulong shared_info_addr;    uint extent_size = 1 << cpu_extent_order();    ulong sz;    /* Sanity! */    BUG_ON(d->domain_id != 0);    if (image_len == 0)        panic("No Dom0 image supplied\n");    printk("*** LOADING DOMAIN 0 ***\n");    /* default is the max(1/16th of memory, CONFIG_MIN_DOM0_PAGES) */    if (dom0_nrpages == 0) {        dom0_nrpages = total_pages >> 4;        if (dom0_nrpages < CONFIG_MIN_DOM0_PAGES)            dom0_nrpages = CONFIG_MIN_DOM0_PAGES;    }    /* Dom0 has to be at least RMA size. */    if (dom0_nrpages < rma_nrpages) {        dom0_nrpages = rma_nrpages;        printk("Increasing DOM0 memory size to %u MiB for RMA.\n",                 ((rma_nrpages << PAGE_SHIFT) >> 20));    }    /* Ensure Dom0 is cpu_extent_order aligned. Round up if        not and let user know we did so. */    if (dom0_nrpages != ALIGN_UP(dom0_nrpages, extent_size)) {        dom0_nrpages = ALIGN_UP(dom0_nrpages, extent_size);        printk("Increasing DOM0 memory size to %u MiB for large pages.\n",                 ((dom0_nrpages << PAGE_SHIFT) >> 20));    }    /* XXX Dom0 currently can't extend past the IO hole. */    if (dom0_nrpages > (platform_iohole_base() >> PAGE_SHIFT)) {        dom0_nrpages = (platform_iohole_base() >> PAGE_SHIFT);        printk("Limiting DOM0 memory size to %u MiB to avoid IO hole.\n",                 ((dom0_nrpages << PAGE_SHIFT) >> 20));    }    /* Set Dom0 max mem, triggering p2m table creation. */    if ((guest_physmap_max_mem_pages(d, dom0_nrpages)) != 0)        panic("Failed to set DOM0 max mem pages value\n");    d->max_pages = dom0_nrpages;    if (0 > allocate_rma(d, cpu_default_rma_order_pages()))        panic("Error allocating domain 0 RMA\n");    rma_sz = rma_size(d->arch.rma_order);    rma = page_to_maddr(d->arch.rma_page);    /* If we are bigger than RMA, allocate extents. */    if (dom0_nrpages > rma_nrpages)        dom0_nrpages = allocate_extents(d, dom0_nrpages, rma_nrpages);    ASSERT(d->tot_pages == dom0_nrpages);    ASSERT(d->tot_pages >= rma_nrpages);    if (opt_dom0_shadow == 0) {        /* 1/64 of memory  */        opt_dom0_shadow = (d->tot_pages >> 6) >> (20 - PAGE_SHIFT);    }    do {        shadow_set_allocation(d, opt_dom0_shadow, &preempt);    } while (preempt);    if (shadow_get_allocation(d) == 0)        panic("shadow allocation failed: %dMib\n", opt_dom0_shadow);    ASSERT( image_len < rma_sz );    eomem = ((ulong)d->shared_info) - rma;    printk("shared_info: 0x%lx,%p\n", eomem, d->shared_info);    /* startup secondary processors */    if ( opt_dom0_max_vcpus == 0 )        opt_dom0_max_vcpus = num_online_cpus();    if ( opt_dom0_max_vcpus > num_online_cpus() )        opt_dom0_max_vcpus = num_online_cpus();    if ( opt_dom0_max_vcpus > MAX_VIRT_CPUS )        opt_dom0_max_vcpus = MAX_VIRT_CPUS;#ifdef BITS_PER_GUEST_LONG    if ( opt_dom0_max_vcpus > BITS_PER_GUEST_LONG(d) )        opt_dom0_max_vcpus = BITS_PER_GUEST_LONG(d);#endif    printk("Dom0 has maximum %u VCPUs\n", opt_dom0_max_vcpus);    for (vcpu = 0; vcpu < opt_dom0_max_vcpus; vcpu++) {        if (NULL == alloc_vcpu(dom0, vcpu, vcpu))            panic("Error creating domain 0 vcpu %d\n", vcpu);        /* for now we pin Dom0 VCPUs to their coresponding CPUs */        if (cpu_isset(vcpu, cpu_online_map))            dom0->vcpu[vcpu]->cpu_affinity = cpumask_of_cpu(vcpu);    }    /* Init VCPU0. */    v = d->vcpu[0];    cpu_init_vcpu(v);    /* convert xen pointer shared_info into guest physical */    shared_info_addr = (ulong)d->shared_info - page_to_maddr(d->arch.rma_page);    /* start loading stuff */    rc = elf_init(&elf, (void *)image_start, image_len);    if (rc)        return rc;#ifdef VERBOSE    elf_set_verbose(&elf);#endif    elf_parse_binary(&elf);    if (0 != (elf_xen_parse(&elf, &parms)))        return rc;    printk("Dom0 kernel: %s, paddr 0x%" PRIx64 " -> 0x%" PRIx64 "\n",            elf_64bit(&elf) ? "64-bit" : "32-bit",            elf.pstart, elf.pend);    /* elf contains virtual addresses that can have the upper bits     * masked while running in real mode, so we do the masking as well     * as well */    parms.virt_kend = RM_MASK(parms.virt_kend, 42);    parms.virt_entry = RM_MASK(parms.virt_entry, 42);    /* set the MSR bit correctly */    if (elf_64bit(&elf))        v->arch.ctxt.msr = MSR_SF;    else        v->arch.ctxt.msr = 0;    /* Load the dom0 kernel. */    elf.dest = (void *)(parms.virt_kstart + rma);    elf_load_binary(&elf);    v->arch.ctxt.pc = parms.virt_entry;    dst = ALIGN_UP(parms.virt_kend + rma, PAGE_SIZE);    /* Load the initrd. */    if (initrd_len > 0) {        ASSERT((dst - rma) + image_len < eomem);        printk("loading initrd: 0x%lx, 0x%lx\n", dst, initrd_len);        memcpy((void *)dst, (void *)initrd_start, initrd_len);        mod_start = dst - rma;        mod_len = image_len;        dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE);    } else {        printk("no initrd\n");    }    v->arch.ctxt.gprs[3] = mod_start;    v->arch.ctxt.gprs[4] = mod_len;    /* OF usually sits here:     *   - Linux needs it to be loaded before the vmlinux or initrd     *   - AIX demands it to be @ 32M.     */    firmware_base = (32 << 20);    if (dst - rma > firmware_base)    panic("Firmware [0x%lx] will over-write images ending: 0x%lx\n",          firmware_base, dst - rma);    dst = firmware_base + rma;    /* Put stack below firmware. */    v->arch.ctxt.gprs[1] = dst - rma - STACK_FRAME_OVERHEAD;    v->arch.ctxt.gprs[2] = 0;    ASSERT((dst - rma) + (ulong)firmware_image_size < eomem);    printk("loading OFH: 0x%lx, RMA: 0x%lx\n", dst, dst - rma);    memcpy((void *)dst, firmware_image_start, (ulong)firmware_image_size);    v->arch.ctxt.gprs[5] = (dst - rma);    ofh_tree = (u64 *)(dst + 0x10);    ASSERT(*ofh_tree == 0xdeadbeef00000000);    /* accomodate for a modest bss section */    dst = ALIGN_UP(dst + (ulong)firmware_image_size + PAGE_SIZE, PAGE_SIZE);    ASSERT((dst - rma) + oftree_len < eomem);    *ofh_tree = dst - rma;    printk("loading OFD: 0x%lx RMA: 0x%lx, 0x%lx\n", dst, dst - rma,           oftree_len);    memcpy((void *)dst, (void *)oftree, oftree_len);    /* fixup and add stuff for dom0 */    sz = ofd_dom0_fixup(d, *ofh_tree + rma, cmdline, shared_info_addr);    printk("modified OFD size: 0x%lx\n", sz);    dst = ALIGN_UP(dst + sz + PAGE_SIZE, PAGE_SIZE);	printk("dom0 initial register state:\n"			"    pc %016lx msr %016lx\n"			"    r1 %016lx r2 %016lx r3 %016lx\n"			"    r4 %016lx r5 %016lx\n",			v->arch.ctxt.pc,			v->arch.ctxt.msr,			v->arch.ctxt.gprs[1],			v->arch.ctxt.gprs[2],			v->arch.ctxt.gprs[3],			v->arch.ctxt.gprs[4],			v->arch.ctxt.gprs[5]);    v->is_initialised = 1;    clear_bit(_VPF_down, &v->pause_flags);    rc = 0;    /* DOM0 is permitted full I/O capabilities. */    rc |= iomem_permit_access(dom0, 0UL, ~0UL);    rc |= irqs_permit_access(dom0, 0, NR_IRQS-1);    BUG_ON(rc != 0);    return 0;}

⌨️ 快捷键说明

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