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 .section .text.head, "ax" 54_ENTRY(_stext); 55_ENTRY(_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 /* 221 * This is where the main kernel code starts. 222 */ 223 224 /* ptr to current */ 225 lis r2,init_task@h 226 ori r2,r2,init_task@l 227 228 /* ptr to current thread */ 229 addi r4,r2,THREAD /* init task's THREAD */ 230 mtspr SPRN_SPRG3,r4 231 232 /* stack */ 233 lis r1,init_thread_union@h 234 ori r1,r1,init_thread_union@l 235 li r0,0 236 stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1) 237 238 bl early_init 239 240/* 241 * Decide what sort of machine this is and initialize the MMU. 242 */ 243 mr r3,r31 244 mr r4,r30 245 mr r5,r29 246 mr r6,r28 247 mr r7,r27 248 bl machine_init 249 bl MMU_init 250 251 /* Setup PTE pointers for the Abatron bdiGDB */ 252 lis r6, swapper_pg_dir@h 253 ori r6, r6, swapper_pg_dir@l 254 lis r5, abatron_pteptrs@h 255 ori r5, r5, abatron_pteptrs@l 256 lis r4, KERNELBASE@h 257 ori r4, r4, KERNELBASE@l 258 stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */ 259 stw r6, 0(r5) 260 261 /* Let's move on */ 262 lis r4,start_kernel@h 263 ori r4,r4,start_kernel@l 264 lis r3,MSR_KERNEL@h 265 ori r3,r3,MSR_KERNEL@l 266 mtspr SPRN_SRR0,r4 267 mtspr SPRN_SRR1,r3 268 rfi /* change context and jump to start_kernel */ 269 270/* 271 * Interrupt vector entry code 272 * 273 * The Book E MMUs are always on so we don't need to handle 274 * interrupts in real mode as with previous PPC processors. In 275 * this case we handle interrupts in the kernel virtual address 276 * space. 277 * 278 * Interrupt vectors are dynamically placed relative to the 279 * interrupt prefix as determined by the address of interrupt_base. 280 * The interrupt vectors offsets are programmed using the labels 281 * for each interrupt vector entry. 282 * 283 * Interrupt vectors must be aligned on a 16 byte boundary. 284 * We align on a 32 byte cache line boundary for good measure. 285 */ 286 287interrupt_base: 288 /* Critical Input Interrupt */ 289 CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception) 290 291 /* Machine Check Interrupt */ 292 CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception) 293 MCHECK_EXCEPTION(0x0210, MachineCheckA, machine_check_exception) 294 295 /* Data Storage Interrupt */ 296 START_EXCEPTION(DataStorage) 297 mtspr SPRN_SPRG0, r10 /* Save some working registers */ 298 mtspr SPRN_SPRG1, r11 299 mtspr SPRN_SPRG4W, r12 300 mtspr SPRN_SPRG5W, r13 301 mfcr r11 302 mtspr SPRN_SPRG7W, r11 303 304 /* 305 * Check if it was a store fault, if not then bail 306 * because a user tried to access a kernel or 307 * read-protected page. Otherwise, get the 308 * offending address and handle it. 309 */ 310 mfspr r10, SPRN_ESR 311 andis. r10, r10, ESR_ST@h 312 beq 2f 313 314 mfspr r10, SPRN_DEAR /* Get faulting address */ 315 316 /* If we are faulting a kernel address, we have to use the 317 * kernel page tables. 318 */ 319 lis r11, PAGE_OFFSET@h 320 cmplw r10, r11 321 blt+ 3f 322 lis r11, swapper_pg_dir@h 323 ori r11, r11, swapper_pg_dir@l 324 325 mfspr r12,SPRN_MMUCR 326 rlwinm r12,r12,0,0,23 /* Clear TID */ 327 328 b 4f 329 330 /* Get the PGD for the current thread */ 3313: 332 mfspr r11,SPRN_SPRG3 333 lwz r11,PGDIR(r11) 334 335 /* Load PID into MMUCR TID */ 336 mfspr r12,SPRN_MMUCR /* Get MMUCR */ 337 mfspr r13,SPRN_PID /* Get PID */ 338 rlwimi r12,r13,0,24,31 /* Set TID */ 339 3404: 341 mtspr SPRN_MMUCR,r12 342 343 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 344 lwzx r11, r12, r11 /* Get pgd/pmd entry */ 345 rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 346 beq 2f /* Bail if no table */ 347 348 rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 349 lwz r11, 4(r12) /* Get pte entry */ 350 351 andi. r13, r11, _PAGE_RW /* Is it writeable? */ 352 beq 2f /* Bail if not */ 353 354 /* Update 'changed'. 355 */ 356 ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE 357 stw r11, 4(r12) /* Update Linux page table */ 358 359 li r13, PPC44x_TLB_SR@l /* Set SR */ 360 rlwimi r13, r11, 29, 29, 29 /* SX = _PAGE_HWEXEC */ 361 rlwimi r13, r11, 0, 30, 30 /* SW = _PAGE_RW */ 362 rlwimi r13, r11, 29, 28, 28 /* UR = _PAGE_USER */ 363 rlwimi r12, r11, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ 364 rlwimi r12, r11, 29, 30, 30 /* (_PAGE_USER>>3)->r12 */ 365 and r12, r12, r11 /* HWEXEC/RW & USER */ 366 rlwimi r13, r12, 0, 26, 26 /* UX = HWEXEC & USER */ 367 rlwimi r13, r12, 3, 27, 27 /* UW = RW & USER */ 368 369 rlwimi r11,r13,0,26,31 /* Insert static perms */ 370 371 rlwinm r11,r11,0,20,15 /* Clear U0-U3 */ 372 373 /* find the TLB index that caused the fault. It has to be here. */ 374 tlbsx r10, 0, r10 375 376 tlbwe r11, r10, PPC44x_TLB_ATTRIB /* Write ATTRIB */ 377 378 /* Done...restore registers and get out of here. 379 */ 380 mfspr r11, SPRN_SPRG7R 381 mtcr r11 382 mfspr r13, SPRN_SPRG5R 383 mfspr r12, SPRN_SPRG4R 384 385 mfspr r11, SPRN_SPRG1 386 mfspr r10, SPRN_SPRG0 387 rfi /* Force context change */ 388 3892: 390 /* 391 * The bailout. Restore registers to pre-exception conditions 392 * and call the heavyweights to help us out. 393 */ 394 mfspr r11, SPRN_SPRG7R 395 mtcr r11 396 mfspr r13, SPRN_SPRG5R 397 mfspr r12, SPRN_SPRG4R 398 399 mfspr r11, SPRN_SPRG1 400 mfspr r10, SPRN_SPRG0 401 b data_access 402 403 /* Instruction Storage Interrupt */ 404 INSTRUCTION_STORAGE_EXCEPTION 405 406 /* External Input Interrupt */ 407 EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE) 408 409 /* Alignment Interrupt */ 410 ALIGNMENT_EXCEPTION 411 412 /* Program Interrupt */ 413 PROGRAM_EXCEPTION 414 415 /* Floating Point Unavailable Interrupt */ 416#ifdef CONFIG_PPC_FPU 417 FP_UNAVAILABLE_EXCEPTION 418#else 419 EXCEPTION(0x2010, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE) 420#endif 421 422 /* System Call Interrupt */ 423 START_EXCEPTION(SystemCall) 424 NORMAL_EXCEPTION_PROLOG 425 EXC_XFER_EE_LITE(0x0c00, DoSyscall) 426 427 /* Auxillary Processor Unavailable Interrupt */ 428 EXCEPTION(0x2020, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE) 429 430 /* Decrementer Interrupt */ 431 DECREMENTER_EXCEPTION 432 433 /* Fixed Internal Timer Interrupt */ 434 /* TODO: Add FIT support */ 435 EXCEPTION(0x1010, FixedIntervalTimer, unknown_exception, EXC_XFER_EE) 436 437 /* Watchdog Timer Interrupt */ 438 /* TODO: Add watchdog support */ 439#ifdef CONFIG_BOOKE_WDT 440 CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException) 441#else 442 CRITICAL_EXCEPTION(0x1020, WatchdogTimer, unknown_exception) 443#endif 444 445 /* Data TLB Error Interrupt */ 446 START_EXCEPTION(DataTLBError) 447 mtspr SPRN_SPRG0, r10 /* Save some working registers */ 448 mtspr SPRN_SPRG1, r11 449 mtspr SPRN_SPRG4W, r12 450 mtspr SPRN_SPRG5W, r13 451 mfcr r11 452 mtspr SPRN_SPRG7W, r11 453 mfspr r10, SPRN_DEAR /* Get faulting address */ 454 455 /* If we are faulting a kernel address, we have to use the 456 * kernel page tables. 457 */ 458 lis r11, PAGE_OFFSET@h 459 cmplw r10, r11 460 blt+ 3f 461 lis r11, swapper_pg_dir@h 462 ori r11, r11, swapper_pg_dir@l 463 464 mfspr r12,SPRN_MMUCR 465 rlwinm r12,r12,0,0,23 /* Clear TID */ 466 467 b 4f 468 469 /* Get the PGD for the current thread */ 4703: 471 mfspr r11,SPRN_SPRG3 472 lwz r11,PGDIR(r11) 473 474 /* Load PID into MMUCR TID */ 475 mfspr r12,SPRN_MMUCR 476 mfspr r13,SPRN_PID /* Get PID */ 477 rlwimi r12,r13,0,24,31 /* Set TID */ 478 4794: 480 mtspr SPRN_MMUCR,r12 481 482 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 483 lwzx r11, r12, r11 /* Get pgd/pmd entry */ 484 rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 485 beq 2f /* Bail if no table */ 486 487 rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 488 lwz r11, 4(r12) /* Get pte entry */ 489 andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ 490 beq 2f /* Bail if not present */ 491 492 ori r11, r11, _PAGE_ACCESSED 493 stw r11, 4(r12) 494 495 /* Jump to common tlb load */ 496 b finish_tlb_load 497 4982: 499 /* The bailout. Restore registers to pre-exception conditions 500 * and call the heavyweights to help us out. 501 */ 502 mfspr r11, SPRN_SPRG7R 503 mtcr r11 504 mfspr r13, SPRN_SPRG5R 505 mfspr r12, SPRN_SPRG4R 506 mfspr r11, SPRN_SPRG1 507 mfspr r10, SPRN_SPRG0 508 b data_access 509 510 /* Instruction TLB Error Interrupt */ 511 /* 512 * Nearly the same as above, except we get our 513 * information from different registers and bailout 514 * to a different point. 515 */ 516 START_EXCEPTION(InstructionTLBError) 517 mtspr SPRN_SPRG0, r10 /* Save some working registers */ 518 mtspr SPRN_SPRG1, r11 519 mtspr SPRN_SPRG4W, r12 520 mtspr SPRN_SPRG5W, r13 521 mfcr r11 522 mtspr SPRN_SPRG7W, r11 523 mfspr r10, SPRN_SRR0 /* Get faulting address */ 524 525 /* If we are faulting a kernel address, we have to use the 526 * kernel page tables. 527 */ 528 lis r11, PAGE_OFFSET@h 529 cmplw r10, r11 530 blt+ 3f 531 lis r11, swapper_pg_dir@h 532 ori r11, r11, swapper_pg_dir@l 533 534 mfspr r12,SPRN_MMUCR 535 rlwinm r12,r12,0,0,23 /* Clear TID */ 536 537 b 4f 538 539 /* Get the PGD for the current thread */ 5403: 541 mfspr r11,SPRN_SPRG3 542 lwz r11,PGDIR(r11) 543 544 /* Load PID into MMUCR TID */ 545 mfspr r12,SPRN_MMUCR 546 mfspr r13,SPRN_PID /* Get PID */ 547 rlwimi r12,r13,0,24,31 /* Set TID */ 548 5494: 550 mtspr SPRN_MMUCR,r12 551 552 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 553 lwzx r11, r12, r11 /* Get pgd/pmd entry */ 554 rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 555 beq 2f /* Bail if no table */ 556 557 rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 558 lwz r11, 4(r12) /* Get pte entry */ 559 andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ 560 beq 2f /* Bail if not present */ 561 562 ori r11, r11, _PAGE_ACCESSED 563 stw r11, 4(r12) 564 565 /* Jump to common TLB load point */ 566 b finish_tlb_load 567 5682: 569 /* The bailout. Restore registers to pre-exception conditions 570 * and call the heavyweights to help us out. 571 */ 572 mfspr r11, SPRN_SPRG7R 573 mtcr r11 574 mfspr r13, SPRN_SPRG5R 575 mfspr r12, SPRN_SPRG4R 576 mfspr r11, SPRN_SPRG1 577 mfspr r10, SPRN_SPRG0 578 b InstructionStorage 579 580 /* Debug Interrupt */ 581 DEBUG_EXCEPTION 582 583/* 584 * Local functions 585 */ 586 /* 587 * Data TLB exceptions will bail out to this point 588 * if they can't resolve the lightweight TLB fault. 589 */ 590data_access: 591 NORMAL_EXCEPTION_PROLOG 592 mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ 593 stw r5,_ESR(r11) 594 mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ 595 EXC_XFER_EE_LITE(0x0300, handle_page_fault) 596 597/* 598 599 * Both the instruction and data TLB miss get to this 600 * point to load the TLB. 601 * r10 - EA of fault 602 * r11 - available to use 603 * r12 - Pointer to the 64-bit PTE 604 * r13 - available to use 605 * MMUCR - loaded with proper value when we get here 606 * Upon exit, we reload everything and RFI. 607 */ 608finish_tlb_load: 609 /* 610 * We set execute, because we don't have the granularity to 611 * properly set this at the page level (Linux problem). 612 * If shared is set, we cause a zero PID->TID load. 613 * Many of these bits are software only. Bits we don't set 614 * here we (properly should) assume have the appropriate value. 615 */ 616 617 /* Load the next available TLB index */ 618 lis r13, tlb_44x_index@ha 619 lwz r13, tlb_44x_index@l(r13) 620 /* Load the TLB high watermark */ 621 lis r11, tlb_44x_hwater@ha 622 lwz r11, tlb_44x_hwater@l(r11) 623 624 /* Increment, rollover, and store TLB index */ 625 addi r13, r13, 1 626 cmpw 0, r13, r11 /* reserve entries */ 627 ble 7f 628 li r13, 0 6297: 630 /* Store the next available TLB index */ 631 lis r11, tlb_44x_index@ha 632 stw r13, tlb_44x_index@l(r11) 633 634 lwz r11, 0(r12) /* Get MS word of PTE */ 635 lwz r12, 4(r12) /* Get LS word of PTE */ 636 rlwimi r11, r12, 0, 0 , 19 /* Insert RPN */ 637 tlbwe r11, r13, PPC44x_TLB_XLAT /* Write XLAT */ 638 639 /* 640 * Create PAGEID. This is the faulting address, 641 * page size, and valid flag. 642 */ 643 li r11, PPC44x_TLB_VALID | PPC44x_TLB_4K 644 rlwimi r10, r11, 0, 20, 31 /* Insert valid and page size */ 645 tlbwe r10, r13, PPC44x_TLB_PAGEID /* Write PAGEID */ 646 647 li r10, PPC44x_TLB_SR@l /* Set SR */ 648 rlwimi r10, r12, 0, 30, 30 /* Set SW = _PAGE_RW */ 649 rlwimi r10, r12, 29, 29, 29 /* SX = _PAGE_HWEXEC */ 650 rlwimi r10, r12, 29, 28, 28 /* UR = _PAGE_USER */ 651 rlwimi r11, r12, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ 652 and r11, r12, r11 /* HWEXEC & USER */ 653 rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */ 654 655 rlwimi r12, r10, 0, 26, 31 /* Insert static perms */ 656 rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */ 657 tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */ 658 659 /* Done...restore registers and get out of here. 660 */ 661 mfspr r11, SPRN_SPRG7R 662 mtcr r11 663 mfspr r13, SPRN_SPRG5R 664 mfspr r12, SPRN_SPRG4R 665 mfspr r11, SPRN_SPRG1 666 mfspr r10, SPRN_SPRG0 667 rfi /* Force context change */ 668 669/* 670 * Global functions 671 */ 672 673/* 674 * Adjust the machine check IVOR on 440A cores 675 */ 676_GLOBAL(__fixup_440A_mcheck) 677 li r3,MachineCheckA@l 678 mtspr SPRN_IVOR1,r3 679 sync 680 blr 681 682/* 683 * extern void giveup_altivec(struct task_struct *prev) 684 * 685 * The 44x core does not have an AltiVec unit. 686 */ 687_GLOBAL(giveup_altivec) 688 blr 689 690/* 691 * extern void giveup_fpu(struct task_struct *prev) 692 * 693 * The 44x core does not have an FPU. 694 */ 695#ifndef CONFIG_PPC_FPU 696_GLOBAL(giveup_fpu) 697 blr 698#endif 699 700_GLOBAL(set_context) 701 702#ifdef CONFIG_BDI_SWITCH 703 /* Context switch the PTE pointer for the Abatron BDI2000. 704 * The PGDIR is the second parameter. 705 */ 706 lis r5, abatron_pteptrs@h 707 ori r5, r5, abatron_pteptrs@l 708 stw r4, 0x4(r5) 709#endif 710 mtspr SPRN_PID,r3 711 isync /* Force context change */ 712 blr 713 714/* 715 * We put a few things here that have to be page-aligned. This stuff 716 * goes at the beginning of the data segment, which is page-aligned. 717 */ 718 .data 719 .align 12 720 .globl sdata 721sdata: 722 .globl empty_zero_page 723empty_zero_page: 724 .space 4096 725 726/* 727 * To support >32-bit physical addresses, we use an 8KB pgdir. 728 */ 729 .globl swapper_pg_dir 730swapper_pg_dir: 731 .space PGD_TABLE_SIZE 732 733/* Reserved 4k for the critical exception stack & 4k for the machine 734 * check stack per CPU for kernel mode exceptions */ 735 .section .bss 736 .align 12 737exception_stack_bottom: 738 .space BOOKE_EXCEPTION_STACK_SIZE 739 .globl exception_stack_top 740exception_stack_top: 741 742/* 743 * Room for two PTE pointers, usually the kernel and current user pointers 744 * to their respective root page table. 745 */ 746abatron_pteptrs: 747 .space 8 748