1/* 2 * Kernel execution entry point code. 3 * 4 * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> 5 * Initial PowerPC version. 6 * Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu> 7 * Rewritten for PReP 8 * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au> 9 * Low-level exception handers, MMU support, and rewrite. 10 * Copyright (c) 1997 Dan Malek <dmalek@jlc.net> 11 * PowerPC 8xx modifications. 12 * Copyright (c) 1998-1999 TiVo, Inc. 13 * PowerPC 403GCX modifications. 14 * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> 15 * PowerPC 403GCX/405GP modifications. 16 * Copyright 2000 MontaVista Software Inc. 17 * PPC405 modifications 18 * PowerPC 403GCX/405GP modifications. 19 * Author: MontaVista Software, Inc. 20 * frank_rowand@mvista.com or source@mvista.com 21 * debbie_chu@mvista.com 22 * Copyright 2002-2005 MontaVista Software, Inc. 23 * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> 24 * 25 * This program is free software; you can redistribute it and/or modify it 26 * under the terms of the GNU General Public License as published by the 27 * Free Software Foundation; either version 2 of the License, or (at your 28 * option) any later version. 29 */ 30 31#include <asm/processor.h> 32#include <asm/page.h> 33#include <asm/mmu.h> 34#include <asm/pgtable.h> 35#include <asm/cputable.h> 36#include <asm/thread_info.h> 37#include <asm/ppc_asm.h> 38#include <asm/asm-offsets.h> 39#include "head_booke.h" 40 41 42/* As with the other PowerPC ports, it is expected that when code 43 * execution begins here, the following registers contain valid, yet 44 * optional, information: 45 * 46 * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.) 47 * r4 - Starting address of the init RAM disk 48 * r5 - Ending address of the init RAM disk 49 * r6 - Start of kernel command line string (e.g. "mem=128") 50 * r7 - End of kernel command line string 51 * 52 */ 53 .text 54_GLOBAL(_stext) 55_GLOBAL(_start) 56 /* 57 * Reserve a word at a fixed location to store the address 58 * of abatron_pteptrs 59 */ 60 nop 61/* 62 * Save parameters we are passed 63 */ 64 mr r31,r3 65 mr r30,r4 66 mr r29,r5 67 mr r28,r6 68 mr r27,r7 69 li r24,0 /* CPU number */ 70 71/* 72 * Set up the initial MMU state 73 * 74 * We are still executing code at the virtual address 75 * mappings set by the firmware for the base of RAM. 76 * 77 * We first invalidate all TLB entries but the one 78 * we are running from. We then load the KERNELBASE 79 * mappings so we can begin to use kernel addresses 80 * natively and so the interrupt vector locations are 81 * permanently pinned (necessary since Book E 82 * implementations always have translation enabled). 83 * 84 * TODO: Use the known TLB entry we are running from to 85 * determine which physical region we are located 86 * in. This can be used to determine where in RAM 87 * (on a shared CPU system) or PCI memory space 88 * (on a DRAMless system) we are located. 89 * For now, we assume a perfect world which means 90 * we are located at the base of DRAM (physical 0). 91 */ 92 93/* 94 * Search TLB for entry that we are currently using. 95 * Invalidate all entries but the one we are using. 96 */ 97 /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */ 98 mfspr r3,SPRN_PID /* Get PID */ 99 mfmsr r4 /* Get MSR */ 100 andi. r4,r4,MSR_IS@l /* TS=1? */ 101 beq wmmucr /* If not, leave STS=0 */ 102 oris r3,r3,PPC44x_MMUCR_STS@h /* Set STS=1 */ 103wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */ 104 sync 105 106 bl invstr /* Find our address */ 107invstr: mflr r5 /* Make it accessible */ 108 tlbsx r23,0,r5 /* Find entry we are in */ 109 li r4,0 /* Start at TLB entry 0 */ 110 li r3,0 /* Set PAGEID inval value */ 1111: cmpw r23,r4 /* Is this our entry? */ 112 beq skpinv /* If so, skip the inval */ 113 tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */ 114skpinv: addi r4,r4,1 /* Increment */ 115 cmpwi r4,64 /* Are we done? */ 116 bne 1b /* If not, repeat */ 117 isync /* If so, context change */ 118 119/* 120 * Configure and load pinned entry into TLB slot 63. 121 */ 122 123 lis r3,PAGE_OFFSET@h 124 ori r3,r3,PAGE_OFFSET@l 125 126 /* Kernel is at the base of RAM */ 127 li r4, 0 /* Load the kernel physical address */ 128 129 /* Load the kernel PID = 0 */ 130 li r0,0 131 mtspr SPRN_PID,r0 132 sync 133 134 /* Initialize MMUCR */ 135 li r5,0 136 mtspr SPRN_MMUCR,r5 137 sync 138 139 /* pageid fields */ 140 clrrwi r3,r3,10 /* Mask off the effective page number */ 141 ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M 142 143 /* xlat fields */ 144 clrrwi r4,r4,10 /* Mask off the real page number */ 145 /* ERPN is 0 for first 4GB page */ 146 147 /* attrib fields */ 148 /* Added guarded bit to protect against speculative loads/stores */ 149 li r5,0 150 ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G) 151 152 li r0,63 /* TLB slot 63 */ 153 154 tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ 155 tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ 156 tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ 157 158 /* Force context change */ 159 mfmsr r0 160 mtspr SPRN_SRR1, r0 161 lis r0,3f@h 162 ori r0,r0,3f@l 163 mtspr SPRN_SRR0,r0 164 sync 165 rfi 166 167 /* If necessary, invalidate original entry we used */ 1683: cmpwi r23,63 169 beq 4f 170 li r6,0 171 tlbwe r6,r23,PPC44x_TLB_PAGEID 172 isync 173 1744: 175#ifdef CONFIG_PPC_EARLY_DEBUG_44x 176 /* Add UART mapping for early debug. */ 177 178 /* pageid fields */ 179 lis r3,PPC44x_EARLY_DEBUG_VIRTADDR@h 180 ori r3,r3,PPC44x_TLB_VALID|PPC44x_TLB_TS|PPC44x_TLB_64K 181 182 /* xlat fields */ 183 lis r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW@h 184 ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH 185 186 /* attrib fields */ 187 li r5,(PPC44x_TLB_SW|PPC44x_TLB_SR|PPC44x_TLB_I|PPC44x_TLB_G) 188 li r0,62 /* TLB slot 0 */ 189 190 tlbwe r3,r0,PPC44x_TLB_PAGEID 191 tlbwe r4,r0,PPC44x_TLB_XLAT 192 tlbwe r5,r0,PPC44x_TLB_ATTRIB 193 194 /* Force context change */ 195 isync 196#endif /* CONFIG_PPC_EARLY_DEBUG_44x */ 197 198 /* Establish the interrupt vector offsets */ 199 SET_IVOR(0, CriticalInput); 200 SET_IVOR(1, MachineCheck); 201 SET_IVOR(2, DataStorage); 202 SET_IVOR(3, InstructionStorage); 203 SET_IVOR(4, ExternalInput); 204 SET_IVOR(5, Alignment); 205 SET_IVOR(6, Program); 206 SET_IVOR(7, FloatingPointUnavailable); 207 SET_IVOR(8, SystemCall); 208 SET_IVOR(9, AuxillaryProcessorUnavailable); 209 SET_IVOR(10, Decrementer); 210 SET_IVOR(11, FixedIntervalTimer); 211 SET_IVOR(12, WatchdogTimer); 212 SET_IVOR(13, DataTLBError); 213 SET_IVOR(14, InstructionTLBError); 214 SET_IVOR(15, Debug); 215 216 /* Establish the interrupt vector base */ 217 lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ 218 mtspr SPRN_IVPR,r4 219 220#ifdef CONFIG_440EP 221 /* Clear DAPUIB flag in CCR0 (enable APU between CPU and FPU) */ 222 mfspr r2,SPRN_CCR0 223 lis r3,0xffef 224 ori r3,r3,0xffff 225 and r2,r2,r3 226 mtspr SPRN_CCR0,r2 227 isync 228#endif 229 230 /* 231 * This is where the main kernel code starts. 232 */ 233 234 /* ptr to current */ 235 lis r2,init_task@h 236 ori r2,r2,init_task@l 237 238 /* ptr to current thread */ 239 addi r4,r2,THREAD /* init task's THREAD */ 240 mtspr SPRN_SPRG3,r4 241 242 /* stack */ 243 lis r1,init_thread_union@h 244 ori r1,r1,init_thread_union@l 245 li r0,0 246 stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1) 247 248 bl early_init 249 250/* 251 * Decide what sort of machine this is and initialize the MMU. 252 */ 253 mr r3,r31 254 mr r4,r30 255 mr r5,r29 256 mr r6,r28 257 mr r7,r27 258 bl machine_init 259 bl MMU_init 260 261 /* Setup PTE pointers for the Abatron bdiGDB */ 262 lis r6, swapper_pg_dir@h 263 ori r6, r6, swapper_pg_dir@l 264 lis r5, abatron_pteptrs@h 265 ori r5, r5, abatron_pteptrs@l 266 lis r4, KERNELBASE@h 267 ori r4, r4, KERNELBASE@l 268 stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */ 269 stw r6, 0(r5) 270 271 /* Let's move on */ 272 lis r4,start_kernel@h 273 ori r4,r4,start_kernel@l 274 lis r3,MSR_KERNEL@h 275 ori r3,r3,MSR_KERNEL@l 276 mtspr SPRN_SRR0,r4 277 mtspr SPRN_SRR1,r3 278 rfi /* change context and jump to start_kernel */ 279 280/* 281 * Interrupt vector entry code 282 * 283 * The Book E MMUs are always on so we don't need to handle 284 * interrupts in real mode as with previous PPC processors. In 285 * this case we handle interrupts in the kernel virtual address 286 * space. 287 * 288 * Interrupt vectors are dynamically placed relative to the 289 * interrupt prefix as determined by the address of interrupt_base. 290 * The interrupt vectors offsets are programmed using the labels 291 * for each interrupt vector entry. 292 * 293 * Interrupt vectors must be aligned on a 16 byte boundary. 294 * We align on a 32 byte cache line boundary for good measure. 295 */ 296 297interrupt_base: 298 /* Critical Input Interrupt */ 299 CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception) 300 301 /* Machine Check Interrupt */ 302#ifdef CONFIG_440A 303 MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception) 304#else 305 CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception) 306#endif 307 308 /* Data Storage Interrupt */ 309 START_EXCEPTION(DataStorage) 310 mtspr SPRN_SPRG0, r10 /* Save some working registers */ 311 mtspr SPRN_SPRG1, r11 312 mtspr SPRN_SPRG4W, r12 313 mtspr SPRN_SPRG5W, r13 314 mfcr r11 315 mtspr SPRN_SPRG7W, r11 316 317 /* 318 * Check if it was a store fault, if not then bail 319 * because a user tried to access a kernel or 320 * read-protected page. Otherwise, get the 321 * offending address and handle it. 322 */ 323 mfspr r10, SPRN_ESR 324 andis. r10, r10, ESR_ST@h 325 beq 2f 326 327 mfspr r10, SPRN_DEAR /* Get faulting address */ 328 329 /* If we are faulting a kernel address, we have to use the 330 * kernel page tables. 331 */ 332 lis r11, TASK_SIZE@h 333 cmplw r10, r11 334 blt+ 3f 335 lis r11, swapper_pg_dir@h 336 ori r11, r11, swapper_pg_dir@l 337 338 mfspr r12,SPRN_MMUCR 339 rlwinm r12,r12,0,0,23 /* Clear TID */ 340 341 b 4f 342 343 /* Get the PGD for the current thread */ 3443: 345 mfspr r11,SPRN_SPRG3 346 lwz r11,PGDIR(r11) 347 348 /* Load PID into MMUCR TID */ 349 mfspr r12,SPRN_MMUCR /* Get MMUCR */ 350 mfspr r13,SPRN_PID /* Get PID */ 351 rlwimi r12,r13,0,24,31 /* Set TID */ 352 3534: 354 mtspr SPRN_MMUCR,r12 355 356 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 357 lwzx r11, r12, r11 /* Get pgd/pmd entry */ 358 rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 359 beq 2f /* Bail if no table */ 360 361 rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 362 lwz r11, 4(r12) /* Get pte entry */ 363 364 andi. r13, r11, _PAGE_RW /* Is it writeable? */ 365 beq 2f /* Bail if not */ 366 367 /* Update 'changed'. 368 */ 369 ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE 370 stw r11, 4(r12) /* Update Linux page table */ 371 372 li r13, PPC44x_TLB_SR@l /* Set SR */ 373 rlwimi r13, r11, 29, 29, 29 /* SX = _PAGE_HWEXEC */ 374 rlwimi r13, r11, 0, 30, 30 /* SW = _PAGE_RW */ 375 rlwimi r13, r11, 29, 28, 28 /* UR = _PAGE_USER */ 376 rlwimi r12, r11, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ 377 rlwimi r12, r11, 29, 30, 30 /* (_PAGE_USER>>3)->r12 */ 378 and r12, r12, r11 /* HWEXEC/RW & USER */ 379 rlwimi r13, r12, 0, 26, 26 /* UX = HWEXEC & USER */ 380 rlwimi r13, r12, 3, 27, 27 /* UW = RW & USER */ 381 382 rlwimi r11,r13,0,26,31 /* Insert static perms */ 383 384 rlwinm r11,r11,0,20,15 /* Clear U0-U3 */ 385 386 /* find the TLB index that caused the fault. It has to be here. */ 387 tlbsx r10, 0, r10 388 389 tlbwe r11, r10, PPC44x_TLB_ATTRIB /* Write ATTRIB */ 390 391 /* Done...restore registers and get out of here. 392 */ 393 mfspr r11, SPRN_SPRG7R 394 mtcr r11 395 mfspr r13, SPRN_SPRG5R 396 mfspr r12, SPRN_SPRG4R 397 398 mfspr r11, SPRN_SPRG1 399 mfspr r10, SPRN_SPRG0 400 rfi /* Force context change */ 401 4022: 403 /* 404 * The bailout. Restore registers to pre-exception conditions 405 * and call the heavyweights to help us out. 406 */ 407 mfspr r11, SPRN_SPRG7R 408 mtcr r11 409 mfspr r13, SPRN_SPRG5R 410 mfspr r12, SPRN_SPRG4R 411 412 mfspr r11, SPRN_SPRG1 413 mfspr r10, SPRN_SPRG0 414 b data_access 415 416 /* Instruction Storage Interrupt */ 417 INSTRUCTION_STORAGE_EXCEPTION 418 419 /* External Input Interrupt */ 420 EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE) 421 422 /* Alignment Interrupt */ 423 ALIGNMENT_EXCEPTION 424 425 /* Program Interrupt */ 426 PROGRAM_EXCEPTION 427 428 /* Floating Point Unavailable Interrupt */ 429#ifdef CONFIG_PPC_FPU 430 FP_UNAVAILABLE_EXCEPTION 431#else 432 EXCEPTION(0x2010, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE) 433#endif 434 435 /* System Call Interrupt */ 436 START_EXCEPTION(SystemCall) 437 NORMAL_EXCEPTION_PROLOG 438 EXC_XFER_EE_LITE(0x0c00, DoSyscall) 439 440 /* Auxillary Processor Unavailable Interrupt */ 441 EXCEPTION(0x2020, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE) 442 443 /* Decrementer Interrupt */ 444 DECREMENTER_EXCEPTION 445 446 /* Fixed Internal Timer Interrupt */ 447 /* TODO: Add FIT support */ 448 EXCEPTION(0x1010, FixedIntervalTimer, unknown_exception, EXC_XFER_EE) 449 450 /* Watchdog Timer Interrupt */ 451 /* TODO: Add watchdog support */ 452#ifdef CONFIG_BOOKE_WDT 453 CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException) 454#else 455 CRITICAL_EXCEPTION(0x1020, WatchdogTimer, unknown_exception) 456#endif 457 458 /* Data TLB Error Interrupt */ 459 START_EXCEPTION(DataTLBError) 460 mtspr SPRN_SPRG0, r10 /* Save some working registers */ 461 mtspr SPRN_SPRG1, r11 462 mtspr SPRN_SPRG4W, r12 463 mtspr SPRN_SPRG5W, r13 464 mfcr r11 465 mtspr SPRN_SPRG7W, r11 466 mfspr r10, SPRN_DEAR /* Get faulting address */ 467 468 /* If we are faulting a kernel address, we have to use the 469 * kernel page tables. 470 */ 471 lis r11, TASK_SIZE@h 472 cmplw r10, r11 473 blt+ 3f 474 lis r11, swapper_pg_dir@h 475 ori r11, r11, swapper_pg_dir@l 476 477 mfspr r12,SPRN_MMUCR 478 rlwinm r12,r12,0,0,23 /* Clear TID */ 479 480 b 4f 481 482 /* Get the PGD for the current thread */ 4833: 484 mfspr r11,SPRN_SPRG3 485 lwz r11,PGDIR(r11) 486 487 /* Load PID into MMUCR TID */ 488 mfspr r12,SPRN_MMUCR 489 mfspr r13,SPRN_PID /* Get PID */ 490 rlwimi r12,r13,0,24,31 /* Set TID */ 491 4924: 493 mtspr SPRN_MMUCR,r12 494 495 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 496 lwzx r11, r12, r11 /* Get pgd/pmd entry */ 497 rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 498 beq 2f /* Bail if no table */ 499 500 rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 501 lwz r11, 4(r12) /* Get pte entry */ 502 andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ 503 beq 2f /* Bail if not present */ 504 505 ori r11, r11, _PAGE_ACCESSED 506 stw r11, 4(r12) 507 508 /* Jump to common tlb load */ 509 b finish_tlb_load 510 5112: 512 /* The bailout. Restore registers to pre-exception conditions 513 * and call the heavyweights to help us out. 514 */ 515 mfspr r11, SPRN_SPRG7R 516 mtcr r11 517 mfspr r13, SPRN_SPRG5R 518 mfspr r12, SPRN_SPRG4R 519 mfspr r11, SPRN_SPRG1 520 mfspr r10, SPRN_SPRG0 521 b data_access 522 523 /* Instruction TLB Error Interrupt */ 524 /* 525 * Nearly the same as above, except we get our 526 * information from different registers and bailout 527 * to a different point. 528 */ 529 START_EXCEPTION(InstructionTLBError) 530 mtspr SPRN_SPRG0, r10 /* Save some working registers */ 531 mtspr SPRN_SPRG1, r11 532 mtspr SPRN_SPRG4W, r12 533 mtspr SPRN_SPRG5W, r13 534 mfcr r11 535 mtspr SPRN_SPRG7W, r11 536 mfspr r10, SPRN_SRR0 /* Get faulting address */ 537 538 /* If we are faulting a kernel address, we have to use the 539 * kernel page tables. 540 */ 541 lis r11, TASK_SIZE@h 542 cmplw r10, r11 543 blt+ 3f 544 lis r11, swapper_pg_dir@h 545 ori r11, r11, swapper_pg_dir@l 546 547 mfspr r12,SPRN_MMUCR 548 rlwinm r12,r12,0,0,23 /* Clear TID */ 549 550 b 4f 551 552 /* Get the PGD for the current thread */ 5533: 554 mfspr r11,SPRN_SPRG3 555 lwz r11,PGDIR(r11) 556 557 /* Load PID into MMUCR TID */ 558 mfspr r12,SPRN_MMUCR 559 mfspr r13,SPRN_PID /* Get PID */ 560 rlwimi r12,r13,0,24,31 /* Set TID */ 561 5624: 563 mtspr SPRN_MMUCR,r12 564 565 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 566 lwzx r11, r12, r11 /* Get pgd/pmd entry */ 567 rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 568 beq 2f /* Bail if no table */ 569 570 rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 571 lwz r11, 4(r12) /* Get pte entry */ 572 andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ 573 beq 2f /* Bail if not present */ 574 575 ori r11, r11, _PAGE_ACCESSED 576 stw r11, 4(r12) 577 578 /* Jump to common TLB load point */ 579 b finish_tlb_load 580 5812: 582 /* The bailout. Restore registers to pre-exception conditions 583 * and call the heavyweights to help us out. 584 */ 585 mfspr r11, SPRN_SPRG7R 586 mtcr r11 587 mfspr r13, SPRN_SPRG5R 588 mfspr r12, SPRN_SPRG4R 589 mfspr r11, SPRN_SPRG1 590 mfspr r10, SPRN_SPRG0 591 b InstructionStorage 592 593 /* Debug Interrupt */ 594 DEBUG_EXCEPTION 595 596/* 597 * Local functions 598 */ 599 /* 600 * Data TLB exceptions will bail out to this point 601 * if they can't resolve the lightweight TLB fault. 602 */ 603data_access: 604 NORMAL_EXCEPTION_PROLOG 605 mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ 606 stw r5,_ESR(r11) 607 mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ 608 EXC_XFER_EE_LITE(0x0300, handle_page_fault) 609 610/* 611 612 * Both the instruction and data TLB miss get to this 613 * point to load the TLB. 614 * r10 - EA of fault 615 * r11 - available to use 616 * r12 - Pointer to the 64-bit PTE 617 * r13 - available to use 618 * MMUCR - loaded with proper value when we get here 619 * Upon exit, we reload everything and RFI. 620 */ 621finish_tlb_load: 622 /* 623 * We set execute, because we don't have the granularity to 624 * properly set this at the page level (Linux problem). 625 * If shared is set, we cause a zero PID->TID load. 626 * Many of these bits are software only. Bits we don't set 627 * here we (properly should) assume have the appropriate value. 628 */ 629 630 /* Load the next available TLB index */ 631 lis r13, tlb_44x_index@ha 632 lwz r13, tlb_44x_index@l(r13) 633 /* Load the TLB high watermark */ 634 lis r11, tlb_44x_hwater@ha 635 lwz r11, tlb_44x_hwater@l(r11) 636 637 /* Increment, rollover, and store TLB index */ 638 addi r13, r13, 1 639 cmpw 0, r13, r11 /* reserve entries */ 640 ble 7f 641 li r13, 0 6427: 643 /* Store the next available TLB index */ 644 lis r11, tlb_44x_index@ha 645 stw r13, tlb_44x_index@l(r11) 646 647 lwz r11, 0(r12) /* Get MS word of PTE */ 648 lwz r12, 4(r12) /* Get LS word of PTE */ 649 rlwimi r11, r12, 0, 0 , 19 /* Insert RPN */ 650 tlbwe r11, r13, PPC44x_TLB_XLAT /* Write XLAT */ 651 652 /* 653 * Create PAGEID. This is the faulting address, 654 * page size, and valid flag. 655 */ 656 li r11, PPC44x_TLB_VALID | PPC44x_TLB_4K 657 rlwimi r10, r11, 0, 20, 31 /* Insert valid and page size */ 658 tlbwe r10, r13, PPC44x_TLB_PAGEID /* Write PAGEID */ 659 660 li r10, PPC44x_TLB_SR@l /* Set SR */ 661 rlwimi r10, r12, 0, 30, 30 /* Set SW = _PAGE_RW */ 662 rlwimi r10, r12, 29, 29, 29 /* SX = _PAGE_HWEXEC */ 663 rlwimi r10, r12, 29, 28, 28 /* UR = _PAGE_USER */ 664 rlwimi r11, r12, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ 665 and r11, r12, r11 /* HWEXEC & USER */ 666 rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */ 667 668 rlwimi r12, r10, 0, 26, 31 /* Insert static perms */ 669 rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */ 670 tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */ 671 672 /* Done...restore registers and get out of here. 673 */ 674 mfspr r11, SPRN_SPRG7R 675 mtcr r11 676 mfspr r13, SPRN_SPRG5R 677 mfspr r12, SPRN_SPRG4R 678 mfspr r11, SPRN_SPRG1 679 mfspr r10, SPRN_SPRG0 680 rfi /* Force context change */ 681 682/* 683 * Global functions 684 */ 685 686/* 687 * extern void giveup_altivec(struct task_struct *prev) 688 * 689 * The 44x core does not have an AltiVec unit. 690 */ 691_GLOBAL(giveup_altivec) 692 blr 693 694/* 695 * extern void giveup_fpu(struct task_struct *prev) 696 * 697 * The 44x core does not have an FPU. 698 */ 699#ifndef CONFIG_PPC_FPU 700_GLOBAL(giveup_fpu) 701 blr 702#endif 703 704_GLOBAL(set_context) 705 706#ifdef CONFIG_BDI_SWITCH 707 /* Context switch the PTE pointer for the Abatron BDI2000. 708 * The PGDIR is the second parameter. 709 */ 710 lis r5, abatron_pteptrs@h 711 ori r5, r5, abatron_pteptrs@l 712 stw r4, 0x4(r5) 713#endif 714 mtspr SPRN_PID,r3 715 isync /* Force context change */ 716 blr 717 718/* 719 * We put a few things here that have to be page-aligned. This stuff 720 * goes at the beginning of the data segment, which is page-aligned. 721 */ 722 .data 723 .align 12 724 .globl sdata 725sdata: 726 .globl empty_zero_page 727empty_zero_page: 728 .space 4096 729 730/* 731 * To support >32-bit physical addresses, we use an 8KB pgdir. 732 */ 733 .globl swapper_pg_dir 734swapper_pg_dir: 735 .space 8192 736 737/* Reserved 4k for the critical exception stack & 4k for the machine 738 * check stack per CPU for kernel mode exceptions */ 739 .section .bss 740 .align 12 741exception_stack_bottom: 742 .space BOOKE_EXCEPTION_STACK_SIZE 743 .globl exception_stack_top 744exception_stack_top: 745 746/* 747 * This space gets a copy of optional info passed to us by the bootstrap 748 * which is used to pass parameters into the kernel like root=/dev/sda1, etc. 749 */ 750 .globl cmd_line 751cmd_line: 752 .space 512 753 754/* 755 * Room for two PTE pointers, usually the kernel and current user pointers 756 * to their respective root page table. 757 */ 758abatron_pteptrs: 759 .space 8 760