diff options
Diffstat (limited to 'tools/libxc/ia64/xc_ia64_hvm_build.c')
-rw-r--r-- | tools/libxc/ia64/xc_ia64_hvm_build.c | 1215 |
1 files changed, 0 insertions, 1215 deletions
diff --git a/tools/libxc/ia64/xc_ia64_hvm_build.c b/tools/libxc/ia64/xc_ia64_hvm_build.c deleted file mode 100644 index 3f9273fa0f..0000000000 --- a/tools/libxc/ia64/xc_ia64_hvm_build.c +++ /dev/null @@ -1,1215 +0,0 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <asm/kregs.h> -#include "xg_private.h" -#include "xenguest.h" -#include "xc_private.h" -#include "xc_elf.h" -#include "xc_efi.h" -#include <stdlib.h> -#include <unistd.h> -#include <assert.h> -#include <zlib.h> -#include "xen/arch-ia64.h" -#include <xen/hvm/ioreq.h> -#include <xen/hvm/params.h> - -static int -xc_ia64_copy_to_domain_pages(xc_interface *xch, uint32_t domid, void* src_page, - unsigned long dst_pfn, int nr_pages) -{ - // N.B. gva should be page aligned - int i; - - for (i = 0; i < nr_pages; i++) { - if (xc_copy_to_domain_page(xch, domid, dst_pfn + i, - src_page + (i << PAGE_SHIFT))) - return -1; - } - - return 0; -} - -#define HOB_SIGNATURE 0x3436474953424f48 // "HOBSIG64" -#define GFW_HOB_START ((4UL<<30)-(14UL<<20)) // 4G - 14M -#define GFW_HOB_SIZE (1UL<<20) // 1M - -typedef struct { - unsigned long signature; - unsigned int type; - unsigned int length; -} HOB_GENERIC_HEADER; - -/* - * INFO HOB is the first data data in one HOB list - * it contains the control information of the HOB list - */ -typedef struct { - HOB_GENERIC_HEADER header; - unsigned long length; // current length of hob - unsigned long cur_pos; // current poisiton of hob - unsigned long buf_size; // size of hob buffer -} HOB_INFO; - -typedef struct{ - unsigned long start; - unsigned long size; -} hob_mem_t; - -typedef enum { - HOB_TYPE_INFO=0, - HOB_TYPE_TERMINAL, - HOB_TYPE_MEM, - HOB_TYPE_PAL_BUS_GET_FEATURES_DATA, - HOB_TYPE_PAL_CACHE_SUMMARY, - HOB_TYPE_PAL_MEM_ATTRIB, - HOB_TYPE_PAL_CACHE_INFO, - HOB_TYPE_PAL_CACHE_PROT_INFO, - HOB_TYPE_PAL_DEBUG_INFO, - HOB_TYPE_PAL_FIXED_ADDR, - HOB_TYPE_PAL_FREQ_BASE, - HOB_TYPE_PAL_FREQ_RATIOS, - HOB_TYPE_PAL_HALT_INFO, - HOB_TYPE_PAL_PERF_MON_INFO, - HOB_TYPE_PAL_PROC_GET_FEATURES, - HOB_TYPE_PAL_PTCE_INFO, - HOB_TYPE_PAL_REGISTER_INFO, - HOB_TYPE_PAL_RSE_INFO, - HOB_TYPE_PAL_TEST_INFO, - HOB_TYPE_PAL_VM_SUMMARY, - HOB_TYPE_PAL_VM_INFO, - HOB_TYPE_PAL_VM_PAGE_SIZE, - HOB_TYPE_NR_VCPU, - HOB_TYPE_NVRAM, - HOB_TYPE_MAX -} hob_type_t; - -static int hob_init(void *buffer ,unsigned long buf_size); -static int add_pal_hob(void* hob_buf); -static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size); -static int add_vcpus_hob(void* hob_buf, unsigned long nr_vcpu); -static int add_nvram_hob(void* hob_buf, unsigned long nvram_addr); -static int build_hob(xc_interface *xch, - void* hob_buf, unsigned long hob_buf_size, - unsigned long dom_mem_size, unsigned long vcpus, - unsigned long nvram_addr); -static int load_hob(xc_interface *xch,uint32_t dom, void *hob_buf); - -static int -xc_ia64_build_hob(xc_interface *xch, uint32_t dom, - unsigned long memsize, unsigned long vcpus, - unsigned long nvram_addr) -{ - char *hob_buf; - - hob_buf = malloc(GFW_HOB_SIZE); - if (hob_buf == NULL) { - PERROR("Could not allocate hob"); - return -1; - } - - if (build_hob(xch, hob_buf, GFW_HOB_SIZE, memsize, vcpus, nvram_addr) < 0) { - free(hob_buf); - PERROR("Could not build hob"); - return -1; - } - - if (load_hob(xch, dom, hob_buf) < 0) { - free(hob_buf); - PERROR("Could not load hob"); - return -1; - } - free(hob_buf); - return 0; - -} - -static int -hob_init(void *buffer, unsigned long buf_size) -{ - HOB_INFO *phit; - HOB_GENERIC_HEADER *terminal; - - if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) { - // buffer too small - return -1; - } - - phit = (HOB_INFO*)buffer; - phit->header.signature = HOB_SIGNATURE; - phit->header.type = HOB_TYPE_INFO; - phit->header.length = sizeof(HOB_INFO); - phit->length = sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER); - phit->cur_pos = 0; - phit->buf_size = buf_size; - - terminal = (HOB_GENERIC_HEADER*)(buffer + sizeof(HOB_INFO)); - terminal->signature = HOB_SIGNATURE; - terminal->type = HOB_TYPE_TERMINAL; - terminal->length = sizeof(HOB_GENERIC_HEADER); - - return 0; -} - -/* - * Add a new HOB to the HOB List. - * - * hob_start - start address of hob buffer - * type - type of the hob to be added - * data - data of the hob to be added - * data_size - size of the data - */ -static int -hob_add(void* hob_start, int type, void* data, int data_size) -{ - HOB_INFO *phit; - HOB_GENERIC_HEADER *newhob, *tail; - - phit = (HOB_INFO*)hob_start; - - if (phit->length + data_size > phit->buf_size) { - // no space for new hob - return -1; - } - - //append new HOB - newhob = (HOB_GENERIC_HEADER*)(hob_start + phit->length - - sizeof(HOB_GENERIC_HEADER)); - newhob->signature = HOB_SIGNATURE; - newhob->type = type; - newhob->length = data_size + sizeof(HOB_GENERIC_HEADER); - memcpy((void*)newhob + sizeof(HOB_GENERIC_HEADER), data, data_size); - - // append terminal HOB - tail = (HOB_GENERIC_HEADER*)(hob_start + phit->length + data_size); - tail->signature = HOB_SIGNATURE; - tail->type = HOB_TYPE_TERMINAL; - tail->length = sizeof(HOB_GENERIC_HEADER); - - // adjust HOB list length - phit->length += sizeof(HOB_GENERIC_HEADER) + data_size; - - return 0; -} - -static int -get_hob_size(xc_interface *xch, void* hob_buf) -{ - HOB_INFO *phit = (HOB_INFO*)hob_buf; - - if (phit->header.signature != HOB_SIGNATURE) { - PERROR("xc_get_hob_size:Incorrect signature"); - return -1; - } - return phit->length; -} - -static int -build_hob(xc_interface *xch, void* hob_buf, unsigned long hob_buf_size, - unsigned long dom_mem_size, unsigned long vcpus, - unsigned long nvram_addr) -{ - //Init HOB List - if (hob_init(hob_buf, hob_buf_size) < 0) { - PERROR("buffer too small"); - goto err_out; - } - - if (add_mem_hob(hob_buf,dom_mem_size) < 0) { - PERROR("Add memory hob failed, buffer too small"); - goto err_out; - } - - if (add_vcpus_hob(hob_buf, vcpus) < 0) { - PERROR("Add NR_VCPU hob failed, buffer too small"); - goto err_out; - } - - if (add_pal_hob( hob_buf ) < 0) { - PERROR("Add PAL hob failed, buffer too small"); - goto err_out; - } - - if (add_nvram_hob( hob_buf, nvram_addr ) < 0) { - PERROR("Add nvram hob failed, buffer too small"); - goto err_out; - } - - return 0; - -err_out: - return -1; -} - -static int -load_hob(xc_interface *xch, uint32_t dom, void *hob_buf) -{ - // hob_buf should be page aligned - int hob_size; - int nr_pages; - - hob_size = get_hob_size(xch, hob_buf); - if (hob_size < 0) { - PERROR("Invalid hob data"); - return -1; - } - - if (hob_size > GFW_HOB_SIZE) { - PERROR("No enough memory for hob data"); - return -1; - } - - nr_pages = (hob_size + PAGE_SIZE -1) >> PAGE_SHIFT; - - return xc_ia64_copy_to_domain_pages(xch, dom, hob_buf, - GFW_HOB_START >> PAGE_SHIFT, nr_pages); -} - -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) -static int -add_mem_hob(void* hob_buf, unsigned long dom_mem_size) -{ - hob_mem_t memhob; - - // less than 3G accounting VGA RAM hole - memhob.start = 0; - if (dom_mem_size < VGA_IO_START) - memhob.size = dom_mem_size; - else - memhob.size = MIN(dom_mem_size + VGA_IO_SIZE, 0xC0000000); - - if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0) - return -1; - - if (dom_mem_size > 0xC0000000) { - // 4G ~ 4G+remain - memhob.start = 0x100000000; //4G - memhob.size = dom_mem_size + VGA_IO_SIZE - 0xC0000000; - if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0) - return -1; - } - return 0; -} - -static int -add_vcpus_hob(void* hob_buf, unsigned long vcpus) -{ - return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus)); -} - -static int -add_nvram_hob(void *hob_buf, unsigned long nvram_addr) -{ - return hob_add(hob_buf, HOB_TYPE_NVRAM, &nvram_addr, sizeof(nvram_addr)); -} - -static const unsigned char config_pal_bus_get_features_data[24] = { - 0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_cache_summary[16] = { - 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_mem_attrib[8] = { - 241, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_cache_info[152] = { - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12, - 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1, - 0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0, - 12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7, - 7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255, - 255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9, - 11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0 -}; - -static const unsigned char config_pal_cache_prot_info[200] = { - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, - 0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, - 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255, - 32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160, - 12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0 -}; - -static const unsigned char config_pal_debug_info[16] = { - 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_fixed_addr[8] = { - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_freq_base[8] = { - 109, 219, 182, 13, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_freq_ratios[24] = { - 11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4, - 0, 0, 0, 7, 0, 0, 0 -}; - -static const unsigned char config_pal_halt_info[64] = { - 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_perf_mon_info[136] = { - 12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_proc_get_features[104] = { - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, - 63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_ptce_info[24] = { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_register_info[64] = { - 255, 0, 47, 127, 17, 17, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 255, 208, 128, 238, 238, 0, 0, 248, 255, 255, 255, 255, 255, 0, 0, 7, 3, - 251, 3, 0, 0, 0, 0, 255, 7, 3, 0, 0, 0, 0, 0, 248, 252, 4, - 252, 255, 255, 255, 255, 2, 248, 252, 255, 255, 255, 255, 255 -}; - -static const unsigned char config_pal_rse_info[16] = { - 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_test_info[48] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_vm_summary[16] = { - 101, 18, 15, 2, 7, 7, 4, 2, 59, 18, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_vm_info[104] = { - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85, - 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0, - 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0 -}; - -static const unsigned char config_pal_vm_page_size[16] = { - 0, 112, 85, 21, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0 -}; - -typedef struct{ - hob_type_t type; - void* data; - unsigned long size; -} hob_batch_t; - -static const hob_batch_t hob_batch[]={ - { HOB_TYPE_PAL_BUS_GET_FEATURES_DATA, - &config_pal_bus_get_features_data, - sizeof(config_pal_bus_get_features_data) - }, - { HOB_TYPE_PAL_CACHE_SUMMARY, - &config_pal_cache_summary, - sizeof(config_pal_cache_summary) - }, - { HOB_TYPE_PAL_MEM_ATTRIB, - &config_pal_mem_attrib, - sizeof(config_pal_mem_attrib) - }, - { HOB_TYPE_PAL_CACHE_INFO, - &config_pal_cache_info, - sizeof(config_pal_cache_info) - }, - { HOB_TYPE_PAL_CACHE_PROT_INFO, - &config_pal_cache_prot_info, - sizeof(config_pal_cache_prot_info) - }, - { HOB_TYPE_PAL_DEBUG_INFO, - &config_pal_debug_info, - sizeof(config_pal_debug_info) - }, - { HOB_TYPE_PAL_FIXED_ADDR, - &config_pal_fixed_addr, - sizeof(config_pal_fixed_addr) - }, - { HOB_TYPE_PAL_FREQ_BASE, - &config_pal_freq_base, - sizeof(config_pal_freq_base) - }, - { HOB_TYPE_PAL_FREQ_RATIOS, - &config_pal_freq_ratios, - sizeof(config_pal_freq_ratios) - }, - { HOB_TYPE_PAL_HALT_INFO, - &config_pal_halt_info, - sizeof(config_pal_halt_info) - }, - { HOB_TYPE_PAL_PERF_MON_INFO, - &config_pal_perf_mon_info, - sizeof(config_pal_perf_mon_info) - }, - { HOB_TYPE_PAL_PROC_GET_FEATURES, - &config_pal_proc_get_features, - sizeof(config_pal_proc_get_features) - }, - { HOB_TYPE_PAL_PTCE_INFO, - &config_pal_ptce_info, - sizeof(config_pal_ptce_info) - }, - { HOB_TYPE_PAL_REGISTER_INFO, - &config_pal_register_info, - sizeof(config_pal_register_info) - }, - { HOB_TYPE_PAL_RSE_INFO, - &config_pal_rse_info, - sizeof(config_pal_rse_info) - }, - { HOB_TYPE_PAL_TEST_INFO, - &config_pal_test_info, - sizeof(config_pal_test_info) - }, - { HOB_TYPE_PAL_VM_SUMMARY, - &config_pal_vm_summary, - sizeof(config_pal_vm_summary) - }, - { HOB_TYPE_PAL_VM_INFO, - &config_pal_vm_info, - sizeof(config_pal_vm_info) - }, - { HOB_TYPE_PAL_VM_PAGE_SIZE, - &config_pal_vm_page_size, - sizeof(config_pal_vm_page_size) - }, -}; - -static int -add_pal_hob(void* hob_buf) -{ - int i; - for (i = 0; i < sizeof(hob_batch)/sizeof(hob_batch_t); i++) { - if (hob_add(hob_buf, hob_batch[i].type, hob_batch[i].data, - hob_batch[i].size) < 0) - return -1; - } - return 0; -} - -// The most significant bit of nvram file descriptor: -// 1: valid; 0: invalid -#define VALIDATE_NVRAM_FD(x) ((1UL<<(sizeof(x)*8 - 1)) | x) -#define IS_VALID_NVRAM_FD(x) ((uint64_t)x >> (sizeof(x)*8 - 1)) -static uint64_t -nvram_init(xc_interface *xch, const char *nvram_path) -{ - uint64_t fd = 0; - fd = open(nvram_path, O_CREAT|O_RDWR, 0644); - - if ( fd < 0 ) - { - PERROR("Nvram open failed at %s. Guest will boot without" - " nvram support!\n", nvram_path); - return -1; - } - - return VALIDATE_NVRAM_FD(fd); -} - -static int -copy_from_nvram_to_GFW(xc_interface *xch, uint32_t dom, int nvram_fd) -{ - unsigned int nr_pages = NVRAM_SIZE >> PAGE_SHIFT; - struct stat file_stat; - char buf[NVRAM_SIZE] = {0}; - - if ( fstat(nvram_fd, &file_stat) < 0 ) - { - PERROR("Cannot get Nvram file info! Guest will boot without " - "nvram support!\n"); - return -1; - } - - if ( 0 == file_stat.st_size ) - { - DPRINTF("Nvram file create successful!\n"); - return 0; - } - - if ( read(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE ) - { - PERROR("Load nvram fail. guest will boot without" - " nvram support!\n"); - return -1; - } - - return xc_ia64_copy_to_domain_pages(xch, dom, buf, - NVRAM_START >> PAGE_SHIFT, nr_pages); -} - - -/* - *Check is the address where NVRAM data located valid - */ -static int is_valid_address(xc_interface *xch, void *addr) -{ - struct nvram_save_addr *p = (struct nvram_save_addr *)addr; - - if ( p->signature == NVRAM_VALID_SIG ) - return 1; - else { - PERROR("Invalid nvram signature. Nvram save failed!"); - return 0; - } -} - -/* - * GFW use 4k page. when doing foreign map, we should 16k align - * the address and map one more page to guarantee all 64k nvram data - * can be got. - */ -static int -copy_from_GFW_to_nvram(xc_interface *xch, uint32_t dom, int nvram_fd) -{ - xen_pfn_t *pfn_list = NULL; - char *tmp_ptr = NULL; - unsigned int nr_pages = 0; - uint64_t addr_from_GFW_4k_align = 0; - uint32_t offset = 0; - uint64_t nvram_base_addr = 0; - char buf[NVRAM_SIZE] = {0}; - int i; - - // map one more page - nr_pages = (NVRAM_SIZE + PAGE_SIZE) >> PAGE_SHIFT; - pfn_list = (xen_pfn_t *)malloc(sizeof(xen_pfn_t) * nr_pages); - if ( NULL == pfn_list ) - { - PERROR("Cannot allocate memory for nvram save!"); - close(nvram_fd); - return -1; - } - - /* - * GFW allocate memory dynamicly to save nvram data - * and save address of the dynamic memory at NVRAM_START. - * To save nvram data to file, we must get the dynamic - * memory address first. - */ - pfn_list[0] = NVRAM_START >> PAGE_SHIFT; - tmp_ptr = (char *)xc_map_foreign_range(xch, dom, PAGE_SIZE, - PROT_READ | PROT_WRITE, pfn_list[0]); - - if ( NULL == tmp_ptr ) - { - PERROR("Cannot get nvram data from GFW!"); - free(pfn_list); - close(nvram_fd); - return -1; - } - - /* Check is NVRAM data vaild */ - if ( !is_valid_address(xch, tmp_ptr) ) - { - free(pfn_list); - munmap(tmp_ptr, PAGE_SIZE); - close(nvram_fd); - return -1; - } - - addr_from_GFW_4k_align = ((struct nvram_save_addr *)tmp_ptr)->addr; - munmap(tmp_ptr, PAGE_SIZE); - - // align address to 16k - offset = addr_from_GFW_4k_align % ( 16 * MEM_K ); - addr_from_GFW_4k_align = addr_from_GFW_4k_align - offset; - for ( i=0; i<nr_pages; i++ ) - pfn_list[i] = (addr_from_GFW_4k_align >> PAGE_SHIFT) + i; - - tmp_ptr = (char *)xc_map_foreign_pages(xch, dom, - PROT_READ | PROT_WRITE, - pfn_list, nr_pages); - if ( NULL == tmp_ptr ) - { - PERROR("Cannot get nvram data from GFW!"); - free(pfn_list); - close(nvram_fd); - return -1; - } - - // calculate nvram data base addrees - nvram_base_addr = (uint64_t)(tmp_ptr + offset); - - memcpy(buf, (void *)nvram_base_addr, NVRAM_SIZE); - free(pfn_list); - munmap(tmp_ptr, NVRAM_SIZE + PAGE_SIZE); - - lseek(nvram_fd, 0, SEEK_SET); - if ( write(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE ) - { - PERROR("Save to nvram fail!"); - return -1; - } - - close(nvram_fd); - - DPRINTF("Nvram save successful!\n"); - - return 0; -} - -int xc_ia64_save_to_nvram(xc_interface *xch, uint32_t dom) -{ - xc_dominfo_t info; - uint64_t nvram_fd = 0; - - if ( xc_domain_getinfo(xch, dom, 1, &info) != 1 ) - { - PERROR("Could not get info for domain"); - return -1; - } - - if ( !info.hvm ) - return 0; - - xc_get_hvm_param(xch, dom, HVM_PARAM_NVRAM_FD, &nvram_fd); - - if ( !IS_VALID_NVRAM_FD(nvram_fd) ) - PERROR("Nvram not initialized. Nvram save failed!"); - else - copy_from_GFW_to_nvram(xch, dom, (int)nvram_fd); - - // although save to nvram maybe fail, we don't return any error number - // to Xend. This is quite logical because damage of NVRAM on native would - // not block OS's executive path. Return error number will cause an - // exception of Xend and block XenU when it destroy. - return 0; -} - -#define NVRAM_DIR "/var/lib/xen/nvram/" -#define NVRAM_FILE_PREFIX "nvram_" - -int xc_ia64_nvram_init(xc_interface *xch, char *dom_name, uint32_t dom) -{ - uint64_t nvram_fd; - char nvram_path[PATH_MAX] = NVRAM_DIR; - - if ( access(nvram_path, R_OK|W_OK|X_OK) == -1 ) { - if ( errno != ENOENT ) - { - PERROR("Error stat'ing NVRAM dir %s.", nvram_path); - return -1; - } - if ( mkdir(nvram_path, 0755) == -1 ) - { - PERROR("Unable to create NVRAM store directory %s.", nvram_path); - return -1; - } - } - - if ( access(nvram_path, R_OK|W_OK|X_OK) == -1 ) { - errno = EACCES; - PERROR("No RWX permission to NVRAM store directory %s.", nvram_path); - return -1; - } - - if ( strlen(nvram_path) + strlen(NVRAM_FILE_PREFIX) + - strlen(dom_name) + 1 > sizeof(nvram_path) ) - { - PERROR("Nvram file path is too long!"); - return -1; - } - strcat(nvram_path, NVRAM_FILE_PREFIX); - strcat(nvram_path, dom_name); - - nvram_fd = nvram_init(xch, nvram_path); - if ( nvram_fd == (uint64_t)(-1) ) - { - xc_set_hvm_param(xch, dom, HVM_PARAM_NVRAM_FD, 0); - return -1; - } - - xc_set_hvm_param(xch, dom, HVM_PARAM_NVRAM_FD, nvram_fd); - return 0; -} - -#define GFW_PAGES (GFW_SIZE >> PAGE_SHIFT) -#define VGA_START_PAGE (VGA_IO_START >> PAGE_SHIFT) -#define VGA_END_PAGE ((VGA_IO_START + VGA_IO_SIZE) >> PAGE_SHIFT) - -static void -xc_ia64_setup_md(efi_memory_desc_t *md, - unsigned long start, unsigned long end) -{ - md->type = EFI_CONVENTIONAL_MEMORY; - md->pad = 0; - md->phys_addr = start; - md->virt_addr = 0; - md->num_pages = (end - start) >> EFI_PAGE_SHIFT; - md->attribute = EFI_MEMORY_WB; -} - -static inline unsigned long -min(unsigned long lhs, unsigned long rhs) -{ - return (lhs < rhs)? lhs: rhs; -} - -static int -xc_ia64_setup_memmap_info(xc_interface *xch, uint32_t dom, - 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(xch, 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."); - 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) { - xc_ia64_setup_md(md, VGA_IO_START + VGA_IO_SIZE, - min(MMIO_START, dom_memsize + VGA_IO_SIZE)); - 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 + VGA_IO_SIZE > MMIO_START) { - xc_ia64_setup_md(md, 4 * MEM_G, dom_memsize + VGA_IO_SIZE + (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 int -xc_ia64_setup_shared_info(xc_interface *xch, 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(xch, 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_populate_physmap_exact() called - * five times, to set parameter 'extent_order' to different value, this is - * convenient to allocate discontiguous memory with different size. - */ -static int -setup_guest(xc_interface *xch, uint32_t dom, unsigned long memsize, - char *image, unsigned long image_size) -{ - xen_pfn_t *pfn_list; - unsigned long dom_memsize = memsize; - unsigned long nr_pages = memsize >> 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; - unsigned long i; - unsigned long pfn; - 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."); - return -1; - } - - // - // Populate - // [0, VGA_IO_START) (VGA_IO_SIZE hole) - // [VGA_IO_START + VGA_IO_SIZE, MMIO_START) (1GB hole) - // [4GB, end) - // - i = 0; - for (pfn = 0; - pfn < MIN((dom_memsize >> PAGE_SHIFT), VGA_START_PAGE); - pfn++) - pfn_list[i++] = pfn; - for (pfn = VGA_END_PAGE; - pfn < (MIN(dom_memsize + VGA_IO_SIZE, MMIO_START) >> PAGE_SHIFT); - pfn++) - pfn_list[i++] = pfn; - for (pfn = ((4 * MEM_G) >> PAGE_SHIFT); - pfn < ((dom_memsize + VGA_IO_SIZE + 1 * MEM_G) >> PAGE_SHIFT); - pfn++) - pfn_list[i++] = pfn; - - rc = xc_domain_populate_physmap_exact(xch, dom, nr_pages, 0, 0, - &pfn_list[0]); - if (rc != 0) { - PERROR("Could not allocate normal memory for Vti guest."); - 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_populate_physmap_exact(xch, dom, GFW_PAGES, - 0, 0, &pfn_list[0]); - if (rc != 0) { - PERROR("Could not allocate GFW memory for Vti guest."); - 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_populate_physmap_exact(xch, 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."); - goto error_out; - } - - domctl.u.arch_setup.flags = 0; - domctl.u.arch_setup.bp = 0; - domctl.u.arch_setup.maxmem = GFW_START + GFW_SIZE; - if (dom_memsize + VGA_IO_SIZE > MMIO_START) - domctl.u.arch_setup.maxmem = dom_memsize + VGA_IO_SIZE + 1 * MEM_G; - domctl.cmd = XEN_DOMCTL_arch_setup; - domctl.domain = (domid_t)dom; - if (xc_domctl(xch, &domctl)) - goto error_out; - - // Load guest firmware - if (xc_ia64_copy_to_domain_pages(xch, 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(xch, &domctl) < 0) { - PERROR("Could not get info on domain"); - goto error_out; - } - - if (xc_ia64_setup_memmap_info(xch, dom, dom_memsize, - pfn_list, nr_special_pages, - memmap_info_pfn, memmap_info_num_pages)) { - PERROR("Could not build memmap info"); - goto error_out; - } - if (xc_ia64_setup_shared_info(xch, dom, - domctl.u.getdomaininfo.shared_info_frame, - memmap_info_pfn, memmap_info_num_pages)) { - PERROR("Could not setup shared_info"); - goto error_out; - } - - xc_get_hvm_param(xch, dom, HVM_PARAM_NVRAM_FD, &nvram_fd); - if ( !IS_VALID_NVRAM_FD(nvram_fd) ) - nvram_start = 0; - else if ( copy_from_nvram_to_GFW(xch, 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(xch, dom, dom_memsize, vcpus, nvram_start) < 0) { - PERROR("Could not build hob"); - goto error_out; - } - - // zero clear all special pages - for (i = 0; i < sizeof(special_pages) / sizeof(special_pages[0]); i++) { - xc_set_hvm_param(xch, dom, - special_pages[i].param, special_pages[i].pfn); - if (xc_clear_domain_page(xch, dom, special_pages[i].pfn)) - goto error_out; - } - - free(pfn_list); - return 0; - -error_out: - return -1; -} - -int -xc_hvm_build(xc_interface *xch, uint32_t domid, const struct xc_hvm_build_args *args) -{ - vcpu_guest_context_any_t st_ctxt_any; - vcpu_guest_context_t *ctxt = &st_ctxt_any.c; - char *image = NULL; - unsigned long image_size; - - image = xc_read_image(xch, args->image_file_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(xch, domid, (unsigned long)args->mem_size, image, - image_size) < 0) { - ERROR("Error constructing guest OS"); - goto error_out; - } - - free(image); - - memset(&st_ctxt_any, 0, sizeof(st_ctxt_any)); - ctxt->regs.ip = 0x80000000ffffffb0UL; - ctxt->regs.ar.fpsr = xc_ia64_fpsr_default(); - ctxt->regs.cr.itir = 14 << 2; - ctxt->regs.psr = IA64_PSR_AC | IA64_PSR_BN; - ctxt->regs.cr.dcr = 0; - ctxt->regs.cr.pta = 15 << 2; - return xc_vcpu_setcontext(xch, domid, 0, &st_ctxt_any); - -error_out: - free(image); - return -1; -} - -/* xc_hvm_build_target_mem: - * Create a domain for a pre-ballooned virtualized Linux, using - * files/filenames. If target < memsize, domain is created with - * memsize pages marked populate-on-demand, and with a PoD cache size - * of target. If target == memsize, pages are populated normally. - * - * XXX:PoD isn't supported yet so setting target does nothing. - */ -int xc_hvm_build_target_mem(xc_interface *xch, - uint32_t domid, - int memsize, - int target, - const char *image_name) -{ - struct xc_hvm_build_args args; - - args.mem_size = (uint64_t)memsize << 20; - args.mem_target = (uint64_t)target << 20; - args.image_file_name = image_name; - - return xc_hvm_build(xch, domid, &args); -} - -/* - * 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 */ - -int -xc_ia64_set_os_type(xc_interface *xch, 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(xch, &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(xch, &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(xch, &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: - */ |