📄 domain_build.c
字号:
/****************************************************************************** * domain_build.c * * Copyright (c) 2002-2005, K A Fraser */#include <xen/config.h>#include <xen/init.h>#include <xen/lib.h>#include <xen/ctype.h>#include <xen/sched.h>#include <xen/smp.h>#include <xen/delay.h>#include <xen/event.h>#include <xen/console.h>#include <xen/kernel.h>#include <xen/domain.h>#include <xen/version.h>#include <xen/iocap.h>#include <xen/bitops.h>#include <xen/compat.h>#include <asm/regs.h>#include <asm/system.h>#include <asm/io.h>#include <asm/processor.h>#include <asm/desc.h>#include <asm/i387.h>#include <asm/paging.h>#include <asm/e820.h>#include <public/version.h>#include <public/libelf.h>extern unsigned long initial_images_nrpages(void);extern void discard_initial_images(void);static long __initdata dom0_nrpages;static long __initdata dom0_min_nrpages;static long __initdata dom0_max_nrpages = LONG_MAX;/* * dom0_mem=[min:<min_amt>,][max:<max_amt>,][<amt>] * * <min_amt>: The minimum amount of memory which should be allocated for dom0. * <max_amt>: The maximum amount of memory which should be allocated for dom0. * <amt>: The precise amount of memory to allocate for dom0. * * Notes: * 1. <amt> is clamped from below by <min_amt> and from above by available * memory and <max_amt> * 2. <min_amt> is clamped from above by available memory and <max_amt> * 3. <min_amt> is ignored if it is greater than <max_amt> * 4. If <amt> is not specified, it is calculated as follows: * "All of memory is allocated to domain 0, minus 1/16th which is reserved * for uses such as DMA buffers (the reservation is clamped to 128MB)." * * Each value can be specified as positive or negative: * If +ve: The specified amount is an absolute value. * If -ve: The specified amount is subtracted from total available memory. */static long __init parse_amt(const char *s, const char **ps){ long pages = parse_size_and_unit((*s == '-') ? s+1 : s, ps) >> PAGE_SHIFT; return (*s == '-') ? -pages : pages;}static void __init parse_dom0_mem(const char *s){ do { if ( !strncmp(s, "min:", 4) ) dom0_min_nrpages = parse_amt(s+4, &s); else if ( !strncmp(s, "max:", 4) ) dom0_max_nrpages = parse_amt(s+4, &s); else dom0_nrpages = parse_amt(s, &s); if ( *s != ',' ) break; } while ( *s++ == ',' );}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);static char opt_dom0_ioports_disable[200] = "";string_param("dom0_ioports_disable", opt_dom0_ioports_disable);#if defined(__i386__)/* No ring-3 access in initial leaf page tables. */#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)#define L3_PROT (_PAGE_PRESENT)#elif defined(__x86_64__)/* Allow ring-3 access in long mode as guest cannot use ring 1 ... */#define BASE_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)#define L1_PROT (BASE_PROT|_PAGE_GUEST_KERNEL)/* ... except for compatibility mode guests. */#define COMPAT_L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)#define L2_PROT (BASE_PROT|_PAGE_DIRTY)#define L3_PROT (BASE_PROT|_PAGE_DIRTY)#define L4_PROT (BASE_PROT|_PAGE_DIRTY)#endif#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)#define round_pgdown(_p) ((_p)&PAGE_MASK)static struct page_info * __init alloc_chunk( struct domain *d, unsigned long max_pages){ struct page_info *page; unsigned int order; /* * Allocate up to 2MB at a time: It prevents allocating very large chunks * from DMA pools before the >4GB pool is fully depleted. */ if ( max_pages > (2UL << (20 - PAGE_SHIFT)) ) max_pages = 2UL << (20 - PAGE_SHIFT); order = get_order_from_pages(max_pages); if ( (max_pages & (max_pages-1)) != 0 ) order--; while ( (page = alloc_domheap_pages(d, order, 0)) == NULL ) if ( order-- == 0 ) break; return page;}static unsigned long __init compute_dom0_nr_pages(void){ unsigned long avail = avail_domheap_pages() + initial_images_nrpages(); /* * If domain 0 allocation isn't specified, reserve 1/16th of available * memory for things like DMA buffers. This reservation is clamped to * a maximum of 128MB. */ if ( dom0_nrpages == 0 ) { dom0_nrpages = avail; dom0_nrpages = min(dom0_nrpages / 16, 128L << (20 - PAGE_SHIFT)); dom0_nrpages = -dom0_nrpages; } /* Negative memory specification means "all memory - specified amount". */ if ( dom0_nrpages < 0 ) dom0_nrpages += avail; if ( dom0_min_nrpages < 0 ) dom0_min_nrpages += avail; if ( dom0_max_nrpages < 0 ) dom0_max_nrpages += avail; /* Clamp dom0 memory according to min/max limits and available memory. */ dom0_nrpages = max(dom0_nrpages, dom0_min_nrpages); dom0_nrpages = min(dom0_nrpages, dom0_max_nrpages); dom0_nrpages = min(dom0_nrpages, (long)avail); return dom0_nrpages;}static void __init process_dom0_ioports_disable(void){ unsigned long io_from, io_to; char *t, *s = opt_dom0_ioports_disable; const char *u; if ( *s == '\0' ) return; while ( (t = strsep(&s, ",")) != NULL ) { io_from = simple_strtoul(t, &u, 16); if ( u == t ) { parse_error: printk("Invalid ioport range <%s> " "in dom0_ioports_disable, skipping\n", t); continue; } if ( *u == '\0' ) io_to = io_from; else if ( *u == '-' ) io_to = simple_strtoul(u + 1, &u, 16); else goto parse_error; if ( (*u != '\0') || (io_to < io_from) || (io_to >= 65536) ) goto parse_error; printk("Disabling dom0 access to ioport range %04lx-%04lx\n", io_from, io_to); if ( ioports_deny_access(dom0, io_from, io_to) != 0 ) BUG(); }}int __init construct_dom0( struct domain *d, unsigned long _image_start, unsigned long image_len, unsigned long _initrd_start, unsigned long initrd_len, char *cmdline){ int i, rc, compatible, compat32, order, machine; struct cpu_user_regs *regs; unsigned long pfn, mfn; unsigned long nr_pages; unsigned long nr_pt_pages; unsigned long alloc_spfn; unsigned long alloc_epfn; unsigned long count; struct page_info *page = NULL; start_info_t *si; struct vcpu *v = d->vcpu[0]; unsigned long long value;#if defined(__i386__) char *image_start = (char *)_image_start; /* use lowmem mappings */ char *initrd_start = (char *)_initrd_start; /* use lowmem mappings */#elif defined(__x86_64__) char *image_start = __va(_image_start); char *initrd_start = __va(_initrd_start);#endif#if CONFIG_PAGING_LEVELS >= 4 l4_pgentry_t *l4tab = NULL, *l4start = NULL;#endif l3_pgentry_t *l3tab = NULL, *l3start = NULL; l2_pgentry_t *l2tab = NULL, *l2start = NULL; l1_pgentry_t *l1tab = NULL, *l1start = NULL; /* * This fully describes the memory layout of the initial domain. All * *_start address are page-aligned, except v_start (and v_end) which are * superpage-aligned. */ struct elf_binary elf; struct elf_dom_parms parms; unsigned long vkern_start; unsigned long vkern_end; unsigned long vinitrd_start; unsigned long vinitrd_end; unsigned long vphysmap_start; unsigned long vphysmap_end; unsigned long vstartinfo_start; unsigned long vstartinfo_end; unsigned long vstack_start; unsigned long vstack_end; unsigned long vpt_start; unsigned long vpt_end; unsigned long v_start; unsigned long v_end; /* Machine address of next candidate page-table page. */ unsigned long mpt_alloc; /* Sanity! */ BUG_ON(d->domain_id != 0); BUG_ON(d->vcpu[0] == NULL); BUG_ON(v->is_initialised); printk("*** LOADING DOMAIN 0 ***\n"); d->max_pages = ~0U; nr_pages = compute_dom0_nr_pages(); if ( (rc = elf_init(&elf, image_start, image_len)) != 0 ) return rc;#ifdef VERBOSE elf_set_verbose(&elf);#endif elf_parse_binary(&elf); if ( (rc = elf_xen_parse(&elf, &parms)) != 0 ) return rc; /* compatibility check */ compatible = 0; compat32 = 0; machine = elf_uval(&elf, elf.ehdr, e_machine); switch (CONFIG_PAGING_LEVELS) { case 3: /* x86_32p */ if (parms.pae == PAEKERN_bimodal) parms.pae = PAEKERN_extended_cr3; printk(" Xen kernel: 32-bit, PAE, lsb\n"); if (elf_32bit(&elf) && parms.pae && machine == EM_386) compatible = 1; break; case 4: /* x86_64 */ printk(" Xen kernel: 64-bit, lsb, compat32\n"); if (elf_32bit(&elf) && parms.pae == PAEKERN_bimodal) parms.pae = PAEKERN_extended_cr3; if (elf_32bit(&elf) && parms.pae && machine == EM_386) { compat32 = 1; compatible = 1; } if (elf_64bit(&elf) && machine == EM_X86_64) compatible = 1; break; } printk(" Dom0 kernel: %s%s, %s, paddr 0x%" PRIx64 " -> 0x%" PRIx64 "\n", elf_64bit(&elf) ? "64-bit" : "32-bit", parms.pae ? ", PAE" : "", elf_msb(&elf) ? "msb" : "lsb", elf.pstart, elf.pend); if ( elf.bsd_symtab_pstart ) printk(" Dom0 symbol map 0x%" PRIx64 " -> 0x%" PRIx64 "\n", elf.bsd_symtab_pstart, elf.bsd_symtab_pend); if ( !compatible ) { printk("Mismatch between Xen and DOM0 kernel\n"); return -EINVAL; }#if defined(__x86_64__) if ( compat32 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -