📄 xc_ia64_hvm_build.c
字号:
unsigned long dom_memsize, /* in bytes */ unsigned long *pfns_special_pages, unsigned long nr_special_pages, unsigned long memmap_info_pfn, unsigned long memmap_info_num_pages){ xen_ia64_memmap_info_t* memmap_info; efi_memory_desc_t *md; uint64_t nr_mds; memmap_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE * memmap_info_num_pages, PROT_READ | PROT_WRITE, memmap_info_pfn); if (memmap_info == NULL) { PERROR("Could not map memmmap_info page.\n"); return -1; } memset(memmap_info, 0, PAGE_SIZE * memmap_info_num_pages); /* * [0, VGA_IO_START = 0xA0000) * [VGA_IO_START + VGA_IO_SIZE = 0xC0000, MMIO_START = 3GB) * [IO_PAGE_START (> 3GB), IO_PAGE_START + IO_PAGE_SIZE) * [STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE) * [BUFFER_IO_PAGE_START, BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE) * [BUFFER_PIO_PAGE_START, BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE) * [memmap_info_pfn << PAGE_SHIFT, * (memmap_info_pfn << PAGE_SHIFT) + PAGE_SIZE) * [GFW_START=4GB - GFW_SIZE, GFW_START + GFW_SIZE = 4GB) * [4GB, ...) */ md = (efi_memory_desc_t*)&memmap_info->memdesc; xc_ia64_setup_md(md, 0, min(VGA_IO_START, dom_memsize)); md++; if (dom_memsize > (VGA_IO_START + VGA_IO_SIZE)) { xc_ia64_setup_md(md, VGA_IO_START + VGA_IO_SIZE, min(MMIO_START, dom_memsize)); md++; } xc_ia64_setup_md(md, IO_PAGE_START, IO_PAGE_START + IO_PAGE_SIZE); md++; xc_ia64_setup_md(md, STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE); md++; xc_ia64_setup_md(md, BUFFER_IO_PAGE_START, BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE); md++; xc_ia64_setup_md(md, BUFFER_PIO_PAGE_START, BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE); md++; xc_ia64_setup_md(md, memmap_info_pfn << PAGE_SHIFT, (memmap_info_pfn << PAGE_SHIFT) + PAGE_SIZE * memmap_info_num_pages); md++; xc_ia64_setup_md(md, GFW_START, GFW_START + GFW_SIZE); md++; if (dom_memsize > MMIO_START) { xc_ia64_setup_md(md, 4 * MEM_G, dom_memsize + (1 * MEM_G)); md++; } nr_mds = md - (efi_memory_desc_t*)&memmap_info->memdesc; assert(nr_mds <= (PAGE_SIZE * memmap_info_num_pages - offsetof(typeof(*memmap_info), memdesc))/sizeof(*md)); memmap_info->efi_memmap_size = nr_mds * sizeof(*md); memmap_info->efi_memdesc_size = sizeof(*md); memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION; munmap(memmap_info, PAGE_SIZE * memmap_info_num_pages); return 0;}/* setup shared_info page */static intxc_ia64_setup_shared_info(int xc_handle, uint32_t dom, unsigned long shared_info_pfn, unsigned long memmap_info_pfn, unsigned long memmap_info_num_pages){ shared_info_t *shared_info; shared_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, shared_info_pfn); if (shared_info == NULL) { PERROR("Could not map shared_info"); return -1; } memset(shared_info, 0, sizeof(*shared_info)); shared_info->arch.memmap_info_num_pages = memmap_info_num_pages; shared_info->arch.memmap_info_pfn = memmap_info_pfn; munmap(shared_info, PAGE_SIZE); return 0;}/* * In this function, we will allocate memory and build P2M/M2P table for VTI * guest. Frist, a pfn list will be initialized discontiguous, normal memory * begins with 0, GFW memory and other five pages at their place defined in * xen/include/public/arch-ia64.h xc_domain_memory_populate_physmap() called * five times, to set parameter 'extent_order' to different value, this is * convenient to allocate discontiguous memory with different size. */static intsetup_guest(int xc_handle, uint32_t dom, unsigned long memsize, char *image, unsigned long image_size){ xen_pfn_t *pfn_list; unsigned long dom_memsize = memsize << 20; unsigned long nr_pages = memsize << (20 - PAGE_SHIFT); unsigned long vcpus; unsigned long nr_special_pages; unsigned long memmap_info_pfn; unsigned long memmap_info_num_pages; unsigned long nvram_start = NVRAM_START, nvram_fd = 0; int rc; long i; const struct hvm_special_page { int param; xen_pfn_t pfn; } special_pages[] = { // pfn-sorted array { HVM_PARAM_IOREQ_PFN, IO_PAGE_START >> PAGE_SHIFT}, { HVM_PARAM_STORE_PFN, STORE_PAGE_START >> PAGE_SHIFT}, { HVM_PARAM_BUFIOREQ_PFN, BUFFER_IO_PAGE_START >> PAGE_SHIFT}, { HVM_PARAM_BUFPIOREQ_PFN, BUFFER_PIO_PAGE_START >> PAGE_SHIFT}, }; DECLARE_DOMCTL; if ((image_size > 12 * MEM_M) || (image_size & (PAGE_SIZE - 1))) { PERROR("Guest firmware size is incorrect [%ld]?", image_size); return -1; } pfn_list = malloc(nr_pages * sizeof(xen_pfn_t)); if (pfn_list == NULL) { PERROR("Could not allocate memory.\n"); return -1; } // Allocate pfn for normal memory for (i = 0; i < dom_memsize >> PAGE_SHIFT; i++) pfn_list[i] = i; // If normal memory > 3G. Reserve 3G ~ 4G for MMIO, GFW and others. for (i = (MMIO_START >> PAGE_SHIFT); i < (dom_memsize >> PAGE_SHIFT); i++) pfn_list[i] += ((1 * MEM_G) >> PAGE_SHIFT); // Allocate memory for VTI guest, up to VGA hole from 0xA0000-0xC0000. rc = xc_domain_memory_populate_physmap(xc_handle, dom, (nr_pages > VGA_START_PAGE) ? VGA_START_PAGE : nr_pages, 0, 0, &pfn_list[0]); // We're not likely to attempt to create a domain with less than // 640k of memory, but test for completeness if (rc == 0 && nr_pages > VGA_END_PAGE) rc = xc_domain_memory_populate_physmap(xc_handle, dom, nr_pages - VGA_END_PAGE, 0, 0, &pfn_list[VGA_END_PAGE]); if (rc != 0) { PERROR("Could not allocate normal memory for Vti guest.\n"); goto error_out; } // We allocate additional pfn for GFW and other five pages, so // the pfn_list is not contiguous. Due to this we must support // old interface xc_ia64_get_pfn_list(). for (i = 0; i < GFW_PAGES; i++) pfn_list[i] = (GFW_START >> PAGE_SHIFT) + i; rc = xc_domain_memory_populate_physmap(xc_handle, dom, GFW_PAGES, 0, 0, &pfn_list[0]); if (rc != 0) { PERROR("Could not allocate GFW memory for Vti guest.\n"); goto error_out; } for (i = 0; i < sizeof(special_pages) / sizeof(special_pages[0]); i++) pfn_list[i] = special_pages[i].pfn; nr_special_pages = i; memmap_info_pfn = pfn_list[nr_special_pages - 1] + 1; memmap_info_num_pages = 1; pfn_list[nr_special_pages] = memmap_info_pfn; nr_special_pages++; rc = xc_domain_memory_populate_physmap(xc_handle, dom, nr_special_pages, 0, 0, &pfn_list[0]); if (rc != 0) { PERROR("Could not allocate IO page or store page or buffer io page.\n"); goto error_out; } domctl.u.arch_setup.flags = XEN_DOMAINSETUP_hvm_guest; domctl.u.arch_setup.bp = 0; domctl.u.arch_setup.maxmem = GFW_START + GFW_SIZE; if (dom_memsize > MMIO_START) domctl.u.arch_setup.maxmem = dom_memsize + 1 * MEM_G; domctl.cmd = XEN_DOMCTL_arch_setup; domctl.domain = (domid_t)dom; if (xc_domctl(xc_handle, &domctl)) goto error_out; // Load guest firmware if (xc_ia64_copy_to_domain_pages(xc_handle, dom, image, (GFW_START + GFW_SIZE - image_size) >> PAGE_SHIFT, image_size >> PAGE_SHIFT)) { PERROR("Could not load guest firmware into domain"); goto error_out; } domctl.cmd = XEN_DOMCTL_getdomaininfo; domctl.domain = (domid_t)dom; if (xc_domctl(xc_handle, &domctl) < 0) { PERROR("Could not get info on domain"); goto error_out; } if (xc_ia64_setup_memmap_info(xc_handle, dom, dom_memsize, pfn_list, nr_special_pages, memmap_info_pfn, memmap_info_num_pages)) { PERROR("Could not build memmap info\n"); goto error_out; } if (xc_ia64_setup_shared_info(xc_handle, dom, domctl.u.getdomaininfo.shared_info_frame, memmap_info_pfn, memmap_info_num_pages)) { PERROR("Could not setup shared_info\n"); goto error_out; } xc_get_hvm_param(xc_handle, dom, HVM_PARAM_NVRAM_FD, &nvram_fd); if ( !IS_VALID_NVRAM_FD(nvram_fd) ) nvram_start = 0; else if ( copy_from_nvram_to_GFW(xc_handle, dom, (int)nvram_fd ) == -1 ) { nvram_start = 0; close(nvram_fd); } vcpus = domctl.u.getdomaininfo.max_vcpu_id + 1; // Hand-off state passed to guest firmware if (xc_ia64_build_hob(xc_handle, dom, dom_memsize, vcpus, nvram_start) < 0) { PERROR("Could not build hob\n"); goto error_out; } // zero clear all special pages for (i = 0; i < sizeof(special_pages) / sizeof(special_pages[0]); i++) { xc_set_hvm_param(xc_handle, dom, special_pages[i].param, special_pages[i].pfn); if (xc_clear_domain_page(xc_handle, dom, special_pages[i].pfn)) goto error_out; } free(pfn_list); return 0;error_out: return -1;}intxc_hvm_build(int xc_handle, uint32_t domid, int memsize, const char *image_name){ vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt; char *image = NULL; unsigned long image_size; unsigned long nr_pages; nr_pages = xc_get_max_pages(xc_handle, domid); if (nr_pages < 0) { PERROR("Could not find total pages for domain"); goto error_out; } image = xc_read_image(image_name, &image_size); if (image == NULL) { PERROR("Could not read guest firmware image %s", image_name); goto error_out; } image_size = (image_size + PAGE_SIZE - 1) & PAGE_MASK; if (setup_guest(xc_handle, domid, (unsigned long)memsize, image, image_size) < 0) { ERROR("Error constructing guest OS"); goto error_out; } free(image); memset(ctxt, 0, sizeof(*ctxt)); ctxt->regs.ip = 0x80000000ffffffb0UL; ctxt->regs.ar.fpsr = xc_ia64_fpsr_default(); ctxt->regs.cr.isr = 1UL << 63; ctxt->regs.psr = IA64_PSR_AC | IA64_PSR_BN; ctxt->regs.cr.dcr = 0; ctxt->regs.cr.pta = 15 << 2; return xc_vcpu_setcontext(xc_handle, domid, 0, ctxt);error_out: free(image); return -1;}/* * From asm/pgtable.h */#define _PAGE_P_BIT 0#define _PAGE_A_BIT 5#define _PAGE_D_BIT 6#define _PAGE_P (1 << _PAGE_P_BIT) /* page present bit */#define _PAGE_A (1 << _PAGE_A_BIT) /* page accessed bit */#define _PAGE_D (1 << _PAGE_D_BIT) /* page dirty bit */#define _PAGE_MA_WB (0x0 << 2) /* write back memory attribute */#define _PAGE_MA_UC (0x4 << 2) /* uncacheable memory attribute */#define _PAGE_AR_RW (2 << 9) /* read & write */intxc_ia64_set_os_type(int xc_handle, char *guest_os_type, uint32_t dom){ DECLARE_DOMCTL; domctl.cmd = XEN_DOMCTL_set_opt_feature; domctl.domain = (domid_t)dom; if (!guest_os_type || !strlen(guest_os_type) || !strcmp("default", guest_os_type)) { /* Nothing */ return 0; } else if (!strcmp("windows", guest_os_type)) { DPRINTF("Enabling Windows guest OS optimizations\n"); /* Windows identity maps regions 4 & 5 */ domctl.u.set_opt_feature.optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG4; domctl.u.set_opt_feature.optf.on = XEN_IA64_OPTF_ON; domctl.u.set_opt_feature.optf.pgprot = (_PAGE_P | _PAGE_A | _PAGE_D | _PAGE_MA_WB | _PAGE_AR_RW); domctl.u.set_opt_feature.optf.key = 0; if (xc_domctl(xc_handle, &domctl)) PERROR("Failed to set region 4 identity mapping for Windows " "guest OS type.\n"); domctl.u.set_opt_feature.optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG5; domctl.u.set_opt_feature.optf.on = XEN_IA64_OPTF_ON; domctl.u.set_opt_feature.optf.pgprot = (_PAGE_P | _PAGE_A | _PAGE_D | _PAGE_MA_UC | _PAGE_AR_RW); domctl.u.set_opt_feature.optf.key = 0; if (xc_domctl(xc_handle, &domctl)) PERROR("Failed to set region 5 identity mapping for Windows " "guest OS type.\n"); return 0; } else if (!strcmp("linux", guest_os_type)) { DPRINTF("Enabling Linux guest OS optimizations\n"); /* Linux identity maps regions 7 */ domctl.u.set_opt_feature.optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG7; domctl.u.set_opt_feature.optf.on = XEN_IA64_OPTF_ON; domctl.u.set_opt_feature.optf.pgprot = (_PAGE_P | _PAGE_A | _PAGE_D | _PAGE_MA_WB | _PAGE_AR_RW); domctl.u.set_opt_feature.optf.key = 0; if (xc_domctl(xc_handle, &domctl)) PERROR("Failed to set region 7 identity mapping for Linux " "guest OS type.\n"); return 0; } DPRINTF("Unknown guest_os_type (%s), using defaults\n", guest_os_type); return 0;}/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -