diff options
Diffstat (limited to 'tools/libxc/xc_dom_ia64.c')
-rw-r--r-- | tools/libxc/xc_dom_ia64.c | 106 |
1 files changed, 102 insertions, 4 deletions
diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c index a6d77c5a55..dfe27e6917 100644 --- a/tools/libxc/xc_dom_ia64.c +++ b/tools/libxc/xc_dom_ia64.c @@ -12,14 +12,20 @@ #include <stdlib.h> #include <string.h> #include <inttypes.h> +#include <assert.h> +#include <asm/kregs.h> #include <xen/xen.h> #include <xen/foreign/ia64.h> +#include <xen/io/protocols.h> #include "xg_private.h" #include "xc_dom.h" #include "xenctrl.h" +#include <asm/dom_fw_common.h> +#include "ia64/xc_dom_ia64_util.h" + /* ------------------------------------------------------------------------ */ static int alloc_magic_pages(struct xc_dom_image *dom) @@ -49,6 +55,13 @@ static int start_info_ia64(struct xc_dom_image *dom) start_info->console.domU.mfn = dom->console_pfn; start_info->console.domU.evtchn = dom->console_evtchn; + /* + * domain_start and domain_size are abused for arch_setup hypercall + * so that we need to clear them here. + */ + XEN_IA64_MEMMAP_INFO_NUM_PAGES(bp) = 0; + XEN_IA64_MEMMAP_INFO_PFN(bp) = 0; + if ( dom->ramdisk_blob ) { start_info->mod_start = dom->ramdisk_seg.vstart; @@ -77,6 +90,8 @@ static int shared_info_ia64(struct xc_dom_image *dom, void *ptr) for (i = 0; i < MAX_VIRT_CPUS; i++) shared_info->vcpu_info[i].evtchn_upcall_mask = 1; shared_info->arch.start_info_pfn = dom->start_info_pfn; + shared_info->arch.memmap_info_num_pages = 1; //XXX + shared_info->arch.memmap_info_pfn = dom->start_info_pfn - 1; return 0; } @@ -92,9 +107,10 @@ static int vcpu_ia64(struct xc_dom_image *dom, void *ptr) memset(ctxt, 0, sizeof(*ctxt)); ctxt->flags = 0; - ctxt->regs.psr = 0; /* all necessary bits filled by hypervisor */ + /* PSR is set according to SAL 3.2.4: AC, IC and BN are set. */ + ctxt->regs.psr = IA64_PSR_AC | IA64_PSR_IC | IA64_PSR_BN; ctxt->regs.ip = dom->parms.virt_entry; - ctxt->regs.cfm = (uint64_t) 1 << 63; + ctxt->regs.cfm = 1UL << 63; #ifdef __ia64__ /* FIXME */ ctxt->regs.ar.fpsr = xc_ia64_fpsr_default(); #endif @@ -107,6 +123,7 @@ static int vcpu_ia64(struct xc_dom_image *dom, void *ptr) static struct xc_dom_arch xc_dom_arch = { .guest_type = "xen-3.0-ia64", + .native_protocol = XEN_IO_PROTO_ABI_IA64, .page_shift = PAGE_SHIFT_IA64, .alloc_magic_pages = alloc_magic_pages, .start_info = start_info_ia64, @@ -116,6 +133,7 @@ static struct xc_dom_arch xc_dom_arch = { static struct xc_dom_arch xc_dom_arch_ia64be = { .guest_type = "xen-3.0-ia64be", + .native_protocol = XEN_IO_PROTO_ABI_IA64, .page_shift = PAGE_SHIFT_IA64, .alloc_magic_pages = alloc_magic_pages, .start_info = start_info_ia64, @@ -129,6 +147,8 @@ static void __init register_arch_hooks(void) xc_dom_register_arch_hooks(&xc_dom_arch_ia64be); } +#include "xc_efi.h" + int arch_setup_meminit(struct xc_dom_image *dom) { xen_pfn_t pfn; @@ -146,6 +166,67 @@ int arch_setup_meminit(struct xc_dom_image *dom) return rc; } +static int ia64_setup_memmap(struct xc_dom_image *dom) +{ + unsigned int page_size = XC_DOM_PAGE_SIZE(dom); + unsigned long memmap_info_num_pages; + unsigned long memmap_info_pfn; + xen_ia64_memmap_info_t* memmap_info; + unsigned int num_mds; + efi_memory_desc_t *md; + + char* start_info; + struct xen_ia64_boot_param* bp; + + /* setup memmap page */ + memmap_info_num_pages = 1; + memmap_info_pfn = dom->start_info_pfn - 1; + xc_dom_printf("%s: memmap: mfn 0x%" PRIpfn " pages 0x%lx\n", + __FUNCTION__, memmap_info_pfn, memmap_info_num_pages); + memmap_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid, + page_size * memmap_info_num_pages, + PROT_READ | PROT_WRITE, + memmap_info_pfn); + if (NULL == memmap_info) + return -1; + /* [0, total_pages) */ + memmap_info->efi_memdesc_size = sizeof(md[0]); + memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION; + num_mds = 0; + md = (efi_memory_desc_t*)&memmap_info->memdesc; + md[num_mds].type = EFI_CONVENTIONAL_MEMORY; + md[num_mds].pad = 0; + md[num_mds].phys_addr = 0; + md[num_mds].virt_addr = 0; + md[num_mds].num_pages = dom->total_pages << (PAGE_SHIFT - EFI_PAGE_SHIFT); + md[num_mds].attribute = EFI_MEMORY_WB; + num_mds++; + memmap_info->efi_memmap_size = num_mds * sizeof(md[0]); + munmap(memmap_info, page_size * memmap_info_num_pages); + assert(num_mds <= + (page_size * memmap_info_num_pages - + offsetof(typeof(*memmap_info), memdesc))/sizeof(*md)); + + /* + * kludge: we need to pass memmap_info page's pfn and other magic pages + * somehow. + * we use xen_ia64_boot_param::efi_memmap::{efi_memmap, efi_memmap_size} + * for this purpose + */ + start_info = xc_map_foreign_range(dom->guest_xc, dom->guest_domid, + page_size, + PROT_READ | PROT_WRITE, + dom->start_info_pfn); + if (NULL == start_info) + return -1; + bp = (struct xen_ia64_boot_param*)(start_info + sizeof(start_info_t)); + memset(bp, 0, sizeof(*bp)); + XEN_IA64_MEMMAP_INFO_NUM_PAGES(bp) = memmap_info_num_pages; + XEN_IA64_MEMMAP_INFO_PFN(bp) = memmap_info_pfn; + munmap(start_info, page_size); + return 0; +} + int arch_setup_bootearly(struct xc_dom_image *dom) { DECLARE_DOMCTL; @@ -153,6 +234,24 @@ int arch_setup_bootearly(struct xc_dom_image *dom) xc_dom_printf("%s: setup firmware\n", __FUNCTION__); + rc = ia64_setup_memmap(dom); + if (rc) + return rc; + + memset(&domctl, 0, sizeof(domctl)); + domctl.cmd = XEN_DOMCTL_arch_setup; + domctl.domain = dom->guest_domid; + domctl.u.arch_setup.flags = XEN_DOMAINSETUP_query; + rc = do_domctl(dom->guest_xc, &domctl); + if (rc) + return rc; + rc = xen_ia64_dom_fw_setup(dom, domctl.u.arch_setup.hypercall_imm, + (dom->start_info_pfn << PAGE_SHIFT) + + sizeof(start_info_t), + dom->total_pages << PAGE_SHIFT); + if (rc) + return rc; + memset(&domctl, 0, sizeof(domctl)); domctl.cmd = XEN_DOMCTL_arch_setup; domctl.domain = dom->guest_domid; @@ -160,8 +259,7 @@ int arch_setup_bootearly(struct xc_dom_image *dom) domctl.u.arch_setup.bp = (dom->start_info_pfn << PAGE_SHIFT) + sizeof(start_info_t); - /* 3 = start info page, xenstore page and console page */ - domctl.u.arch_setup.maxmem = (dom->total_pages - 3) << PAGE_SHIFT; + domctl.u.arch_setup.maxmem = dom->total_pages << PAGE_SHIFT; rc = do_domctl(dom->guest_xc, &domctl); return rc; } |