1ebf5747bSPedro F. Giffuni /*- 2ebf5747bSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-NetBSD 3ebf5747bSPedro F. Giffuni * 41a9cdd37SRoger Pau Monné * Copyright (c) 2004 Christian Limpach. 51a9cdd37SRoger Pau Monné * Copyright (c) 2004-2006,2008 Kip Macy 69b4e54d3SRoger Pau Monné * Copyright (c) 2008 The NetBSD Foundation, Inc. 71a9cdd37SRoger Pau Monné * Copyright (c) 2013 Roger Pau Monné <roger.pau@citrix.com> 81a9cdd37SRoger Pau Monné * All rights reserved. 91a9cdd37SRoger Pau Monné * 101a9cdd37SRoger Pau Monné * Redistribution and use in source and binary forms, with or without 111a9cdd37SRoger Pau Monné * modification, are permitted provided that the following conditions 121a9cdd37SRoger Pau Monné * are met: 131a9cdd37SRoger Pau Monné * 1. Redistributions of source code must retain the above copyright 141a9cdd37SRoger Pau Monné * notice, this list of conditions and the following disclaimer. 151a9cdd37SRoger Pau Monné * 2. Redistributions in binary form must reproduce the above copyright 161a9cdd37SRoger Pau Monné * notice, this list of conditions and the following disclaimer in the 171a9cdd37SRoger Pau Monné * documentation and/or other materials provided with the distribution. 181a9cdd37SRoger Pau Monné * 191a9cdd37SRoger Pau Monné * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND 201a9cdd37SRoger Pau Monné * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 211a9cdd37SRoger Pau Monné * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 221a9cdd37SRoger Pau Monné * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 231a9cdd37SRoger Pau Monné * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 241a9cdd37SRoger Pau Monné * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 251a9cdd37SRoger Pau Monné * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 261a9cdd37SRoger Pau Monné * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 271a9cdd37SRoger Pau Monné * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 281a9cdd37SRoger Pau Monné * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 291a9cdd37SRoger Pau Monné * SUCH DAMAGE. 301a9cdd37SRoger Pau Monné */ 311a9cdd37SRoger Pau Monné 321a9cdd37SRoger Pau Monné #include <sys/cdefs.h> 331a9cdd37SRoger Pau Monné __FBSDID("$FreeBSD$"); 341a9cdd37SRoger Pau Monné 35c98a2727SRoger Pau Monné #include "opt_ddb.h" 36721555e7SZbigniew Bodek #include "opt_kstack_pages.h" 37c98a2727SRoger Pau Monné 381a9cdd37SRoger Pau Monné #include <sys/param.h> 391a9cdd37SRoger Pau Monné #include <sys/bus.h> 401a9cdd37SRoger Pau Monné #include <sys/kernel.h> 411a9cdd37SRoger Pau Monné #include <sys/reboot.h> 421a9cdd37SRoger Pau Monné #include <sys/systm.h> 43079f7ef8SRoger Pau Monné #include <sys/malloc.h> 44c98a2727SRoger Pau Monné #include <sys/linker.h> 451a9cdd37SRoger Pau Monné #include <sys/lock.h> 461a9cdd37SRoger Pau Monné #include <sys/rwlock.h> 47aa389b4fSRoger Pau Monné #include <sys/boot.h> 4897baeefdSRoger Pau Monné #include <sys/ctype.h> 49079f7ef8SRoger Pau Monné #include <sys/mutex.h> 50079f7ef8SRoger Pau Monné #include <sys/smp.h> 51*a2495c36SRoger Pau Monné #include <sys/efi.h> 521a9cdd37SRoger Pau Monné 531a9cdd37SRoger Pau Monné #include <vm/vm.h> 541a9cdd37SRoger Pau Monné #include <vm/vm_extern.h> 551a9cdd37SRoger Pau Monné #include <vm/vm_kern.h> 561a9cdd37SRoger Pau Monné #include <vm/vm_page.h> 571a9cdd37SRoger Pau Monné #include <vm/vm_map.h> 581a9cdd37SRoger Pau Monné #include <vm/vm_object.h> 591a9cdd37SRoger Pau Monné #include <vm/vm_pager.h> 601a9cdd37SRoger Pau Monné #include <vm/vm_param.h> 611a9cdd37SRoger Pau Monné 62b0663c33SRoger Pau Monné #include <machine/_inttypes.h> 63fae92773SJohn Baldwin #include <machine/intr_machdep.h> 64fae92773SJohn Baldwin #include <x86/apicvar.h> 6597baeefdSRoger Pau Monné #include <x86/init.h> 661e69553eSRoger Pau Monné #include <machine/pc/bios.h> 67079f7ef8SRoger Pau Monné #include <machine/smp.h> 6844e06d15SRoger Pau Monné #include <machine/intr_machdep.h> 69*a2495c36SRoger Pau Monné #include <machine/md_var.h> 70ca49b334SRoger Pau Monné #include <machine/metadata.h> 7197baeefdSRoger Pau Monné 721a9cdd37SRoger Pau Monné #include <xen/xen-os.h> 73b0663c33SRoger Pau Monné #include <xen/hvm.h> 741a9cdd37SRoger Pau Monné #include <xen/hypervisor.h> 75b7df74eeSWarner Losh #include <xen/xenstore/xenstorevar.h> 76842471b3SRoger Pau Monné #include <xen/xen_pv.h> 7744e06d15SRoger Pau Monné #include <xen/xen_msi.h> 781a9cdd37SRoger Pau Monné 79b0663c33SRoger Pau Monné #include <xen/interface/arch-x86/hvm/start_info.h> 80079f7ef8SRoger Pau Monné #include <xen/interface/vcpu.h> 81079f7ef8SRoger Pau Monné 825f05c794SRoger Pau Monné #include <dev/xen/timer/timer.h> 835f05c794SRoger Pau Monné 84c98a2727SRoger Pau Monné #ifdef DDB 85c98a2727SRoger Pau Monné #include <ddb/ddb.h> 86c98a2727SRoger Pau Monné #endif 87c98a2727SRoger Pau Monné 881a9cdd37SRoger Pau Monné /* Native initial function */ 891a9cdd37SRoger Pau Monné extern u_int64_t hammer_time(u_int64_t, u_int64_t); 901a9cdd37SRoger Pau Monné /* Xen initial function */ 91b0663c33SRoger Pau Monné uint64_t hammer_time_xen_legacy(start_info_t *, uint64_t); 92b0663c33SRoger Pau Monné uint64_t hammer_time_xen(vm_paddr_t); 931a9cdd37SRoger Pau Monné 941e69553eSRoger Pau Monné #define MAX_E820_ENTRIES 128 951e69553eSRoger Pau Monné 9697baeefdSRoger Pau Monné /*--------------------------- Forward Declarations ---------------------------*/ 97b0663c33SRoger Pau Monné static caddr_t xen_legacy_pvh_parse_preload_data(uint64_t); 98b0663c33SRoger Pau Monné static caddr_t xen_pvh_parse_preload_data(uint64_t); 99b0663c33SRoger Pau Monné static void xen_pvh_parse_memmap(caddr_t, vm_paddr_t *, int *); 10097baeefdSRoger Pau Monné 101079f7ef8SRoger Pau Monné #ifdef SMP 102079f7ef8SRoger Pau Monné static int xen_pv_start_all_aps(void); 103079f7ef8SRoger Pau Monné #endif 104079f7ef8SRoger Pau Monné 105079f7ef8SRoger Pau Monné /*---------------------------- Extern Declarations ---------------------------*/ 106079f7ef8SRoger Pau Monné #ifdef SMP 107079f7ef8SRoger Pau Monné /* Variables used by amd64 mp_machdep to start APs */ 108079f7ef8SRoger Pau Monné extern char *doublefault_stack; 109b345111bSMateusz Guzik extern char *mce_stack; 110079f7ef8SRoger Pau Monné extern char *nmi_stack; 11192849603SRoger Pau Monné extern char *dbg_stack; 112079f7ef8SRoger Pau Monné #endif 113079f7ef8SRoger Pau Monné 114c98a2727SRoger Pau Monné /* 115c98a2727SRoger Pau Monné * Placed by the linker at the end of the bss section, which is the last 116c98a2727SRoger Pau Monné * section loaded by Xen before loading the symtab and strtab. 117c98a2727SRoger Pau Monné */ 118c98a2727SRoger Pau Monné extern uint32_t end; 119c98a2727SRoger Pau Monné 12097baeefdSRoger Pau Monné /*-------------------------------- Global Data -------------------------------*/ 12197baeefdSRoger Pau Monné /* Xen init_ops implementation. */ 122b0663c33SRoger Pau Monné struct init_ops xen_legacy_init_ops = { 123b0663c33SRoger Pau Monné .parse_preload_data = xen_legacy_pvh_parse_preload_data, 1245f05c794SRoger Pau Monné .early_clock_source_init = xen_clock_init, 1255f05c794SRoger Pau Monné .early_delay = xen_delay, 126b0663c33SRoger Pau Monné .parse_memmap = xen_pvh_parse_memmap, 127079f7ef8SRoger Pau Monné #ifdef SMP 128079f7ef8SRoger Pau Monné .start_all_aps = xen_pv_start_all_aps, 129079f7ef8SRoger Pau Monné #endif 13044e06d15SRoger Pau Monné .msi_init = xen_msi_init, 13197baeefdSRoger Pau Monné }; 13297baeefdSRoger Pau Monné 133b0663c33SRoger Pau Monné struct init_ops xen_pvh_init_ops = { 134b0663c33SRoger Pau Monné .parse_preload_data = xen_pvh_parse_preload_data, 135b0663c33SRoger Pau Monné .early_clock_source_init = xen_clock_init, 136b0663c33SRoger Pau Monné .early_delay = xen_delay, 137b0663c33SRoger Pau Monné .parse_memmap = xen_pvh_parse_memmap, 138b0663c33SRoger Pau Monné #ifdef SMP 139b0663c33SRoger Pau Monné .mp_bootaddress = mp_bootaddress, 140b0663c33SRoger Pau Monné .start_all_aps = native_start_all_aps, 141b0663c33SRoger Pau Monné #endif 142b0663c33SRoger Pau Monné .msi_init = msi_init, 143b0663c33SRoger Pau Monné }; 144b0663c33SRoger Pau Monné 1451e69553eSRoger Pau Monné static struct bios_smap xen_smap[MAX_E820_ENTRIES]; 1461e69553eSRoger Pau Monné 147cfa0b7b8SRoger Pau Monné static start_info_t *legacy_start_info; 148b0663c33SRoger Pau Monné static struct hvm_start_info *start_info; 149cfa0b7b8SRoger Pau Monné 150cfa0b7b8SRoger Pau Monné /*----------------------- Legacy PVH start_info accessors --------------------*/ 151cfa0b7b8SRoger Pau Monné static vm_paddr_t 152cfa0b7b8SRoger Pau Monné legacy_get_xenstore_mfn(void) 153cfa0b7b8SRoger Pau Monné { 154cfa0b7b8SRoger Pau Monné 155cfa0b7b8SRoger Pau Monné return (legacy_start_info->store_mfn); 156cfa0b7b8SRoger Pau Monné } 157cfa0b7b8SRoger Pau Monné 158cfa0b7b8SRoger Pau Monné static evtchn_port_t 159cfa0b7b8SRoger Pau Monné legacy_get_xenstore_evtchn(void) 160cfa0b7b8SRoger Pau Monné { 161cfa0b7b8SRoger Pau Monné 162cfa0b7b8SRoger Pau Monné return (legacy_start_info->store_evtchn); 163cfa0b7b8SRoger Pau Monné } 164cfa0b7b8SRoger Pau Monné 165cfa0b7b8SRoger Pau Monné static vm_paddr_t 166cfa0b7b8SRoger Pau Monné legacy_get_console_mfn(void) 167cfa0b7b8SRoger Pau Monné { 168cfa0b7b8SRoger Pau Monné 169cfa0b7b8SRoger Pau Monné return (legacy_start_info->console.domU.mfn); 170cfa0b7b8SRoger Pau Monné } 171cfa0b7b8SRoger Pau Monné 172cfa0b7b8SRoger Pau Monné static evtchn_port_t 173cfa0b7b8SRoger Pau Monné legacy_get_console_evtchn(void) 174cfa0b7b8SRoger Pau Monné { 175cfa0b7b8SRoger Pau Monné 176cfa0b7b8SRoger Pau Monné return (legacy_start_info->console.domU.evtchn); 177cfa0b7b8SRoger Pau Monné } 178cfa0b7b8SRoger Pau Monné 179cfa0b7b8SRoger Pau Monné static uint32_t 180cfa0b7b8SRoger Pau Monné legacy_get_start_flags(void) 181cfa0b7b8SRoger Pau Monné { 182cfa0b7b8SRoger Pau Monné 183cfa0b7b8SRoger Pau Monné return (legacy_start_info->flags); 184cfa0b7b8SRoger Pau Monné } 185cfa0b7b8SRoger Pau Monné 186cfa0b7b8SRoger Pau Monné struct hypervisor_info legacy_info = { 187cfa0b7b8SRoger Pau Monné .get_xenstore_mfn = legacy_get_xenstore_mfn, 188cfa0b7b8SRoger Pau Monné .get_xenstore_evtchn = legacy_get_xenstore_evtchn, 189cfa0b7b8SRoger Pau Monné .get_console_mfn = legacy_get_console_mfn, 190cfa0b7b8SRoger Pau Monné .get_console_evtchn = legacy_get_console_evtchn, 191cfa0b7b8SRoger Pau Monné .get_start_flags = legacy_get_start_flags, 192cfa0b7b8SRoger Pau Monné }; 193cfa0b7b8SRoger Pau Monné 19497baeefdSRoger Pau Monné /*-------------------------------- Xen PV init -------------------------------*/ 1951a9cdd37SRoger Pau Monné /* 196cfa0b7b8SRoger Pau Monné * First function called by the Xen legacy PVH boot sequence. 1971a9cdd37SRoger Pau Monné * 1981a9cdd37SRoger Pau Monné * Set some Xen global variables and prepare the environment so it is 1991a9cdd37SRoger Pau Monné * as similar as possible to what native FreeBSD init function expects. 2001a9cdd37SRoger Pau Monné */ 2011a9cdd37SRoger Pau Monné uint64_t 202b0663c33SRoger Pau Monné hammer_time_xen_legacy(start_info_t *si, uint64_t xenstack) 2031a9cdd37SRoger Pau Monné { 2041a9cdd37SRoger Pau Monné uint64_t physfree; 2051a9cdd37SRoger Pau Monné uint64_t *PT4 = (u_int64_t *)xenstack; 2061a9cdd37SRoger Pau Monné uint64_t *PT3 = (u_int64_t *)(xenstack + PAGE_SIZE); 2071a9cdd37SRoger Pau Monné uint64_t *PT2 = (u_int64_t *)(xenstack + 2 * PAGE_SIZE); 2081a9cdd37SRoger Pau Monné int i; 209ddbc1b43SRoger Pau Monné char *kenv; 2101a9cdd37SRoger Pau Monné 2111a9cdd37SRoger Pau Monné xen_domain_type = XEN_PV_DOMAIN; 2121a9cdd37SRoger Pau Monné vm_guest = VM_GUEST_XEN; 2131a9cdd37SRoger Pau Monné 2141a9cdd37SRoger Pau Monné if ((si == NULL) || (xenstack == 0)) { 215c203fa69SRoger Pau Monné xc_printf("ERROR: invalid start_info or xen stack, halting\n"); 2161a9cdd37SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 2171a9cdd37SRoger Pau Monné } 2181a9cdd37SRoger Pau Monné 219c203fa69SRoger Pau Monné xc_printf("FreeBSD PVH running on %s\n", si->magic); 220c203fa69SRoger Pau Monné 2211a9cdd37SRoger Pau Monné /* We use 3 pages of xen stack for the boot pagetables */ 2221a9cdd37SRoger Pau Monné physfree = xenstack + 3 * PAGE_SIZE - KERNBASE; 2231a9cdd37SRoger Pau Monné 2241a9cdd37SRoger Pau Monné /* Setup Xen global variables */ 225cfa0b7b8SRoger Pau Monné legacy_start_info = si; 2261a9cdd37SRoger Pau Monné HYPERVISOR_shared_info = 2271a9cdd37SRoger Pau Monné (shared_info_t *)(si->shared_info + KERNBASE); 2281a9cdd37SRoger Pau Monné 2291a9cdd37SRoger Pau Monné /* 2301a9cdd37SRoger Pau Monné * Use the stack Xen gives us to build the page tables 2311a9cdd37SRoger Pau Monné * as native FreeBSD expects to find them (created 2321a9cdd37SRoger Pau Monné * by the boot trampoline). 2331a9cdd37SRoger Pau Monné */ 2341a9cdd37SRoger Pau Monné for (i = 0; i < (PAGE_SIZE / sizeof(uint64_t)); i++) { 2355f35f84fSRoger Pau Monné /* 2365f35f84fSRoger Pau Monné * Each slot of the level 4 pages points 2375f35f84fSRoger Pau Monné * to the same level 3 page 2385f35f84fSRoger Pau Monné */ 2391a9cdd37SRoger Pau Monné PT4[i] = ((uint64_t)&PT3[0]) - KERNBASE; 2401a9cdd37SRoger Pau Monné PT4[i] |= PG_V | PG_RW | PG_U; 2411a9cdd37SRoger Pau Monné 2425f35f84fSRoger Pau Monné /* 2435f35f84fSRoger Pau Monné * Each slot of the level 3 pages points 2445f35f84fSRoger Pau Monné * to the same level 2 page 2455f35f84fSRoger Pau Monné */ 2461a9cdd37SRoger Pau Monné PT3[i] = ((uint64_t)&PT2[0]) - KERNBASE; 2471a9cdd37SRoger Pau Monné PT3[i] |= PG_V | PG_RW | PG_U; 2481a9cdd37SRoger Pau Monné 2495f35f84fSRoger Pau Monné /* 2505f35f84fSRoger Pau Monné * The level 2 page slots are mapped with 2515f35f84fSRoger Pau Monné * 2MB pages for 1GB. 2525f35f84fSRoger Pau Monné */ 2531a9cdd37SRoger Pau Monné PT2[i] = i * (2 * 1024 * 1024); 2541a9cdd37SRoger Pau Monné PT2[i] |= PG_V | PG_RW | PG_PS | PG_U; 2551a9cdd37SRoger Pau Monné } 2561a9cdd37SRoger Pau Monné load_cr3(((uint64_t)&PT4[0]) - KERNBASE); 2571a9cdd37SRoger Pau Monné 258ddbc1b43SRoger Pau Monné /* 259ddbc1b43SRoger Pau Monné * Init an empty static kenv using a free page. The contents will be 260ddbc1b43SRoger Pau Monné * filled from the parse_preload_data hook. 261ddbc1b43SRoger Pau Monné */ 262ddbc1b43SRoger Pau Monné kenv = (void *)(physfree + KERNBASE); 263ddbc1b43SRoger Pau Monné physfree += PAGE_SIZE; 2643f102f58SMateusz Guzik bzero_early(kenv, PAGE_SIZE); 265ddbc1b43SRoger Pau Monné init_static_kenv(kenv, PAGE_SIZE); 266ddbc1b43SRoger Pau Monné 26797baeefdSRoger Pau Monné /* Set the hooks for early functions that diverge from bare metal */ 268b0663c33SRoger Pau Monné init_ops = xen_legacy_init_ops; 269842471b3SRoger Pau Monné apic_ops = xen_apic_ops; 270cfa0b7b8SRoger Pau Monné hypervisor_info = legacy_info; 27197baeefdSRoger Pau Monné 2721a9cdd37SRoger Pau Monné /* Now we can jump into the native init function */ 2731a9cdd37SRoger Pau Monné return (hammer_time(0, physfree)); 2741a9cdd37SRoger Pau Monné } 27597baeefdSRoger Pau Monné 276b0663c33SRoger Pau Monné uint64_t 277b0663c33SRoger Pau Monné hammer_time_xen(vm_paddr_t start_info_paddr) 278b0663c33SRoger Pau Monné { 279b0663c33SRoger Pau Monné struct hvm_modlist_entry *mod; 280b0663c33SRoger Pau Monné struct xen_add_to_physmap xatp; 281b0663c33SRoger Pau Monné uint64_t physfree; 282b0663c33SRoger Pau Monné char *kenv; 283b0663c33SRoger Pau Monné int rc; 284b0663c33SRoger Pau Monné 285b0663c33SRoger Pau Monné xen_domain_type = XEN_HVM_DOMAIN; 286b0663c33SRoger Pau Monné vm_guest = VM_GUEST_XEN; 287b0663c33SRoger Pau Monné 288b0663c33SRoger Pau Monné rc = xen_hvm_init_hypercall_stubs(XEN_HVM_INIT_EARLY); 289b0663c33SRoger Pau Monné if (rc) { 290b0663c33SRoger Pau Monné xc_printf("ERROR: failed to initialize hypercall page: %d\n", 291b0663c33SRoger Pau Monné rc); 292b0663c33SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 293b0663c33SRoger Pau Monné } 294b0663c33SRoger Pau Monné 295b0663c33SRoger Pau Monné start_info = (struct hvm_start_info *)(start_info_paddr + KERNBASE); 296b0663c33SRoger Pau Monné if (start_info->magic != XEN_HVM_START_MAGIC_VALUE) { 297b0663c33SRoger Pau Monné xc_printf("Unknown magic value in start_info struct: %#x\n", 298b0663c33SRoger Pau Monné start_info->magic); 299b0663c33SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 300b0663c33SRoger Pau Monné } 301b0663c33SRoger Pau Monné 302b0663c33SRoger Pau Monné /* 303b0663c33SRoger Pau Monné * The hvm_start_into structure is always appended after loading 304b0663c33SRoger Pau Monné * the kernel and modules. 305b0663c33SRoger Pau Monné */ 306b0663c33SRoger Pau Monné physfree = roundup2(start_info_paddr + PAGE_SIZE, PAGE_SIZE); 307b0663c33SRoger Pau Monné 308b0663c33SRoger Pau Monné xatp.domid = DOMID_SELF; 309b0663c33SRoger Pau Monné xatp.idx = 0; 310b0663c33SRoger Pau Monné xatp.space = XENMAPSPACE_shared_info; 311b0663c33SRoger Pau Monné xatp.gpfn = atop(physfree); 312b0663c33SRoger Pau Monné if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) { 313b0663c33SRoger Pau Monné xc_printf("ERROR: failed to setup shared_info page\n"); 314b0663c33SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 315b0663c33SRoger Pau Monné } 316b0663c33SRoger Pau Monné HYPERVISOR_shared_info = (shared_info_t *)(physfree + KERNBASE); 317b0663c33SRoger Pau Monné physfree += PAGE_SIZE; 318b0663c33SRoger Pau Monné 319b0663c33SRoger Pau Monné /* 320b0663c33SRoger Pau Monné * Init a static kenv using a free page. The contents will be filled 321b0663c33SRoger Pau Monné * from the parse_preload_data hook. 322b0663c33SRoger Pau Monné */ 323b0663c33SRoger Pau Monné kenv = (void *)(physfree + KERNBASE); 324b0663c33SRoger Pau Monné physfree += PAGE_SIZE; 3253f102f58SMateusz Guzik bzero_early(kenv, PAGE_SIZE); 326b0663c33SRoger Pau Monné init_static_kenv(kenv, PAGE_SIZE); 327b0663c33SRoger Pau Monné 328b0663c33SRoger Pau Monné if (start_info->modlist_paddr != 0) { 329b0663c33SRoger Pau Monné if (start_info->modlist_paddr >= physfree) { 330b0663c33SRoger Pau Monné xc_printf( 331b0663c33SRoger Pau Monné "ERROR: unexpected module list memory address\n"); 332b0663c33SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 333b0663c33SRoger Pau Monné } 334b0663c33SRoger Pau Monné if (start_info->nr_modules == 0) { 335b0663c33SRoger Pau Monné xc_printf( 336b0663c33SRoger Pau Monné "ERROR: modlist_paddr != 0 but nr_modules == 0\n"); 337b0663c33SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 338b0663c33SRoger Pau Monné } 339b0663c33SRoger Pau Monné mod = (struct hvm_modlist_entry *) 340b0663c33SRoger Pau Monné (vm_paddr_t)start_info->modlist_paddr + KERNBASE; 341b0663c33SRoger Pau Monné if (mod[0].paddr >= physfree) { 342b0663c33SRoger Pau Monné xc_printf("ERROR: unexpected module memory address\n"); 343b0663c33SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 344b0663c33SRoger Pau Monné } 345b0663c33SRoger Pau Monné } 346b0663c33SRoger Pau Monné 347b0663c33SRoger Pau Monné /* Set the hooks for early functions that diverge from bare metal */ 348b0663c33SRoger Pau Monné init_ops = xen_pvh_init_ops; 349b0663c33SRoger Pau Monné hvm_start_flags = start_info->flags; 350b0663c33SRoger Pau Monné 351b0663c33SRoger Pau Monné /* Now we can jump into the native init function */ 352b0663c33SRoger Pau Monné return (hammer_time(0, physfree)); 353b0663c33SRoger Pau Monné } 354b0663c33SRoger Pau Monné 35597baeefdSRoger Pau Monné /*-------------------------------- PV specific -------------------------------*/ 356079f7ef8SRoger Pau Monné #ifdef SMP 357079f7ef8SRoger Pau Monné static bool 358079f7ef8SRoger Pau Monné start_xen_ap(int cpu) 359079f7ef8SRoger Pau Monné { 360079f7ef8SRoger Pau Monné struct vcpu_guest_context *ctxt; 361079f7ef8SRoger Pau Monné int ms, cpus = mp_naps; 362edc82223SKonstantin Belousov const size_t stacksize = kstack_pages * PAGE_SIZE; 363079f7ef8SRoger Pau Monné 364079f7ef8SRoger Pau Monné /* allocate and set up an idle stack data page */ 36583a90bffSAlan Cox bootstacks[cpu] = (void *)kmem_malloc(stacksize, M_WAITOK | M_ZERO); 36683a90bffSAlan Cox doublefault_stack = (char *)kmem_malloc(PAGE_SIZE, M_WAITOK | M_ZERO); 36783a90bffSAlan Cox mce_stack = (char *)kmem_malloc(PAGE_SIZE, M_WAITOK | M_ZERO); 36883a90bffSAlan Cox nmi_stack = (char *)kmem_malloc(PAGE_SIZE, M_WAITOK | M_ZERO); 36983a90bffSAlan Cox dbg_stack = (void *)kmem_malloc(PAGE_SIZE, M_WAITOK | M_ZERO); 37083a90bffSAlan Cox dpcpu = (void *)kmem_malloc(DPCPU_SIZE, M_WAITOK | M_ZERO); 371079f7ef8SRoger Pau Monné 372edc82223SKonstantin Belousov bootSTK = (char *)bootstacks[cpu] + kstack_pages * PAGE_SIZE - 8; 373079f7ef8SRoger Pau Monné bootAP = cpu; 374079f7ef8SRoger Pau Monné 375079f7ef8SRoger Pau Monné ctxt = malloc(sizeof(*ctxt), M_TEMP, M_WAITOK | M_ZERO); 376079f7ef8SRoger Pau Monné 377079f7ef8SRoger Pau Monné ctxt->flags = VGCF_IN_KERNEL; 378079f7ef8SRoger Pau Monné ctxt->user_regs.rip = (unsigned long) init_secondary; 379079f7ef8SRoger Pau Monné ctxt->user_regs.rsp = (unsigned long) bootSTK; 380079f7ef8SRoger Pau Monné 381079f7ef8SRoger Pau Monné /* Set the AP to use the same page tables */ 382079f7ef8SRoger Pau Monné ctxt->ctrlreg[3] = KPML4phys; 383079f7ef8SRoger Pau Monné 384079f7ef8SRoger Pau Monné if (HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, ctxt)) 385079f7ef8SRoger Pau Monné panic("unable to initialize AP#%d", cpu); 386079f7ef8SRoger Pau Monné 387079f7ef8SRoger Pau Monné free(ctxt, M_TEMP); 388079f7ef8SRoger Pau Monné 389079f7ef8SRoger Pau Monné /* Launch the vCPU */ 390079f7ef8SRoger Pau Monné if (HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL)) 391079f7ef8SRoger Pau Monné panic("unable to start AP#%d", cpu); 392079f7ef8SRoger Pau Monné 393079f7ef8SRoger Pau Monné /* Wait up to 5 seconds for it to start. */ 394079f7ef8SRoger Pau Monné for (ms = 0; ms < 5000; ms++) { 395079f7ef8SRoger Pau Monné if (mp_naps > cpus) 396079f7ef8SRoger Pau Monné return (true); 397079f7ef8SRoger Pau Monné DELAY(1000); 398079f7ef8SRoger Pau Monné } 399079f7ef8SRoger Pau Monné 400079f7ef8SRoger Pau Monné return (false); 401079f7ef8SRoger Pau Monné } 402079f7ef8SRoger Pau Monné 403079f7ef8SRoger Pau Monné static int 404079f7ef8SRoger Pau Monné xen_pv_start_all_aps(void) 405079f7ef8SRoger Pau Monné { 406079f7ef8SRoger Pau Monné int cpu; 407079f7ef8SRoger Pau Monné 408079f7ef8SRoger Pau Monné mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN); 409079f7ef8SRoger Pau Monné 410079f7ef8SRoger Pau Monné for (cpu = 1; cpu < mp_ncpus; cpu++) { 411079f7ef8SRoger Pau Monné /* attempt to start the Application Processor */ 412079f7ef8SRoger Pau Monné if (!start_xen_ap(cpu)) 413079f7ef8SRoger Pau Monné panic("AP #%d failed to start!", cpu); 414079f7ef8SRoger Pau Monné 415079f7ef8SRoger Pau Monné CPU_SET(cpu, &all_cpus); /* record AP in CPU map */ 416079f7ef8SRoger Pau Monné } 417079f7ef8SRoger Pau Monné 418079f7ef8SRoger Pau Monné return (mp_naps); 419079f7ef8SRoger Pau Monné } 420079f7ef8SRoger Pau Monné #endif /* SMP */ 421079f7ef8SRoger Pau Monné 42297baeefdSRoger Pau Monné /* 423b0663c33SRoger Pau Monné * When booted as a PVH guest FreeBSD needs to avoid using the RSDP address 424b0663c33SRoger Pau Monné * hint provided by the loader because it points to the native set of ACPI 425b0663c33SRoger Pau Monné * tables instead of the ones crafted by Xen. The acpi.rsdp env variable is 426b0663c33SRoger Pau Monné * removed from kenv if present, and a new acpi.rsdp is added to kenv that 427b0663c33SRoger Pau Monné * points to the address of the Xen crafted RSDP. 42897baeefdSRoger Pau Monné */ 429b0663c33SRoger Pau Monné static bool reject_option(const char *option) 43097baeefdSRoger Pau Monné { 431b0663c33SRoger Pau Monné static const char *reject[] = { 432b0663c33SRoger Pau Monné "acpi.rsdp", 433b0663c33SRoger Pau Monné }; 434b0663c33SRoger Pau Monné unsigned int i; 43597baeefdSRoger Pau Monné 436b0663c33SRoger Pau Monné for (i = 0; i < nitems(reject); i++) 437b0663c33SRoger Pau Monné if (strncmp(option, reject[i], strlen(reject[i])) == 0) 438b0663c33SRoger Pau Monné return (true); 43997baeefdSRoger Pau Monné 440b0663c33SRoger Pau Monné return (false); 441b0663c33SRoger Pau Monné } 44297baeefdSRoger Pau Monné 443b0663c33SRoger Pau Monné static void 444b0663c33SRoger Pau Monné xen_pvh_set_env(char *env, bool (*filter)(const char *)) 445b0663c33SRoger Pau Monné { 446b0663c33SRoger Pau Monné char *option; 44797baeefdSRoger Pau Monné 448b0663c33SRoger Pau Monné if (env == NULL) 449b0663c33SRoger Pau Monné return; 450b0663c33SRoger Pau Monné 451b0663c33SRoger Pau Monné option = env; 452b0663c33SRoger Pau Monné while (*option != 0) { 453b0663c33SRoger Pau Monné char *value; 454b0663c33SRoger Pau Monné 455b0663c33SRoger Pau Monné if (filter != NULL && filter(option)) { 456b0663c33SRoger Pau Monné option += strlen(option) + 1; 457b0663c33SRoger Pau Monné continue; 458b0663c33SRoger Pau Monné } 459b0663c33SRoger Pau Monné 460b0663c33SRoger Pau Monné value = option; 461b0663c33SRoger Pau Monné option = strsep(&value, "="); 462b0663c33SRoger Pau Monné if (kern_setenv(option, value) != 0) 463b0663c33SRoger Pau Monné xc_printf("unable to add kenv %s=%s\n", option, value); 464b0663c33SRoger Pau Monné option = value + strlen(value) + 1; 465b0663c33SRoger Pau Monné } 46697baeefdSRoger Pau Monné } 46797baeefdSRoger Pau Monné 468c98a2727SRoger Pau Monné #ifdef DDB 469c98a2727SRoger Pau Monné /* 470c98a2727SRoger Pau Monné * The way Xen loads the symtab is different from the native boot loader, 471c98a2727SRoger Pau Monné * because it's tailored for NetBSD. So we have to adapt and use the same 472c98a2727SRoger Pau Monné * method as NetBSD. Portions of the code below have been picked from NetBSD: 473c98a2727SRoger Pau Monné * sys/kern/kern_ksyms.c CVS Revision 1.71. 474c98a2727SRoger Pau Monné */ 475c98a2727SRoger Pau Monné static void 476b0663c33SRoger Pau Monné xen_pvh_parse_symtab(void) 477c98a2727SRoger Pau Monné { 478c98a2727SRoger Pau Monné Elf_Ehdr *ehdr; 479c98a2727SRoger Pau Monné Elf_Shdr *shdr; 480c98a2727SRoger Pau Monné uint32_t size; 481c98a2727SRoger Pau Monné int i, j; 482c98a2727SRoger Pau Monné 483c98a2727SRoger Pau Monné size = end; 484c98a2727SRoger Pau Monné 485c98a2727SRoger Pau Monné ehdr = (Elf_Ehdr *)(&end + 1); 486c98a2727SRoger Pau Monné if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || 487c98a2727SRoger Pau Monné ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || 488c98a2727SRoger Pau Monné ehdr->e_version > 1) { 489c98a2727SRoger Pau Monné xc_printf("Unable to load ELF symtab: invalid symbol table\n"); 490c98a2727SRoger Pau Monné return; 491c98a2727SRoger Pau Monné } 492c98a2727SRoger Pau Monné 493c98a2727SRoger Pau Monné shdr = (Elf_Shdr *)((uint8_t *)ehdr + ehdr->e_shoff); 494c98a2727SRoger Pau Monné /* Find the symbol table and the corresponding string table. */ 495c98a2727SRoger Pau Monné for (i = 1; i < ehdr->e_shnum; i++) { 496c98a2727SRoger Pau Monné if (shdr[i].sh_type != SHT_SYMTAB) 497c98a2727SRoger Pau Monné continue; 498c98a2727SRoger Pau Monné if (shdr[i].sh_offset == 0) 499c98a2727SRoger Pau Monné continue; 500c98a2727SRoger Pau Monné ksymtab = (uintptr_t)((uint8_t *)ehdr + shdr[i].sh_offset); 501c98a2727SRoger Pau Monné ksymtab_size = shdr[i].sh_size; 502c98a2727SRoger Pau Monné j = shdr[i].sh_link; 503c98a2727SRoger Pau Monné if (shdr[j].sh_offset == 0) 504c98a2727SRoger Pau Monné continue; /* Can this happen? */ 505c98a2727SRoger Pau Monné kstrtab = (uintptr_t)((uint8_t *)ehdr + shdr[j].sh_offset); 506c98a2727SRoger Pau Monné break; 507c98a2727SRoger Pau Monné } 508c98a2727SRoger Pau Monné 509b0663c33SRoger Pau Monné if (ksymtab == 0 || kstrtab == 0) 510c98a2727SRoger Pau Monné xc_printf( 511c98a2727SRoger Pau Monné "Unable to load ELF symtab: could not find symtab or strtab\n"); 512c98a2727SRoger Pau Monné } 513c98a2727SRoger Pau Monné #endif 514c98a2727SRoger Pau Monné 51597baeefdSRoger Pau Monné static caddr_t 516b0663c33SRoger Pau Monné xen_legacy_pvh_parse_preload_data(uint64_t modulep) 51797baeefdSRoger Pau Monné { 518ca49b334SRoger Pau Monné caddr_t kmdp; 519ca49b334SRoger Pau Monné vm_ooffset_t off; 520ca49b334SRoger Pau Monné vm_paddr_t metadata; 52169dcb7e7SIan Lepore char *envp; 522ca49b334SRoger Pau Monné 523cfa0b7b8SRoger Pau Monné if (legacy_start_info->mod_start != 0) { 524cfa0b7b8SRoger Pau Monné preload_metadata = (caddr_t)legacy_start_info->mod_start; 525ca49b334SRoger Pau Monné 526ca49b334SRoger Pau Monné kmdp = preload_search_by_type("elf kernel"); 527ca49b334SRoger Pau Monné if (kmdp == NULL) 528ca49b334SRoger Pau Monné kmdp = preload_search_by_type("elf64 kernel"); 529ca49b334SRoger Pau Monné KASSERT(kmdp != NULL, ("unable to find kernel")); 530ca49b334SRoger Pau Monné 531ca49b334SRoger Pau Monné /* 532ca49b334SRoger Pau Monné * Xen has relocated the metadata and the modules, 533ca49b334SRoger Pau Monné * so we need to recalculate it's position. This is 534ca49b334SRoger Pau Monné * done by saving the original modulep address and 535ca49b334SRoger Pau Monné * then calculating the offset with mod_start, 536ca49b334SRoger Pau Monné * which contains the relocated modulep address. 537ca49b334SRoger Pau Monné */ 538b829c841SRoger Pau Monné metadata = MD_FETCH(kmdp, MODINFOMD_MODULEP, vm_paddr_t); 539cfa0b7b8SRoger Pau Monné off = legacy_start_info->mod_start - metadata; 540ca49b334SRoger Pau Monné 541ca49b334SRoger Pau Monné preload_bootstrap_relocate(off); 542ca49b334SRoger Pau Monné 543ca49b334SRoger Pau Monné boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 54469dcb7e7SIan Lepore envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 54569dcb7e7SIan Lepore if (envp != NULL) 54669dcb7e7SIan Lepore envp += off; 547b0663c33SRoger Pau Monné xen_pvh_set_env(envp, NULL); 548ca49b334SRoger Pau Monné } else { 54997baeefdSRoger Pau Monné /* Parse the extra boot information given by Xen */ 550b0663c33SRoger Pau Monné boot_parse_cmdline_delim(legacy_start_info->cmd_line, ","); 551ca49b334SRoger Pau Monné kmdp = NULL; 552ca49b334SRoger Pau Monné } 55397baeefdSRoger Pau Monné 554b0663c33SRoger Pau Monné boothowto |= boot_env_to_howto(); 555b0663c33SRoger Pau Monné 556c98a2727SRoger Pau Monné #ifdef DDB 557b0663c33SRoger Pau Monné xen_pvh_parse_symtab(); 558b0663c33SRoger Pau Monné #endif 559b0663c33SRoger Pau Monné return (kmdp); 560b0663c33SRoger Pau Monné } 561b0663c33SRoger Pau Monné 562b0663c33SRoger Pau Monné static caddr_t 563b0663c33SRoger Pau Monné xen_pvh_parse_preload_data(uint64_t modulep) 564b0663c33SRoger Pau Monné { 565b0663c33SRoger Pau Monné caddr_t kmdp; 566b0663c33SRoger Pau Monné vm_ooffset_t off; 567b0663c33SRoger Pau Monné vm_paddr_t metadata; 568b0663c33SRoger Pau Monné char *envp; 569b0663c33SRoger Pau Monné char acpi_rsdp[19]; 570b0663c33SRoger Pau Monné 571b0663c33SRoger Pau Monné if (start_info->modlist_paddr != 0) { 572b0663c33SRoger Pau Monné struct hvm_modlist_entry *mod; 573b6d85a5fSRoger Pau Monné const char *cmdline; 574b0663c33SRoger Pau Monné 575b0663c33SRoger Pau Monné mod = (struct hvm_modlist_entry *) 576b0663c33SRoger Pau Monné (start_info->modlist_paddr + KERNBASE); 577b6d85a5fSRoger Pau Monné cmdline = mod[0].cmdline_paddr ? 578b6d85a5fSRoger Pau Monné (const char *)(mod[0].cmdline_paddr + KERNBASE) : NULL; 579b6d85a5fSRoger Pau Monné 580b6d85a5fSRoger Pau Monné if (strcmp(cmdline, "header") == 0) { 581b6d85a5fSRoger Pau Monné struct xen_header *header; 582b6d85a5fSRoger Pau Monné 583b6d85a5fSRoger Pau Monné header = (struct xen_header *)(mod[0].paddr + KERNBASE); 584b6d85a5fSRoger Pau Monné 585b6d85a5fSRoger Pau Monné if ((header->flags & XENHEADER_HAS_MODULEP_OFFSET) != 586b6d85a5fSRoger Pau Monné XENHEADER_HAS_MODULEP_OFFSET) { 587b6d85a5fSRoger Pau Monné xc_printf("Unable to load module metadata\n"); 588b6d85a5fSRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 589b6d85a5fSRoger Pau Monné } 590b6d85a5fSRoger Pau Monné 591b6d85a5fSRoger Pau Monné preload_metadata = (caddr_t)(mod[0].paddr + 592b6d85a5fSRoger Pau Monné header->modulep_offset + KERNBASE); 593b6d85a5fSRoger Pau Monné 594b6d85a5fSRoger Pau Monné kmdp = preload_search_by_type("elf kernel"); 595b6d85a5fSRoger Pau Monné if (kmdp == NULL) 596b6d85a5fSRoger Pau Monné kmdp = preload_search_by_type("elf64 kernel"); 597b6d85a5fSRoger Pau Monné if (kmdp == NULL) { 598b6d85a5fSRoger Pau Monné xc_printf("Unable to find kernel\n"); 599b6d85a5fSRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 600b6d85a5fSRoger Pau Monné } 601b6d85a5fSRoger Pau Monné 602b6d85a5fSRoger Pau Monné /* 603b6d85a5fSRoger Pau Monné * Xen has relocated the metadata and the modules, so 604b6d85a5fSRoger Pau Monné * we need to recalculate it's position. This is done 605b6d85a5fSRoger Pau Monné * by saving the original modulep address and then 606b6d85a5fSRoger Pau Monné * calculating the offset from the real modulep 607b6d85a5fSRoger Pau Monné * position. 608b6d85a5fSRoger Pau Monné */ 609b6d85a5fSRoger Pau Monné metadata = MD_FETCH(kmdp, MODINFOMD_MODULEP, 610b6d85a5fSRoger Pau Monné vm_paddr_t); 611b6d85a5fSRoger Pau Monné off = mod[0].paddr + header->modulep_offset - metadata + 612b6d85a5fSRoger Pau Monné KERNBASE; 613b6d85a5fSRoger Pau Monné } else { 614b0663c33SRoger Pau Monné preload_metadata = (caddr_t)(mod[0].paddr + KERNBASE); 615b0663c33SRoger Pau Monné 616b0663c33SRoger Pau Monné kmdp = preload_search_by_type("elf kernel"); 617b0663c33SRoger Pau Monné if (kmdp == NULL) 618b0663c33SRoger Pau Monné kmdp = preload_search_by_type("elf64 kernel"); 619b6d85a5fSRoger Pau Monné if (kmdp == NULL) { 620b6d85a5fSRoger Pau Monné xc_printf("Unable to find kernel\n"); 621b6d85a5fSRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 622b6d85a5fSRoger Pau Monné } 623b0663c33SRoger Pau Monné 624b0663c33SRoger Pau Monné metadata = MD_FETCH(kmdp, MODINFOMD_MODULEP, vm_paddr_t); 625b0663c33SRoger Pau Monné off = mod[0].paddr + KERNBASE - metadata; 626b6d85a5fSRoger Pau Monné } 627b0663c33SRoger Pau Monné 628b0663c33SRoger Pau Monné preload_bootstrap_relocate(off); 629b0663c33SRoger Pau Monné 630b0663c33SRoger Pau Monné boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 631b0663c33SRoger Pau Monné envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 632b0663c33SRoger Pau Monné if (envp != NULL) 633b0663c33SRoger Pau Monné envp += off; 634b0663c33SRoger Pau Monné xen_pvh_set_env(envp, reject_option); 635*a2495c36SRoger Pau Monné 636*a2495c36SRoger Pau Monné if (MD_FETCH(kmdp, MODINFOMD_EFI_MAP, void *) != NULL) 637*a2495c36SRoger Pau Monné strlcpy(bootmethod, "UEFI", sizeof(bootmethod)); 638*a2495c36SRoger Pau Monné else 639*a2495c36SRoger Pau Monné strlcpy(bootmethod, "BIOS", sizeof(bootmethod)); 640b0663c33SRoger Pau Monné } else { 641b0663c33SRoger Pau Monné /* Parse the extra boot information given by Xen */ 642b0663c33SRoger Pau Monné if (start_info->cmdline_paddr != 0) 643b0663c33SRoger Pau Monné boot_parse_cmdline_delim( 644b0663c33SRoger Pau Monné (char *)(start_info->cmdline_paddr + KERNBASE), 645b0663c33SRoger Pau Monné ","); 646b0663c33SRoger Pau Monné kmdp = NULL; 647*a2495c36SRoger Pau Monné strlcpy(bootmethod, "XEN", sizeof(bootmethod)); 648b0663c33SRoger Pau Monné } 649b0663c33SRoger Pau Monné 650b0663c33SRoger Pau Monné boothowto |= boot_env_to_howto(); 651b0663c33SRoger Pau Monné 652b0663c33SRoger Pau Monné snprintf(acpi_rsdp, sizeof(acpi_rsdp), "%#" PRIx64, 653b0663c33SRoger Pau Monné start_info->rsdp_paddr); 654b0663c33SRoger Pau Monné kern_setenv("acpi.rsdp", acpi_rsdp); 655b0663c33SRoger Pau Monné 656b0663c33SRoger Pau Monné #ifdef DDB 657b0663c33SRoger Pau Monné xen_pvh_parse_symtab(); 658c98a2727SRoger Pau Monné #endif 659ca49b334SRoger Pau Monné return (kmdp); 66097baeefdSRoger Pau Monné } 6611e69553eSRoger Pau Monné 6621e69553eSRoger Pau Monné static void 663b0663c33SRoger Pau Monné xen_pvh_parse_memmap(caddr_t kmdp, vm_paddr_t *physmap, int *physmap_idx) 6641e69553eSRoger Pau Monné { 6651e69553eSRoger Pau Monné struct xen_memory_map memmap; 6661e69553eSRoger Pau Monné u_int32_t size; 6671e69553eSRoger Pau Monné int rc; 6681e69553eSRoger Pau Monné 6691e69553eSRoger Pau Monné /* Fetch the E820 map from Xen */ 6701e69553eSRoger Pau Monné memmap.nr_entries = MAX_E820_ENTRIES; 6711e69553eSRoger Pau Monné set_xen_guest_handle(memmap.buffer, xen_smap); 6721e69553eSRoger Pau Monné rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap); 673b0663c33SRoger Pau Monné if (rc) { 674b0663c33SRoger Pau Monné xc_printf("ERROR: unable to fetch Xen E820 memory map: %d\n", 675b0663c33SRoger Pau Monné rc); 676b0663c33SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 677b0663c33SRoger Pau Monné } 678b0663c33SRoger Pau Monné 6791e69553eSRoger Pau Monné size = memmap.nr_entries * sizeof(xen_smap[0]); 6801e69553eSRoger Pau Monné 6811e69553eSRoger Pau Monné bios_add_smap_entries(xen_smap, size, physmap, physmap_idx); 6821e69553eSRoger Pau Monné } 683