1ebf5747bSPedro F. Giffuni /*- 2b61a5730SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 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> 33c98a2727SRoger Pau Monné #include "opt_ddb.h" 34721555e7SZbigniew Bodek #include "opt_kstack_pages.h" 35c98a2727SRoger Pau Monné 361a9cdd37SRoger Pau Monné #include <sys/param.h> 371a9cdd37SRoger Pau Monné #include <sys/bus.h> 381a9cdd37SRoger Pau Monné #include <sys/kernel.h> 391a9cdd37SRoger Pau Monné #include <sys/reboot.h> 401a9cdd37SRoger Pau Monné #include <sys/systm.h> 41079f7ef8SRoger Pau Monné #include <sys/malloc.h> 42c98a2727SRoger Pau Monné #include <sys/linker.h> 431a9cdd37SRoger Pau Monné #include <sys/lock.h> 441a9cdd37SRoger Pau Monné #include <sys/rwlock.h> 45aa389b4fSRoger Pau Monné #include <sys/boot.h> 4697baeefdSRoger Pau Monné #include <sys/ctype.h> 47079f7ef8SRoger Pau Monné #include <sys/mutex.h> 48079f7ef8SRoger Pau Monné #include <sys/smp.h> 49a2495c36SRoger Pau Monné #include <sys/efi.h> 509d6ae1e3SColin Percival #include <sys/tslog.h> 511a9cdd37SRoger Pau Monné 521a9cdd37SRoger Pau Monné #include <vm/vm.h> 531a9cdd37SRoger Pau Monné #include <vm/vm_extern.h> 541a9cdd37SRoger Pau Monné #include <vm/vm_kern.h> 551a9cdd37SRoger Pau Monné #include <vm/vm_page.h> 561a9cdd37SRoger Pau Monné #include <vm/vm_map.h> 571a9cdd37SRoger Pau Monné #include <vm/vm_object.h> 581a9cdd37SRoger Pau Monné #include <vm/vm_pager.h> 591a9cdd37SRoger Pau Monné #include <vm/vm_param.h> 601a9cdd37SRoger Pau Monné 61b0663c33SRoger Pau Monné #include <machine/_inttypes.h> 62fae92773SJohn Baldwin #include <machine/intr_machdep.h> 631b5e5ff6SRoger Pau Monné #include <x86/acpica_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> 69a2495c36SRoger Pau Monné #include <machine/md_var.h> 70ca49b334SRoger Pau Monné #include <machine/metadata.h> 7177cb05dbSRoger Pau Monné #include <machine/cpu.h> 7297baeefdSRoger Pau Monné 731a9cdd37SRoger Pau Monné #include <xen/xen-os.h> 74b0663c33SRoger Pau Monné #include <xen/hvm.h> 751a9cdd37SRoger Pau Monné #include <xen/hypervisor.h> 76b7df74eeSWarner Losh #include <xen/xenstore/xenstorevar.h> 77842471b3SRoger Pau Monné #include <xen/xen_pv.h> 781a9cdd37SRoger Pau Monné 79a8ea1540SColin Percival #include <contrib/xen/arch-x86/cpuid.h> 80ad7dd514SElliott Mitchell #include <contrib/xen/arch-x86/hvm/start_info.h> 81ad7dd514SElliott Mitchell #include <contrib/xen/vcpu.h> 82079f7ef8SRoger Pau Monné 835f05c794SRoger Pau Monné #include <dev/xen/timer/timer.h> 845f05c794SRoger Pau Monné 85c98a2727SRoger Pau Monné #ifdef DDB 86c98a2727SRoger Pau Monné #include <ddb/ddb.h> 87c98a2727SRoger Pau Monné #endif 88c98a2727SRoger Pau Monné 891a9cdd37SRoger Pau Monné /* Native initial function */ 901a9cdd37SRoger Pau Monné extern u_int64_t hammer_time(u_int64_t, u_int64_t); 911a9cdd37SRoger Pau Monné /* Xen initial function */ 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 ---------------------------*/ 97*b72ae900SAhmad Khalifa static void xen_pvh_parse_preload_data(uint64_t); 98*b72ae900SAhmad Khalifa static void pvh_parse_memmap(vm_paddr_t *, int *); 9997baeefdSRoger Pau Monné 100079f7ef8SRoger Pau Monné /*---------------------------- Extern Declarations ---------------------------*/ 101c98a2727SRoger Pau Monné /* 102c98a2727SRoger Pau Monné * Placed by the linker at the end of the bss section, which is the last 103c98a2727SRoger Pau Monné * section loaded by Xen before loading the symtab and strtab. 104c98a2727SRoger Pau Monné */ 105c98a2727SRoger Pau Monné extern uint32_t end; 106c98a2727SRoger Pau Monné 10797baeefdSRoger Pau Monné /*-------------------------------- Global Data -------------------------------*/ 108b0663c33SRoger Pau Monné struct init_ops xen_pvh_init_ops = { 109b0663c33SRoger Pau Monné .parse_preload_data = xen_pvh_parse_preload_data, 110b0663c33SRoger Pau Monné .early_clock_source_init = xen_clock_init, 111b0663c33SRoger Pau Monné .early_delay = xen_delay, 112023a025bSColin Percival .parse_memmap = pvh_parse_memmap, 113b0663c33SRoger Pau Monné }; 114b0663c33SRoger Pau Monné 1151e69553eSRoger Pau Monné static struct bios_smap xen_smap[MAX_E820_ENTRIES]; 1161e69553eSRoger Pau Monné 117b0663c33SRoger Pau Monné static struct hvm_start_info *start_info; 118cfa0b7b8SRoger Pau Monné 11997baeefdSRoger Pau Monné /*-------------------------------- Xen PV init -------------------------------*/ 12097baeefdSRoger Pau Monné 121a8ea1540SColin Percival static int 122a8ea1540SColin Percival isxen(void) 123a8ea1540SColin Percival { 124a8ea1540SColin Percival static int xen = -1; 125a8ea1540SColin Percival uint32_t base; 126a8ea1540SColin Percival u_int regs[4]; 127a8ea1540SColin Percival 128a8ea1540SColin Percival if (xen != -1) 129a8ea1540SColin Percival return (xen); 130a8ea1540SColin Percival 131a8ea1540SColin Percival /* 132a8ea1540SColin Percival * The full code for identifying which hypervisor we're running under 133a8ea1540SColin Percival * is in sys/x86/x86/identcpu.c and runs later in the boot process; 134a8ea1540SColin Percival * this is sufficient to distinguish Xen PVH booting from non-Xen PVH 135a8ea1540SColin Percival * and skip some very early Xen-specific code in the non-Xen case. 136a8ea1540SColin Percival */ 137a8ea1540SColin Percival xen = 0; 138a8ea1540SColin Percival for (base = 0x40000000; base < 0x40010000; base += 0x100) { 139a8ea1540SColin Percival do_cpuid(base, regs); 140a8ea1540SColin Percival if (regs[1] == XEN_CPUID_SIGNATURE_EBX && 141a8ea1540SColin Percival regs[2] == XEN_CPUID_SIGNATURE_ECX && 142a8ea1540SColin Percival regs[3] == XEN_CPUID_SIGNATURE_EDX) { 143a8ea1540SColin Percival xen = 1; 144a8ea1540SColin Percival break; 145a8ea1540SColin Percival } 146a8ea1540SColin Percival } 147a8ea1540SColin Percival return (xen); 148a8ea1540SColin Percival } 149a8ea1540SColin Percival 150a8ea1540SColin Percival #define CRASH(...) do { \ 1518f5406c7SRoger Pau Monné if (isxen()) \ 152a8ea1540SColin Percival xc_printf(__VA_ARGS__); \ 153a8ea1540SColin Percival halt(); \ 154a8ea1540SColin Percival } while (0) 155a8ea1540SColin Percival 156b0663c33SRoger Pau Monné uint64_t 157b0663c33SRoger Pau Monné hammer_time_xen(vm_paddr_t start_info_paddr) 158b0663c33SRoger Pau Monné { 159b0663c33SRoger Pau Monné struct hvm_modlist_entry *mod; 160b0663c33SRoger Pau Monné uint64_t physfree; 161b0663c33SRoger Pau Monné 162b0663c33SRoger Pau Monné start_info = (struct hvm_start_info *)(start_info_paddr + KERNBASE); 163b0663c33SRoger Pau Monné if (start_info->magic != XEN_HVM_START_MAGIC_VALUE) { 164a8ea1540SColin Percival CRASH("Unknown magic value in start_info struct: %#x\n", 165b0663c33SRoger Pau Monné start_info->magic); 166b0663c33SRoger Pau Monné } 167b0663c33SRoger Pau Monné 168b0663c33SRoger Pau Monné /* 16977cb05dbSRoger Pau Monné * Select the higher address to use as physfree: either after 17077cb05dbSRoger Pau Monné * start_info, after the kernel, after the memory map or after any of 17177cb05dbSRoger Pau Monné * the modules. We assume enough memory to be available after the 17277cb05dbSRoger Pau Monné * selected address for the needs of very early memory allocations. 173b0663c33SRoger Pau Monné */ 17477cb05dbSRoger Pau Monné physfree = roundup2(start_info_paddr + sizeof(struct hvm_start_info), 17577cb05dbSRoger Pau Monné PAGE_SIZE); 17677cb05dbSRoger Pau Monné physfree = MAX(roundup2((vm_paddr_t)_end - KERNBASE, PAGE_SIZE), 17777cb05dbSRoger Pau Monné physfree); 17877cb05dbSRoger Pau Monné 17977cb05dbSRoger Pau Monné if (start_info->memmap_paddr != 0) 18077cb05dbSRoger Pau Monné physfree = MAX(roundup2(start_info->memmap_paddr + 18177cb05dbSRoger Pau Monné start_info->memmap_entries * 18277cb05dbSRoger Pau Monné sizeof(struct hvm_memmap_table_entry), PAGE_SIZE), 18377cb05dbSRoger Pau Monné physfree); 18477cb05dbSRoger Pau Monné 18577cb05dbSRoger Pau Monné if (start_info->modlist_paddr != 0) { 18677cb05dbSRoger Pau Monné unsigned int i; 18777cb05dbSRoger Pau Monné 18877cb05dbSRoger Pau Monné if (start_info->nr_modules == 0) { 189a8ea1540SColin Percival CRASH( 19077cb05dbSRoger Pau Monné "ERROR: modlist_paddr != 0 but nr_modules == 0\n"); 19177cb05dbSRoger Pau Monné } 19277cb05dbSRoger Pau Monné mod = (struct hvm_modlist_entry *) 19377cb05dbSRoger Pau Monné (start_info->modlist_paddr + KERNBASE); 19477cb05dbSRoger Pau Monné for (i = 0; i < start_info->nr_modules; i++) 19577cb05dbSRoger Pau Monné physfree = MAX(roundup2(mod[i].paddr + mod[i].size, 19677cb05dbSRoger Pau Monné PAGE_SIZE), physfree); 19777cb05dbSRoger Pau Monné } 198b0663c33SRoger Pau Monné 199b0663c33SRoger Pau Monné /* Set the hooks for early functions that diverge from bare metal */ 200b0663c33SRoger Pau Monné init_ops = xen_pvh_init_ops; 201b0663c33SRoger Pau Monné hvm_start_flags = start_info->flags; 202b0663c33SRoger Pau Monné 203b0663c33SRoger Pau Monné /* Now we can jump into the native init function */ 204b0663c33SRoger Pau Monné return (hammer_time(0, physfree)); 205b0663c33SRoger Pau Monné } 206b0663c33SRoger Pau Monné 20797baeefdSRoger Pau Monné /*-------------------------------- PV specific -------------------------------*/ 208079f7ef8SRoger Pau Monné 209c98a2727SRoger Pau Monné #ifdef DDB 210c98a2727SRoger Pau Monné /* 211c98a2727SRoger Pau Monné * The way Xen loads the symtab is different from the native boot loader, 212c98a2727SRoger Pau Monné * because it's tailored for NetBSD. So we have to adapt and use the same 213c98a2727SRoger Pau Monné * method as NetBSD. Portions of the code below have been picked from NetBSD: 214c98a2727SRoger Pau Monné * sys/kern/kern_ksyms.c CVS Revision 1.71. 215c98a2727SRoger Pau Monné */ 216c98a2727SRoger Pau Monné static void 217b0663c33SRoger Pau Monné xen_pvh_parse_symtab(void) 218c98a2727SRoger Pau Monné { 219c98a2727SRoger Pau Monné Elf_Ehdr *ehdr; 220c98a2727SRoger Pau Monné Elf_Shdr *shdr; 221c98a2727SRoger Pau Monné int i, j; 222c98a2727SRoger Pau Monné 223c98a2727SRoger Pau Monné ehdr = (Elf_Ehdr *)(&end + 1); 224c98a2727SRoger Pau Monné if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || 225c98a2727SRoger Pau Monné ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || 226c98a2727SRoger Pau Monné ehdr->e_version > 1) { 227a8ea1540SColin Percival if (isxen()) 228c98a2727SRoger Pau Monné xc_printf("Unable to load ELF symtab: invalid symbol table\n"); 229c98a2727SRoger Pau Monné return; 230c98a2727SRoger Pau Monné } 231c98a2727SRoger Pau Monné 232c98a2727SRoger Pau Monné shdr = (Elf_Shdr *)((uint8_t *)ehdr + ehdr->e_shoff); 233c98a2727SRoger Pau Monné /* Find the symbol table and the corresponding string table. */ 234c98a2727SRoger Pau Monné for (i = 1; i < ehdr->e_shnum; i++) { 235c98a2727SRoger Pau Monné if (shdr[i].sh_type != SHT_SYMTAB) 236c98a2727SRoger Pau Monné continue; 237c98a2727SRoger Pau Monné if (shdr[i].sh_offset == 0) 238c98a2727SRoger Pau Monné continue; 239c98a2727SRoger Pau Monné ksymtab = (uintptr_t)((uint8_t *)ehdr + shdr[i].sh_offset); 240c98a2727SRoger Pau Monné ksymtab_size = shdr[i].sh_size; 241c98a2727SRoger Pau Monné j = shdr[i].sh_link; 242c98a2727SRoger Pau Monné if (shdr[j].sh_offset == 0) 243c98a2727SRoger Pau Monné continue; /* Can this happen? */ 244c98a2727SRoger Pau Monné kstrtab = (uintptr_t)((uint8_t *)ehdr + shdr[j].sh_offset); 245c98a2727SRoger Pau Monné break; 246c98a2727SRoger Pau Monné } 247c98a2727SRoger Pau Monné 248a8ea1540SColin Percival if ((ksymtab == 0 || kstrtab == 0) && isxen()) 249c98a2727SRoger Pau Monné xc_printf( 250c98a2727SRoger Pau Monné "Unable to load ELF symtab: could not find symtab or strtab\n"); 251c98a2727SRoger Pau Monné } 252c98a2727SRoger Pau Monné #endif 253c98a2727SRoger Pau Monné 254*b72ae900SAhmad Khalifa static void 255b0663c33SRoger Pau Monné xen_pvh_parse_preload_data(uint64_t modulep) 256b0663c33SRoger Pau Monné { 257b0663c33SRoger Pau Monné vm_ooffset_t off; 258b0663c33SRoger Pau Monné vm_paddr_t metadata; 259b0663c33SRoger Pau Monné char *envp; 260b0663c33SRoger Pau Monné 2619d6ae1e3SColin Percival TSENTER(); 262b0663c33SRoger Pau Monné if (start_info->modlist_paddr != 0) { 263b0663c33SRoger Pau Monné struct hvm_modlist_entry *mod; 264b6d85a5fSRoger Pau Monné const char *cmdline; 265b0663c33SRoger Pau Monné 266b0663c33SRoger Pau Monné mod = (struct hvm_modlist_entry *) 267b0663c33SRoger Pau Monné (start_info->modlist_paddr + KERNBASE); 268b6d85a5fSRoger Pau Monné cmdline = mod[0].cmdline_paddr ? 269b6d85a5fSRoger Pau Monné (const char *)(mod[0].cmdline_paddr + KERNBASE) : NULL; 270b6d85a5fSRoger Pau Monné 271b6d85a5fSRoger Pau Monné if (strcmp(cmdline, "header") == 0) { 272b6d85a5fSRoger Pau Monné struct xen_header *header; 273b6d85a5fSRoger Pau Monné 274b6d85a5fSRoger Pau Monné header = (struct xen_header *)(mod[0].paddr + KERNBASE); 275b6d85a5fSRoger Pau Monné 276b6d85a5fSRoger Pau Monné if ((header->flags & XENHEADER_HAS_MODULEP_OFFSET) != 277b6d85a5fSRoger Pau Monné XENHEADER_HAS_MODULEP_OFFSET) { 278b6d85a5fSRoger Pau Monné xc_printf("Unable to load module metadata\n"); 279b6d85a5fSRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 280b6d85a5fSRoger Pau Monné } 281b6d85a5fSRoger Pau Monné 282b6d85a5fSRoger Pau Monné preload_metadata = (caddr_t)(mod[0].paddr + 283b6d85a5fSRoger Pau Monné header->modulep_offset + KERNBASE); 284b6d85a5fSRoger Pau Monné 285b6d85a5fSRoger Pau Monné /* 286b6d85a5fSRoger Pau Monné * Xen has relocated the metadata and the modules, so 287b6d85a5fSRoger Pau Monné * we need to recalculate it's position. This is done 288b6d85a5fSRoger Pau Monné * by saving the original modulep address and then 289b6d85a5fSRoger Pau Monné * calculating the offset from the real modulep 290b6d85a5fSRoger Pau Monné * position. 291b6d85a5fSRoger Pau Monné */ 292*b72ae900SAhmad Khalifa off = header->modulep_offset; 293b6d85a5fSRoger Pau Monné } else { 294b0663c33SRoger Pau Monné preload_metadata = (caddr_t)(mod[0].paddr + KERNBASE); 295*b72ae900SAhmad Khalifa off = 0; 296*b72ae900SAhmad Khalifa } 297b0663c33SRoger Pau Monné 298*b72ae900SAhmad Khalifa /* Initialize preload_kmdp */ 299*b72ae900SAhmad Khalifa preload_initkmdp(false); 300*b72ae900SAhmad Khalifa if (preload_kmdp == NULL) { 301*b72ae900SAhmad Khalifa xc_printf("Unable to find kernel metadata\n"); 302b6d85a5fSRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 303b6d85a5fSRoger Pau Monné } 304b0663c33SRoger Pau Monné 305*b72ae900SAhmad Khalifa metadata = MD_FETCH(preload_kmdp, MODINFOMD_MODULEP, 306*b72ae900SAhmad Khalifa vm_paddr_t); 307*b72ae900SAhmad Khalifa off += mod[0].paddr + KERNBASE - metadata; 308b0663c33SRoger Pau Monné 309b0663c33SRoger Pau Monné preload_bootstrap_relocate(off); 310b0663c33SRoger Pau Monné 311*b72ae900SAhmad Khalifa boothowto = MD_FETCH(preload_kmdp, MODINFOMD_HOWTO, int); 312*b72ae900SAhmad Khalifa envp = MD_FETCH(preload_kmdp, MODINFOMD_ENVP, char *); 313b0663c33SRoger Pau Monné if (envp != NULL) 314b0663c33SRoger Pau Monné envp += off; 3151b5e5ff6SRoger Pau Monné init_static_kenv(envp, 0); 316a2495c36SRoger Pau Monné 317*b72ae900SAhmad Khalifa if (MD_FETCH(preload_kmdp, MODINFOMD_EFI_MAP, void *) != NULL) 318a2495c36SRoger Pau Monné strlcpy(bootmethod, "UEFI", sizeof(bootmethod)); 319a2495c36SRoger Pau Monné else 320a2495c36SRoger Pau Monné strlcpy(bootmethod, "BIOS", sizeof(bootmethod)); 321b0663c33SRoger Pau Monné } else { 3221b5e5ff6SRoger Pau Monné static char kenv_buffer[PAGE_SIZE]; 3231b5e5ff6SRoger Pau Monné 3241b5e5ff6SRoger Pau Monné /* Provide a static kenv so the command line can be parsed. */ 3251b5e5ff6SRoger Pau Monné init_static_kenv(kenv_buffer, sizeof(kenv_buffer)); 3261b5e5ff6SRoger Pau Monné 327b0663c33SRoger Pau Monné /* Parse the extra boot information given by Xen */ 328b0663c33SRoger Pau Monné if (start_info->cmdline_paddr != 0) 329b0663c33SRoger Pau Monné boot_parse_cmdline_delim( 330b0663c33SRoger Pau Monné (char *)(start_info->cmdline_paddr + KERNBASE), 331c4a4011cSColin Percival ", \t\n"); 33213f34e21SColin Percival strlcpy(bootmethod, "PVH", sizeof(bootmethod)); 333b0663c33SRoger Pau Monné } 334b0663c33SRoger Pau Monné 335b0663c33SRoger Pau Monné boothowto |= boot_env_to_howto(); 336b0663c33SRoger Pau Monné 3371b5e5ff6SRoger Pau Monné /* 3381b5e5ff6SRoger Pau Monné * When booted as a PVH guest FreeBSD must not use the RSDP address 3391b5e5ff6SRoger Pau Monné * hint provided by the loader because it points to the native set of 3401b5e5ff6SRoger Pau Monné * ACPI tables instead of the ones crafted by Xen. 3411b5e5ff6SRoger Pau Monné */ 3421b5e5ff6SRoger Pau Monné acpi_set_root(start_info->rsdp_paddr); 343b0663c33SRoger Pau Monné 344b0663c33SRoger Pau Monné #ifdef DDB 345b0663c33SRoger Pau Monné xen_pvh_parse_symtab(); 346c98a2727SRoger Pau Monné #endif 3479d6ae1e3SColin Percival TSEXIT(); 34897baeefdSRoger Pau Monné } 3491e69553eSRoger Pau Monné 3501e69553eSRoger Pau Monné static void 351*b72ae900SAhmad Khalifa pvh_parse_memmap_start_info(vm_paddr_t *physmap, 352023a025bSColin Percival int *physmap_idx) 353023a025bSColin Percival { 354023a025bSColin Percival const struct hvm_memmap_table_entry * entries; 355023a025bSColin Percival size_t nentries; 356023a025bSColin Percival size_t i; 357023a025bSColin Percival 358023a025bSColin Percival /* Extract from HVM start_info. */ 359023a025bSColin Percival entries = (struct hvm_memmap_table_entry *)(start_info->memmap_paddr + KERNBASE); 360023a025bSColin Percival nentries = start_info->memmap_entries; 361023a025bSColin Percival 362023a025bSColin Percival /* Convert into E820 format and handle one by one. */ 363023a025bSColin Percival for (i = 0; i < nentries; i++) { 364023a025bSColin Percival struct bios_smap entry; 365023a025bSColin Percival 366023a025bSColin Percival entry.base = entries[i].addr; 367023a025bSColin Percival entry.length = entries[i].size; 368023a025bSColin Percival 369023a025bSColin Percival /* 370023a025bSColin Percival * Luckily for us, the XEN_HVM_MEMMAP_TYPE_* values exactly 371023a025bSColin Percival * match the SMAP_TYPE_* values so we don't need to translate 372023a025bSColin Percival * anything here. 373023a025bSColin Percival */ 374023a025bSColin Percival entry.type = entries[i].type; 375023a025bSColin Percival 376023a025bSColin Percival bios_add_smap_entries(&entry, 1, physmap, physmap_idx); 377023a025bSColin Percival } 378023a025bSColin Percival } 379023a025bSColin Percival 380023a025bSColin Percival static void 381*b72ae900SAhmad Khalifa xen_pvh_parse_memmap(vm_paddr_t *physmap, int *physmap_idx) 3821e69553eSRoger Pau Monné { 3831e69553eSRoger Pau Monné struct xen_memory_map memmap; 3841e69553eSRoger Pau Monné u_int32_t size; 3851e69553eSRoger Pau Monné int rc; 3861e69553eSRoger Pau Monné 387a8ea1540SColin Percival /* We should only reach here if we're running under Xen. */ 388a8ea1540SColin Percival KASSERT(isxen(), ("xen_pvh_parse_memmap reached when !Xen")); 389a8ea1540SColin Percival 3901e69553eSRoger Pau Monné /* Fetch the E820 map from Xen */ 3911e69553eSRoger Pau Monné memmap.nr_entries = MAX_E820_ENTRIES; 3921e69553eSRoger Pau Monné set_xen_guest_handle(memmap.buffer, xen_smap); 3931e69553eSRoger Pau Monné rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap); 394b0663c33SRoger Pau Monné if (rc) { 395b0663c33SRoger Pau Monné xc_printf("ERROR: unable to fetch Xen E820 memory map: %d\n", 396b0663c33SRoger Pau Monné rc); 397b0663c33SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 398b0663c33SRoger Pau Monné } 399b0663c33SRoger Pau Monné 4001e69553eSRoger Pau Monné size = memmap.nr_entries * sizeof(xen_smap[0]); 4011e69553eSRoger Pau Monné 4021e69553eSRoger Pau Monné bios_add_smap_entries(xen_smap, size, physmap, physmap_idx); 4031e69553eSRoger Pau Monné } 404023a025bSColin Percival 405023a025bSColin Percival static void 406*b72ae900SAhmad Khalifa pvh_parse_memmap(vm_paddr_t *physmap, int *physmap_idx) 407023a025bSColin Percival { 408023a025bSColin Percival 409023a025bSColin Percival /* 410023a025bSColin Percival * If version >= 1 and memmap_paddr != 0, use the memory map provided 411023a025bSColin Percival * in the start_info structure; if not, we're running under legacy 412023a025bSColin Percival * Xen and need to use the Xen hypercall. 413023a025bSColin Percival */ 414023a025bSColin Percival if ((start_info->version >= 1) && (start_info->memmap_paddr != 0)) 415*b72ae900SAhmad Khalifa pvh_parse_memmap_start_info(physmap, physmap_idx); 416023a025bSColin Percival else 417*b72ae900SAhmad Khalifa xen_pvh_parse_memmap(physmap, physmap_idx); 418023a025bSColin Percival } 419