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

📄 domain.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
	return rc;}// remove following line if not privifying in memory//#define HAVE_PRIVIFY_MEMORY#ifndef HAVE_PRIVIFY_MEMORY#define	privify_memory(x,y) do {} while(0)#endifstatic void __init loaddomainelfimage(struct domain *d, struct elf_binary *elf,				      unsigned long phys_load_offset){	const elf_phdr *phdr;	int phnum, h, filesz, memsz;	unsigned long elfaddr, dom_mpaddr, dom_imva;	struct page_info *p;	phnum = elf_uval(elf, elf->ehdr, e_phnum);	for (h = 0; h < phnum; h++) {		phdr = elf_phdr_by_index(elf, h);		if (!elf_phdr_is_loadable(elf, phdr))		    continue;		filesz = elf_uval(elf, phdr, p_filesz);		memsz = elf_uval(elf, phdr, p_memsz);		elfaddr = (unsigned long) elf->image + elf_uval(elf, phdr, p_offset);		dom_mpaddr = elf_uval(elf, phdr, p_paddr);		dom_mpaddr += phys_load_offset;		while (memsz > 0) {			p = assign_new_domain_page(d,dom_mpaddr);			BUG_ON (unlikely(p == NULL));			dom_imva = __va_ul(page_to_maddr(p));			if (filesz > 0) {				if (filesz >= PAGE_SIZE)					copy_page((void *) dom_imva,					          (void *) elfaddr);				else {					// copy partial page					memcpy((void *) dom_imva,					       (void *) elfaddr, filesz);					// zero the rest of page					memset((void *) dom_imva+filesz, 0,					       PAGE_SIZE-filesz);				}//FIXME: This test for code seems to find a lot more than objdump -x does				if (elf_uval(elf, phdr, p_flags) & PF_X) {					privify_memory(dom_imva,PAGE_SIZE);					flush_icache_range(dom_imva,							   dom_imva+PAGE_SIZE);				}			}			else if (memsz > 0) {                                /* always zero out entire page */				clear_page((void *) dom_imva);			}			memsz -= PAGE_SIZE;			filesz -= PAGE_SIZE;			elfaddr += PAGE_SIZE;			dom_mpaddr += PAGE_SIZE;		}	}}static void __init calc_dom0_size(void){	unsigned long domheap_pages;	unsigned long p2m_pages;	unsigned long spare_hv_pages;	unsigned long max_dom0_size;	/* Estimate maximum memory we can safely allocate for dom0	 * by subtracting the p2m table allocation and a chunk of memory	 * for DMA and PCI mapping from the available domheap pages. The	 * chunk for DMA, PCI, etc., is a guestimate, as xen doesn't seem	 * to have a good idea of what those requirements might be ahead	 * of time, calculated at 128MB + 1MB per 4GB of system memory */	domheap_pages = avail_domheap_pages();	p2m_pages = domheap_pages / PTRS_PER_PTE;	spare_hv_pages = 8192 + (domheap_pages / 4096);	max_dom0_size = (domheap_pages - (p2m_pages + spare_hv_pages))			 * PAGE_SIZE;	printk("Maximum permitted dom0 size: %luMB\n",	       max_dom0_size / (1024*1024));	/* validate proposed dom0_size, fix up as needed */	if (dom0_size > max_dom0_size) {		printk("Reducing dom0 memory allocation from %luK to %luK "		       "to fit available memory\n",		       dom0_size / 1024, max_dom0_size / 1024);		dom0_size = max_dom0_size;	}	/* dom0_mem=0 can be passed in to give all available mem to dom0 */	if (dom0_size == 0) {		printk("Allocating all available memory to dom0\n");		dom0_size = max_dom0_size;	}	/* Check dom0 size.  */	if (dom0_size < 4 * 1024 * 1024) {		panic("dom0_mem is too small, boot aborted"			" (try e.g. dom0_mem=256M or dom0_mem=65536K)\n");	}	if (running_on_sim) {		dom0_size = 128*1024*1024; //FIXME: Should be configurable	}	/* no need to allocate pages for now	 * pages are allocated by map_new_domain_page() via loaddomainelfimage()	 */}/* * Domain 0 has direct access to all devices absolutely. However * the major point of this stub here, is to allow alloc_dom_mem * handled with order > 0 request. Dom0 requires that bit set to * allocate memory for other domains. */static void __init physdev_init_dom0(struct domain *d){	if (iomem_permit_access(d, 0UL, ~0UL))		BUG();	if (irqs_permit_access(d, 0, NR_IRQS-1))		BUG();	if (ioports_permit_access(d, 0, 0xffff))		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;	start_info_t *si;	dom0_vga_console_info_t *ci;	struct vcpu *v = d->vcpu[0];	unsigned long max_pages;	struct elf_binary elf;	struct elf_dom_parms parms;	unsigned long p_start;	unsigned long pkern_start;	unsigned long pkern_entry;	unsigned long pkern_end;	unsigned long pinitrd_start = 0;	unsigned long pstart_info;	unsigned long phys_load_offset;	struct page_info *start_info_page;	unsigned long bp_mpa;	struct ia64_boot_param *bp;//printk("construct_dom0: starting\n");	/* Sanity! */	BUG_ON(d != dom0);	BUG_ON(d->vcpu[0] == NULL);	BUG_ON(v->is_initialised);	printk("*** LOADING DOMAIN 0 ***\n");	calc_dom0_size();	max_pages = dom0_size / PAGE_SIZE;	d->max_pages = max_pages;	d->tot_pages = 0;	rc = elf_init(&elf, (void*)image_start, image_len);	if ( rc != 0 )	    return rc;#ifdef VERBOSE	elf_set_verbose(&elf);#endif	elf_parse_binary(&elf);	if (0 != (elf_xen_parse(&elf, &parms)))		return rc;	/*	 * We cannot rely on the load address in the ELF headers to	 * determine the meta physical address at which the image	 * is loaded.  Patch the address to match the real one, based	 * on xen_pstart	 */	phys_load_offset = xen_pstart - elf.pstart;	elf.pstart += phys_load_offset;	elf.pend += phys_load_offset;	parms.virt_kstart += phys_load_offset;	parms.virt_kend += phys_load_offset;	parms.virt_entry += phys_load_offset;	printk(" Dom0 kernel: %s, %s, paddr 0x%" PRIx64 " -> 0x%" PRIx64 "\n",	       elf_64bit(&elf) ? "64-bit" : "32-bit",	       elf_msb(&elf)   ? "msb"    : "lsb",	       elf.pstart, elf.pend);        if (!elf_64bit(&elf) ||	    elf_uval(&elf, elf.ehdr, e_machine) != EM_IA_64) {		printk("Incompatible kernel binary\n");		return -1;	}	p_start = parms.virt_base;	pkern_start = parms.virt_kstart;	pkern_end = parms.virt_kend;	pkern_entry = parms.virt_entry;//printk("p_start=%lx, pkern_start=%lx, pkern_end=%lx, pkern_entry=%lx\n",p_start,pkern_start,pkern_end,pkern_entry);	if ( (p_start & (PAGE_SIZE-1)) != 0 )	{	    printk("Initial guest OS must load to a page boundary.\n");	    return -EINVAL;	}	pstart_info = PAGE_ALIGN(pkern_end);	if(initrd_start && initrd_len){	    unsigned long offset;	    /* The next page aligned boundary after the start info.	       Note: EFI_PAGE_SHIFT = 12 <= PAGE_SHIFT */	    pinitrd_start = pstart_info + PAGE_SIZE;	    if ((pinitrd_start + initrd_len - phys_load_offset) >= dom0_size)		    panic("%s: not enough memory assigned to dom0", __func__);	    for (offset = 0; offset < initrd_len; offset += PAGE_SIZE) {		struct page_info *p;		p = assign_new_domain_page(d, pinitrd_start + offset);		if (p == NULL)		    panic("%s: can't allocate page for initrd image", __func__);		if (initrd_len < offset + PAGE_SIZE)		    memcpy(page_to_virt(p), (void*)(initrd_start + offset),		           initrd_len - offset);		else		    copy_page(page_to_virt(p), (void*)(initrd_start + offset));	    }	}	printk("METAPHYSICAL MEMORY ARRANGEMENT:\n"	       " Kernel image:  %lx->%lx\n"	       " Entry address: %lx\n"	       " Init. ramdisk: %lx len %lx\n"	       " Start info.:   %lx->%lx\n",	       pkern_start, pkern_end, pkern_entry, pinitrd_start, initrd_len,	       pstart_info, pstart_info + PAGE_SIZE);	if ( (pkern_end - pkern_start) > (max_pages * PAGE_SIZE) )	{	    printk("Initial guest OS requires too much space\n"	           "(%luMB is greater than %luMB limit)\n",	           (pkern_end-pkern_start)>>20,	           (max_pages <<PAGE_SHIFT)>>20);	    return -ENOMEM;	}	// if high 3 bits of pkern start are non-zero, error	// if pkern end is after end of metaphysical memory, error	//  (we should be able to deal with this... later)	/* Mask all upcalls... */	for ( i = 1; i < MAX_VIRT_CPUS; i++ )	    d->shared_info->vcpu_info[i].evtchn_upcall_mask = 1;	if (dom0_max_vcpus == 0)	    dom0_max_vcpus = MAX_VIRT_CPUS;	if (dom0_max_vcpus > num_online_cpus())	    dom0_max_vcpus = num_online_cpus();	if (dom0_max_vcpus > MAX_VIRT_CPUS)	    dom0_max_vcpus = MAX_VIRT_CPUS;		printk ("Dom0 max_vcpus=%d\n", dom0_max_vcpus);	for ( i = 1; i < dom0_max_vcpus; i++ )	    if (alloc_vcpu(d, i, i) == NULL)		panic("Cannot allocate dom0 vcpu %d\n", i);	/* Copy the OS image. */	loaddomainelfimage(d, &elf, phys_load_offset);	BUILD_BUG_ON(sizeof(start_info_t) + sizeof(dom0_vga_console_info_t) +	             sizeof(struct ia64_boot_param) > PAGE_SIZE);	/* Set up start info area. */	d->shared_info->arch.start_info_pfn = pstart_info >> PAGE_SHIFT;	start_info_page = assign_new_domain_page(d, pstart_info);	if (start_info_page == NULL)		panic("can't allocate start info page");	si = page_to_virt(start_info_page);	clear_page(si);	snprintf(si->magic, sizeof(si->magic), "xen-3.0-ia64");	si->nr_pages     = max_pages;	si->flags = SIF_INITDOMAIN|SIF_PRIVILEGED;	printk("Dom0: 0x%lx\n", (u64)dom0);	v->is_initialised = 1;	clear_bit(_VPF_down, &v->pause_flags);	/* Build firmware.	   Note: Linux kernel reserve memory used by start_info, so there is	   no need to remove it from MDT.  */	bp_mpa = pstart_info + sizeof(struct start_info);	rc = dom_fw_setup(d, bp_mpa, max_pages * PAGE_SIZE);	if (rc != 0)		return rc;	/* Fill boot param.  */	strlcpy((char *)si->cmd_line, dom0_command_line, sizeof(si->cmd_line));	bp = (struct ia64_boot_param *)((unsigned char *)si +	                                sizeof(start_info_t));	bp->command_line = pstart_info + offsetof (start_info_t, cmd_line);	/* We assume console has reached the last line!  */	bp->console_info.num_cols = ia64_boot_param->console_info.num_cols;	bp->console_info.num_rows = ia64_boot_param->console_info.num_rows;	bp->console_info.orig_x = 0;	bp->console_info.orig_y = bp->console_info.num_rows == 0 ?	                          0 : bp->console_info.num_rows - 1;	bp->initrd_start = pinitrd_start;	bp->initrd_size = ia64_boot_param->initrd_size;	ci = (dom0_vga_console_info_t *)((unsigned char *)si +			                 sizeof(start_info_t) +	                                 sizeof(struct ia64_boot_param));	if (fill_console_start_info(ci)) {		si->console.dom0.info_off = sizeof(start_info_t) +		                            sizeof(struct ia64_boot_param);		si->console.dom0.info_size = sizeof(dom0_vga_console_info_t);	}	vcpu_init_regs (v);	vcpu_regs(v)->r28 = bp_mpa;	vcpu_regs (v)->cr_iip = pkern_entry;	physdev_init_dom0(d);	return 0;}void machine_restart(unsigned int delay_millisecs){	mdelay(delay_millisecs);	console_start_sync();	if (running_on_sim)		printk ("machine_restart called.  spinning...\n");	else		(*efi.reset_system)(EFI_RESET_WARM,0,0,NULL);	while(1);}extern void cpu_halt(void);void machine_halt(void){	console_start_sync();#ifdef CONFIG_SMP	smp_send_stop();#endif	printk ("machine_halt called.  spinning...\n");	while(1);}void sync_vcpu_execstate(struct vcpu *v){//	__ia64_save_fpu(v->arch._thread.fph);	// FIXME SMP: Anything else needed here for SMP?}/* This function is taken from xen/arch/x86/domain.c */longarch_do_vcpu_op(int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg){	long rc = 0;	switch (cmd) {	case VCPUOP_register_runstate_memory_area:	{		struct vcpu_register_runstate_memory_area area;		struct vcpu_runstate_info runstate;		rc = -EFAULT;		if (copy_from_guest(&area, arg, 1))			break;		if (!guest_handle_okay(area.addr.h, 1))			break;		rc = 0;		runstate_guest(v) = area.addr.h;		if (v == current) {			__copy_to_guest(runstate_guest(v), &v->runstate, 1);		} else {			vcpu_runstate_get(v, &runstate);			__copy_to_guest(runstate_guest(v), &runstate, 1);		}		break;	}	default:		rc = -ENOSYS;		break;	}	return rc;}static void __init parse_dom0_mem(char *s){	dom0_size = parse_size_and_unit(s, NULL);}custom_param("dom0_mem", parse_dom0_mem);/* * Helper function for the optimization stuff handling the identity mapping * feature. */static inline unsigned longoptf_identity_mapping_cmd_to_flg(unsigned long cmd){	switch(cmd) {	case XEN_IA64_OPTF_IDENT_MAP_REG7:		return XEN_IA64_OPTF_IDENT_MAP_REG7_FLG;	case XEN_IA64_OPTF_IDENT_MAP_REG4:		return XEN_IA64_OPTF_IDENT_MAP_REG4_FLG;	case XEN_IA64_OPTF_IDENT_MAP_REG5:		return XEN_IA64_OPTF_IDENT_MAP_REG5_FLG;	default:		BUG();		return 0;	}	/* NOTREACHED */}static inline voidoptf_set_identity_mapping(unsigned long* mask, struct identity_mapping* im,			  struct xen_ia64_opt_feature* f){	unsigned long flag = optf_identity_mapping_cmd_to_flg(f->cmd);	if (f->on) {		*mask |= flag;		im->pgprot = f->pgprot;		im->key = f->key;	} else {		*mask &= ~flag;		im->pgprot = 0;		im->key = 0;	}}/* * Switch an optimization feature on/off. * The vcpu

⌨️ 快捷键说明

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