11a9cdd37SRoger Pau Monné /* 21a9cdd37SRoger Pau Monné * Copyright (c) 2004 Christian Limpach. 31a9cdd37SRoger Pau Monné * Copyright (c) 2004-2006,2008 Kip Macy 41a9cdd37SRoger Pau Monné * Copyright (c) 2013 Roger Pau Monné <roger.pau@citrix.com> 51a9cdd37SRoger Pau Monné * All rights reserved. 61a9cdd37SRoger Pau Monné * 71a9cdd37SRoger Pau Monné * Redistribution and use in source and binary forms, with or without 81a9cdd37SRoger Pau Monné * modification, are permitted provided that the following conditions 91a9cdd37SRoger Pau Monné * are met: 101a9cdd37SRoger Pau Monné * 1. Redistributions of source code must retain the above copyright 111a9cdd37SRoger Pau Monné * notice, this list of conditions and the following disclaimer. 121a9cdd37SRoger Pau Monné * 2. Redistributions in binary form must reproduce the above copyright 131a9cdd37SRoger Pau Monné * notice, this list of conditions and the following disclaimer in the 141a9cdd37SRoger Pau Monné * documentation and/or other materials provided with the distribution. 151a9cdd37SRoger Pau Monné * 161a9cdd37SRoger Pau Monné * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND 171a9cdd37SRoger Pau Monné * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 181a9cdd37SRoger Pau Monné * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 191a9cdd37SRoger Pau Monné * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 201a9cdd37SRoger Pau Monné * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 211a9cdd37SRoger Pau Monné * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 221a9cdd37SRoger Pau Monné * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 231a9cdd37SRoger Pau Monné * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 241a9cdd37SRoger Pau Monné * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 251a9cdd37SRoger Pau Monné * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261a9cdd37SRoger Pau Monné * SUCH DAMAGE. 271a9cdd37SRoger Pau Monné */ 281a9cdd37SRoger Pau Monné 291a9cdd37SRoger Pau Monné #include <sys/cdefs.h> 301a9cdd37SRoger Pau Monné __FBSDID("$FreeBSD$"); 311a9cdd37SRoger Pau Monné 321a9cdd37SRoger Pau Monné #include <sys/param.h> 331a9cdd37SRoger Pau Monné #include <sys/bus.h> 341a9cdd37SRoger Pau Monné #include <sys/kernel.h> 351a9cdd37SRoger Pau Monné #include <sys/reboot.h> 361a9cdd37SRoger Pau Monné #include <sys/systm.h> 371a9cdd37SRoger Pau Monné #include <sys/lock.h> 381a9cdd37SRoger Pau Monné #include <sys/rwlock.h> 39aa389b4fSRoger Pau Monné #include <sys/boot.h> 4097baeefdSRoger Pau Monné #include <sys/ctype.h> 411a9cdd37SRoger Pau Monné 421a9cdd37SRoger Pau Monné #include <vm/vm.h> 431a9cdd37SRoger Pau Monné #include <vm/vm_extern.h> 441a9cdd37SRoger Pau Monné #include <vm/vm_kern.h> 451a9cdd37SRoger Pau Monné #include <vm/vm_page.h> 461a9cdd37SRoger Pau Monné #include <vm/vm_map.h> 471a9cdd37SRoger Pau Monné #include <vm/vm_object.h> 481a9cdd37SRoger Pau Monné #include <vm/vm_pager.h> 491a9cdd37SRoger Pau Monné #include <vm/vm_param.h> 501a9cdd37SRoger Pau Monné 5197baeefdSRoger Pau Monné #include <x86/init.h> 5297baeefdSRoger Pau Monné 531a9cdd37SRoger Pau Monné #include <xen/xen-os.h> 541a9cdd37SRoger Pau Monné #include <xen/hypervisor.h> 551a9cdd37SRoger Pau Monné 56*5f05c794SRoger Pau Monné #include <dev/xen/timer/timer.h> 57*5f05c794SRoger Pau Monné 581a9cdd37SRoger Pau Monné /* Native initial function */ 591a9cdd37SRoger Pau Monné extern u_int64_t hammer_time(u_int64_t, u_int64_t); 601a9cdd37SRoger Pau Monné /* Xen initial function */ 611a9cdd37SRoger Pau Monné uint64_t hammer_time_xen(start_info_t *, uint64_t); 621a9cdd37SRoger Pau Monné 6397baeefdSRoger Pau Monné /*--------------------------- Forward Declarations ---------------------------*/ 6497baeefdSRoger Pau Monné static caddr_t xen_pv_parse_preload_data(u_int64_t); 6597baeefdSRoger Pau Monné 6697baeefdSRoger Pau Monné /*-------------------------------- Global Data -------------------------------*/ 6797baeefdSRoger Pau Monné /* Xen init_ops implementation. */ 6897baeefdSRoger Pau Monné struct init_ops xen_init_ops = { 6997baeefdSRoger Pau Monné .parse_preload_data = xen_pv_parse_preload_data, 70*5f05c794SRoger Pau Monné .early_clock_source_init = xen_clock_init, 71*5f05c794SRoger Pau Monné .early_delay = xen_delay, 7297baeefdSRoger Pau Monné }; 7397baeefdSRoger Pau Monné 7497baeefdSRoger Pau Monné /*-------------------------------- Xen PV init -------------------------------*/ 751a9cdd37SRoger Pau Monné /* 761a9cdd37SRoger Pau Monné * First function called by the Xen PVH boot sequence. 771a9cdd37SRoger Pau Monné * 781a9cdd37SRoger Pau Monné * Set some Xen global variables and prepare the environment so it is 791a9cdd37SRoger Pau Monné * as similar as possible to what native FreeBSD init function expects. 801a9cdd37SRoger Pau Monné */ 811a9cdd37SRoger Pau Monné uint64_t 821a9cdd37SRoger Pau Monné hammer_time_xen(start_info_t *si, uint64_t xenstack) 831a9cdd37SRoger Pau Monné { 841a9cdd37SRoger Pau Monné uint64_t physfree; 851a9cdd37SRoger Pau Monné uint64_t *PT4 = (u_int64_t *)xenstack; 861a9cdd37SRoger Pau Monné uint64_t *PT3 = (u_int64_t *)(xenstack + PAGE_SIZE); 871a9cdd37SRoger Pau Monné uint64_t *PT2 = (u_int64_t *)(xenstack + 2 * PAGE_SIZE); 881a9cdd37SRoger Pau Monné int i; 891a9cdd37SRoger Pau Monné 901a9cdd37SRoger Pau Monné xen_domain_type = XEN_PV_DOMAIN; 911a9cdd37SRoger Pau Monné vm_guest = VM_GUEST_XEN; 921a9cdd37SRoger Pau Monné 931a9cdd37SRoger Pau Monné if ((si == NULL) || (xenstack == 0)) { 94c203fa69SRoger Pau Monné xc_printf("ERROR: invalid start_info or xen stack, halting\n"); 951a9cdd37SRoger Pau Monné HYPERVISOR_shutdown(SHUTDOWN_crash); 961a9cdd37SRoger Pau Monné } 971a9cdd37SRoger Pau Monné 98c203fa69SRoger Pau Monné xc_printf("FreeBSD PVH running on %s\n", si->magic); 99c203fa69SRoger Pau Monné 1001a9cdd37SRoger Pau Monné /* We use 3 pages of xen stack for the boot pagetables */ 1011a9cdd37SRoger Pau Monné physfree = xenstack + 3 * PAGE_SIZE - KERNBASE; 1021a9cdd37SRoger Pau Monné 1031a9cdd37SRoger Pau Monné /* Setup Xen global variables */ 1041a9cdd37SRoger Pau Monné HYPERVISOR_start_info = si; 1051a9cdd37SRoger Pau Monné HYPERVISOR_shared_info = 1061a9cdd37SRoger Pau Monné (shared_info_t *)(si->shared_info + KERNBASE); 1071a9cdd37SRoger Pau Monné 1081a9cdd37SRoger Pau Monné /* 1091a9cdd37SRoger Pau Monné * Setup some misc global variables for Xen devices 1101a9cdd37SRoger Pau Monné * 1111a9cdd37SRoger Pau Monné * XXX: Devices that need these specific variables should 1121a9cdd37SRoger Pau Monné * be rewritten to fetch this info by themselves from the 1131a9cdd37SRoger Pau Monné * start_info page. 1141a9cdd37SRoger Pau Monné */ 1151a9cdd37SRoger Pau Monné xen_store = (struct xenstore_domain_interface *) 1161a9cdd37SRoger Pau Monné (ptoa(si->store_mfn) + KERNBASE); 117c203fa69SRoger Pau Monné console_page = (char *)(ptoa(si->console.domU.mfn) + KERNBASE); 1181a9cdd37SRoger Pau Monné 1191a9cdd37SRoger Pau Monné /* 1201a9cdd37SRoger Pau Monné * Use the stack Xen gives us to build the page tables 1211a9cdd37SRoger Pau Monné * as native FreeBSD expects to find them (created 1221a9cdd37SRoger Pau Monné * by the boot trampoline). 1231a9cdd37SRoger Pau Monné */ 1241a9cdd37SRoger Pau Monné for (i = 0; i < (PAGE_SIZE / sizeof(uint64_t)); i++) { 1251a9cdd37SRoger Pau Monné /* Each slot of the level 4 pages points to the same level 3 page */ 1261a9cdd37SRoger Pau Monné PT4[i] = ((uint64_t)&PT3[0]) - KERNBASE; 1271a9cdd37SRoger Pau Monné PT4[i] |= PG_V | PG_RW | PG_U; 1281a9cdd37SRoger Pau Monné 1291a9cdd37SRoger Pau Monné /* Each slot of the level 3 pages points to the same level 2 page */ 1301a9cdd37SRoger Pau Monné PT3[i] = ((uint64_t)&PT2[0]) - KERNBASE; 1311a9cdd37SRoger Pau Monné PT3[i] |= PG_V | PG_RW | PG_U; 1321a9cdd37SRoger Pau Monné 1331a9cdd37SRoger Pau Monné /* The level 2 page slots are mapped with 2MB pages for 1GB. */ 1341a9cdd37SRoger Pau Monné PT2[i] = i * (2 * 1024 * 1024); 1351a9cdd37SRoger Pau Monné PT2[i] |= PG_V | PG_RW | PG_PS | PG_U; 1361a9cdd37SRoger Pau Monné } 1371a9cdd37SRoger Pau Monné load_cr3(((uint64_t)&PT4[0]) - KERNBASE); 1381a9cdd37SRoger Pau Monné 13997baeefdSRoger Pau Monné /* Set the hooks for early functions that diverge from bare metal */ 14097baeefdSRoger Pau Monné init_ops = xen_init_ops; 14197baeefdSRoger Pau Monné 1421a9cdd37SRoger Pau Monné /* Now we can jump into the native init function */ 1431a9cdd37SRoger Pau Monné return (hammer_time(0, physfree)); 1441a9cdd37SRoger Pau Monné } 14597baeefdSRoger Pau Monné 14697baeefdSRoger Pau Monné /*-------------------------------- PV specific -------------------------------*/ 14797baeefdSRoger Pau Monné /* 14897baeefdSRoger Pau Monné * Functions to convert the "extra" parameters passed by Xen 14997baeefdSRoger Pau Monné * into FreeBSD boot options. 15097baeefdSRoger Pau Monné */ 15197baeefdSRoger Pau Monné static void 15297baeefdSRoger Pau Monné xen_pv_set_env(void) 15397baeefdSRoger Pau Monné { 15497baeefdSRoger Pau Monné char *cmd_line_next, *cmd_line; 15597baeefdSRoger Pau Monné size_t env_size; 15697baeefdSRoger Pau Monné 15797baeefdSRoger Pau Monné cmd_line = HYPERVISOR_start_info->cmd_line; 15897baeefdSRoger Pau Monné env_size = sizeof(HYPERVISOR_start_info->cmd_line); 15997baeefdSRoger Pau Monné 16097baeefdSRoger Pau Monné /* Skip leading spaces */ 16197baeefdSRoger Pau Monné for (; isspace(*cmd_line) && (env_size != 0); cmd_line++) 16297baeefdSRoger Pau Monné env_size--; 16397baeefdSRoger Pau Monné 16497baeefdSRoger Pau Monné /* Replace ',' with '\0' */ 16597baeefdSRoger Pau Monné for (cmd_line_next = cmd_line; strsep(&cmd_line_next, ",") != NULL;) 16697baeefdSRoger Pau Monné ; 16797baeefdSRoger Pau Monné 16897baeefdSRoger Pau Monné init_static_kenv(cmd_line, env_size); 16997baeefdSRoger Pau Monné } 17097baeefdSRoger Pau Monné 17197baeefdSRoger Pau Monné static void 17297baeefdSRoger Pau Monné xen_pv_set_boothowto(void) 17397baeefdSRoger Pau Monné { 17497baeefdSRoger Pau Monné int i; 17597baeefdSRoger Pau Monné 17697baeefdSRoger Pau Monné /* get equivalents from the environment */ 17797baeefdSRoger Pau Monné for (i = 0; howto_names[i].ev != NULL; i++) { 17897baeefdSRoger Pau Monné if (getenv(howto_names[i].ev) != NULL) 17997baeefdSRoger Pau Monné boothowto |= howto_names[i].mask; 18097baeefdSRoger Pau Monné } 18197baeefdSRoger Pau Monné } 18297baeefdSRoger Pau Monné 18397baeefdSRoger Pau Monné static caddr_t 18497baeefdSRoger Pau Monné xen_pv_parse_preload_data(u_int64_t modulep) 18597baeefdSRoger Pau Monné { 18697baeefdSRoger Pau Monné /* Parse the extra boot information given by Xen */ 18797baeefdSRoger Pau Monné xen_pv_set_env(); 18897baeefdSRoger Pau Monné xen_pv_set_boothowto(); 18997baeefdSRoger Pau Monné 19097baeefdSRoger Pau Monné return (NULL); 19197baeefdSRoger Pau Monné } 192