1239671Srwatson/*- 2239671Srwatson * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org> 3264897Sbrooks * Copyright (c) 2012-2014 Robert N. M. Watson 4239671Srwatson * All rights reserved. 5239671Srwatson * 6244899Srwatson * This software was developed by SRI International and the University of 7244899Srwatson * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 8244899Srwatson * ("CTSRD"), as part of the DARPA CRASH research programme. 9244899Srwatson * 10239671Srwatson * Redistribution and use in source and binary forms, with or without 11239671Srwatson * modification, are permitted provided that the following conditions 12239671Srwatson * are met: 13239671Srwatson * 1. Redistributions of source code must retain the above copyright 14239671Srwatson * notice, this list of conditions and the following disclaimer. 15239671Srwatson * 2. Redistributions in binary form must reproduce the above copyright 16239671Srwatson * notice, this list of conditions and the following disclaimer in the 17239671Srwatson * documentation and/or other materials provided with the distribution. 18239671Srwatson * 19239671Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20239671Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21239671Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22239671Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23239671Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24239671Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25239671Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26239671Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27239671Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28239671Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29239671Srwatson * SUCH DAMAGE. 30239671Srwatson */ 31239671Srwatson#include <sys/cdefs.h> 32239671Srwatson__FBSDID("$FreeBSD$"); 33239671Srwatson 34239671Srwatson#include "opt_ddb.h" 35244899Srwatson#include "opt_platform.h" 36239671Srwatson 37239671Srwatson#include <sys/param.h> 38239671Srwatson#include <sys/conf.h> 39239671Srwatson#include <sys/kernel.h> 40239671Srwatson#include <sys/systm.h> 41239671Srwatson#include <sys/imgact.h> 42239671Srwatson#include <sys/bio.h> 43239671Srwatson#include <sys/buf.h> 44239671Srwatson#include <sys/bus.h> 45239671Srwatson#include <sys/cpu.h> 46239671Srwatson#include <sys/cons.h> 47239671Srwatson#include <sys/exec.h> 48245330Srwatson#include <sys/linker.h> 49239671Srwatson#include <sys/ucontext.h> 50239671Srwatson#include <sys/proc.h> 51239671Srwatson#include <sys/kdb.h> 52239671Srwatson#include <sys/ptrace.h> 53239671Srwatson#include <sys/reboot.h> 54239671Srwatson#include <sys/signalvar.h> 55239671Srwatson#include <sys/sysent.h> 56239671Srwatson#include <sys/sysproto.h> 57239671Srwatson#include <sys/user.h> 58239671Srwatson 59244942Srwatson#ifdef FDT 60244899Srwatson#include <dev/fdt/fdt_common.h> 61244899Srwatson#include <dev/ofw/openfirm.h> 62244942Srwatson#endif 63244899Srwatson 64239671Srwatson#include <vm/vm.h> 65239671Srwatson#include <vm/vm_object.h> 66239671Srwatson#include <vm/vm_page.h> 67239671Srwatson 68264897Sbrooks#include <machine/bootinfo.h> 69239671Srwatson#include <machine/clock.h> 70239671Srwatson#include <machine/cpu.h> 71239671Srwatson#include <machine/cpuregs.h> 72239671Srwatson#include <machine/hwfunc.h> 73239671Srwatson#include <machine/md_var.h> 74245330Srwatson#include <machine/metadata.h> 75239671Srwatson#include <machine/pmap.h> 76239671Srwatson#include <machine/trap.h> 77239671Srwatson 78239671Srwatsonextern int *edata; 79239671Srwatsonextern int *end; 80239671Srwatson 81239671Srwatsonvoid 82239671Srwatsonplatform_cpu_init() 83239671Srwatson{ 84239671Srwatson /* Nothing special */ 85239671Srwatson} 86239671Srwatson 87239671Srwatsonstatic void 88239671Srwatsonmips_init(void) 89239671Srwatson{ 90239671Srwatson int i; 91275858Sbr#ifdef FDT 92275858Sbr struct mem_region mr[FDT_MEM_REGIONS]; 93296265Sandrew uint64_t val; 94296189Swma int mr_cnt; 95275858Sbr int j; 96275858Sbr#endif 97239671Srwatson 98239671Srwatson for (i = 0; i < 10; i++) { 99239671Srwatson phys_avail[i] = 0; 100239671Srwatson } 101239671Srwatson 102239671Srwatson /* phys_avail regions are in bytes */ 103239671Srwatson phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end); 104239671Srwatson phys_avail[1] = ctob(realmem); 105239671Srwatson 106239671Srwatson dump_avail[0] = phys_avail[0]; 107239671Srwatson dump_avail[1] = phys_avail[1]; 108239671Srwatson 109239671Srwatson physmem = realmem; 110239671Srwatson 111275858Sbr#ifdef FDT 112275858Sbr if (fdt_get_mem_regions(mr, &mr_cnt, &val) == 0) { 113275858Sbr 114275858Sbr physmem = btoc(val); 115275858Sbr 116275858Sbr KASSERT((phys_avail[0] >= mr[0].mr_start) && \ 117275858Sbr (phys_avail[0] < (mr[0].mr_start + mr[0].mr_size)), 118275858Sbr ("First region is not within FDT memory range")); 119275858Sbr 120275858Sbr /* Limit size of the first region */ 121275936Sbr phys_avail[1] = (mr[0].mr_start + MIN(mr[0].mr_size, ctob(realmem))); 122275858Sbr dump_avail[1] = phys_avail[1]; 123275858Sbr 124275858Sbr /* Add the rest of regions */ 125275858Sbr for (i = 1, j = 2; i < mr_cnt; i++, j+=2) { 126275858Sbr phys_avail[j] = mr[i].mr_start; 127275936Sbr phys_avail[j+1] = (mr[i].mr_start + mr[i].mr_size); 128275858Sbr dump_avail[j] = phys_avail[j]; 129275858Sbr dump_avail[j+1] = phys_avail[j+1]; 130275858Sbr } 131275858Sbr } 132275858Sbr#endif 133275858Sbr 134239671Srwatson init_param1(); 135239671Srwatson init_param2(physmem); 136239671Srwatson mips_cpu_init(); 137239671Srwatson pmap_bootstrap(); 138239671Srwatson mips_proc0_init(); 139239671Srwatson mutex_init(); 140239671Srwatson kdb_init(); 141239671Srwatson#ifdef KDB 142239671Srwatson if (boothowto & RB_KDB) 143239671Srwatson kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 144239671Srwatson#endif 145239671Srwatson} 146239671Srwatson 147239671Srwatson/* 148239671Srwatson * Perform a board-level soft-reset. 149239671Srwatson */ 150239671Srwatsonvoid 151239671Srwatsonplatform_reset(void) 152239671Srwatson{ 153239671Srwatson 154256745Sbrooks /* XXX SMP will likely require us to do more. */ 155256745Sbrooks __asm__ __volatile__( 156256745Sbrooks "mfc0 $k0, $12\n\t" 157256745Sbrooks "li $k1, 0x00100000\n\t" 158256745Sbrooks "or $k0, $k0, $k1\n\t" 159256745Sbrooks "mtc0 $k0, $12\n"); 160256745Sbrooks for( ; ; ) 161256745Sbrooks __asm__ __volatile("wait"); 162239671Srwatson} 163239671Srwatson 164265089Sbz#ifdef FDT 165265089Sbz/* Parse cmd line args as env - copied from xlp_machdep. */ 166265089Sbz/* XXX-BZ this should really be centrally provided for all (boot) code. */ 167265089Sbzstatic void 168265089Sbz_parse_bootargs(char *cmdline) 169265089Sbz{ 170265089Sbz char *n, *v; 171265089Sbz 172265089Sbz while ((v = strsep(&cmdline, " \n")) != NULL) { 173265089Sbz if (*v == '\0') 174265089Sbz continue; 175265089Sbz if (*v == '-') { 176265089Sbz while (*v != '\0') { 177265089Sbz v++; 178265089Sbz switch (*v) { 179265089Sbz case 'a': boothowto |= RB_ASKNAME; break; 180265089Sbz /* Someone should simulate that ;-) */ 181265089Sbz case 'C': boothowto |= RB_CDROM; break; 182265089Sbz case 'd': boothowto |= RB_KDB; break; 183265089Sbz case 'D': boothowto |= RB_MULTIPLE; break; 184265089Sbz case 'm': boothowto |= RB_MUTE; break; 185265089Sbz case 'g': boothowto |= RB_GDB; break; 186265089Sbz case 'h': boothowto |= RB_SERIAL; break; 187265089Sbz case 'p': boothowto |= RB_PAUSE; break; 188265089Sbz case 'r': boothowto |= RB_DFLTROOT; break; 189265089Sbz case 's': boothowto |= RB_SINGLE; break; 190265089Sbz case 'v': boothowto |= RB_VERBOSE; break; 191265089Sbz } 192265089Sbz } 193265089Sbz } else { 194265089Sbz n = strsep(&v, "="); 195265089Sbz if (v == NULL) 196273234Sdavide kern_setenv(n, "1"); 197265089Sbz else 198273234Sdavide kern_setenv(n, v); 199265089Sbz } 200265089Sbz } 201265089Sbz} 202265089Sbz#endif 203265089Sbz 204239671Srwatsonvoid 205239671Srwatsonplatform_start(__register_t a0, __register_t a1, __register_t a2, 206239671Srwatson __register_t a3) 207239671Srwatson{ 208264897Sbrooks struct bootinfo *bootinfop; 209239671Srwatson vm_offset_t kernend; 210239671Srwatson uint64_t platform_counter_freq; 211239671Srwatson int argc = a0; 212239671Srwatson char **argv = (char **)a1; 213239671Srwatson char **envp = (char **)a2; 214264897Sbrooks long memsize; 215245330Srwatson#ifdef FDT 216265089Sbz char buf[2048]; /* early stack supposedly big enough */ 217245330Srwatson vm_offset_t dtbp; 218265089Sbz phandle_t chosen; 219245330Srwatson void *kmdp; 220245330Srwatson#endif 221239671Srwatson int i; 222239671Srwatson 223239671Srwatson /* clear the BSS and SBSS segments */ 224239671Srwatson kernend = (vm_offset_t)&end; 225239671Srwatson memset(&edata, 0, kernend - (vm_offset_t)(&edata)); 226239671Srwatson 227239671Srwatson mips_postboot_fixup(); 228239671Srwatson 229239671Srwatson mips_pcpu0_init(); 230239671Srwatson 231264897Sbrooks /* 232264897Sbrooks * Over time, we've changed out boot-time binary interface for the 233264897Sbrooks * kernel. Miniboot simply provides a 'memsize' in a3, whereas the 234264897Sbrooks * FreeBSD boot loader provides a 'bootinfo *' in a3. While slightly 235264897Sbrooks * grody, we support both here by detecting 'pointer-like' values in 236264897Sbrooks * a3 and assuming physical memory can never be that back. 237264897Sbrooks * 238264897Sbrooks * XXXRW: Pull more values than memsize out of bootinfop -- e.g., 239264897Sbrooks * module information. 240264897Sbrooks */ 241264897Sbrooks if (a3 >= 0x9800000000000000ULL) { 242264897Sbrooks bootinfop = (void *)a3; 243264897Sbrooks memsize = bootinfop->bi_memsize; 244264897Sbrooks preload_metadata = (caddr_t)bootinfop->bi_modulep; 245264897Sbrooks } else { 246264897Sbrooks bootinfop = NULL; 247264897Sbrooks memsize = a3; 248264897Sbrooks } 249264897Sbrooks 250245329Srwatson#ifdef FDT 251245330Srwatson /* 252245330Srwatson * Find the dtb passed in by the boot loader (currently fictional). 253245330Srwatson */ 254245330Srwatson kmdp = preload_search_by_type("elf kernel"); 255287000Sroyger dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t); 256245330Srwatson 257245330Srwatson#if defined(FDT_DTB_STATIC) 258245330Srwatson /* 259245330Srwatson * In case the device tree blob was not retrieved (from metadata) try 260245330Srwatson * to use the statically embedded one. 261245330Srwatson */ 262245330Srwatson if (dtbp == (vm_offset_t)NULL) 263245330Srwatson dtbp = (vm_offset_t)&fdt_static_dtb; 264245330Srwatson#else 265245330Srwatson#error "Non-static FDT not yet supported on BERI" 266245329Srwatson#endif 267245329Srwatson 268245329Srwatson if (OF_install(OFW_FDT, 0) == FALSE) 269245329Srwatson while (1); 270259265Sbz if (OF_init((void *)dtbp) != 0) 271245329Srwatson while (1); 272264605Sbz 273264605Sbz /* 274264897Sbrooks * Configure more boot-time parameters passed in by loader. 275264605Sbz */ 276264897Sbrooks boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 277293045Sian init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *), 0); 278245329Srwatson 279239671Srwatson /* 280265089Sbz * Get bootargs from FDT if specified. 281265089Sbz */ 282265089Sbz chosen = OF_finddevice("/chosen"); 283265089Sbz if (OF_getprop(chosen, "bootargs", buf, sizeof(buf)) != -1) 284265089Sbz _parse_bootargs(buf); 285265089Sbz#endif 286265089Sbz 287265089Sbz /* 288239671Srwatson * XXXRW: We have no way to compare wallclock time to cycle rate on 289239671Srwatson * BERI, so for now assume we run at the MALTA default (100MHz). 290239671Srwatson */ 291239671Srwatson platform_counter_freq = MIPS_DEFAULT_HZ; 292239671Srwatson mips_timer_early_init(platform_counter_freq); 293239671Srwatson 294239671Srwatson cninit(); 295239671Srwatson printf("entry: platform_start()\n"); 296239671Srwatson 297239671Srwatson bootverbose = 1; 298239671Srwatson if (bootverbose) { 299239671Srwatson printf("cmd line: "); 300239671Srwatson for (i = 0; i < argc; i++) 301239671Srwatson printf("%s ", argv[i]); 302239671Srwatson printf("\n"); 303239671Srwatson 304239671Srwatson printf("envp:\n"); 305239671Srwatson for (i = 0; envp[i]; i += 2) 306239671Srwatson printf("\t%s = %s\n", envp[i], envp[i+1]); 307239671Srwatson 308264897Sbrooks if (bootinfop != NULL) 309264897Sbrooks printf("bootinfo found at %p\n", bootinfop); 310264897Sbrooks 311264897Sbrooks printf("memsize = %p\n", (void *)memsize); 312239671Srwatson } 313239671Srwatson 314239671Srwatson realmem = btoc(memsize); 315239671Srwatson mips_init(); 316239671Srwatson 317239671Srwatson mips_timer_init_params(platform_counter_freq, 0); 318239671Srwatson} 319