1 /* $NetBSD: machdep.c,v 1.38 2002/05/09 12:37:59 uch Exp $ */ 2 3 /*- 4 * Copyright (c) 2001, 2002 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_md.h" 37 #include "opt_ddb.h" 38 #include "opt_kgdb.h" 39 #include "fs_mfs.h" 40 #include "fs_nfs.h" 41 #include "biconsdev.h" 42 #include "opt_kloader_kernel_path.h" 43 #include "debug_hpc.h" 44 #include "hd64465if.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/user.h> 50 51 #include <sys/reboot.h> 52 #include <sys/mount.h> 53 #include <sys/sysctl.h> 54 #include <sys/kcore.h> 55 #include <sys/boot_flag.h> 56 57 #include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 58 59 #include <sh3/cpu.h> 60 #include <sh3/exception.h> 61 #include <sh3/cache.h> 62 #include <sh3/clock.h> 63 #include <sh3/intcreg.h> 64 65 #ifdef KGDB 66 #include <sys/kgdb.h> 67 #endif 68 #if defined(DDB) || defined(KGDB) 69 #include <machine/db_machdep.h> 70 #include <ddb/db_sym.h> 71 #include <ddb/db_extern.h> 72 #ifndef DB_ELFSIZE 73 #error Must define DB_ELFSIZE! 74 #endif 75 #define ELFSIZE DB_ELFSIZE 76 #include <sys/exec_elf.h> 77 #endif /* DDB || KGDB */ 78 79 #include <dev/cons.h> /* consdev */ 80 #include <dev/md.h> 81 82 #include <machine/bootinfo.h> 83 #include <machine/platid.h> 84 #include <machine/platid_mask.h> 85 #include <machine/autoconf.h> /* makebootdev() */ 86 #include <machine/kloader.h> 87 #include <machine/intr.h> 88 89 #ifdef NFS 90 #include <nfs/rpcv2.h> 91 #include <nfs/nfsproto.h> 92 #include <nfs/nfs.h> 93 #include <nfs/nfsmount.h> 94 #endif 95 96 #include <hpcsh/dev/hd6446x/hd6446xintcvar.h> 97 #include <hpcsh/dev/hd6446x/hd6446xintcreg.h> 98 #include <hpcsh/dev/hd64465/hd64465var.h> 99 100 #ifdef DEBUG 101 #define DPRINTF_ENABLE 102 #define DPRINTF_DEBUG machdep_debug 103 #endif /* DEBUG */ 104 #include <machine/debug.h> 105 106 /* 107 * D-RAM location (Windows CE machine specific) 108 * 109 * Jornada 690 (32MB model) SH7709A 110 * + SH7709A split CS3 to 2 banks. 111 * 112 * CS3 (0x0c000000-0x0fffffff 113 * 0x0c000000 --- onboard 16MByte 114 * 0x0d000000 --- onboard 16MByte (shadow) 115 * 0x0e000000 --- extension 16MByte 116 * 0x0f000000 --- extension 16MByte (shadow) 117 * 118 * PERSONA HPW-650PA (16MB model) SH7750 119 * SH7750 120 * 121 * CS3 (0x0c000000-0x0fffffff 122 * 0x0c000000 --- onboard 16MByte 123 * 0x0d000000 --- onboard 16MByte (shadow) 124 * 0x0e000000 --- onboard 16MByte (shadow) 125 * 0x0f000000 --- onboard 16MByte (shadow) 126 */ 127 128 #define SH_CS3_START 0x0c000000 129 #define SH_CS3_END (SH_CS3_START + 0x04000000) 130 131 #define SH7709_CS3_BANK0_START 0x0c000000 132 #define SH7709_CS3_BANK0_END (SH7709_CS3_BANK0_START + 0x02000000) 133 #define SH7709_CS3_BANK1_START 0x0e000000 134 #define SH7709_CS3_BANK1_END (SH7709_CS3_BANK1_START + 0x02000000) 135 136 /* Machine */ 137 char machine[] = MACHINE; 138 char machine_arch[] = MACHINE_ARCH; 139 extern char cpu_model[]; 140 struct bootinfo *bootinfo; 141 142 /* Physical memory */ 143 static int mem_cluster_init(paddr_t); 144 static void mem_cluster_load(void); 145 static void __find_dram_shadow(paddr_t, paddr_t); 146 #ifdef NARLY_MEMORY_PROBE 147 static int __check_dram(paddr_t, paddr_t); 148 #endif 149 int mem_cluster_cnt; 150 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 151 152 void main(void) __attribute__((__noreturn__)); 153 void machine_startup(int, char *[], struct bootinfo *) 154 __attribute__((__noreturn__)); 155 156 void 157 machine_startup(int argc, char *argv[], struct bootinfo *bi) 158 { 159 extern char edata[], end[]; 160 vaddr_t kernend; 161 size_t symbolsize; 162 int i; 163 char *p; 164 /* 165 * this routines stack is never polluted since stack pointer 166 * is lower than kernel text segment, and at exiting, stack pointer 167 * is changed to proc0. 168 */ 169 struct kloader_bootinfo kbi; 170 171 /* Symbol table size */ 172 symbolsize = 0; 173 if (memcmp(&end, ELFMAG, SELFMAG) == 0) { 174 Elf_Ehdr *eh = (void *)end; 175 Elf_Shdr *sh = (void *)(end + eh->e_shoff); 176 for(i = 0; i < eh->e_shnum; i++, sh++) 177 if (sh->sh_offset > 0 && 178 (sh->sh_offset + sh->sh_size) > symbolsize) 179 symbolsize = sh->sh_offset + sh->sh_size; 180 } 181 182 /* Clear BSS */ 183 memset(edata, 0, end - edata); 184 185 /* Setup bootinfo */ 186 bootinfo = &kbi.bootinfo; 187 memcpy(bootinfo, bi, sizeof(struct bootinfo)); 188 if (bootinfo->magic == BOOTINFO_MAGIC) { 189 platid.dw.dw0 = bootinfo->platid_cpu; 190 platid.dw.dw1 = bootinfo->platid_machine; 191 } 192 193 /* CPU initialize */ 194 if (platid_match(&platid, &platid_mask_CPU_SH_3)) 195 sh_cpu_init(CPU_ARCH_SH3, CPU_PRODUCT_7709A); 196 else if (platid_match(&platid, &platid_mask_CPU_SH_4)) 197 sh_cpu_init(CPU_ARCH_SH4, CPU_PRODUCT_7750); 198 199 /* Start to determine heap area */ 200 kernend = (vaddr_t)sh3_round_page(end + symbolsize); 201 202 /* Setup bootstrap options */ 203 makebootdev("wd0"); /* default boot device */ 204 boothowto = 0; 205 for (i = 1; i < argc; i++) { /* skip 1st arg (kernel name). */ 206 char *cp = argv[i]; 207 switch (*cp) { 208 case 'b': 209 /* boot device: -b=sd0 etc. */ 210 p = cp + 2; 211 #ifdef NFS 212 if (strcmp(p, "nfs") == 0) 213 mountroot = nfs_mountroot; 214 else 215 makebootdev(p); 216 #else /* NFS */ 217 makebootdev(p); 218 #endif /* NFS */ 219 break; 220 default: 221 BOOT_FLAG(*cp, boothowto); 222 break; 223 } 224 } 225 226 #ifdef MFS 227 /* 228 * Check to see if a mini-root was loaded into memory. It resides 229 * at the start of the next page just after the end of BSS. 230 */ 231 if (boothowto & RB_MINIROOT) { 232 size_t fssz; 233 fssz = sh3_round_page(mfs_initminiroot((void *)kernend)); 234 #ifdef MEMORY_DISK_DYNAMIC 235 md_root_setconf((caddr_t)kernend, fssz); 236 #endif 237 kernend += fssz; 238 } 239 #endif /* MFS */ 240 241 /* Console */ 242 consinit(); 243 #ifdef HPC_DEBUG_LCD 244 dbg_lcd_test(); 245 #endif 246 /* copy boot parameter for kloader */ 247 kloader_bootinfo_set(&kbi, argc, argv, bi, TRUE); 248 249 /* Find memory cluster. and load to UVM */ 250 physmem = mem_cluster_init(SH3_P1SEG_TO_PHYS(kernend)); 251 _DPRINTF("total memory = %dMbyte\n", (int)(sh3_ptob(physmem) >> 20)); 252 mem_cluster_load(); 253 254 /* Initialize proc0 u-area */ 255 sh_proc0_init(); 256 257 /* Initialize pmap and start to address translation */ 258 pmap_bootstrap(); 259 260 /* Debugger. */ 261 #ifdef DDB 262 if (symbolsize) { 263 ddb_init(symbolsize, &end, end + symbolsize); 264 _DPRINTF("symbol size = %d byte\n", symbolsize); 265 } 266 if (boothowto & RB_KDB) 267 Debugger(); 268 #endif /* DDB */ 269 #ifdef KGDB 270 if (boothowto & RB_KDB) { 271 if (kgdb_dev == NODEV) { 272 printf("no kgdb console.\n"); 273 } else { 274 kgdb_debug_init = 1; 275 kgdb_connect(1); 276 } 277 } 278 #endif /* KGDB */ 279 280 /* Jump to main */ 281 __asm__ __volatile__( 282 "jmp @%0;" 283 "mov %1, sp" 284 :: "r"(main),"r"(proc0.p_md.md_pcb->pcb_sf.sf_r7_bank)); 285 /* NOTREACHED */ 286 while (1) 287 ; 288 } 289 290 void 291 cpu_startup() 292 { 293 platid_t cpu; 294 int cpuclock, pclock; 295 296 cpuclock = sh_clock_get_cpuclock(); 297 pclock = sh_clock_get_pclock(); 298 299 sh_startup(); 300 301 memcpy(&cpu, &platid, sizeof(platid_t)); 302 cpu.dw.dw1 = 0; /* clear platform */ 303 sprintf(cpu_model, "[%s] %s", platid_name(&platid), platid_name(&cpu)); 304 305 #define MHZ(x) ((x) / 1000000), (((x) % 1000000) / 1000) 306 printf("%s %d.%02d MHz PCLOCK %d.%02d MHz\n", cpu_model, 307 MHZ(cpuclock), MHZ(pclock)); 308 } 309 310 int 311 cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 312 void *newp, size_t newlen, struct proc *p) 313 { 314 /* all sysctl names at this level are terminal */ 315 if (namelen != 1) 316 return (ENOTDIR); /* overloaded */ 317 318 switch (name[0]) { 319 case CPU_CONSDEV: 320 return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tab->cn_dev, 321 sizeof cn_tab->cn_dev)); 322 default: 323 } 324 325 return (EOPNOTSUPP); 326 } 327 328 void 329 cpu_reboot(int howto, char *bootstr) 330 { 331 332 /* take a snap shot before clobbering any registers */ 333 if (curproc) 334 savectx(curpcb); 335 336 /* If system is cold, just halt. */ 337 if (cold) { 338 howto |= RB_HALT; 339 goto haltsys; 340 } 341 342 /* If "always halt" was specified as a boot flag, obey. */ 343 if ((boothowto & RB_HALT) != 0) { 344 howto |= RB_HALT; 345 } 346 347 #ifdef KLOADER_KERNEL_PATH 348 if ((howto & RB_HALT) == 0) 349 kloader_reboot_setup(KLOADER_KERNEL_PATH); 350 #endif 351 352 boothowto = howto; 353 if ((howto & RB_NOSYNC) == 0) { 354 /* 355 * Synchronize the disks.... 356 */ 357 vfs_shutdown(); 358 359 /* 360 * If we've been adjusting the clock, the todr 361 * will be out of synch; adjust it now. 362 */ 363 resettodr(); 364 } 365 366 /* Disable interrupts. */ 367 splhigh(); 368 369 /* If rebooting and a dump is requested do it. */ 370 #if notyet 371 if (howto & RB_DUMP) 372 dumpsys(); 373 #endif 374 375 haltsys: 376 /* run any shutdown hooks */ 377 doshutdownhooks(); 378 379 /* Finally, halt/reboot the system. */ 380 if (howto & RB_HALT) { 381 printf("halted.\n"); 382 } else { 383 #ifdef KLOADER_KERNEL_PATH 384 kloader_reboot(); 385 /* NOTREACHED */ 386 #endif 387 } 388 389 #if NHD64465IF > 0 390 hd64465_shutdown(); 391 #endif 392 393 cpu_reset(); 394 /*NOTREACHED*/ 395 while(1) 396 ; 397 } 398 399 /* return # of physical pages. */ 400 int 401 mem_cluster_init(paddr_t addr) 402 { 403 phys_ram_seg_t *seg; 404 int npages, i; 405 406 /* cluster 0 is always kernel myself. */ 407 mem_clusters[0].start = SH_CS3_START; 408 mem_clusters[0].size = addr - SH_CS3_START; 409 mem_cluster_cnt = 1; 410 411 /* search CS3 */ 412 #ifdef SH3 413 /* SH7709A's CS3 is splited to 2 banks. */ 414 if (CPU_IS_SH3) { 415 __find_dram_shadow(addr, SH7709_CS3_BANK0_END); 416 __find_dram_shadow(SH7709_CS3_BANK1_START, 417 SH7709_CS3_BANK1_END); 418 } 419 #endif 420 #ifdef SH4 421 /* contig CS3 */ 422 if (CPU_IS_SH4) { 423 __find_dram_shadow(addr, SH_CS3_END); 424 } 425 #endif 426 _DPRINTF("mem_cluster_cnt = %d\n", mem_cluster_cnt); 427 npages = 0; 428 for (i = 0, seg = mem_clusters; i < mem_cluster_cnt; i++, seg++) { 429 _DPRINTF("mem_clusters[%d] = {0x%lx+0x%lx <0x%lx}", i, 430 (paddr_t)seg->start, (paddr_t)seg->size, 431 (paddr_t)seg->start + (paddr_t)seg->size); 432 npages += sh3_btop(seg->size); 433 #ifdef NARLY_MEMORY_PROBE 434 if (i == 0) { 435 _DPRINTF(" don't check.\n"); 436 continue; 437 } 438 if (__check_dram((paddr_t)seg->start, (paddr_t)seg->start + 439 (paddr_t)seg->size) != 0) 440 panic("D-RAM check failed."); 441 #else 442 _DPRINTF("\n"); 443 #endif /* NARLY_MEMORY_PROBE */ 444 } 445 446 return (npages); 447 } 448 449 void 450 mem_cluster_load() 451 { 452 paddr_t start, end; 453 psize_t size; 454 int i; 455 456 /* Cluster 0 is always the kernel, which doesn't get loaded. */ 457 sh_dcache_wbinv_all(); 458 for (i = 1; i < mem_cluster_cnt; i++) { 459 start = (paddr_t)mem_clusters[i].start; 460 size = (psize_t)mem_clusters[i].size; 461 462 _DPRINTF("loading 0x%lx,0x%lx\n", start, size); 463 memset((void *)SH3_PHYS_TO_P1SEG(start), 0, size); 464 end = atop(start + size); 465 start = atop(start); 466 uvm_page_physload(start, end, start, end, VM_FREELIST_DEFAULT); 467 } 468 sh_dcache_wbinv_all(); 469 } 470 471 void 472 __find_dram_shadow(paddr_t start, paddr_t end) 473 { 474 vaddr_t page, startaddr, endaddr; 475 int x; 476 477 _DPRINTF("search D-RAM from 0x%08lx for 0x%08lx\n", start, end); 478 startaddr = SH3_PHYS_TO_P2SEG(start); 479 endaddr = SH3_PHYS_TO_P2SEG(end); 480 481 page = startaddr; 482 483 x = random(); 484 *(volatile int *)(page + 0) = x; 485 *(volatile int *)(page + 4) = ~x; 486 487 if (*(volatile int *)(page + 0) != x || 488 *(volatile int *)(page + 4) != ~x) 489 return; 490 491 for (page += NBPG; page < endaddr; page += NBPG) { 492 if (*(volatile int *)(page + 0) == x && 493 *(volatile int *)(page + 4) == ~x) { 494 goto memend_found; 495 } 496 } 497 498 page -= NBPG; 499 *(volatile int *)(page + 0) = x; 500 *(volatile int *)(page + 4) = ~x; 501 502 if (*(volatile int *)(page + 0) != x || 503 *(volatile int *)(page + 4) != ~x) 504 return; /* no memory in this bank */ 505 506 memend_found: 507 KASSERT(mem_cluster_cnt < VM_PHYSSEG_MAX); 508 509 mem_clusters[mem_cluster_cnt].start = start; 510 mem_clusters[mem_cluster_cnt].size = page - startaddr; 511 512 /* skip kernel area */ 513 if (mem_cluster_cnt == 1) 514 mem_clusters[1].size -= mem_clusters[0].size; 515 516 mem_cluster_cnt++; 517 } 518 519 #ifdef NARLY_MEMORY_PROBE 520 int 521 __check_dram(paddr_t start, paddr_t end) 522 { 523 u_int8_t *page; 524 int i, x; 525 526 _DPRINTF(" checking..."); 527 for (; start < end; start += NBPG) { 528 page = (u_int8_t *)SH3_PHYS_TO_P2SEG (start); 529 x = random(); 530 for (i = 0; i < NBPG; i += 4) 531 *(volatile int *)(page + i) = (x ^ i); 532 for (i = 0; i < NBPG; i += 4) 533 if (*(volatile int *)(page + i) != (x ^ i)) 534 goto bad; 535 x = random(); 536 for (i = 0; i < NBPG; i += 4) 537 *(volatile int *)(page + i) = (x ^ i); 538 for (i = 0; i < NBPG; i += 4) 539 if (*(volatile int *)(page + i) != (x ^ i)) 540 goto bad; 541 } 542 _DPRINTF("success.\n"); 543 return (0); 544 bad: 545 _DPRINTF("failed.\n"); 546 return (1); 547 } 548 #endif /* NARLY_MEMORY_PROBE */ 549 550 void 551 intc_intr(int ssr, int spc, int ssp) 552 { 553 struct intc_intrhand *ih; 554 int evtcode; 555 u_int16_t r; 556 557 evtcode = _reg_read_4(CPU_IS_SH3 ? SH7709_INTEVT2 : SH4_INTEVT); 558 559 ih = EVTCODE_IH(evtcode); 560 KDASSERT(ih->ih_func); 561 /* 562 * On entry, all interrrupts are disabled, 563 * and exception is enabled for P3 access. (kernel stack is P3, 564 * SH3 may or may not cause TLB miss when access stack.) 565 * Enable higher level interrupt here. 566 */ 567 r = _reg_read_2(HD6446X_NIRR); 568 569 splx(ih->ih_level); 570 571 if (evtcode == SH_INTEVT_TMU0_TUNI0) { 572 struct clockframe cf; 573 cf.spc = spc; 574 cf.ssr = ssr; 575 cf.ssp = ssp; 576 (*ih->ih_func)(&cf); 577 __dbg_heart_beat(HEART_BEAT_RED); 578 } else if (evtcode == 579 (CPU_IS_SH3 ? SH7709_INTEVT2_IRQ4 : SH_INTEVT_IRL11)) { 580 int cause = r & hd6446x_ienable; 581 struct hd6446x_intrhand *hh = &hd6446x_intrhand[ffs(cause) - 1]; 582 if (cause == 0) { 583 printf("masked HD6446x interrupt.0x%04x\n", r); 584 _reg_write_2(HD6446X_NIRR, 0x0000); 585 return; 586 } 587 /* Enable higher level interrupt*/ 588 hd6446x_intr_resume(hh->hh_ipl); 589 KDASSERT(hh->hh_func != NULL); 590 (*hh->hh_func)(hh->hh_arg); 591 __dbg_heart_beat(HEART_BEAT_GREEN); 592 } else { 593 (*ih->ih_func)(ih->ih_arg); 594 __dbg_heart_beat(HEART_BEAT_BLUE); 595 } 596 } 597 598