1 1.39 thorpej /* $NetBSD: ibm4xx_machdep.c,v 1.39 2024/03/05 14:15:34 thorpej Exp $ */ 2 1.1 shige /* Original: ibm40x_machdep.c,v 1.3 2005/01/17 17:19:36 shige Exp $ */ 3 1.1 shige 4 1.1 shige /* 5 1.1 shige * Copyright 2001, 2002 Wasabi Systems, Inc. 6 1.1 shige * All rights reserved. 7 1.1 shige * 8 1.1 shige * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc. 9 1.1 shige * 10 1.1 shige * Redistribution and use in source and binary forms, with or without 11 1.1 shige * modification, are permitted provided that the following conditions 12 1.1 shige * are met: 13 1.1 shige * 1. Redistributions of source code must retain the above copyright 14 1.1 shige * notice, this list of conditions and the following disclaimer. 15 1.1 shige * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 shige * notice, this list of conditions and the following disclaimer in the 17 1.1 shige * documentation and/or other materials provided with the distribution. 18 1.1 shige * 3. All advertising materials mentioning features or use of this software 19 1.1 shige * must display the following acknowledgement: 20 1.1 shige * This product includes software developed for the NetBSD Project by 21 1.1 shige * Wasabi Systems, Inc. 22 1.1 shige * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23 1.1 shige * or promote products derived from this software without specific prior 24 1.1 shige * written permission. 25 1.1 shige * 26 1.1 shige * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27 1.1 shige * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 1.1 shige * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 1.1 shige * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30 1.1 shige * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 1.1 shige * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 1.1 shige * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 1.1 shige * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 1.1 shige * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 1.1 shige * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 1.1 shige * POSSIBILITY OF SUCH DAMAGE. 37 1.1 shige */ 38 1.1 shige 39 1.1 shige /* 40 1.1 shige * Copyright (C) 1995, 1996 Wolfgang Solfrank. 41 1.1 shige * Copyright (C) 1995, 1996 TooLs GmbH. 42 1.1 shige * All rights reserved. 43 1.1 shige * 44 1.1 shige * Redistribution and use in source and binary forms, with or without 45 1.1 shige * modification, are permitted provided that the following conditions 46 1.1 shige * are met: 47 1.1 shige * 1. Redistributions of source code must retain the above copyright 48 1.1 shige * notice, this list of conditions and the following disclaimer. 49 1.1 shige * 2. Redistributions in binary form must reproduce the above copyright 50 1.1 shige * notice, this list of conditions and the following disclaimer in the 51 1.1 shige * documentation and/or other materials provided with the distribution. 52 1.1 shige * 3. All advertising materials mentioning features or use of this software 53 1.1 shige * must display the following acknowledgement: 54 1.1 shige * This product includes software developed by TooLs GmbH. 55 1.1 shige * 4. The name of TooLs GmbH may not be used to endorse or promote products 56 1.1 shige * derived from this software without specific prior written permission. 57 1.1 shige * 58 1.1 shige * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 59 1.1 shige * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 60 1.1 shige * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 61 1.1 shige * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 62 1.1 shige * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 63 1.1 shige * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 64 1.1 shige * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 65 1.1 shige * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 66 1.1 shige * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 67 1.1 shige * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 68 1.1 shige */ 69 1.1 shige 70 1.1 shige #include <sys/cdefs.h> 71 1.39 thorpej __KERNEL_RCSID(0, "$NetBSD: ibm4xx_machdep.c,v 1.39 2024/03/05 14:15:34 thorpej Exp $"); 72 1.1 shige 73 1.30 rin #include "ksyms.h" 74 1.30 rin 75 1.30 rin #ifdef _KERNEL_OPT 76 1.1 shige #include "opt_ddb.h" 77 1.1 shige #include "opt_kgdb.h" 78 1.17 matt #include "opt_modular.h" 79 1.30 rin #endif 80 1.1 shige 81 1.1 shige #include <sys/param.h> 82 1.33 rin #include <sys/cpu.h> 83 1.33 rin #include <sys/ksyms.h> 84 1.36 rin #include <sys/mount.h> 85 1.1 shige #include <sys/msgbuf.h> 86 1.36 rin #include <sys/pmf.h> 87 1.1 shige #include <sys/proc.h> 88 1.36 rin #include <sys/reboot.h> 89 1.36 rin #include <sys/systm.h> 90 1.36 rin 91 1.36 rin #include <dev/cons.h> 92 1.1 shige 93 1.1 shige #include <uvm/uvm_extern.h> 94 1.1 shige 95 1.1 shige #if defined(DDB) 96 1.1 shige #include <machine/db_machdep.h> 97 1.1 shige #include <ddb/db_extern.h> 98 1.1 shige #endif 99 1.1 shige 100 1.1 shige #if defined(KGDB) 101 1.1 shige #include <sys/kgdb.h> 102 1.1 shige #endif 103 1.1 shige 104 1.1 shige #include <machine/powerpc.h> 105 1.16 matt #include <machine/trap.h> 106 1.16 matt 107 1.33 rin #include <powerpc/pcb.h> 108 1.1 shige #include <powerpc/spr.h> 109 1.16 matt 110 1.16 matt #include <powerpc/ibm4xx/cpu.h> 111 1.33 rin #include <powerpc/ibm4xx/spr.h> 112 1.1 shige 113 1.1 shige /* 114 1.1 shige * Global variables used here and there 115 1.1 shige */ 116 1.1 shige paddr_t msgbuf_paddr; 117 1.1 shige vaddr_t msgbuf_vaddr; 118 1.1 shige char msgbuf[MSGBUFSIZE]; 119 1.1 shige 120 1.17 matt #if NKSYMS || defined(DDB) || defined(MODULAR) 121 1.17 matt void *startsym, *endsym; 122 1.17 matt #endif 123 1.17 matt 124 1.32 rin #ifdef MODULAR 125 1.32 rin register_t cpu_psluserset = PSL_USERSET; 126 1.32 rin register_t cpu_pslusermod = PSL_USERMOD; 127 1.32 rin register_t cpu_pslusermask = PSL_USERMASK; 128 1.32 rin #endif 129 1.32 rin 130 1.17 matt /* 131 1.17 matt * Trap vectors 132 1.17 matt */ 133 1.17 matt extern const uint32_t defaulttrap[], defaultsize; 134 1.17 matt extern const uint32_t sctrap[], scsize; 135 1.24 rin extern const uint32_t accesstrap[], accesssize; 136 1.24 rin extern const uint32_t criticaltrap[], criticalsize; 137 1.17 matt extern const uint32_t tlbimiss4xx[], tlbim4size; 138 1.17 matt extern const uint32_t tlbdmiss4xx[], tlbdm4size; 139 1.17 matt extern const uint32_t pitfitwdog[], pitfitwdogsize; 140 1.17 matt extern const uint32_t errata51handler[], errata51size; 141 1.19 rin #if defined(DDB) 142 1.17 matt extern const uint32_t ddblow[], ddbsize; 143 1.17 matt #endif 144 1.17 matt static const struct exc_info trap_table[] = { 145 1.17 matt { EXC_SC, sctrap, (uintptr_t)&scsize }, 146 1.24 rin { EXC_ALI, accesstrap, (uintptr_t)&accesssize }, 147 1.24 rin { EXC_DSI, accesstrap, (uintptr_t)&accesssize }, 148 1.24 rin { EXC_MCHK, criticaltrap, (uintptr_t)&criticalsize }, 149 1.17 matt { EXC_ITMISS, tlbimiss4xx, (uintptr_t)&tlbim4size }, 150 1.17 matt { EXC_DTMISS, tlbdmiss4xx, (uintptr_t)&tlbdm4size }, 151 1.17 matt { EXC_PIT, pitfitwdog, (uintptr_t)&pitfitwdogsize }, 152 1.24 rin { EXC_DEBUG, criticaltrap, (uintptr_t)&criticalsize }, 153 1.17 matt { (EXC_DTMISS|EXC_ALI), 154 1.17 matt errata51handler, (uintptr_t)&errata51size }, 155 1.17 matt #if defined(DDB) 156 1.17 matt { EXC_PGM, ddblow, (uintptr_t)&ddbsize }, 157 1.35 rin #else 158 1.35 rin { EXC_PGM, accesstrap, (uintptr_t)&accesssize }, 159 1.20 rin #endif 160 1.17 matt }; 161 1.17 matt 162 1.36 rin void 163 1.36 rin cpu_reboot(int howto, char *what) 164 1.36 rin { 165 1.36 rin static int syncing; 166 1.36 rin static char str[256]; 167 1.36 rin char *ap = str, *ap1 = ap; 168 1.36 rin 169 1.36 rin boothowto = howto; 170 1.36 rin if (!cold && !(howto & RB_NOSYNC) && !syncing) { 171 1.36 rin syncing = 1; 172 1.36 rin vfs_shutdown(); /* sync */ 173 1.36 rin } 174 1.36 rin 175 1.36 rin splhigh(); 176 1.36 rin 177 1.36 rin if (!cold && (howto & RB_DUMP)) 178 1.36 rin ibm4xx_dumpsys(); 179 1.36 rin 180 1.36 rin doshutdownhooks(); 181 1.36 rin 182 1.36 rin pmf_system_shutdown(boothowto); 183 1.36 rin 184 1.36 rin if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { 185 1.36 rin /* Power off here if we know how... */ 186 1.36 rin } 187 1.36 rin 188 1.36 rin if (howto & RB_HALT) { 189 1.36 rin printf("The operating system has halted.\n" 190 1.36 rin "Press any key to reboot.\n\n"); 191 1.36 rin 192 1.36 rin cnpollc(1); 193 1.36 rin cngetc(); 194 1.36 rin cnpollc(0); 195 1.36 rin } 196 1.36 rin 197 1.36 rin printf("rebooting...\n\n"); 198 1.36 rin if (what && *what) { 199 1.36 rin if (strlen(what) > sizeof(str) - 5) 200 1.36 rin printf("boot string too large, ignored\n"); 201 1.36 rin else { 202 1.36 rin strcpy(str, what); 203 1.36 rin ap1 = ap = str + strlen(str); 204 1.36 rin *ap++ = ' '; 205 1.36 rin } 206 1.36 rin } 207 1.36 rin *ap++ = '-'; 208 1.36 rin if (howto & RB_SINGLE) 209 1.36 rin *ap++ = 's'; 210 1.36 rin if (howto & RB_KDB) 211 1.36 rin *ap++ = 'd'; 212 1.36 rin *ap++ = '\0'; 213 1.36 rin if (ap[-2] == '-') 214 1.36 rin *ap1 = '\0'; 215 1.36 rin 216 1.36 rin /* flush cache for msgbuf */ 217 1.36 rin __syncicache((void *)msgbuf_paddr, round_page(MSGBUFSIZE)); 218 1.36 rin 219 1.36 rin ppc4xx_reset(); 220 1.36 rin 221 1.36 rin printf("ppc4xx_reset() failed!\n"); 222 1.36 rin 223 1.37 rin for (;;) { 224 1.36 rin #if defined(DDB) 225 1.36 rin Debugger(); 226 1.36 rin #elif defined(KGDB) 227 1.36 rin kgdb_connect(1); 228 1.36 rin #else 229 1.36 rin continue; 230 1.36 rin #endif 231 1.36 rin } 232 1.36 rin } 233 1.36 rin 234 1.17 matt /* 235 1.17 matt * Install a trap vector. We cannot use memcpy because the 236 1.17 matt * destination may be zero. 237 1.17 matt */ 238 1.17 matt static void 239 1.17 matt trap_copy(const uint32_t *src, vaddr_t dest, size_t len) 240 1.17 matt { 241 1.17 matt uint32_t *dest_p = (void *)dest; 242 1.17 matt 243 1.17 matt while (len > 0) { 244 1.17 matt *dest_p++ = *src++; 245 1.17 matt len -= sizeof(uint32_t); 246 1.17 matt } 247 1.17 matt } 248 1.17 matt 249 1.1 shige /* 250 1.1 shige * ibm4xx_init: 251 1.1 shige */ 252 1.1 shige void 253 1.17 matt ibm4xx_init(vaddr_t startkernel, vaddr_t endkernel, void (*handler)(void)) 254 1.1 shige { 255 1.1 shige /* Initialize cache info for memcpy, etc. */ 256 1.1 shige cpu_probe_cache(); 257 1.1 shige 258 1.1 shige /* 259 1.17 matt * Initialize current pcb and pmap pointers. 260 1.1 shige */ 261 1.17 matt KASSERT(curcpu() == &cpu_info[0]); 262 1.17 matt KASSERT(lwp0.l_cpu == curcpu()); 263 1.17 matt KASSERT(curlwp == &lwp0); 264 1.12 rmind 265 1.17 matt curpcb = lwp_getpcb(curlwp); 266 1.12 rmind memset(curpcb, 0, sizeof(struct pcb)); 267 1.1 shige 268 1.1 shige curpcb->pcb_pm = pmap_kernel(); 269 1.1 shige 270 1.17 matt for (uintptr_t exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) { 271 1.17 matt trap_copy(defaulttrap, exc, (uintptr_t)&defaultsize); 272 1.17 matt } 273 1.1 shige 274 1.17 matt for (size_t i = 0; i < __arraycount(trap_table); i++) { 275 1.25 rin KASSERT(trap_table[i].exc_size <= 0x100); 276 1.17 matt trap_copy(trap_table[i].exc_addr, trap_table[i].exc_vector, 277 1.18 kiyohara trap_table[i].exc_size); 278 1.17 matt } 279 1.18 kiyohara 280 1.1 shige __syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100); 281 1.17 matt 282 1.1 shige mtspr(SPR_EVPR, 0); /* Set Exception vector base */ 283 1.1 shige 284 1.1 shige /* Handle trap instruction as PGM exception */ 285 1.17 matt mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) & ~DBCR0_TDE); 286 1.1 shige 287 1.1 shige /* 288 1.1 shige * external interrupt handler install 289 1.1 shige */ 290 1.18 kiyohara if (handler) 291 1.34 rin ibm4xx_install_extint(handler); 292 1.1 shige 293 1.1 shige /* 294 1.1 shige * Now enable translation (and machine checks/recoverable interrupts). 295 1.1 shige */ 296 1.5 perry __asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0; isync" 297 1.38 rin : : "r" (0), "K" (PSL_IR|PSL_DR)); 298 1.1 shige /* XXXX PSL_ME - With ME set kernel gets stuck... */ 299 1.1 shige 300 1.17 matt /* 301 1.17 matt * turn on console after enable translation 302 1.17 matt */ 303 1.17 matt consinit(); 304 1.17 matt 305 1.22 cherry uvm_md_init(); 306 1.17 matt 307 1.18 kiyohara /* 308 1.18 kiyohara * Initialize pmap module. 309 1.18 kiyohara */ 310 1.18 kiyohara pmap_bootstrap(startkernel, endkernel); 311 1.17 matt 312 1.17 matt /* 313 1.18 kiyohara * Let's take all the indirect calls via our stubs and patch 314 1.17 matt * them to be direct calls. 315 1.17 matt */ 316 1.17 matt cpu_fixup_stubs(); 317 1.17 matt 318 1.17 matt #if NKSYMS || defined(DDB) || defined(MODULAR) 319 1.17 matt ksyms_addsyms_elf((uintptr_t)endsym - (uintptr_t)startsym, 320 1.17 matt startsym, endsym); 321 1.17 matt #endif 322 1.1 shige } 323 1.1 shige 324 1.1 shige void 325 1.1 shige ibm4xx_install_extint(void (*handler)(void)) 326 1.1 shige { 327 1.1 shige extern int extint, extsize; 328 1.1 shige extern u_long extint_call; 329 1.1 shige u_long offset = (u_long)handler - (u_long)&extint_call; 330 1.1 shige int msr; 331 1.1 shige 332 1.1 shige #ifdef DIAGNOSTIC 333 1.1 shige if (offset > 0x1ffffff) 334 1.1 shige panic("install_extint: too far away"); 335 1.1 shige #endif 336 1.38 rin __asm volatile ("mfmsr %0; wrteei 0" : "=r" (msr)); 337 1.1 shige extint_call = (extint_call & 0xfc000003) | offset; 338 1.1 shige memcpy((void *)EXC_EXI, &extint, (size_t)&extsize); 339 1.1 shige __syncicache((void *)&extint_call, sizeof extint_call); 340 1.1 shige __syncicache((void *)EXC_EXI, (int)&extsize); 341 1.38 rin __asm volatile ("mtmsr %0" :: "r" (msr)); 342 1.1 shige } 343 1.1 shige 344 1.1 shige /* 345 1.1 shige * ibm4xx_cpu_startup: 346 1.1 shige * Machine dependent startup code. 347 1.1 shige */ 348 1.1 shige void 349 1.1 shige ibm4xx_cpu_startup(const char *model) 350 1.1 shige { 351 1.1 shige vaddr_t minaddr, maxaddr; 352 1.1 shige char pbuf[9]; 353 1.1 shige 354 1.1 shige KASSERT(curcpu() != NULL); 355 1.1 shige KASSERT(lwp0.l_cpu != NULL); 356 1.1 shige KASSERT(curcpu()->ci_intstk != 0); 357 1.15 matt KASSERT(curcpu()->ci_idepth == -1); 358 1.1 shige 359 1.1 shige /* 360 1.1 shige * Initialize error message buffer (at end of core). 361 1.1 shige */ 362 1.1 shige #if 0 /* For some reason this fails... --Artem 363 1.1 shige * Besides, do we really have to put it at the end of core? 364 1.1 shige * Let's use static buffer for now 365 1.1 shige */ 366 1.2 yamt if (!(msgbuf_vaddr = uvm_km_alloc(kernel_map, round_page(MSGBUFSIZE), 367 1.2 yamt 0, UVM_KMF_VAONLY))) 368 1.1 shige panic("startup: no room for message buffer"); 369 1.1 shige for (i = 0; i < btoc(MSGBUFSIZE); i++) 370 1.1 shige pmap_kenter_pa(msgbuf_vaddr + i * PAGE_SIZE, 371 1.9 cegger msgbuf_paddr + i * PAGE_SIZE, 372 1.9 cegger VM_PROT_READ|VM_PROT_WRITE, 0); 373 1.7 christos initmsgbuf((void *)msgbuf_vaddr, round_page(MSGBUFSIZE)); 374 1.1 shige #else 375 1.7 christos initmsgbuf((void *)msgbuf, round_page(MSGBUFSIZE)); 376 1.1 shige #endif 377 1.1 shige 378 1.3 lukem printf("%s%s", copyright, version); 379 1.1 shige if (model != NULL) 380 1.1 shige printf("Model: %s\n", model); 381 1.1 shige 382 1.1 shige format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 383 1.1 shige printf("total memory = %s\n", pbuf); 384 1.1 shige 385 1.1 shige minaddr = 0; 386 1.1 shige /* 387 1.1 shige * Allocate a submap for physio 388 1.1 shige */ 389 1.1 shige phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 390 1.6 thorpej VM_PHYS_SIZE, 0, false, NULL); 391 1.1 shige 392 1.1 shige /* 393 1.1 shige * No need to allocate an mbuf cluster submap. Mbuf clusters 394 1.1 shige * are allocated via the pool allocator, and we use direct-mapped 395 1.1 shige * pool pages. 396 1.1 shige */ 397 1.1 shige 398 1.29 ad format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 399 1.1 shige printf("avail memory = %s\n", pbuf); 400 1.1 shige } 401 1.1 shige 402 1.1 shige /* 403 1.1 shige * ibm4xx_dumpsys: 404 1.1 shige * Crash dump handling. 405 1.1 shige */ 406 1.1 shige void 407 1.1 shige ibm4xx_dumpsys(void) 408 1.1 shige { 409 1.1 shige 410 1.1 shige printf("dumpsys: TBD\n"); 411 1.1 shige } 412