1/* $NetBSD: machdep.c,v 1.33 2024/03/05 14:15:31 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 2001, 2004, 2005 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.33 2024/03/05 14:15:31 thorpej Exp $"); 31 32#include "opt_ddb.h" 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37#include <sys/proc.h> 38#include <sys/buf.h> 39#include <sys/reboot.h> 40#include <sys/mount.h> 41#include <sys/kcore.h> 42#include <sys/boot_flag.h> 43#include <sys/device.h> 44#include <sys/cpu.h> 45 46#include <uvm/uvm_extern.h> 47 48#include <machine/bootinfo.h> 49#include <machine/locore.h> 50#include <machine/sbdvar.h> /* System board */ 51#include <machine/wired_map.h> 52 53#include <mips/cache.h> 54 55#ifdef DDB 56#include <machine/db_machdep.h> 57#include <ddb/db_sym.h> 58#include <ddb/db_extern.h> 59#include <ddb/db_output.h> 60#include <sys/exec_elf.h> 61#endif 62 63#include <dev/cons.h> 64 65#include <ews4800mips/ews4800mips/cons_machdep.h> 66 67vsize_t kseg2iobufsize; /* to reserve PTEs for KSEG2 I/O space */ 68 69/* maps for VM objects */ 70struct vm_map *phys_map; 71 72/* referenced by mips_machdep.c:cpu_dump() */ 73int mem_cluster_cnt; 74phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 75 76void mach_init(int, char *[], struct bootinfo *); 77void option(int, char *[], struct bootinfo *); 78/* NMI */ 79void nmi_exception(void); 80 81void 82mach_init(int argc, char *argv[], struct bootinfo *bi) 83{ 84 extern char kernel_text[], edata[], end[]; 85 void *v; 86 int i; 87 88 /* Clear BSS */ 89 if (bi == NULL || bi->bi_size != sizeof(struct bootinfo)) { 90 /* 91 * No bootinfo, so assume we are loaded by 92 * the firmware directly and have to clear BSS here. 93 */ 94 memset(edata, 0, end - edata); 95 } 96 97 /* Setup early-console with BIOS ROM routines */ 98 rom_cons_init(); 99 100 /* Initialize machine dependent System-Board ops. */ 101 sbd_init(); 102 103 __asm volatile("move %0, $29" : "=r"(v)); 104 printf("kernel_text=%p edata=%p end=%p sp=%p\n", 105 kernel_text, edata, end, v); 106 107 option(argc, argv, bi); 108 109 uvm_md_init(); 110 111 /* Fill mem_clusters and mem_cluster_cnt */ 112 (*platform.mem_init)(kernel_text, 113 (bi && bi->bi_nsym) ? (void *)bi->bi_esym : end); 114 115 /* 116 * make sure that we don't call BIOS console from now 117 * because wired mappings set up by BIOS will be discarded 118 * in mips_vector_init(). 119 */ 120 cn_tab = NULL; 121 122 mips_vector_init(NULL, false); 123 124 memcpy((void *)0x80000200, ews4800mips_nmi_vec, 32); /* NMI */ 125 mips_dcache_wbinv_all(); 126 mips_icache_sync_all(); 127 128 /* setup cpu_info */ 129 curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2) / hz; 130 curcpu()->ci_divisor_delay = 131 ((curcpu()->ci_cpu_freq + 500000) / 1000000); 132 if (mips_options.mips_cpu_flags & CPU_MIPS_DOUBLE_COUNT) { 133 curcpu()->ci_cycles_per_hz /= 2; 134 curcpu()->ci_divisor_delay /= 2; 135 } 136 137 /* Load memory to UVM */ 138 for (i = 1; i < mem_cluster_cnt; i++) { 139 phys_ram_seg_t *p; 140 paddr_t start; 141 size_t size; 142 p = &mem_clusters[i]; 143 start = p->start; 144 size = p->size; 145 uvm_page_physload(atop(start), atop(start + size), 146 atop(start), atop(start + size), VM_FREELIST_DEFAULT); 147 } 148 149 cpu_setmodel("NEC %s", platform.name); 150 151 mips_init_msgbuf(); 152 153 pmap_bootstrap(); 154 155 mips_init_lwp0_uarea(); 156} 157 158void 159option(int argc, char *argv[], struct bootinfo *bi) 160{ 161 extern char __boot_kernel_name[]; 162 bool boot_device_set; 163 char *p; 164 int i; 165 166 printf("argc=%d argv=%p syminfo=%p\n", argc, argv, bi); 167 printf("version=%d size=%d nsym=%d ssym=%p esym=%p\n", 168 bi->bi_version, bi->bi_size, bi->bi_nsym, bi->bi_ssym, bi->bi_esym); 169 170 for (i = 0; i < argc; i++) 171 printf("[%d] %s\n", i, argv[i]); 172 173#ifdef DDB 174 /* Load symbol table */ 175 if (bi->bi_nsym) 176 ksyms_addsyms_elf(bi->bi_esym - bi->bi_ssym, 177 (void *)bi->bi_ssym, (void *)bi->bi_esym); 178#endif 179 /* Parse option */ 180 boot_device_set = false; 181 for (i = 2; i < argc; i++) { 182 p = argv[i]; 183 /* prompt for root device */ 184 if (p[0] == '-' && p[1] == 'a') 185 boot_device_set = true; 186 187 /* root device option. ex) -b=net:netbsd, -b=sd0k:netbsd */ 188 if (p[0] == '-' && p[1] == 'b') { 189 boot_device_set = true; 190 strcpy(__boot_kernel_name, p + 3); 191 } 192 } 193 194 if (!boot_device_set) 195 strcpy(__boot_kernel_name, argv[1]); 196 197 /* Memory address information from IPL */ 198 sbd_memcluster_init(bi->bi_mainfo); 199} 200 201void 202mips_machdep_cache_config(void) 203{ 204 205 /* Set L2-cache size */ 206 if (platform.cache_config) 207 (*platform.cache_config)(); 208} 209 210void 211cpu_startup(void) 212{ 213 vaddr_t minaddr, maxaddr; 214 char pbuf[9]; 215 216 printf("%s%s", copyright, version); 217 printf("%s %dMHz\n", cpu_getmodel(), platform.cpu_clock / 1000000); 218 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 219 printf("total memory = %s\n", pbuf); 220 221 minaddr = 0; 222 /* 223 * Allocate a submap for physio. 224 */ 225 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 226 VM_PHYS_SIZE, 0, false, NULL); 227 228 /* 229 * (No need to allocate an mbuf cluster submap. Mbuf clusters 230 * are allocated via the pool allocator, and we use KSEG to 231 * map those pages.) 232 */ 233 format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 234 printf("avail memory = %s\n", pbuf); 235} 236 237void 238cpu_reboot(int howto, char *bootstr) 239{ 240 static int waittime = -1; 241 242 /* Take a snapshot before clobbering any registers. */ 243 savectx(curpcb); 244 245 if (cold) { 246 howto |= RB_HALT; 247 goto haltsys; 248 } 249 250 /* If "always halt" was specified as a boot flag, obey. */ 251 if (boothowto & RB_HALT) 252 howto |= RB_HALT; 253 254 boothowto = howto; 255 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 256 waittime = 0; 257 vfs_shutdown(); 258 } 259 260 splhigh(); 261 262 if (howto & RB_DUMP) 263 dumpsys(); 264 265 haltsys: 266 doshutdownhooks(); 267 268 pmf_system_shutdown(boothowto); 269 270 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 271 if (platform.poweroff) { 272 DELAY(1000000); 273 (*platform.poweroff)(); 274 } 275 } 276 277 if (howto & RB_HALT) { 278 printf("System halted. Hit any key to reboot.\n\n"); 279 (void)cngetc(); 280 } 281 282 printf("rebooting...\n"); 283 DELAY(1000000); 284 if (platform.reboot) 285 (*platform.reboot)(); 286 287 printf("reboot failed.\n"); 288 for (;;) 289 ; 290 /* NOTREACHED */ 291} 292 293#ifdef DDB 294void 295__db_print_symbol(db_expr_t value) 296{ 297 const char *name; 298 db_expr_t offset; 299 300 db_find_xtrn_sym_and_offset((db_addr_t)value, &name, &offset); 301 302 if (name != NULL && offset <= db_maxoff && offset != value) 303 db_print_loc_and_inst(value); 304 else 305 db_printf("\n"); 306 307} 308#endif 309