1 /* $NetBSD: machdep.c,v 1.6 2002/08/25 20:21:40 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the NetBSD 18 * Foundation, Inc. and its contributors. 19 * 4. Neither the name of The NetBSD Foundation nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include "opt_ddb.h" 37 #include "opt_kloader_kernel_path.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/user.h> 43 #include <sys/buf.h> 44 #include <sys/reboot.h> 45 #include <sys/mount.h> 46 #include <sys/kcore.h> 47 #include <sys/boot_flag.h> 48 49 #include <uvm/uvm_extern.h> 50 51 #ifdef DDB 52 #include <machine/db_machdep.h> 53 #include <ddb/db_sym.h> 54 #include <ddb/db_extern.h> 55 #ifndef DB_ELFSIZE 56 #error Must define DB_ELFSIZE! 57 #endif 58 #define ELFSIZE DB_ELFSIZE 59 #include <sys/exec_elf.h> 60 #endif 61 62 #include <dev/cons.h> /* cntab access (cpu_reboot) */ 63 #include <machine/bootinfo.h> 64 #include <machine/psl.h> 65 #include <machine/intr.h>/* hardintr_init */ 66 #include <playstation2/playstation2/sifbios.h> 67 #include <playstation2/playstation2/interrupt.h> 68 #ifdef KLOADER_KERNEL_PATH 69 #include <playstation2/playstation2/kloader.h> 70 #endif 71 72 /* For sysctl_hw */ 73 extern char cpu_model[]; 74 75 struct cpu_info cpu_info_store; 76 77 struct vm_map *exec_map; 78 struct vm_map *mb_map; 79 struct vm_map *phys_map; 80 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 81 int mem_cluster_cnt; 82 int physmem; /* for buffer cache, vnode cache estimation */ 83 84 #ifdef DEBUG 85 static void bootinfo_dump(void); 86 #endif 87 88 void mach_init(void); 89 /* 90 * Do all the stuff that locore normally does before calling main(). 91 */ 92 void 93 mach_init() 94 { 95 extern char kernel_text[], edata[], end[]; 96 extern struct user *proc0paddr; 97 caddr_t kernend, v; 98 paddr_t start; 99 size_t size; 100 101 /* 102 * Clear the BSS segment. 103 */ 104 kernend = (caddr_t)mips_round_page(end); 105 memset(edata, 0, kernend - edata); 106 107 /* disable all interrupt */ 108 interrupt_init_bootstrap(); 109 110 /* enable SIF BIOS */ 111 sifbios_init(); 112 113 consinit(); 114 115 printf("kernel_text=%p edata=%p end=%p\n", kernel_text, edata, end); 116 117 #ifdef DEBUG 118 bootinfo_dump(); 119 #endif 120 uvm_setpagesize(); 121 physmem = atop(PS2_MEMORY_SIZE); 122 123 /* 124 * Copy exception-dispatch code down to exception vector. 125 * Initialize locore-function vector. 126 * Clear out the I and D caches. 127 */ 128 mips_vector_init(); 129 130 /* 131 * Load the rest of the available pages into the VM system. 132 */ 133 start = (paddr_t)round_page(MIPS_KSEG0_TO_PHYS(kernend)); 134 size = PS2_MEMORY_SIZE - start - BOOTINFO_BLOCK_SIZE; 135 memset((void *)MIPS_PHYS_TO_KSEG1(start), 0, size); 136 137 /* kernel itself */ 138 mem_clusters[0].start = trunc_page(MIPS_KSEG0_TO_PHYS(kernel_text)); 139 mem_clusters[0].size = start - mem_clusters[0].start; 140 /* heap */ 141 mem_clusters[1].start = start; 142 mem_clusters[1].size = size; 143 /* load */ 144 printf("load memory %#lx, %#x\n", start, size); 145 uvm_page_physload(atop(start), atop(start + size), 146 atop(start), atop(start + size), VM_FREELIST_DEFAULT); 147 148 strcpy(cpu_model, "SONY PlayStation 2"); 149 150 /* 151 * Initialize error message buffer (at end of core). 152 */ 153 mips_init_msgbuf(); 154 155 /* 156 * Compute the size of system data structures. pmap_bootstrap() 157 * needs some of this information. 158 */ 159 size = (vsize_t)allocsys(NULL, NULL); 160 161 pmap_bootstrap(); 162 163 /* 164 * Allocate space for proc0's USPACE. 165 */ 166 v = (caddr_t)uvm_pageboot_alloc(USPACE); 167 proc0.p_addr = proc0paddr = (struct user *)v; 168 proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1; 169 curpcb = &proc0.p_addr->u_pcb; 170 curpcb->pcb_context[11] = PSL_LOWIPL; /* SR */ 171 #ifdef IPL_ICU_MASK 172 curpcb->pcb_ppl = 0; 173 #endif 174 175 /* 176 * Allocate space for system data structures. These data structures 177 * are allocated here instead of cpu_startup() because physical 178 * memory is directly addressable. We don't have to map these into 179 * virtual address space. 180 */ 181 v = (caddr_t)uvm_pageboot_alloc(size); 182 if ((allocsys(v, NULL) - v) != size) 183 panic("mach_init: table size inconsistency"); 184 } 185 186 /* 187 * Allocate memory for variable-sized tables, 188 */ 189 void 190 cpu_startup() 191 { 192 u_int i, base, residual; 193 vaddr_t minaddr, maxaddr; 194 vsize_t size; 195 char pbuf[9]; 196 197 /* 198 * Good {morning,afternoon,evening,night}. 199 */ 200 printf(version); 201 printf("%s\n", cpu_model); 202 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 203 printf("%s memory", pbuf); 204 205 /* 206 * Allocate virtual address space for file I/O buffers. 207 * Note they are different than the array of headers, 'buf', 208 * and usually occupy more virtual memory than physical. 209 */ 210 size = MAXBSIZE * nbuf; 211 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size), 212 NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_NONE, 213 UVM_PROT_NONE, UVM_INH_NONE, UVM_ADV_NORMAL, 0)) != 0) 214 panic("startup: cannot allocate VM for buffers"); 215 minaddr = (vaddr_t)buffers; 216 base = bufpages / nbuf; 217 residual = bufpages % nbuf; 218 for (i = 0; i < nbuf; i++) { 219 vsize_t curbufsize; 220 vaddr_t curbuf; 221 struct vm_page *pg; 222 223 /* 224 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 225 * that MAXBSIZE space, we allocate and map (base+1) pages 226 * for the first "residual" buffers, and then we allocate 227 * "base" pages for the rest. 228 */ 229 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 230 curbufsize = NBPG * ((i < residual) ? (base + 1) : base); 231 232 while (curbufsize) { 233 pg = uvm_pagealloc(NULL, 0, NULL, 0); 234 if (pg == NULL) 235 panic("cpu_startup: not enough memory for " 236 "buffer cache"); 237 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 238 VM_PROT_READ|VM_PROT_WRITE); 239 curbuf += PAGE_SIZE; 240 curbufsize -= PAGE_SIZE; 241 } 242 } 243 pmap_update(pmap_kernel()); 244 245 /* 246 * Allocate a submap for exec arguments. This map effectively 247 * limits the number of processes exec'ing at any time. 248 */ 249 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 250 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 251 /* 252 * Allocate a submap for physio. 253 */ 254 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 255 VM_PHYS_SIZE, 0, FALSE, NULL); 256 257 /* 258 * (No need to allocate an mbuf cluster submap. Mbuf clusters 259 * are allocated via the pool allocator, and we use KSEG to 260 * map those pages.) 261 */ 262 263 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 264 printf(", %s free", pbuf); 265 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 266 printf(", %s in %u buffers\n", pbuf, nbuf); 267 268 /* 269 * Set up buffers, so they can be used to read disk labels. 270 */ 271 bufinit(); 272 } 273 274 void 275 cpu_reboot(int howto, char *bootstr) 276 { 277 static int waittime = -1; 278 279 /* Take a snapshot before clobbering any registers. */ 280 if (curproc) 281 savectx((struct user *)curpcb); 282 283 if (cold) { 284 howto |= RB_HALT; 285 goto haltsys; 286 } 287 288 /* If "always halt" was specified as a boot flag, obey. */ 289 if (boothowto & RB_HALT) { 290 howto |= RB_HALT; 291 } 292 293 #ifdef KLOADER_KERNEL_PATH 294 if ((howto & RB_HALT) == 0) 295 kloader_reboot_setup(KLOADER_KERNEL_PATH); 296 #endif 297 298 boothowto = howto; 299 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 300 waittime = 0; 301 vfs_shutdown(); 302 303 /* 304 * If we've been adjusting the clock, the todr 305 * will be out of synch; adjust it now. 306 */ 307 resettodr(); 308 } 309 310 splhigh(); 311 312 if (howto & RB_DUMP) 313 dumpsys(); 314 315 haltsys: 316 doshutdownhooks(); 317 318 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 319 sifbios_halt(0); /* power down */ 320 else if (howto & RB_HALT) 321 sifbios_halt(1); /* halt */ 322 else { 323 #ifdef KLOADER_KERNEL_PATH 324 kloader_reboot(); 325 /* NOTREACHED */ 326 #endif 327 sifbios_halt(2); /* reset */ 328 } 329 330 while (1) 331 ; 332 /* NOTREACHED */ 333 } 334 335 #ifdef DEBUG 336 void 337 bootinfo_dump() 338 { 339 printf("devconf=%#x, option=%#x, rtc=%#x, pcmcia_type=%#x," 340 "sysconf=%#x\n", 341 BOOTINFO_REF(BOOTINFO_DEVCONF), 342 BOOTINFO_REF(BOOTINFO_OPTION_PTR), 343 BOOTINFO_REF(BOOTINFO_RTC), 344 BOOTINFO_REF(BOOTINFO_PCMCIA_TYPE), 345 BOOTINFO_REF(BOOTINFO_SYSCONF)); 346 } 347 #endif /* DEBUG */ 348