beri_machdep.c revision 270058
1309260Scognet/*- 2309260Scognet * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org> 3309260Scognet * Copyright (c) 2012 Robert N. M. Watson 4309260Scognet * All rights reserved. 5309260Scognet * 6309260Scognet * This software was developed by SRI International and the University of 7309260Scognet * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 8309260Scognet * ("CTSRD"), as part of the DARPA CRASH research programme. 9309260Scognet * 10309260Scognet * Redistribution and use in source and binary forms, with or without 11309260Scognet * modification, are permitted provided that the following conditions 12309260Scognet * are met: 13309260Scognet * 1. Redistributions of source code must retain the above copyright 14309260Scognet * notice, this list of conditions and the following disclaimer. 15309260Scognet * 2. Redistributions in binary form must reproduce the above copyright 16309260Scognet * notice, this list of conditions and the following disclaimer in the 17309260Scognet * documentation and/or other materials provided with the distribution. 18309260Scognet * 19309260Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20309260Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21309260Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22309260Scognet * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23309260Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24309260Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25309260Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26309260Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27309260Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28309260Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29309260Scognet * SUCH DAMAGE. 30309260Scognet */ 31309260Scognet#include <sys/cdefs.h> 32309260Scognet__FBSDID("$FreeBSD: stable/10/sys/mips/beri/beri_machdep.c 270058 2014-08-16 14:14:29Z bz $"); 33309260Scognet 34309260Scognet#include "opt_ddb.h" 35309260Scognet#include "opt_platform.h" 36309260Scognet 37309260Scognet#include <sys/param.h> 38309260Scognet#include <sys/conf.h> 39309260Scognet#include <sys/kernel.h> 40309260Scognet#include <sys/systm.h> 41309260Scognet#include <sys/imgact.h> 42309260Scognet#include <sys/bio.h> 43309260Scognet#include <sys/buf.h> 44309260Scognet#include <sys/bus.h> 45309260Scognet#include <sys/cpu.h> 46309260Scognet#include <sys/cons.h> 47309260Scognet#include <sys/exec.h> 48309260Scognet#include <sys/linker.h> 49309260Scognet#include <sys/ucontext.h> 50309260Scognet#include <sys/proc.h> 51309260Scognet#include <sys/kdb.h> 52309260Scognet#include <sys/ptrace.h> 53309260Scognet#include <sys/reboot.h> 54309260Scognet#include <sys/signalvar.h> 55309260Scognet#include <sys/sysent.h> 56309260Scognet#include <sys/sysproto.h> 57309260Scognet#include <sys/user.h> 58309260Scognet 59309260Scognet#ifdef FDT 60309260Scognet#include <dev/fdt/fdt_common.h> 61309260Scognet#include <dev/ofw/openfirm.h> 62309260Scognet#endif 63309260Scognet 64309260Scognet#include <vm/vm.h> 65309260Scognet#include <vm/vm_object.h> 66309260Scognet#include <vm/vm_page.h> 67309260Scognet 68309260Scognet#include <machine/clock.h> 69309260Scognet#include <machine/cpu.h> 70309260Scognet#include <machine/cpuregs.h> 71309260Scognet#include <machine/hwfunc.h> 72309260Scognet#include <machine/md_var.h> 73309260Scognet#include <machine/metadata.h> 74309260Scognet#include <machine/pmap.h> 75309260Scognet#include <machine/trap.h> 76309260Scognet 77309260Scognetextern int *edata; 78309260Scognetextern int *end; 79309260Scognet 80309260Scognetvoid 81309260Scognetplatform_cpu_init() 82309260Scognet{ 83309260Scognet /* Nothing special */ 84309260Scognet} 85309260Scognet 86309260Scognetstatic void 87309260Scognetmips_init(void) 88309260Scognet{ 89309260Scognet int i; 90309260Scognet 91309260Scognet for (i = 0; i < 10; i++) { 92309260Scognet phys_avail[i] = 0; 93309260Scognet } 94309260Scognet 95309260Scognet /* phys_avail regions are in bytes */ 96309260Scognet phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end); 97309260Scognet phys_avail[1] = ctob(realmem); 98309260Scognet 99309260Scognet dump_avail[0] = phys_avail[0]; 100309260Scognet dump_avail[1] = phys_avail[1]; 101309260Scognet 102309260Scognet physmem = realmem; 103309260Scognet 104309260Scognet init_param1(); 105309260Scognet init_param2(physmem); 106309260Scognet mips_cpu_init(); 107309260Scognet pmap_bootstrap(); 108309260Scognet mips_proc0_init(); 109309260Scognet mutex_init(); 110309260Scognet kdb_init(); 111309260Scognet#ifdef KDB 112309260Scognet if (boothowto & RB_KDB) 113309260Scognet kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 114309260Scognet#endif 115309260Scognet} 116309260Scognet 117309260Scognet/* 118309260Scognet * Perform a board-level soft-reset. 119309260Scognet */ 120309260Scognetvoid 121309260Scognetplatform_reset(void) 122309260Scognet{ 123309260Scognet 124309260Scognet /* XXX SMP will likely require us to do more. */ 125309260Scognet __asm__ __volatile__( 126309260Scognet "mfc0 $k0, $12\n\t" 127309260Scognet "li $k1, 0x00100000\n\t" 128309260Scognet "or $k0, $k0, $k1\n\t" 129309260Scognet "mtc0 $k0, $12\n"); 130309260Scognet for( ; ; ) 131309260Scognet __asm__ __volatile("wait"); 132309260Scognet} 133309260Scognet 134309260Scognet#ifdef FDT 135309260Scognet/* Parse cmd line args as env - copied from xlp_machdep. */ 136309260Scognet/* XXX-BZ this should really be centrally provided for all (boot) code. */ 137309260Scognetstatic void 138309260Scognet_parse_bootargs(char *cmdline) 139309260Scognet{ 140309260Scognet char *n, *v; 141309260Scognet 142309260Scognet while ((v = strsep(&cmdline, " \n")) != NULL) { 143309260Scognet if (*v == '\0') 144309260Scognet continue; 145309260Scognet if (*v == '-') { 146309260Scognet while (*v != '\0') { 147309260Scognet v++; 148309260Scognet switch (*v) { 149309260Scognet case 'a': boothowto |= RB_ASKNAME; break; 150309260Scognet /* Someone should simulate that ;-) */ 151309260Scognet case 'C': boothowto |= RB_CDROM; break; 152309260Scognet case 'd': boothowto |= RB_KDB; break; 153309260Scognet case 'D': boothowto |= RB_MULTIPLE; break; 154309260Scognet case 'm': boothowto |= RB_MUTE; break; 155309260Scognet case 'g': boothowto |= RB_GDB; break; 156309260Scognet case 'h': boothowto |= RB_SERIAL; break; 157309260Scognet case 'p': boothowto |= RB_PAUSE; break; 158309260Scognet case 'r': boothowto |= RB_DFLTROOT; break; 159309260Scognet case 's': boothowto |= RB_SINGLE; break; 160309260Scognet case 'v': boothowto |= RB_VERBOSE; break; 161309260Scognet } 162309260Scognet } 163309260Scognet } else { 164309260Scognet n = strsep(&v, "="); 165309260Scognet if (v == NULL) 166309260Scognet setenv(n, "1"); 167309260Scognet else 168309260Scognet setenv(n, v); 169309260Scognet } 170309260Scognet } 171309260Scognet} 172309260Scognet#endif 173309260Scognet 174309260Scognetvoid 175309260Scognetplatform_start(__register_t a0, __register_t a1, __register_t a2, 176309260Scognet __register_t a3) 177309260Scognet{ 178309260Scognet vm_offset_t kernend; 179309260Scognet uint64_t platform_counter_freq; 180309260Scognet int argc = a0; 181309260Scognet char **argv = (char **)a1; 182309260Scognet char **envp = (char **)a2; 183309260Scognet unsigned int memsize = a3; 184309260Scognet#ifdef FDT 185309260Scognet char buf[2048]; /* early stack supposedly big enough */ 186309260Scognet vm_offset_t dtbp; 187309260Scognet phandle_t chosen; 188309260Scognet void *kmdp; 189309260Scognet#endif 190309260Scognet int i; 191309260Scognet 192309260Scognet /* clear the BSS and SBSS segments */ 193309260Scognet kernend = (vm_offset_t)&end; 194309260Scognet memset(&edata, 0, kernend - (vm_offset_t)(&edata)); 195309260Scognet 196309260Scognet mips_postboot_fixup(); 197309260Scognet 198309260Scognet mips_pcpu0_init(); 199309260Scognet 200309260Scognet#ifdef FDT 201309260Scognet /* 202309260Scognet * Find the dtb passed in by the boot loader (currently fictional). 203309260Scognet */ 204309260Scognet kmdp = preload_search_by_type("elf kernel"); 205309260Scognet if (kmdp != NULL) 206309260Scognet dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t); 207309260Scognet else 208309260Scognet dtbp = (vm_offset_t)NULL; 209309260Scognet 210309260Scognet#if defined(FDT_DTB_STATIC) 211309260Scognet /* 212309260Scognet * In case the device tree blob was not retrieved (from metadata) try 213309260Scognet * to use the statically embedded one. 214309260Scognet */ 215309260Scognet if (dtbp == (vm_offset_t)NULL) 216309260Scognet dtbp = (vm_offset_t)&fdt_static_dtb; 217309260Scognet#else 218309260Scognet#error "Non-static FDT not yet supported on BERI" 219309260Scognet#endif 220309260Scognet 221309260Scognet if (OF_install(OFW_FDT, 0) == FALSE) 222309260Scognet while (1); 223309260Scognet if (OF_init((void *)dtbp) != 0) 224309260Scognet while (1); 225309260Scognet 226309260Scognet /* 227309260Scognet * Get bootargs from FDT if specified. 228309260Scognet */ 229309260Scognet chosen = OF_finddevice("/chosen"); 230309260Scognet if (OF_getprop(chosen, "bootargs", buf, sizeof(buf)) != -1) 231309260Scognet _parse_bootargs(buf); 232309260Scognet#endif 233309260Scognet 234309260Scognet /* 235309260Scognet * XXXRW: We have no way to compare wallclock time to cycle rate on 236309260Scognet * BERI, so for now assume we run at the MALTA default (100MHz). 237309260Scognet */ 238309260Scognet platform_counter_freq = MIPS_DEFAULT_HZ; 239309260Scognet mips_timer_early_init(platform_counter_freq); 240309260Scognet 241309260Scognet cninit(); 242309260Scognet printf("entry: platform_start()\n"); 243309260Scognet 244309260Scognet bootverbose = 1; 245309260Scognet if (bootverbose) { 246309260Scognet printf("cmd line: "); 247309260Scognet for (i = 0; i < argc; i++) 248309260Scognet printf("%s ", argv[i]); 249309260Scognet printf("\n"); 250309260Scognet 251309260Scognet printf("envp:\n"); 252309260Scognet for (i = 0; envp[i]; i += 2) 253309260Scognet printf("\t%s = %s\n", envp[i], envp[i+1]); 254309260Scognet 255309260Scognet printf("memsize = %08x\n", memsize); 256309260Scognet } 257309260Scognet 258309260Scognet realmem = btoc(memsize); 259309260Scognet mips_init(); 260309260Scognet 261309260Scognet mips_timer_init_params(platform_counter_freq, 0); 262309260Scognet} 263309260Scognet