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