1 /* $NetBSD: machdep.c,v 1.3 2002/01/31 16:25:56 uch 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/sysctl.h> 47 #include <sys/kcore.h> 48 #include <sys/boot_flag.h> 49 50 #ifdef DDB 51 #include <machine/db_machdep.h> 52 #include <ddb/db_sym.h> 53 #include <ddb/db_extern.h> 54 #ifndef DB_ELFSIZE 55 #error Must define DB_ELFSIZE! 56 #endif 57 #define ELFSIZE DB_ELFSIZE 58 #include <sys/exec_elf.h> 59 #endif 60 61 #include <dev/cons.h> /* cntab access (cpu_reboot) */ 62 #include <machine/bootinfo.h> 63 #include <machine/psl.h> 64 #include <machine/intr.h>/* hardintr_init */ 65 #include <playstation2/playstation2/sifbios.h> 66 #include <playstation2/playstation2/interrupt.h> 67 #ifdef KLOADER_KERNEL_PATH 68 #include <playstation2/playstation2/kloader.h> 69 #endif 70 71 /* For sysctl. */ 72 char machine[] = MACHINE; 73 char machine_arch[] = MACHINE_ARCH; 74 char cpu_model[] = "SONY PlayStation 2"; 75 76 struct cpu_info cpu_info_store; 77 78 struct vm_map *exec_map; 79 struct vm_map *mb_map; 80 struct vm_map *phys_map; 81 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 82 int mem_cluster_cnt; 83 int physmem; /* for buffer cache, vnode cache estimation */ 84 85 #ifdef DEBUG 86 static void bootinfo_dump(void); 87 #endif 88 89 void mach_init(void); 90 /* 91 * Do all the stuff that locore normally does before calling main(). 92 */ 93 void 94 mach_init() 95 { 96 extern char kernel_text[], edata[], end[]; 97 extern struct user *proc0paddr; 98 caddr_t kernend, v; 99 paddr_t start; 100 size_t size; 101 102 /* 103 * Clear the BSS segment. 104 */ 105 kernend = (caddr_t)mips_round_page(end); 106 memset(edata, 0, kernend - edata); 107 108 /* disable all interrupt */ 109 interrupt_init_bootstrap(); 110 111 /* enable SIF BIOS */ 112 sifbios_init(); 113 114 consinit(); 115 116 printf("kernel_text=%p edata=%p end=%p\n", kernel_text, edata, end); 117 118 #ifdef DEBUG 119 bootinfo_dump(); 120 #endif 121 uvm_setpagesize(); 122 physmem = atop(PS2_MEMORY_SIZE); 123 124 /* 125 * Copy exception-dispatch code down to exception vector. 126 * Initialize locore-function vector. 127 * Clear out the I and D caches. 128 */ 129 mips_vector_init(); 130 131 /* 132 * Load the rest of the available pages into the VM system. 133 */ 134 start = (paddr_t)round_page(MIPS_KSEG0_TO_PHYS(kernend)); 135 size = PS2_MEMORY_SIZE - start - BOOTINFO_BLOCK_SIZE; 136 memset((void *)MIPS_PHYS_TO_KSEG1(start), 0, size); 137 138 /* kernel itself */ 139 mem_clusters[0].start = trunc_page(MIPS_KSEG0_TO_PHYS(kernel_text)); 140 mem_clusters[0].size = start - mem_clusters[0].start; 141 /* heap */ 142 mem_clusters[1].start = start; 143 mem_clusters[1].size = size; 144 /* load */ 145 printf("load memory %#lx, %#x\n", start, size); 146 uvm_page_physload(atop(start), atop(start + size), 147 atop(start), atop(start + size), VM_FREELIST_DEFAULT); 148 149 /* 150 * Initialize error message buffer (at end of core). 151 */ 152 mips_init_msgbuf(); 153 154 /* 155 * Compute the size of system data structures. pmap_bootstrap() 156 * needs some of this information. 157 */ 158 size = (vsize_t)allocsys(NULL, NULL); 159 160 pmap_bootstrap(); 161 162 /* 163 * Allocate space for proc0's USPACE. 164 */ 165 v = (caddr_t)uvm_pageboot_alloc(USPACE); 166 proc0.p_addr = proc0paddr = (struct user *)v; 167 proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1; 168 curpcb = &proc0.p_addr->u_pcb; 169 curpcb->pcb_context[11] = PSL_LOWIPL; /* SR */ 170 #ifdef IPL_ICU_MASK 171 curpcb->pcb_ppl = 0; 172 #endif 173 174 /* 175 * Allocate space for system data structures. These data structures 176 * are allocated here instead of cpu_startup() because physical 177 * memory is directly addressable. We don't have to map these into 178 * virtual address space. 179 */ 180 v = (caddr_t)uvm_pageboot_alloc(size); 181 if ((allocsys(v, NULL) - v) != size) 182 panic("mach_init: table size inconsistency"); 183 } 184 185 /* 186 * Allocate memory for variable-sized tables, 187 */ 188 void 189 cpu_startup() 190 { 191 unsigned i; 192 int 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 %d 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 /* 275 * Machine dependent system variables. 276 */ 277 int 278 cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 279 size_t newlen, struct proc *p) 280 { 281 /* All sysctl names at this level are terminal. */ 282 if (namelen != 1) 283 return (ENOTDIR); 284 285 switch (name[0]) { 286 case CPU_CONSDEV: 287 return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tab->cn_dev, 288 sizeof cn_tab->cn_dev)); 289 default: 290 return (EOPNOTSUPP); 291 } 292 /* NOTREACHED */ 293 } 294 295 void 296 cpu_reboot(int howto, char *bootstr) 297 { 298 static int waittime = -1; 299 300 /* Take a snapshot before clobbering any registers. */ 301 if (curproc) 302 savectx((struct user *)curpcb); 303 304 if (cold) { 305 howto |= RB_HALT; 306 goto haltsys; 307 } 308 309 /* If "always halt" was specified as a boot flag, obey. */ 310 if (boothowto & RB_HALT) { 311 howto |= RB_HALT; 312 } 313 314 #ifdef KLOADER_KERNEL_PATH 315 if ((howto & RB_HALT) == 0) 316 kloader_reboot_setup(KLOADER_KERNEL_PATH); 317 #endif 318 319 boothowto = howto; 320 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 321 waittime = 0; 322 vfs_shutdown(); 323 324 /* 325 * If we've been adjusting the clock, the todr 326 * will be out of synch; adjust it now. 327 */ 328 resettodr(); 329 } 330 331 splhigh(); 332 333 if (howto & RB_DUMP) 334 dumpsys(); 335 336 haltsys: 337 doshutdownhooks(); 338 339 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 340 sifbios_halt(0); /* power down */ 341 else if (howto & RB_HALT) 342 sifbios_halt(1); /* halt */ 343 else { 344 #ifdef KLOADER_KERNEL_PATH 345 kloader_reboot(); 346 /* NOTREACHED */ 347 #endif 348 sifbios_halt(2); /* reset */ 349 } 350 351 while (1) 352 ; 353 /* NOTREACHED */ 354 } 355 356 #ifdef DEBUG 357 void 358 bootinfo_dump() 359 { 360 printf("devconf=%#x, option=%#x, rtc=%#x, pcmcia_type=%#x," 361 "sysconf=%#x\n", 362 BOOTINFO_REF(BOOTINFO_DEVCONF), 363 BOOTINFO_REF(BOOTINFO_OPTION_PTR), 364 BOOTINFO_REF(BOOTINFO_RTC), 365 BOOTINFO_REF(BOOTINFO_PCMCIA_TYPE), 366 BOOTINFO_REF(BOOTINFO_SYSCONF)); 367 } 368 #endif /* DEBUG */ 369