1 /* $NetBSD: machdep.c,v 1.3 2003/07/15 01:37:36 lukem Exp $ */ 2 3 /*- 4 * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Juergen Hannken-Illjes. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.3 2003/07/15 01:37:36 lukem Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/buf.h> 44 #include <sys/msgbuf.h> 45 #include <sys/kernel.h> 46 #include <sys/mount.h> 47 #include <sys/proc.h> 48 #include <sys/user.h> 49 #include <sys/reboot.h> 50 #include <sys/properties.h> 51 #include <sys/ksyms.h> 52 53 #include <uvm/uvm_extern.h> 54 55 #include <net/netisr.h> 56 57 #include <machine/explora.h> 58 #include <machine/bus.h> 59 #include <machine/powerpc.h> 60 #include <machine/trap.h> 61 62 #include <powerpc/spr.h> 63 #include <powerpc/ibm4xx/dcr403cgx.h> 64 65 #include "ksyms.h" 66 67 #if NKSYMS || defined(DDB) || defined(LKM) 68 #include <machine/db_machdep.h> 69 #include <ddb/db_extern.h> 70 #endif 71 72 #define MEMREGIONS 2 73 #define TLB_PG_SIZE (16*1024*1024) 74 75 char cpu_model[80]; 76 char machine[] = MACHINE; /* from <machine/param.h> */ 77 char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */ 78 79 extern struct user *proc0paddr; 80 81 struct propdb *board_info = NULL; 82 struct vm_map *phys_map = NULL; 83 struct vm_map *mb_map = NULL; 84 struct vm_map *exec_map = NULL; 85 char msgbuf[MSGBUFSIZE]; 86 paddr_t msgbuf_paddr; 87 static unsigned cpuspeed = 66000000; 88 static unsigned memsize; 89 90 static struct mem_region phys_mem[MEMREGIONS]; 91 static struct mem_region avail_mem[MEMREGIONS]; 92 93 void bootstrap(u_int, u_int); 94 static void install_extint(void (*)(void)); 95 int lcsplx(int); 96 97 /* 98 * Trap vectors 99 */ 100 extern int defaulttrap, defaultsize; 101 extern int sctrap, scsize; 102 extern int alitrap, alisize; 103 extern int dsitrap, dsisize; 104 extern int isitrap, isisize; 105 extern int mchktrap, mchksize; 106 extern int tlbimiss4xx, tlbim4size; 107 extern int tlbdmiss4xx, tlbdm4size; 108 extern int pitfitwdog, pitfitwdogsize; 109 extern int debugtrap, debugsize; 110 extern int errata51handler, errata51size; 111 #ifdef DDB 112 extern int ddblow, ddbsize; 113 #endif 114 static struct { 115 int vector; 116 void *addr; 117 void *size; 118 } trap_table[] = { 119 { EXC_SC, &sctrap, &scsize }, 120 { EXC_ALI, &alitrap, &alisize }, 121 { EXC_DSI, &dsitrap, &dsisize }, 122 { EXC_ISI, &isitrap, &isisize }, 123 { EXC_MCHK, &mchktrap, &mchksize }, 124 { EXC_ITMISS, &tlbimiss4xx, &tlbim4size }, 125 { EXC_DTMISS, &tlbdmiss4xx, &tlbdm4size }, 126 { EXC_PIT, &pitfitwdog, &pitfitwdogsize }, 127 { EXC_DEBUG, &debugtrap, &debugsize }, 128 { (EXC_DTMISS|EXC_ALI), &errata51handler, &errata51size }, 129 #if defined(DDB) 130 { EXC_PGM, &ddblow, &ddbsize }, 131 #endif /* DDB */ 132 }; 133 134 static void 135 set_tlb(int idx, u_int addr, u_int flags) 136 { 137 u_int lo, hi; 138 139 addr &= ~(TLB_PG_SIZE-1); 140 141 lo = addr | TLB_EX | TLB_WR | flags; 142 #ifdef PPC_4XX_NOCACHE 143 lo |= TLB_I; 144 #endif 145 hi = addr | TLB_VALID | TLB_PG_16M; 146 147 asm volatile( 148 " tlbwe %1,%0,1 \n" 149 " tlbwe %2,%0,0 \n" 150 " sync \n" 151 : : "r" (idx), "r" (lo), "r" (hi) ); 152 } 153 154 void 155 bootstrap(u_int startkernel, u_int endkernel) 156 { 157 u_int i, j, t, br[4]; 158 u_int maddr, msize, size; 159 struct cpu_info * const ci = &cpu_info[0]; 160 161 consinit(); 162 163 br[0] = mfdcr(DCR_BR4); 164 br[1] = mfdcr(DCR_BR5); 165 br[2] = mfdcr(DCR_BR6); 166 br[3] = mfdcr(DCR_BR7); 167 168 for (i = 0; i < 4; i++) 169 for (j = i+1; j < 4; j++) 170 if (br[j] < br[i]) 171 t = br[j], br[j] = br[i], br[i] = t; 172 173 for (i = 0, size = 0; i < 4; i++) { 174 if (((br[i] >> 19) & 3) != 3) 175 continue; 176 maddr = ((br[i] >> 24) & 0xff) << 20; 177 msize = 1 << (20 + ((br[i] >> 21) & 7)); 178 if (maddr+msize > size) 179 size = maddr+msize; 180 } 181 182 phys_mem[0].start = 0; 183 phys_mem[0].size = size & ~PGOFSET; 184 avail_mem[0].start = startkernel; 185 avail_mem[0].size = size-startkernel; 186 187 asm volatile( 188 " mtpid %0 \n" 189 " sync \n" 190 : : "r" (1) ); 191 192 /* 193 * Setup initial tlbs. 194 * Physical memory is mapped into the first (reserved) tlbs. 195 * Memory of potential console devices is mapped into the 196 * last tlbs. They are only needed until the devices are configured. 197 */ 198 199 t = 0; 200 for (maddr = 0; maddr < phys_mem[0].size; maddr += TLB_PG_SIZE) 201 set_tlb(t++, maddr, 0); 202 203 t = NTLB-1; 204 set_tlb(t--, BASE_FB, TLB_I | TLB_G); 205 set_tlb(t--, BASE_FB2, TLB_I | TLB_G); 206 set_tlb(t--, BASE_COM, TLB_I | TLB_G); 207 208 /* Disable all external interrupts */ 209 mtdcr(DCR_EXIER, 0); 210 211 /* Disable all timer interrupts */ 212 mtspr(SPR_TCR, 0); 213 214 /* Initialize cache info for memcpy, etc. */ 215 cpu_probe_cache(); 216 217 /* 218 * Initialize lwp0 and current pcb and pmap pointers. 219 */ 220 lwp0.l_cpu = ci; 221 lwp0.l_addr = proc0paddr; 222 memset(lwp0.l_addr, 0, sizeof *lwp0.l_addr); 223 224 curpcb = &proc0paddr->u_pcb; 225 curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel(); 226 227 /* 228 * Install trap vectors. 229 */ 230 231 for (i = EXC_RSVD; i <= EXC_LAST; i += 0x100) 232 memcpy((void *)i, &defaulttrap, (size_t)&defaultsize); 233 234 for (i = 0; i < sizeof(trap_table)/sizeof(trap_table[0]); i++) { 235 memcpy((void *)trap_table[i].vector, trap_table[i].addr, 236 (size_t)trap_table[i].size); 237 } 238 239 __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100); 240 241 /* 242 * Set Exception vector base. 243 * Handle trap instruction as PGM exception. 244 */ 245 246 mtspr(SPR_EVPR, 0); 247 248 t = mfspr(SPR_DBCR0); 249 t &= ~DBCR0_TDE; 250 mtspr(SPR_DBCR0, t); 251 252 /* 253 * External interrupt handler install. 254 */ 255 256 install_extint(ext_intr); 257 258 /* 259 * Now enable translation (and machine checks/recoverable interrupts). 260 */ 261 asm volatile ( 262 " mfmsr %0 \n" 263 " ori %0,%0,%1 \n" 264 " mtmsr %0 \n" 265 " sync \n" 266 : : "r" (0), "K" (PSL_IR|PSL_DR|PSL_ME) ); 267 268 uvm_setpagesize(); 269 270 /* 271 * Initialize pmap module. 272 */ 273 pmap_bootstrap(startkernel, endkernel); 274 275 #if NKSYMS || defined(DDB) || defined(LKM) 276 ksyms_init(0, NULL, NULL); 277 #endif 278 279 fake_mapiodev = 0; 280 } 281 282 static void 283 install_extint(void (*handler)(void)) 284 { 285 extern int extint, extsize; 286 extern u_long extint_call; 287 u_long offset = (u_long)handler - (u_long)&extint_call; 288 int omsr, msr; 289 290 #ifdef DIAGNOSTIC 291 if (offset > 0x1ffffff) 292 panic("install_extint: too far away"); 293 #endif 294 asm volatile ( 295 " mfmsr %0 \n" 296 " andi. %1,%0,%2 \n" 297 " mtmsr %1 \n" 298 : "=r" (omsr), "=r" (msr) : "K" ((u_short)~PSL_EE) ); 299 extint_call = (extint_call & 0xfc000003) | offset; 300 memcpy((void *)EXC_EXI, &extint, (size_t)&extsize); 301 __syncicache((void *)&extint_call, sizeof extint_call); 302 __syncicache((void *)EXC_EXI, (int)&extsize); 303 asm volatile ( 304 " mtmsr %0 \n" 305 : : "r" (omsr) ); 306 } 307 308 void 309 cpu_startup(void) 310 { 311 caddr_t v; 312 vaddr_t minaddr, maxaddr; 313 u_int sz, i, base, residual; 314 char pbuf[9]; 315 316 /* 317 * Initialize error message buffer (before start of kernel) 318 */ 319 initmsgbuf((caddr_t)msgbuf, round_page(MSGBUFSIZE)); 320 321 printf("%s", version); 322 printf("NCD Explora451\n"); 323 324 memsize = ctob(physmem); 325 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 326 printf("total memory = %s\n", pbuf); 327 328 /* 329 * Find out how much space we need, allocate it, 330 * and then give everything true virtual addresses. 331 */ 332 sz = (u_int)allocsys(NULL, NULL); 333 if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0) 334 panic("startup: no room for tables"); 335 if (allocsys(v, NULL) - v != sz) 336 panic("startup: table size inconsistency"); 337 338 /* 339 * Now allocate buffers proper. They are different than the above 340 * in that they usually occupy more virtual memory than physical. 341 */ 342 sz = MAXBSIZE * nbuf; 343 minaddr = 0; 344 if (uvm_map(kernel_map, (vaddr_t *)&minaddr, round_page(sz), 345 NULL, UVM_UNKNOWN_OFFSET, 0, 346 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 347 UVM_ADV_NORMAL, 0)) != 0) 348 panic("startup: cannot allocate VM for buffers"); 349 buffers = (char *)minaddr; 350 base = bufpages / nbuf; 351 residual = bufpages % nbuf; 352 if (base >= MAXBSIZE) { 353 /* Don't want to alloc more physical mem than ever needed */ 354 base = MAXBSIZE; 355 residual = 0; 356 } 357 for (i = 0; i < nbuf; i++) { 358 vsize_t curbufsize; 359 vaddr_t curbuf; 360 struct vm_page *pg; 361 362 curbuf = (vaddr_t)buffers + i * MAXBSIZE; 363 curbufsize = NBPG * (i < residual ? base + 1 : base); 364 365 while (curbufsize) { 366 pg = uvm_pagealloc(NULL, 0, NULL, 0); 367 if (pg == NULL) 368 panic("cpu_startup: not enough memory for " 369 "buffer cache"); 370 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 371 VM_PROT_READ | VM_PROT_WRITE); 372 curbuf += PAGE_SIZE; 373 curbufsize -= PAGE_SIZE; 374 } 375 } 376 377 /* 378 * Allocate a submap for exec arguments. This map effectively 379 * limits the number of processes exec'ing at any time. 380 */ 381 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 382 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 383 384 /* 385 * Allocate a submap for physio 386 */ 387 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 388 VM_PHYS_SIZE, 0, FALSE, NULL); 389 390 /* 391 * No need to allocate an mbuf cluster submap. Mbuf clusters 392 * are allocated via the pool allocator, and we use direct-mapped 393 * pool pages. 394 */ 395 396 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 397 printf("avail memory = %s\n", pbuf); 398 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 399 printf("using %u buffers containing %s of memory\n", nbuf, pbuf); 400 401 /* 402 * Set up the buffers. 403 */ 404 bufinit(); 405 406 /* 407 * Set up the board properties database. 408 */ 409 if (!(board_info = propdb_create("board info"))) 410 panic("Cannot create board info database"); 411 412 if (board_info_set("processor-frequency", &cpuspeed, 413 sizeof(&cpuspeed), PROP_CONST, 0)) 414 panic("setting processor-frequency"); 415 if (board_info_set("mem-size", &memsize, 416 sizeof(&memsize), PROP_CONST, 0)) 417 panic("setting mem-size"); 418 } 419 420 int 421 lcsplx(int ipl) 422 { 423 return spllower(ipl); /*XXX*/ 424 } 425 426 void 427 softnet(void) 428 { 429 int isr; 430 431 isr = netisr; 432 netisr = 0; 433 434 #define DONETISR(bit, fn) \ 435 do { \ 436 if (isr & (1 << bit)) \ 437 fn(); \ 438 } while (0) 439 440 #include <net/netisr_dispatch.h> 441 442 #undef DONETISR 443 } 444 445 #include "com.h" 446 void 447 softserial(void) 448 { 449 #if NCOM > 0 450 void comsoft(void); /* XXX from dev/ic/com.c */ 451 452 comsoft(); 453 #endif 454 } 455 456 void 457 cpu_reboot(int howto, char *what) 458 { 459 static int syncing = 0; 460 461 boothowto = howto; 462 if (!cold && !(howto & RB_NOSYNC) && !syncing) { 463 syncing = 1; 464 vfs_shutdown(); 465 resettodr(); 466 } 467 468 splhigh(); 469 470 if (!cold && (howto & RB_DUMP)) 471 /*XXX dumpsys()*/; 472 473 doshutdownhooks(); 474 475 if (howto & RB_HALT) { 476 printf("halted\n\n"); 477 478 while (1) 479 ; 480 } 481 482 printf("rebooting\n\n"); 483 484 /* flush cache for msgbuf */ 485 __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); 486 487 ppc4xx_reset(); 488 489 #ifdef DDB 490 while (1) 491 Debugger(); 492 #else 493 while (1) 494 ; 495 #endif 496 } 497 498 void 499 inittodr(time_t base) 500 { 501 if (base > 365*24*60*60 && time.tv_sec < 365*24*60*60) 502 time.tv_sec = base; 503 } 504 505 void 506 resettodr(void) 507 { 508 } 509 510 void 511 mem_regions(struct mem_region **mem, struct mem_region **avail) 512 { 513 *mem = phys_mem; 514 *avail = avail_mem; 515 } 516