1/* virtex5 ppc440x5 machine assist */ 2#include "mem.h" 3 4#define MICROBOOT 1 /* if defined, see microboot.s for startup */ 5 6/* 7 * Special Purpose Registers of interest here (440 versions) 8 */ 9#define SPR_CCR0 0x3b3 /* Core Configuration Register 0 */ 10#define SPR_CCR1 0x378 /* core configuration register 1 */ 11#define SPR_DAC1 0x13c /* Data Address Compare 1 */ 12#define SPR_DAC2 0x13d /* Data Address Compare 2 */ 13#define SPR_DBCR0 0x134 /* Debug Control Register 0 */ 14#define SPR_DBCR1 0x135 /* Debug Control Register 1 */ 15#define SPR_DBCR2 0x136 /* Debug Control Register 2 */ 16#define SPR_DBSR 0x130 /* Debug Status Register */ 17#define SPR_DVC1 0x13e /* Data Value Compare 1 */ 18#define SPR_DVC2 0x13f /* Data Value Compare 2 */ 19#define SPR_DEAR 0x3D /* Data Error Address Register */ 20#define SPR_ESR 0x3E /* Exception Syndrome Register */ 21#define SPR_IAC1 0x138 /* Instruction Address Compare 1 */ 22#define SPR_IAC2 0x139 /* Instruction Address Compare 2 */ 23#define SPR_IAC3 0x13a /* Instruction Address Compare 3 */ 24#define SPR_IAC4 0x13b /* Instruction Address Compare 4 */ 25#define SPR_PID 0x30 /* Process ID (not the same as 405) */ 26#define SPR_PVR 0x11f /* Processor Version Register */ 27 28#define SPR_SPRG0 0x110 /* SPR General 0 */ 29#define SPR_SPRG1 0x111 /* SPR General 1 */ 30#define SPR_SPRG2 0x112 /* SPR General 2 */ 31#define SPR_SPRG3 0x113 /* SPR General 3 */ 32 33/* beware that these registers differ in R/W ability on 440 compared to 405 */ 34#define SPR_SPRG4R 0x104 /* SPR general 4; user/supervisor R */ 35#define SPR_SPRG5R 0x105 /* SPR general 5; user/supervisor R */ 36#define SPR_SPRG6R 0x106 /* SPR general 6; user/supervisor R */ 37#define SPR_SPRG7R 0x107 /* SPR general 7; user/supervisor R */ 38#define SPR_SPRG4W 0x114 /* SPR General 4; supervisor W */ 39#define SPR_SPRG5W 0x115 /* SPR General 5; supervisor W */ 40#define SPR_SPRG6W 0x116 /* SPR General 6; supervisor W */ 41#define SPR_SPRG7W 0x117 /* SPR General 7; supervisor W */ 42 43#define SPR_SRR0 0x01a /* Save/Restore Register 0 */ 44#define SPR_SRR1 0x01b /* Save/Restore Register 1 */ 45#define SPR_CSRR0 0x03a /* Critical Save/Restore Register 0 */ 46#define SPR_CSRR1 0x03b /* Critical Save/Restore Register 1 */ 47#define SPR_TBL 0x11c /* Time Base Lower */ 48#define SPR_TBU 0x11d /* Time Base Upper */ 49#define SPR_PIR 0x11e /* Processor Identity Register */ 50 51#define SPR_TCR 0x154 /* timer control */ 52#define SPR_TSR 0x150 /* timer status */ 53#define SPR_MMUCR 0x3B2 /* mmu control */ 54#define SPR_DNV0 0x390 /* data cache normal victim 0-3 */ 55#define SPR_DNV1 0x391 56#define SPR_DNV2 0x392 57#define SPR_DNV3 0x393 58#define SPR_DTV0 0x394 /* data cache transient victim 0-3 */ 59#define SPR_DTV1 0x395 60#define SPR_DTV2 0x396 61#define SPR_DTV3 0x397 62#define SPR_DVLIM 0x398 /* data cache victim limit */ 63#define SPR_INV0 0x370 /* instruction cache normal victim 0-3 */ 64#define SPR_INV1 0x371 65#define SPR_INV2 0x372 66#define SPR_INV3 0x374 67#define SPR_ITV0 0x374 /* instruction cache transient victim 0-3 */ 68#define SPR_ITV1 0x375 69#define SPR_ITV2 0x376 70#define SPR_ITV3 0x377 71#define SPR_IVOR(n) (0x190+(n)) /* interrupt vector offset registers 0-15 */ 72#define SPR_IVPR 0x03F /* instruction vector prefix register */ 73#define SPR_IVLIM 0x399 /* instruction cache victim limit */ 74 75#define SPR_MCSRR0 0x23A /* 440GX only */ 76#define SPR_MCSRR1 0x23B 77#define SPR_MCSR 0x23C 78 79#define SPR_DEC 0x16 /* on 440 they've gone back to using DEC instead of PIT ... */ 80#define SPR_DECAR 0x36 /* ... with the auto-reload register now visible */ 81 82/* 440 */ 83 84/* use of SPRG registers in save/restore */ 85#define SAVER0 SPR_SPRG0 86#define SAVER1 SPR_SPRG1 87#define SAVELR SPR_SPRG2 88#define SAVEXX SPR_SPRG3 89 90/* special instruction definitions */ 91#define BDNZ BC 16,0, 92#define BDNE BC 0,2, 93 94#define TBRL 268 /* read time base lower in MFTB */ 95#define TBRU 269 /* read time base upper in MFTB */ 96#define MFTB(tbr,d) WORD $((31<<26)|((d)<<21)|((tbr&0x1f)<<16)|(((tbr>>5)&0x1f)<<11)|(371<<1)) 97 98//#define TLBIA WORD $((31<<26)|(370<<1)) // not in 440 99#define TLBSYNC WORD $((31<<26)|(566<<1)) 100 101/* 400 models; perhaps others */ 102#define ICCCI(a,b) WORD $((31<<26)|((a)<<16)|((b)<<11)|(966<<1)) 103#define DCCCI(a,b) WORD $((31<<26)|((a)<<16)|((b)<<11)|(454<<1)) 104/* these follow the source -> dest ordering */ 105#define DCREAD(s,t) WORD $((31<<26)|((t)<<21)|((s)<<11)|(486<<1)) 106#define DCRF(n) ((((n)>>5)&0x1F)|(((n)&0x1F)<<5)) 107#define MTDCR(s,n) WORD $((31<<26)|((s)<<21)|(DCRF(n)<<11)|(451<<1)) 108#define MFDCR(n,t) WORD $((31<<26)|((t)<<21)|(DCRF(n)<<11)|(323<<1)) 109#define MSYNC WORD $((31<<26)|(598<<1)) 110#define TLBRELO(a,t) WORD $((31<<26)|((t)<<21)|((a)<<16)|(2<<11)|(946<<1)) 111#define TLBREMD(a,t) WORD $((31<<26)|((t)<<21)|((a)<<16)|(1<<11)|(946<<1)) 112#define TLBREHI(a,t) WORD $((31<<26)|((t)<<21)|((a)<<16)|(0<<11)|(946<<1)) 113#define TLBWELO(s,a) WORD $((31<<26)|((s)<<21)|((a)<<16)|(2<<11)|(978<<1)) 114#define TLBWEMD(s,a) WORD $((31<<26)|((s)<<21)|((a)<<16)|(1<<11)|(978<<1)) 115#define TLBWEHI(s,a) WORD $((31<<26)|((s)<<21)|((a)<<16)|(0<<11)|(978<<1)) 116#define TLBSXF(a,b,t) WORD $((31<<26)|((t)<<21)|((a)<<16)|((b)<<11)|(914<<1)) 117#define TLBSXCC(a,b,t) WORD $((31<<26)|((t)<<21)|((a)<<16)|((b)<<11)|(914<<1)|1) 118/* these are useless because there aren't CE/CEI equivalents for critical interrupts */ 119//#define WRTMSR_EE(s) WORD $((31<<26)|((s)<<21)|(131<<1)) 120//#define WRTMSR_EEI(e) WORD $((31<<26)|((e)<<15)|(163<<1)) 121 122/* on some models mtmsr doesn't synchronise enough (eg, 603e) */ 123#define MSRSYNC MSYNC; ISYNC 124 125/* 126 * on the 4xx series, the prefetcher madly fetches across RFI, sys call, 127 * and others; use BR 0(PC) to stop. 128 */ 129#define RFI WORD $((19<<26)|(50<<1)); BR 0(PC) 130// #define RFCI WORD $((19<<26)|(51<<1)); BR 0(PC) 131 132/* 133 * print progress character iff on cpu0. 134 * steps on R7 and R8, needs SB set and TLB entry for i/o registers set. 135 */ 136#define STEP(c, zero, notzero) \ 137 MOVW SPR(SPR_PIR), R7; \ 138 CMP R7, R0; \ 139 BEQ zero; \ 140 CMP R7, $017; \ 141 BNE notzero; \ 142zero: MOVW $(Uartlite+4), R7; \ 143 MOVW $(c), R8; \ 144 MOVW R8, 0(R7); \ 145notzero: SYNC 146 147//#define STEP(c, z, nz) 148#define PROG(n) MOVW $(n), R18 /* pre-uart progress indicator */ 149 150#define UREGSPACE (UREGSIZE+8) 151 152 NOSCHED 153 154TEXT start<>(SB), 1, $-4 155PROG(1) 156 /* except during trap handling, R0 is zero from now on */ 157 MOVW $0, R0 158 159 /* 160 * setup MSR 161 * turn off interrupts (clear ME, CE) 162 * use 0x000 as exception prefix 163 * enable kernel vm (clear IS, DS) 164 * clear, then enable machine checks 165 */ 166 MOVW $~0, R3 167 MOVW R3, SPR(SPR_MCSR) /* clear all bits */ 168 MSRSYNC 169 MOVW R0, SPR(SPR_ESR) 170 MSRSYNC 171PROG(2) 172 MOVW $MSR_ME, R3 173 MOVW R3, MSR 174 MSRSYNC 175 MOVW R0, CR 176 177 /* setup SB for pre mmu */ 178 MOVW $setSB(SB), R2 179 180 MOVW $19, R19 181 MOVW $20, R20 182 MOVW $21, R21 183 MOVW $22, R22 184 MOVW $23, R23 185 MOVW $24, R24 186PROG(3) 187#ifndef MICROBOOT 188 /* 189 * Invalidate the caches. 190 */ 191 ICCCI(0, 2) /* errata cpu_121 reveals that EA is used; we'll use SB */ 192 DCCCI(0, 2) /* dcache must not be in use */ 193 MSYNC 194#endif 195 MOVW R0, SPR(SPR_DBCR0) 196 MOVW R0, SPR(SPR_DBCR1) 197 MOVW R0, SPR(SPR_DBCR2) 198 ISYNC 199 MOVW $~0, R3 200 MOVW R3, SPR(SPR_DBSR) 201 202 /* 203 * CCR0: 204 * recover from data parity = 1 205 * disable gathering = 0 206 * disable trace broadcast = 1 207 * force load/store alignment = 0 (was 1) 208 * 0: fill 1+0 speculative lines on icache miss 209 * CCR1: 210 * normal parity, normal cache operation 211 * cpu timer advances with tick of CPU input clock (not timer clock) TO DO? 212 */ 213#ifndef MICROBOOT 214 MOVW $((1<<30)|(0<<21)|(1<<15)|(0<<8)|(0<<2)), R3 215 MOVW R3, SPR(SPR_CCR0) 216 MOVW $(0<<7), R3 /* TCS=0 */ 217 MOVW R3, SPR(SPR_CCR1) 218#endif 219 /* clear i/d cache regions */ 220 MOVW R0, SPR(SPR_INV0) 221 MOVW R0, SPR(SPR_INV1) 222 MOVW R0, SPR(SPR_INV2) 223 MOVW R0, SPR(SPR_INV3) 224 MOVW R0, SPR(SPR_DNV0) 225 MOVW R0, SPR(SPR_DNV1) 226 MOVW R0, SPR(SPR_DNV2) 227 MOVW R0, SPR(SPR_DNV3) 228 229 /* set i/d cache limits (all normal) */ 230 MOVW $((0<<22)|(63<<11)|(0<<0)), R3 /* TFLOOR=0, TCEILING=63 ways, NFLOOR = 0 */ 231 MOVW R3, SPR(SPR_DVLIM) 232 MOVW R3, SPR(SPR_IVLIM) 233 234PROG(4) 235 /* 236 * set other system configuration values 237 */ 238 MOVW R0, SPR(SPR_TBL) 239 MOVW R0, SPR(SPR_TBU) 240 MOVW R0, SPR(SPR_DEC) 241 MOVW $~0, R3 242 MOVW R3, SPR(SPR_TSR) 243 MOVW R0, SPR(SPR_TCR) 244 ISYNC 245 246 /* 247 * on the 440, the mmu is always on; kernelmmu just adds tlb entries. 248 * ppc440x5 cpu core manual §3.1 has the story about shadow 249 * tlbs and the like at reset. 250 */ 251PROG(5) 252 BL kernelmmu(SB) 253 /* now running with MMU initialised & in kernel address space */ 254 255 TLBWEHI(0,0) 256 TLBWEMD(0,0) 257 TLBWELO(0,0) 258 259 MOVW $setSB(SB), R2 260 /* it's now safe to print */ 261STEP('\r', zerobootcr, notbootcr) 262STEP('\n', zerobootnl, notbootnl) 263STEP('P', zerobootP, notbootP) 264 265 /* make the vectors match the old values */ 266 MOVW $PHYSSRAM, R3 267 MOVW R3, SPR(SPR_IVPR) /* vector prefix at PHYSSRAM */ 268 MOVW $INT_CI, R3 269 MOVW R3, SPR(SPR_IVOR(0)) 270 MOVW $INT_MCHECK, R3 271 MOVW R3, SPR(SPR_IVOR(1)) 272 MOVW $INT_DSI, R3 273 MOVW R3, SPR(SPR_IVOR(2)) 274 MOVW $INT_ISI, R3 275 MOVW R3, SPR(SPR_IVOR(3)) 276 MOVW $INT_EI, R3 277 MOVW R3, SPR(SPR_IVOR(4)) 278 MOVW $INT_ALIGN, R3 279 MOVW R3, SPR(SPR_IVOR(5)) 280 MOVW $INT_PROG, R3 281 MOVW R3, SPR(SPR_IVOR(6)) 282 MOVW $INT_FPU, R3 283 MOVW R3, SPR(SPR_IVOR(7)) /* reserved (FPU?) */ 284 MOVW $INT_SYSCALL, R3 285 MOVW R3, SPR(SPR_IVOR(8)) /* system call */ 286 MOVW $INT_TRACE, R3 287 MOVW R3, SPR(SPR_IVOR(9)) /* reserved (trace?) */ 288 MOVW $INT_PIT, R3 289 MOVW R3, SPR(SPR_IVOR(10)) /* decrementer */ 290 MOVW $INT_FIT, R3 291 MOVW R3, SPR(SPR_IVOR(11)) /* fixed interval */ 292 MOVW $INT_WDT, R3 293 MOVW R3, SPR(SPR_IVOR(12)) /* watchdog */ 294 MOVW $INT_DMISS, R3 295 MOVW R3, SPR(SPR_IVOR(13)) /* data TLB */ 296 MOVW $INT_IMISS, R3 297 MOVW R3, SPR(SPR_IVOR(14)) /* instruction TLB */ 298 MOVW $INT_DEBUG, R3 299 MOVW R3, SPR(SPR_IVOR(15)) /* debug */ 300STEP('l', zerobootl, notbootl) 301 302 /* 303 * Set up SB, vector space (16KiB, 64KiB aligned), 304 * extern registers (m->, up->) and stack. 305 * Mach (and stack) will be cleared along with the 306 * rest of BSS below if this is CPU#0. 307 * Memstart is the first free memory location 308 * after the kernel. 309 */ 310 /* set R2 to correct value */ 311 MOVW $setSB(SB), R2 312 313 /* invalidate the caches again to flush any addresses below KZERO */ 314 ICCCI(0, 2) /* errata cpu_121 reveals that EA is used; we'll use SB */ 315 ISYNC 316 317 MOVW SPR(SPR_PIR), R7 318 CMP R7, $017 319 BNE notcpu0b 320 MOVW R0, R7 321notcpu0b: 322 CMP R0, R7 323 BNE notcpu0 324 325 /* set up Mach */ 326 /* for cpu0 */ 327 MOVW $mach0(SB), R(MACH) 328 /* put stack in sram below microboot temporarily */ 329 MOVW $0xfffffe00, R1 330// ADD $(MACHSIZE-8), R(MACH), R1 /* set stack */ 331 332// SUB $4, R(MACH), R3 333// ADD $4, R1, R4 334//clrmach: 335// MOVWU R0, 4(R3) 336// CMP R3, R4 337// BNE clrmach 338 339STEP('a', zeroboota, notboota) 340 341 MOVW $PHYSSRAM, R6 /* vectors at bottom of sram */ 342 MOVW R0, R(USER) /* up-> */ 343 MOVW R0, 0(R(MACH)) 344 345_CPU0: /* boot processor */ 346 MOVW $edata-4(SB), R3 347 MOVW R1, R4 /* stop before microboot */ 348_clrbss: /* clear BSS */ 349 MOVWU R0, 4(R3) 350 CMP R3, R4 351 BNE _clrbss 352 353STEP('n', zerobootn, notbootn) 354// MOVW R4, memstart(SB) /* start of unused memory */ 355 MOVW R0, memstart(SB) /* start of unused memory: dram */ 356 MOVW R6, vectorbase(SB) /* 64KiB aligned vector base, for trapinit */ 357 358STEP(' ', zerobootsp, notbootsp) 359 BL main(SB) 360 BR 0(PC) /* paranoia -- not reached */ 361 362notcpu0: 363 MOVW $mach0(SB), R(MACH) 364 ADD $(MACHSIZE-8), R(MACH) /* cpu1 */ 365 /* put stack in sram below microboot & cpu0's stack temporarily */ 366 MOVW $0xfffffb00, R1 367 368 /* give cpu0 time to set things up */ 369 MOVW $(10*1024*1024), R3 370spin: 371 SUB $1, R3 372 CMP R0, R3 373 BNE spin 374 375 BL main(SB) 376 BR 0(PC) /* paranoia -- not reached */ 377 378 379GLOBL mach0(SB), $(MAXMACH*BY2PG) 380 381TEXT kernelmmu(SB), 1, $-4 382PROG(6) 383#ifndef MICROBOOT 384 /* make following TLB entries shared, TID=PID=0 */ 385 MOVW R0, SPR(SPR_PID) 386 387 /* 388 * allocate cache on store miss, disable U1 as transient, 389 * disable U2 as SWOA, no dcbf or icbi exception, tlbsx search 0. 390 */ 391 MOVW R0, SPR(SPR_MMUCR) 392 ISYNC 393#endif 394 395 /* map various things 1:1 */ 396 MOVW $tlbtab(SB), R4 397 MOVW $tlbtabe(SB), R5 398 MOVW $(3*4), R6 /* sizeof a tlb entry */ 399// ADD R6, R4 /* skip first 2 TLB entries in tlbtab */ 400// ADD R6, R4 /* skip first 2 TLB entries in tlbtab */ 401 SUB R4, R5 402 DIVW R6, R5 /* R5 gets # of tlb entries in table */ 403 SUB $4, R4 /* back up before MOVWU */ 404 MOVW R5, CTR 405 MOVW $63, R3 406// SUB $2, R3 /* skip first 2 TLB entries in TLB (#62-63) */ 407 SYNC 408 ISYNC 409PROG(7) 410ltlb: 411 MOVWU 4(R4), R5 /* TLBHI */ 412 TLBWEHI(5,3) 413 MOVWU 4(R4), R5 /* TLBMD */ 414 TLBWEMD(5,3) 415 MOVWU 4(R4), R5 /* TLBLO */ 416 TLBWELO(5,3) 417 SUB $1, R3 418 BDNZ ltlb 419PROG(8) 420 /* clear all remaining entries to remove any aliasing from boot */ 421#ifndef MICROBOOT 422 CMP R3, R0 423 BEQ cltlbe 424 MOVW R0, R5 425cltlb: 426 /* can't use 0 (R0) as first operand */ 427 TLBWEHI(5,3) 428 TLBWEMD(5,3) 429 TLBWELO(5,3) 430 SUB $1, R3 431 CMP R3, $0 432 BGE cltlb 433cltlbe: 434#endif 435 SYNC 436 ISYNC /* switch to new TLBs */ 437PROG(9) 438#ifdef MICROBOOT 439 RETURN 440#else 441 /* 442 * this is no longer true; the microboot has done this: 443 * we're currently relying on the shadow I/D TLBs. to switch to 444 * the new TLBs, we need a synchronising instruction. 445 */ 446 MOVW LR, R4 447 MOVW R4, SPR(SPR_SRR0) 448 MOVW MSR, R4 449 MOVW R4, SPR(SPR_SRR1) 450 /* 451 * resume in kernel mode in caller; R3 has the index of the first 452 * unneeded TLB entry 453 */ 454 RFI 455#endif 456 457TEXT tlbinval(SB), 1, $-4 458 TLBWEHI(0, 3) 459 TLBWEMD(0, 3) 460 TLBWELO(0, 3) 461 ISYNC 462 RETURN 463 464TEXT splhi(SB), 1, $-4 465 MOVW MSR, R3 466 RLWNM $0, R3, $~MSR_EE, R4 467 RLWNM $0, R4, $~MSR_CE, R4 468 MOVW R4, MSR 469 MSRSYNC 470 MOVW LR, R31 471 MOVW R31, 4(R(MACH)) /* save PC in m->splpc */ 472 RETURN 473 474TEXT splx(SB), 1, $-4 475 MOVW LR, R31 476 MOVW R31, 4(R(MACH)) /* save PC in m->splpc */ 477 /* fall though */ 478 479TEXT splxpc(SB), 1, $-4 480 MOVW MSR, R4 481 RLWMI $0, R3, $MSR_EE, R4 482 RLWMI $0, R3, $MSR_CE, R4 483 MOVW R4, MSR 484 MSRSYNC 485 RETURN 486 487TEXT spllo(SB), 1, $-4 488 MOVW MSR, R3 489 OR $MSR_EE, R3, R4 490 OR $MSR_CE, R4 491 MOVW R4, MSR 492 MSRSYNC 493 RETURN 494 495TEXT spldone(SB), 1, $-4 496 RETURN 497 498TEXT islo(SB), 1, $-4 499 MOVW MSR, R3 500 MOVW $(MSR_EE|MSR_CE), R4 501 AND R4, R3 502 RETURN 503 504/* invalidate region of i-cache */ 505TEXT icflush(SB), 1, $-4 /* icflush(virtaddr, count) */ 506 MOVW n+4(FP), R4 507 RLWNM $0, R3, $~(ICACHELINESZ-1), R5 508 SUB R5, R3 509 ADD R3, R4 510 ADD $(ICACHELINESZ-1), R4 511 SRAW $ICACHELINELOG, R4 512 MOVW R4, CTR 513icf0: ICBI (R5) 514 ADD $ICACHELINESZ, R5 515 BDNZ icf0 516 ISYNC 517 RETURN 518 519TEXT sync(SB), 1, $0 520 SYNC 521 RETURN 522 523TEXT isync(SB), 1, $0 524 ISYNC 525 RETURN 526 527/* write-back then invalidate region of d-cache */ 528TEXT dcflush(SB), 1, $-4 /* dcflush(virtaddr, count) */ 529 MOVW n+4(FP), R4 530 RLWNM $0, R3, $~(DCACHELINESZ-1), R5 531 CMP R4, $0 532 BLE dcf1 533 SYNC 534 SUB R5, R3 535 ADD R3, R4 536 ADD $(DCACHELINESZ-1), R4 537 SRAW $DCACHELINELOG, R4 538 MOVW R4, CTR 539dcf0: DCBF (R5) 540 ADD $DCACHELINESZ, R5 541 BDNZ dcf0 542dcf1: 543 SYNC 544 RETURN 545 546TEXT cacheson(SB), 1, $-4 547 MOVW $1, R3 /* return value: true iff caches on */ 548 RETURN 549 550TEXT cachesinvalidate(SB), 1, $-4 551 ICCCI(0, 2) /* errata cpu_121 reveals that EA is used; we'll use SB */ 552 DCCCI(0, 2) /* dcache must not be in use (or just needs to be clean?) */ 553 MSYNC 554 RETURN 555 556TEXT getpit(SB), 1, $0 557 MOVW SPR(SPR_DEC), R3 /* they've moved it back to DEC */ 558 RETURN 559 560TEXT putpit(SB), 1, $0 561 MOVW R3, SPR(SPR_DEC) 562 MOVW R3, SPR(SPR_DECAR) 563 RETURN 564 565TEXT putpid(SB), 1, $0 566 MOVW R3, SPR(SPR_PID) 567 MOVW SPR(SPR_MMUCR), R4 568 RLWMI $0, R3, $0xFF, R4 569 MOVW R4, SPR(SPR_MMUCR) 570 RETURN 571 572TEXT getpid(SB), 1, $0 573 MOVW SPR(SPR_PID), R3 574 RETURN 575 576TEXT getpir(SB), 1, $-4 577 MOVW SPR(SPR_PIR), R3 578 CMP R3, $017 579 BNE normal 580 MOVW R0, R3 581normal: 582 RETURN 583 584TEXT putstid(SB), 1, $0 585 MOVW SPR(SPR_MMUCR), R4 586 RLWMI $0, R3, $0xFF, R4 587 MOVW R4, SPR(SPR_MMUCR) 588 RETURN 589 590TEXT getstid(SB), 1, $0 591 MOVW SPR(SPR_MMUCR), R3 592 RLWNM $0, R3, $0xFF, R3 593 RETURN 594 595TEXT gettbl(SB), 1, $0 596 MFTB(TBRL, 3) 597 RETURN 598 599TEXT gettbu(SB), 1, $0 600 MFTB(TBRU, 3) 601 RETURN 602 603TEXT gettsr(SB), 1, $0 604 MOVW SPR(SPR_TSR), R3 605 RETURN 606 607TEXT puttsr(SB), 1, $0 608 MOVW R3, SPR(SPR_TSR) 609 RETURN 610 611TEXT puttcr(SB), 1, $0 612 MOVW R3, SPR(SPR_TCR) 613 RETURN 614 615TEXT getpvr(SB), 1, $0 616 MOVW SPR(SPR_PVR), R3 617 RETURN 618 619TEXT getmsr(SB), 1, $0 620 MOVW MSR, R3 621 RETURN 622 623TEXT putmsr(SB), 1, $0 624 SYNC 625 MOVW R3, MSR 626 MSRSYNC 627 RETURN 628 629TEXT getmcsr(SB), 1, $0 630 MOVW SPR(SPR_MCSR), R3 631 RETURN 632 633TEXT putmcsr(SB), 1, $-4 634 MOVW R3, SPR(SPR_MCSR) 635 RETURN 636 637TEXT getesr(SB), 1, $0 638 MOVW SPR(SPR_ESR), R3 639 RETURN 640 641TEXT putesr(SB), 1, $0 642 MOVW R3, SPR(SPR_ESR) 643 RETURN 644 645TEXT putevpr(SB), 1, $0 646 MOVW R3, SPR(SPR_IVPR) 647 RETURN 648 649TEXT getccr0(SB), 1, $-4 650 MOVW SPR(SPR_CCR0), R3 651 RETURN 652 653TEXT setsp(SB), 1, $0 654 MOVW R3, R1 655 RETURN 656 657TEXT getsp(SB), 1, $0 658 MOVW R1, R3 659 RETURN 660 661TEXT getdear(SB), 1, $0 662 MOVW SPR(SPR_DEAR), R3 663 RETURN 664 665TEXT tas32(SB), 1, $0 666 SYNC 667 MOVW R3, R4 668 MOVW $0xdead,R5 669tas1: 670 DCBF (R4) /* fix for 603x bug */ 671 LWAR (R4), R3 672 CMP R3, $0 673 BNE tas0 674 STWCCC R5, (R4) 675 BNE tas1 676tas0: 677 SYNC 678 ISYNC 679 RETURN 680 681TEXT eieio(SB), 1, $0 682 EIEIO 683 RETURN 684 685TEXT syncall(SB), 1, $0 686 SYNC 687 ISYNC 688 RETURN 689 690TEXT _xinc(SB), 1, $0 /* void _xinc(long *); */ 691 MOVW R3, R4 692xincloop: 693 DCBF (R4) /* fix for 603x bug */ 694 LWAR (R4), R3 695 ADD $1, R3 696 STWCCC R3, (R4) 697 BNE xincloop 698 RETURN 699 700TEXT _xdec(SB), 1, $0 /* long _xdec(long *); */ 701 MOVW R3, R4 702xdecloop: 703 DCBF (R4) /* fix for 603x bug */ 704 LWAR (R4), R3 705 ADD $-1, R3 706 STWCCC R3, (R4) 707 BNE xdecloop 708 RETURN 709 710TEXT cas32(SB), 1, $0 /* int cas32(void*, u32int, u32int) */ 711 MOVW R3, R4 /* addr */ 712 MOVW old+4(FP), R5 713 MOVW new+8(FP), R6 714 DCBF (R4) /* fix for 603x bug? */ 715 LWAR (R4), R3 716 CMP R3, R5 717 BNE fail 718 STWCCC R6, (R4) 719 BNE fail 720 MOVW $1, R3 721 RETURN 722fail: 723 MOVW $0, R3 724 RETURN 725 726TEXT tlbwrx(SB), 1, $-4 727 MOVW hi+4(FP), R5 728 MOVW mid+8(FP), R6 729 MOVW lo+12(FP), R7 730 MSYNC 731 TLBWEHI(5, 3) 732 TLBWEMD(6, 3) 733 TLBWELO(7, 3) 734 ISYNC 735 RETURN 736 737TEXT tlbrehi(SB), 1, $-4 738 TLBREHI(3, 3) 739 RETURN 740 741TEXT tlbremd(SB), 1, $-4 742 TLBREMD(3, 3) 743 RETURN 744 745TEXT tlbrelo(SB), 1, $-4 746 TLBRELO(3, 3) 747 RETURN 748 749TEXT tlbsxcc(SB), 1, $-4 750 TLBSXCC(0, 3, 3) 751 BEQ tlbsxcc0 752 MOVW $-1, R3 /* not found */ 753tlbsxcc0: 754 RETURN 755 756TEXT gotopc(SB), 1, $0 757 MOVW R3, CTR 758 MOVW LR, R31 /* for trace back */ 759 BR (CTR) 760 761 762/* 763 * following Book E, traps thankfully leave the mmu on. 764 * the following code has been executed at the exception 765 * vector location already: 766 * MOVW R0, SPR(SAVER0) 767 * MOVW LR, R0 768 * MOVW R0, SPR(SAVELR) 769 * BL trapvec(SB) 770 */ 771TEXT trapvec(SB), 1, $-4 772 MOVW LR, R0 773 MOVW R0, SPR(SAVEXX) /* save ivoff--interrupt vector offset */ 774/* entry point for critical interrupts, machine checks, and faults */ 775trapcommon: 776 MOVW R1, SPR(SAVER1) /* save stack pointer */ 777 /* did we come from user space? */ 778 MOVW SPR(SPR_SRR1), R0 779 MOVW CR, R1 780 MOVW R0, CR 781 BC 4,17,ktrap /* if MSR[PR]=0, we are in kernel space */ 782 783 /* switch to kernel stack */ 784 MOVW R1, CR 785 786 MOVW SPR(SPR_SPRG7R), R1 /* up->kstack+KSTACK-UREGSPACE, set in touser and sysrforkret */ 787 788 BL saveureg(SB) 789 MOVW $mach0(SB), R(MACH) 790 MOVW 8(R(MACH)), R(USER) 791 BL trap(SB) 792 BR restoreureg 793 794ktrap: 795 MOVW R1, CR 796 MOVW SPR(SAVER1), R1 797 SUB $UREGSPACE, R1 /* push onto current kernel stack */ 798 BL saveureg(SB) 799 BL trap(SB) 800 801restoreureg: 802 MOVMW 48(R1), R2 /* r2:r31 */ 803 /* defer R1 */ 804 MOVW 40(R1), R0 805 MOVW R0, SPR(SAVER0) 806 MOVW 36(R1), R0 807 MOVW R0, CTR 808 MOVW 32(R1), R0 809 MOVW R0, XER 810 MOVW 28(R1), R0 811 MOVW R0, CR /* CR */ 812 MOVW 24(R1), R0 813 MOVW R0, LR 814 MOVW 20(R1), R0 815 MOVW R0, SPR(SPR_SPRG7W) /* kstack for traps from user space */ 816 MOVW 16(R1), R0 817 MOVW R0, SPR(SPR_SRR0) /* old PC */ 818 MOVW 12(R1), R0 819 RLWNM $0, R0, $~MSR_WE, R0 /* remove wait state */ 820 MOVW R0, SPR(SPR_SRR1) /* old MSR */ 821 /* cause, skip */ 822 MOVW 44(R1), R1 /* old SP */ 823 MOVW SPR(SAVER0), R0 824 RFI 825 826/* 827 * critical trap/interrupt. 828 * the only one we can take is machine check, synchronously, and 829 * outside any other trap handler. 830 * [MSR_ME not cleared => handler may be interrupted by machine check] 831 */ 832TEXT trapcritvec(SB), 1, $-4 833 MOVW LR, R0 834 MOVW R0, SPR(SAVEXX) 835 MOVW SPR(SPR_CSRR0), R0 /* PC or excepting insn */ 836 MOVW R0, SPR(SPR_SRR0) 837 MOVW SPR(SPR_CSRR1), R0 /* old MSR */ 838 MOVW R0, SPR(SPR_SRR1) 839 BR trapcommon 840 841/* 842 * machine check. 843 * make it look like the others. 844 */ 845TEXT trapmvec(SB), 1, $-4 846 MOVW LR, R0 847 MOVW R0, SPR(SAVEXX) 848 MOVW SPR(SPR_MCSRR0), R0 /* PC or excepting insn */ 849 MOVW R0, SPR(SPR_SRR0) 850 MOVW SPR(SPR_MCSRR1), R0 /* old MSR */ 851 MOVW R0, SPR(SPR_SRR1) 852 BR trapcommon 853 854/* 855 * enter with stack set and mapped. 856 * on return, SB (R2) has been set, and R3 has the Ureg*, 857 * the MMU has been re-enabled, kernel text and PC are in KSEG, 858 * Stack (R1), R(MACH) and R(USER) are set by caller, if required. 859 */ 860TEXT saveureg(SB), 1, $-4 861/* 862 * save state 863 */ 864 MOVMW R2, 48(R1) /* save gprs r2 to r31 */ 865 MOVW $setSB(SB), R2 866 MOVW SPR(SAVER1), R4 867 MOVW R4, 44(R1) 868 MOVW SPR(SAVER0), R5 869 MOVW R5, 40(R1) 870 MOVW CTR, R6 871 MOVW R6, 36(R1) 872 MOVW XER, R4 873 MOVW R4, 32(R1) 874 MOVW CR, R5 875 MOVW R5, 28(R1) 876 MOVW SPR(SAVELR), R6 /* LR */ 877 MOVW R6, 24(R1) 878 MOVW SPR(SPR_SPRG7R), R6 /* up->kstack+KSTACK-UREGSPACE */ 879 MOVW R6, 20(R1) 880 MOVW SPR(SPR_SRR0), R0 881 MOVW R0, 16(R1) /* PC of excepting insn (or next insn) */ 882 MOVW SPR(SPR_SRR1), R0 883 MOVW R0, 12(R1) /* old MSR */ 884 MOVW SPR(SAVEXX), R0 885 MOVW R0, 8(R1) /* cause/vector */ 886 ADD $8, R1, R3 /* Ureg* */ 887 STWCCC R3, (R1) /* break any pending reservations */ 888 MOVW $0, R0 /* compiler/linker expect R0 to be zero */ 889 RETURN 890 891/* 892 * restore state from Ureg and return from trap/interrupt 893 */ 894TEXT sysrforkret(SB), 1, $-4 895 MOVW R1, 20(R1) /* up->kstack+KSTACK-UREGSPACE set in ureg */ 896 BR restoreureg 897 898/* 899 * 4xx specific 900 */ 901TEXT firmware(SB), 1, $0 902 MOVW $(3<<28), R3 903 MOVW R3, SPR(SPR_DBCR0) /* system reset */ 904 BR 0(PC) 905