11.8Sthorpej/* $NetBSD: machdep.c,v 1.8 2024/03/05 14:15:31 thorpej Exp $ */ 21.1Smrg 31.1Smrg/* 41.1Smrg * Copyright 2000, 2001 51.1Smrg * Broadcom Corporation. All rights reserved. 61.1Smrg * 71.1Smrg * This software is furnished under license and may be used and copied only 81.1Smrg * in accordance with the following terms and conditions. Subject to these 91.1Smrg * conditions, you may download, copy, install, use, modify and distribute 101.1Smrg * modified or unmodified copies of this software in source and/or binary 111.1Smrg * form. No title or ownership is transferred hereby. 121.1Smrg * 131.1Smrg * 1) Any source code used, modified or distributed must reproduce and 141.1Smrg * retain this copyright notice and list of conditions as they appear in 151.1Smrg * the source file. 161.1Smrg * 171.1Smrg * 2) No right is granted to use any trade name, trademark, or logo of 181.1Smrg * Broadcom Corporation. The "Broadcom Corporation" name may not be 191.1Smrg * used to endorse or promote products derived from this software 201.1Smrg * without the prior written permission of Broadcom Corporation. 211.1Smrg * 221.1Smrg * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 231.1Smrg * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 241.1Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 251.1Smrg * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 261.1Smrg * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 271.1Smrg * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 281.1Smrg * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 291.1Smrg * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 301.1Smrg * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 311.1Smrg * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 321.1Smrg * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 331.1Smrg */ 341.1Smrg 351.1Smrg/* 361.1Smrg * Copyright (c) 2000 Soren S. Jorvang. All rights reserved. 371.1Smrg * 381.1Smrg * Redistribution and use in source and binary forms, with or without 391.1Smrg * modification, are permitted provided that the following conditions 401.1Smrg * are met: 411.1Smrg * 1. Redistributions of source code must retain the above copyright 421.1Smrg * notice, this list of conditions, and the following disclaimer. 431.1Smrg * 2. Redistributions in binary form must reproduce the above copyright 441.1Smrg * notice, this list of conditions and the following disclaimer in the 451.1Smrg * documentation and/or other materials provided with the distribution. 461.1Smrg * 471.1Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 481.1Smrg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 491.1Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 501.1Smrg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 511.1Smrg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 521.1Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 531.1Smrg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 541.1Smrg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 551.1Smrg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 561.1Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 571.1Smrg * SUCH DAMAGE. 581.1Smrg */ 591.1Smrg 601.1Smrg#include <sys/cdefs.h> 611.8Sthorpej__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.8 2024/03/05 14:15:31 thorpej Exp $"); 621.1Smrg 631.1Smrg#include "opt_ddb.h" 641.1Smrg#include "opt_execfmt.h" 651.1Smrg#include "opt_modular.h" 661.1Smrg 671.1Smrg#include <sys/param.h> 681.1Smrg#include <sys/buf.h> 691.1Smrg#include <sys/conf.h> 701.1Smrg#include <sys/cpu.h> 711.1Smrg#include <sys/device.h> 721.1Smrg#include <sys/exec.h> 731.1Smrg#include <sys/file.h> 741.1Smrg#include <sys/intr.h> 751.1Smrg#include <sys/kcore.h> 761.1Smrg#include <sys/kernel.h> 771.1Smrg#include <sys/ksyms.h> 781.1Smrg#include <sys/mbuf.h> 791.1Smrg#include <sys/mount.h> 801.1Smrg#include <sys/msgbuf.h> 811.1Smrg#include <sys/proc.h> 821.1Smrg#include <sys/reboot.h> 831.1Smrg#include <sys/syscallargs.h> 841.1Smrg#include <sys/systm.h> 851.1Smrg 861.1Smrg#include <uvm/uvm_extern.h> 871.1Smrg 881.1Smrg#include <mips/locore.h> 891.1Smrg#include <mips/psl.h> 901.1Smrg#include <mips/pte.h> 911.1Smrg#include <mips/reg.h> 921.1Smrg 931.1Smrg#include <mips/cfe/cfe_api.h> 941.1Smrg 951.2Smrg#include <evbmips/sbmips/autoconf.h> 961.2Smrg#include <evbmips/sbmips/swarm.h> 971.2Smrg#include <evbmips/sbmips/systemsw.h> 981.1Smrg 991.1Smrg#if 0 /* XXXCGD */ 1001.2Smrg#include <evbmips/sbmips/nvram.h> 1011.1Smrg#endif /* XXXCGD */ 1021.2Smrg#include <evbmips/sbmips/leds.h> 1031.1Smrg 1041.1Smrg#include <mips/sibyte/dev/sbbuswatchvar.h> 1051.1Smrg 1061.1Smrg#include "ksyms.h" 1071.1Smrg 1081.1Smrg#if NKSYMS || defined(DDB) || defined(MODULAR) 1091.1Smrg#include <mips/db_machdep.h> 1101.1Smrg#include <ddb/db_access.h> 1111.1Smrg#include <ddb/db_sym.h> 1121.1Smrg#include <ddb/db_extern.h> 1131.1Smrg#include <sys/exec_elf.h> 1141.1Smrg#endif 1151.1Smrg 1161.1Smrg#include <dev/cons.h> 1171.1Smrg 1181.1Smrg#if NKSYMS || defined(DDB) || defined(MODULAR) 1191.1Smrg/* start and end of kernel symbol table */ 1201.1Smrgvoid *ksym_start, *ksym_end; 1211.1Smrg#endif 1221.1Smrg 1231.1Smrg/* Maps for VM objects. */ 1241.1Smrgstruct vm_map *phys_map = NULL; 1251.1Smrg 1261.1Smrgchar bootstring[512]; /* Boot command */ 1271.1Smrgint netboot; /* Are we netbooting? */ 1281.1Smrgint cfe_present; 1291.1Smrg 1301.1Smrgstruct bootinfo_v1 bootinfo; 1311.1Smrg 1321.1Smrgphys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 1331.1Smrgint mem_cluster_cnt; 1341.1Smrg 1351.1Smrgvoid configure(void); 1361.1Smrgvoid mach_init(long, long, long, long); 1371.1Smrg 1381.1Smrgextern void *esym; 1391.1Smrg 1401.5Ssimonb#ifdef _LP64 1411.5Ssimonb/* 1421.5Ssimonb * We do this KSEG0 to PHYS to KSEG0 dance if running 64-bit because 1431.5Ssimonb * CFE passes in parameters as 32-bit addresses. When used as a 64-bit 1441.5Ssimonb * address these CFE parameters are in user (XKUSEG) space and can't be 1451.5Ssimonb * accessed! Convert these to a physical address and and then to the 1461.5Ssimonb * proper KSEG0 address so we can use them in the kernel. 1471.5Ssimonb */ 1481.5Ssimonb#define CFE_TO_KERNEL_PTR(x) MIPS_PHYS_TO_KSEG0(MIPS_KSEG0_TO_PHYS(x)) 1491.5Ssimonb#else 1501.5Ssimonb#define CFE_TO_KERNEL_PTR(x) (x) 1511.5Ssimonb#endif 1521.5Ssimonb 1531.1Smrg/* 1541.1Smrg * Do all the stuff that locore normally does before calling main(). 1551.1Smrg */ 1561.1Smrgvoid 1571.1Smrgmach_init(long fwhandle, long magic, long bootdata, long reserved) 1581.1Smrg{ 1591.1Smrg void *kernend; 1601.1Smrg extern char edata[], end[]; 1611.1Smrg uint32_t config; 1621.1Smrg 1631.1Smrg /* XXX this code must run on the target CPU */ 1641.1Smrg config = mips3_cp0_config_read(); 1651.1Smrg config &= ~MIPS3_CONFIG_K0_MASK; 1661.1Smrg config |= 0x05; /* XXX. cacheable coherent */ 1671.1Smrg mips3_cp0_config_write(config); 1681.1Smrg 1691.1Smrg /* Zero BSS. XXXCGD: uh, is this really necessary still? */ 1701.1Smrg memset(edata, 0, end - edata); 1711.1Smrg 1721.1Smrg /* 1731.1Smrg * Copy the bootinfo structure from the boot loader. 1741.1Smrg * this has to be done before mips_vector_init is 1751.1Smrg * called because we may need CFE's TLB handler 1761.1Smrg */ 1771.1Smrg 1781.1Smrg if (magic == BOOTINFO_MAGIC) 1791.1Smrg memcpy(&bootinfo, (struct bootinfo_v1 *)bootdata, 1801.1Smrg sizeof bootinfo); 1811.1Smrg else if (reserved == CFE_EPTSEAL) { 1821.1Smrg magic = BOOTINFO_MAGIC; 1831.1Smrg memset(&bootinfo, 0, sizeof bootinfo); 1841.1Smrg bootinfo.version = BOOTINFO_VERSION; 1851.1Smrg bootinfo.fwhandle = fwhandle; 1861.1Smrg bootinfo.fwentry = bootdata; 1871.1Smrg bootinfo.ssym = (vaddr_t)end; 1881.1Smrg bootinfo.esym = (vaddr_t)end; 1891.1Smrg } 1901.1Smrg 1911.1Smrg kernend = (void *)mips_round_page(end); 1921.1Smrg#if NKSYMS || defined(DDB) || defined(MODULAR) 1931.1Smrg if (magic == BOOTINFO_MAGIC) { 1941.5Ssimonb ksym_start = (void *)CFE_TO_KERNEL_PTR(bootinfo.ssym); 1951.5Ssimonb ksym_end = (void *)CFE_TO_KERNEL_PTR(bootinfo.esym); 1961.1Smrg kernend = (void *)mips_round_page((vaddr_t)ksym_end); 1971.1Smrg } 1981.1Smrg#endif 1991.1Smrg 2001.1Smrg consinit(); 2011.1Smrg 2021.1Smrg uvm_md_init(); 2031.1Smrg 2041.1Smrg /* 2051.1Smrg * Copy exception-dispatch code down to exception vector. 2061.1Smrg * Initialize locore-function vector. 2071.1Smrg * Clear out the I and D caches. 2081.1Smrg */ 2091.1Smrg#ifdef MULTIPROCESSOR 2101.1Smrg mips_vector_init(NULL, true); 2111.1Smrg#else 2121.1Smrg mips_vector_init(NULL, false); 2131.1Smrg#endif 2141.1Smrg 2151.1Smrg mips_locoresw.lsw_bus_error = sibyte_bus_watch_check; 2161.1Smrg 2171.1Smrg sb1250_ipl_map_init(); 2181.1Smrg 2191.1Smrg#ifdef DEBUG 2201.1Smrg printf("fwhandle=%08X magic=%08X bootdata=%08X reserved=%08X\n", 2211.1Smrg (u_int)fwhandle, (u_int)magic, (u_int)bootdata, (u_int)reserved); 2221.1Smrg#endif 2231.1Smrg 2241.1Smrg cpu_setmodel("sb1250"); 2251.1Smrg 2261.1Smrg if (magic == BOOTINFO_MAGIC) { 2271.1Smrg int idx; 2281.1Smrg int added; 2291.1Smrg uint64_t start, len, type; 2301.1Smrg 2311.5Ssimonb cfe_init(CFE_TO_KERNEL_PTR(bootinfo.fwhandle), 2321.5Ssimonb CFE_TO_KERNEL_PTR(bootinfo.fwentry)); 2331.1Smrg cfe_present = 1; 2341.1Smrg 2351.1Smrg idx = 0; 2361.1Smrg physmem = 0; 2371.1Smrg mem_cluster_cnt = 0; 2381.1Smrg while (cfe_enummem(idx, 0, &start, &len, &type) == 0) { 2391.1Smrg added = 0; 2401.4Ssimonb printf("Memory Block #%d start %08"PRIx64" len %08"PRIx64": %s: ", 2411.1Smrg idx, start, len, (type == CFE_MI_AVAILABLE) ? 2421.1Smrg "Available" : "Reserved"); 2431.1Smrg if ((type == CFE_MI_AVAILABLE) && 2441.1Smrg (mem_cluster_cnt < VM_PHYSSEG_MAX)) { 2451.1Smrg /* 2461.1Smrg * XXX Ignore memory above 256MB for now, it 2471.1Smrg * XXX needs special handling. 2481.1Smrg */ 2491.1Smrg if (start < (256*1024*1024)) { 2501.1Smrg physmem += btoc(((int) len)); 2511.1Smrg mem_clusters[mem_cluster_cnt].start = 2521.1Smrg (long) start; 2531.1Smrg mem_clusters[mem_cluster_cnt].size = 2541.1Smrg (long) len; 2551.1Smrg mem_cluster_cnt++; 2561.1Smrg added = 1; 2571.1Smrg } 2581.1Smrg } 2591.1Smrg if (added) 2601.1Smrg printf("added to map\n"); 2611.1Smrg else 2621.1Smrg printf("not added to map\n"); 2631.1Smrg idx++; 2641.1Smrg } 2651.1Smrg 2661.1Smrg } else { 2671.1Smrg /* 2681.1Smrg * Handle the case of not being called from the firmware. 2691.1Smrg */ 2701.1Smrg /* XXX hardwire to 32MB; should be kernel config option */ 2711.1Smrg physmem = 32 * 1024 * 1024 / 4096; 2721.1Smrg mem_clusters[0].start = 0; 2731.1Smrg mem_clusters[0].size = ctob(physmem); 2741.1Smrg mem_cluster_cnt = 1; 2751.1Smrg } 2761.1Smrg 2771.1Smrg 2781.1Smrg for (u_int i = 0; i < sizeof(bootinfo.boot_flags); i++) { 2791.1Smrg switch (bootinfo.boot_flags[i]) { 2801.1Smrg case '\0': 2811.1Smrg break; 2821.1Smrg case ' ': 2831.1Smrg continue; 2841.1Smrg case '-': 2851.1Smrg while (bootinfo.boot_flags[i] != ' ' && 2861.1Smrg bootinfo.boot_flags[i] != '\0') { 2871.1Smrg switch (bootinfo.boot_flags[i]) { 2881.1Smrg case 'a': 2891.1Smrg boothowto |= RB_ASKNAME; 2901.1Smrg break; 2911.1Smrg case 'd': 2921.1Smrg boothowto |= RB_KDB; 2931.1Smrg break; 2941.1Smrg case 's': 2951.1Smrg boothowto |= RB_SINGLE; 2961.1Smrg break; 2971.1Smrg } 2981.1Smrg i++; 2991.1Smrg } 3001.1Smrg } 3011.1Smrg } 3021.1Smrg 3031.1Smrg /* 3041.1Smrg * Load the rest of the available pages into the VM system. 3051.1Smrg */ 3061.1Smrg mips_page_physload(MIPS_KSEG0_START, (vaddr_t) kernend, 3071.1Smrg mem_clusters, mem_cluster_cnt, NULL, 0); 3081.1Smrg 3091.1Smrg /* 3101.1Smrg * Initialize error message buffer (at end of core). 3111.1Smrg */ 3121.1Smrg mips_init_msgbuf(); 3131.1Smrg 3141.1Smrg pmap_bootstrap(); 3151.1Smrg 3161.1Smrg /* 3171.1Smrg * Allocate uarea for lwp0 and set it. 3181.1Smrg */ 3191.1Smrg mips_init_lwp0_uarea(); 3201.1Smrg 3211.1Smrg /* 3221.1Smrg * Initialize debuggers, and break into them, if appropriate. 3231.1Smrg */ 3241.1Smrg#if NKSYMS || defined(DDB) || defined(MODULAR) 3251.1Smrg ksyms_addsyms_elf(((uintptr_t)ksym_end - (uintptr_t)ksym_start), 3261.1Smrg ksym_start, ksym_end); 3271.1Smrg#endif 3281.1Smrg 3291.1Smrg if (boothowto & RB_KDB) { 3301.1Smrg#if defined(DDB) 3311.1Smrg Debugger(); 3321.1Smrg#endif 3331.1Smrg } 3341.1Smrg 3351.1Smrg#ifdef MULTIPROCESSOR 3361.6Sandvar mips_fixup_exceptions(mips_fixup_zero_relative, NULL); 3371.1Smrg#endif 3381.1Smrg} 3391.1Smrg 3401.1Smrg/* 3411.1Smrg * Allocate memory for variable-sized tables, 3421.1Smrg */ 3431.1Smrgvoid 3441.1Smrgcpu_startup(void) 3451.1Smrg{ 3461.1Smrg /* 3471.1Smrg * Just do the common stuff. 3481.1Smrg */ 3491.1Smrg cpu_startup_common(); 3501.1Smrg} 3511.1Smrg 3521.1Smrgint waittime = -1; 3531.1Smrg 3541.1Smrgvoid 3551.1Smrgcpu_reboot(int howto, char *bootstr) 3561.1Smrg{ 3571.1Smrg 3581.1Smrg /* Take a snapshot before clobbering any registers. */ 3591.1Smrg savectx(curpcb); 3601.1Smrg 3611.1Smrg if (cold) { 3621.1Smrg howto |= RB_HALT; 3631.1Smrg goto haltsys; 3641.1Smrg } 3651.1Smrg 3661.1Smrg /* If "always halt" was specified as a boot flag, obey. */ 3671.1Smrg if (boothowto & RB_HALT) 3681.1Smrg howto |= RB_HALT; 3691.1Smrg 3701.1Smrg boothowto = howto; 3711.1Smrg if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 3721.1Smrg waittime = 0; 3731.1Smrg vfs_shutdown(); 3741.1Smrg } 3751.1Smrg 3761.1Smrg splhigh(); 3771.1Smrg 3781.1Smrg if (howto & RB_DUMP) 3791.1Smrg dumpsys(); 3801.1Smrg 3811.1Smrghaltsys: 3821.1Smrg doshutdownhooks(); 3831.1Smrg 3841.1Smrg pmf_system_shutdown(boothowto); 3851.1Smrg 3861.1Smrg if (howto & RB_HALT) { 3871.1Smrg printf("\n"); 3881.1Smrg printf("The operating system has halted.\n"); 3891.1Smrg printf("Please press any key to reboot.\n\n"); 3901.1Smrg cnpollc(1); /* For proper keyboard command handling */ 3911.1Smrg cngetc(); 3921.1Smrg cnpollc(0); 3931.1Smrg } 3941.1Smrg 3951.1Smrg printf("rebooting...\n\n"); 3961.1Smrg 3971.1Smrg if (cfe_present) { 3981.1Smrg /* 3991.1Smrg * XXX 4001.1Smrg * For some reason we can't return to CFE with 4011.1Smrg * and do a warm start. Need to look into this... 4021.1Smrg */ 4031.1Smrg cfe_exit(0, (howto & RB_DUMP) ? 1 : 0); 4041.1Smrg printf("cfe_exit didn't!\n"); 4051.1Smrg } 4061.1Smrg 4071.1Smrg printf("WARNING: reboot failed!\n"); 4081.1Smrg 4091.1Smrg for (;;); 4101.1Smrg} 4111.1Smrg 4121.1Smrgstatic void 4131.1Smrgcswarm_setled(u_int index, char c) 4141.1Smrg{ 4151.1Smrg volatile u_char *led_ptr = 4161.1Smrg (void *)MIPS_PHYS_TO_KSEG1(SWARM_LEDS_PHYS); 4171.1Smrg 4181.1Smrg if (index < 4) 4191.1Smrg led_ptr[0x20 + ((3 - index) << 3)] = c; 4201.1Smrg} 4211.1Smrg 4221.1Smrgvoid 4231.1Smrgcswarm_setleds(const char *str) 4241.1Smrg{ 4251.1Smrg int i; 4261.1Smrg 4271.1Smrg for (i = 0; i < 4 && str[i]; i++) 4281.1Smrg cswarm_setled(i, str[i]); 4291.1Smrg for (; i < 4; i++) 4301.1Smrg cswarm_setled(' ', str[i]); 4311.1Smrg} 4321.1Smrg 4331.1Smrgint 4341.1Smrgsbmips_cca_for_pa(paddr_t pa) 4351.1Smrg{ 4361.1Smrg int rv; 4371.1Smrg 4381.1Smrg rv = 2; /* Uncached. */ 4391.1Smrg 4401.1Smrg /* Check each DRAM region. */ 4411.1Smrg if ((pa >= 0x0000000000 && pa <= 0x000fffffff) || /* DRAM 0 */ 4421.1Smrg (pa >= 0x0080000000 && pa <= 0x008fffffff) || /* DRAM 1 */ 4431.1Smrg (pa >= 0x0090000000 && pa <= 0x009fffffff) || /* DRAM 2 */ 4441.1Smrg (pa >= 0x00c0000000 && pa <= 0x00cfffffff) || /* DRAM 3 */ 4451.1Smrg#ifdef _MIPS_PADDR_T_64BIT 4461.1Smrg (pa >= 0x0100000000LL && pa <= 0x07ffffffffLL) || /* DRAM exp */ 4471.1Smrg#endif 4481.1Smrg 0) { 4491.1Smrg rv = 5; /* Cacheable coherent. */ 4501.1Smrg } 4511.1Smrg 4521.1Smrg return (rv); 4531.1Smrg} 454