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#ifdef CONFIG_440A 293 MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception) 294#else 295 CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception) 296#endif 297 298 /* Data Storage Interrupt */ 299 START_EXCEPTION(DataStorage) 300 mtspr SPRN_SPRG0, r10 /* Save some working registers */ 301 mtspr SPRN_SPRG1, r11 302 mtspr SPRN_SPRG4W, r12 303 mtspr SPRN_SPRG5W, r13 304 mfcr r11 305 mtspr SPRN_SPRG7W, r11 306 307 /* 308 * Check if it was a store fault, if not then bail 309 * because a user tried to access a kernel or 310 * read-protected page. Otherwise, get the 311 * offending address and handle it. 312 */ 313 mfspr r10, SPRN_ESR 314 andis. r10, r10, ESR_ST@h 315 beq 2f 316 317 mfspr r10, SPRN_DEAR /* Get faulting address */ 318 319 /* If we are faulting a kernel address, we have to use the 320 * kernel page tables. 321 */ 322 lis r11, PAGE_OFFSET@h 323 cmplw r10, r11 324 blt+ 3f 325 lis r11, swapper_pg_dir@h 326 ori r11, r11, swapper_pg_dir@l 327 328 mfspr r12,SPRN_MMUCR 329 rlwinm r12,r12,0,0,23 /* Clear TID */ 330 331 b 4f 332 333 /* Get the PGD for the current thread */ 3343: 335 mfspr r11,SPRN_SPRG3 336 lwz r11,PGDIR(r11) 337 338 /* Load PID into MMUCR TID */ 339 mfspr r12,SPRN_MMUCR /* Get MMUCR */ 340 mfspr r13,SPRN_PID /* Get PID */ 341 rlwimi r12,r13,0,24,31 /* Set TID */ 342 3434: 344 mtspr SPRN_MMUCR,r12 345 346 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 347 lwzx r11, r12, r11 /* Get pgd/pmd entry */ 348 rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 349 beq 2f /* Bail if no table */ 350 351 rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 352 lwz r11, 4(r12) /* Get pte entry */ 353 354 andi. r13, r11, _PAGE_RW /* Is it writeable? */ 355 beq 2f /* Bail if not */ 356 357 /* Update 'changed'. 358 */ 359 ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE 360 stw r11, 4(r12) /* Update Linux page table */ 361 362 li r13, PPC44x_TLB_SR@l /* Set SR */ 363 rlwimi r13, r11, 29, 29, 29 /* SX = _PAGE_HWEXEC */ 364 rlwimi r13, r11, 0, 30, 30 /* SW = _PAGE_RW */ 365 rlwimi r13, r11, 29, 28, 28 /* UR = _PAGE_USER */ 366 rlwimi r12, r11, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ 367 rlwimi r12, r11, 29, 30, 30 /* (_PAGE_USER>>3)->r12 */ 368 and r12, r12, r11 /* HWEXEC/RW & USER */ 369 rlwimi r13, r12, 0, 26, 26 /* UX = HWEXEC & USER */ 370 rlwimi r13, r12, 3, 27, 27 /* UW = RW & USER */ 371 372 rlwimi r11,r13,0,26,31 /* Insert static perms */ 373 374 rlwinm r11,r11,0,20,15 /* Clear U0-U3 */ 375 376 /* find the TLB index that caused the fault. It has to be here. */ 377 tlbsx r10, 0, r10 378 379 tlbwe r11, r10, PPC44x_TLB_ATTRIB /* Write ATTRIB */ 380 381 /* Done...restore registers and get out of here. 382 */ 383 mfspr r11, SPRN_SPRG7R 384 mtcr r11 385 mfspr r13, SPRN_SPRG5R 386 mfspr r12, SPRN_SPRG4R 387 388 mfspr r11, SPRN_SPRG1 389 mfspr r10, SPRN_SPRG0 390 rfi /* Force context change */ 391 3922: 393 /* 394 * The bailout. Restore registers to pre-exception conditions 395 * and call the heavyweights to help us out. 396 */ 397 mfspr r11, SPRN_SPRG7R 398 mtcr r11 399 mfspr r13, SPRN_SPRG5R 400 mfspr r12, SPRN_SPRG4R 401 402 mfspr r11, SPRN_SPRG1 403 mfspr r10, SPRN_SPRG0 404 b data_access 405 406 /* Instruction Storage Interrupt */ 407 INSTRUCTION_STORAGE_EXCEPTION 408 409 /* External Input Interrupt */ 410 EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE) 411 412 /* Alignment Interrupt */ 413 ALIGNMENT_EXCEPTION 414 415 /* Program Interrupt */ 416 PROGRAM_EXCEPTION 417 418 /* Floating Point Unavailable Interrupt */ 419#ifdef CONFIG_PPC_FPU 420 FP_UNAVAILABLE_EXCEPTION 421#else 422 EXCEPTION(0x2010, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE) 423#endif 424 425 /* System Call Interrupt */ 426 START_EXCEPTION(SystemCall) 427 NORMAL_EXCEPTION_PROLOG 428 EXC_XFER_EE_LITE(0x0c00, DoSyscall) 429 430 /* Auxillary Processor Unavailable Interrupt */ 431 EXCEPTION(0x2020, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE) 432 433 /* Decrementer Interrupt */ 434 DECREMENTER_EXCEPTION 435 436 /* Fixed Internal Timer Interrupt */ 437 /* TODO: Add FIT support */ 438 EXCEPTION(0x1010, FixedIntervalTimer, unknown_exception, EXC_XFER_EE) 439 440 /* Watchdog Timer Interrupt */ 441 /* TODO: Add watchdog support */ 442#ifdef CONFIG_BOOKE_WDT 443 CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException) 444#else 445 CRITICAL_EXCEPTION(0x1020, WatchdogTimer, unknown_exception) 446#endif 447 448 /* Data TLB Error Interrupt */ 449 START_EXCEPTION(DataTLBError) 450 mtspr SPRN_SPRG0, r10 /* Save some working registers */ 451 mtspr SPRN_SPRG1, r11 452 mtspr SPRN_SPRG4W, r12 453 mtspr SPRN_SPRG5W, r13 454 mfcr r11 455 mtspr SPRN_SPRG7W, r11 456 mfspr r10, SPRN_DEAR /* Get faulting address */ 457 458 /* If we are faulting a kernel address, we have to use the 459 * kernel page tables. 460 */ 461 lis r11, PAGE_OFFSET@h 462 cmplw r10, r11 463 blt+ 3f 464 lis r11, swapper_pg_dir@h 465 ori r11, r11, swapper_pg_dir@l 466 467 mfspr r12,SPRN_MMUCR 468 rlwinm r12,r12,0,0,23 /* Clear TID */ 469 470 b 4f 471 472 /* Get the PGD for the current thread */ 4733: 474 mfspr r11,SPRN_SPRG3 475 lwz r11,PGDIR(r11) 476 477 /* Load PID into MMUCR TID */ 478 mfspr r12,SPRN_MMUCR 479 mfspr r13,SPRN_PID /* Get PID */ 480 rlwimi r12,r13,0,24,31 /* Set TID */ 481 4824: 483 mtspr SPRN_MMUCR,r12 484 485 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 486 lwzx r11, r12, r11 /* Get pgd/pmd entry */ 487 rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 488 beq 2f /* Bail if no table */ 489 490 rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 491 lwz r11, 4(r12) /* Get pte entry */ 492 andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ 493 beq 2f /* Bail if not present */ 494 495 ori r11, r11, _PAGE_ACCESSED 496 stw r11, 4(r12) 497 498 /* Jump to common tlb load */ 499 b finish_tlb_load 500 5012: 502 /* The bailout. Restore registers to pre-exception conditions 503 * and call the heavyweights to help us out. 504 */ 505 mfspr r11, SPRN_SPRG7R 506 mtcr r11 507 mfspr r13, SPRN_SPRG5R 508 mfspr r12, SPRN_SPRG4R 509 mfspr r11, SPRN_SPRG1 510 mfspr r10, SPRN_SPRG0 511 b data_access 512 513 /* Instruction TLB Error Interrupt */ 514 /* 515 * Nearly the same as above, except we get our 516 * information from different registers and bailout 517 * to a different point. 518 */ 519 START_EXCEPTION(InstructionTLBError) 520 mtspr SPRN_SPRG0, r10 /* Save some working registers */ 521 mtspr SPRN_SPRG1, r11 522 mtspr SPRN_SPRG4W, r12 523 mtspr SPRN_SPRG5W, r13 524 mfcr r11 525 mtspr SPRN_SPRG7W, r11 526 mfspr r10, SPRN_SRR0 /* Get faulting address */ 527 528 /* If we are faulting a kernel address, we have to use the 529 * kernel page tables. 530 */ 531 lis r11, PAGE_OFFSET@h 532 cmplw r10, r11 533 blt+ 3f 534 lis r11, swapper_pg_dir@h 535 ori r11, r11, swapper_pg_dir@l 536 537 mfspr r12,SPRN_MMUCR 538 rlwinm r12,r12,0,0,23 /* Clear TID */ 539 540 b 4f 541 542 /* Get the PGD for the current thread */ 5433: 544 mfspr r11,SPRN_SPRG3 545 lwz r11,PGDIR(r11) 546 547 /* Load PID into MMUCR TID */ 548 mfspr r12,SPRN_MMUCR 549 mfspr r13,SPRN_PID /* Get PID */ 550 rlwimi r12,r13,0,24,31 /* Set TID */ 551 5524: 553 mtspr SPRN_MMUCR,r12 554 555 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 556 lwzx r11, r12, r11 /* Get pgd/pmd entry */ 557 rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 558 beq 2f /* Bail if no table */ 559 560 rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 561 lwz r11, 4(r12) /* Get pte entry */ 562 andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ 563 beq 2f /* Bail if not present */ 564 565 ori r11, r11, _PAGE_ACCESSED 566 stw r11, 4(r12) 567 568 /* Jump to common TLB load point */ 569 b finish_tlb_load 570 5712: 572 /* The bailout. Restore registers to pre-exception conditions 573 * and call the heavyweights to help us out. 574 */ 575 mfspr r11, SPRN_SPRG7R 576 mtcr r11 577 mfspr r13, SPRN_SPRG5R 578 mfspr r12, SPRN_SPRG4R 579 mfspr r11, SPRN_SPRG1 580 mfspr r10, SPRN_SPRG0 581 b InstructionStorage 582 583 /* Debug Interrupt */ 584 DEBUG_EXCEPTION 585 586/* 587 * Local functions 588 */ 589 /* 590 * Data TLB exceptions will bail out to this point 591 * if they can't resolve the lightweight TLB fault. 592 */ 593data_access: 594 NORMAL_EXCEPTION_PROLOG 595 mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ 596 stw r5,_ESR(r11) 597 mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ 598 EXC_XFER_EE_LITE(0x0300, handle_page_fault) 599 600/* 601 602 * Both the instruction and data TLB miss get to this 603 * point to load the TLB. 604 * r10 - EA of fault 605 * r11 - available to use 606 * r12 - Pointer to the 64-bit PTE 607 * r13 - available to use 608 * MMUCR - loaded with proper value when we get here 609 * Upon exit, we reload everything and RFI. 610 */ 611finish_tlb_load: 612 /* 613 * We set execute, because we don't have the granularity to 614 * properly set this at the page level (Linux problem). 615 * If shared is set, we cause a zero PID->TID load. 616 * Many of these bits are software only. Bits we don't set 617 * here we (properly should) assume have the appropriate value. 618 */ 619 620 /* Load the next available TLB index */ 621 lis r13, tlb_44x_index@ha 622 lwz r13, tlb_44x_index@l(r13) 623 /* Load the TLB high watermark */ 624 lis r11, tlb_44x_hwater@ha 625 lwz r11, tlb_44x_hwater@l(r11) 626 627 /* Increment, rollover, and store TLB index */ 628 addi r13, r13, 1 629 cmpw 0, r13, r11 /* reserve entries */ 630 ble 7f 631 li r13, 0 6327: 633 /* Store the next available TLB index */ 634 lis r11, tlb_44x_index@ha 635 stw r13, tlb_44x_index@l(r11) 636 637 lwz r11, 0(r12) /* Get MS word of PTE */ 638 lwz r12, 4(r12) /* Get LS word of PTE */ 639 rlwimi r11, r12, 0, 0 , 19 /* Insert RPN */ 640 tlbwe r11, r13, PPC44x_TLB_XLAT /* Write XLAT */ 641 642 /* 643 * Create PAGEID. This is the faulting address, 644 * page size, and valid flag. 645 */ 646 li r11, PPC44x_TLB_VALID | PPC44x_TLB_4K 647 rlwimi r10, r11, 0, 20, 31 /* Insert valid and page size */ 648 tlbwe r10, r13, PPC44x_TLB_PAGEID /* Write PAGEID */ 649 650 li r10, PPC44x_TLB_SR@l /* Set SR */ 651 rlwimi r10, r12, 0, 30, 30 /* Set SW = _PAGE_RW */ 652 rlwimi r10, r12, 29, 29, 29 /* SX = _PAGE_HWEXEC */ 653 rlwimi r10, r12, 29, 28, 28 /* UR = _PAGE_USER */ 654 rlwimi r11, r12, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ 655 and r11, r12, r11 /* HWEXEC & USER */ 656 rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */ 657 658 rlwimi r12, r10, 0, 26, 31 /* Insert static perms */ 659 rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */ 660 tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */ 661 662 /* Done...restore registers and get out of here. 663 */ 664 mfspr r11, SPRN_SPRG7R 665 mtcr r11 666 mfspr r13, SPRN_SPRG5R 667 mfspr r12, SPRN_SPRG4R 668 mfspr r11, SPRN_SPRG1 669 mfspr r10, SPRN_SPRG0 670 rfi /* Force context change */ 671 672/* 673 * Global functions 674 */ 675 676/* 677 * extern void giveup_altivec(struct task_struct *prev) 678 * 679 * The 44x core does not have an AltiVec unit. 680 */ 681_GLOBAL(giveup_altivec) 682 blr 683 684/* 685 * extern void giveup_fpu(struct task_struct *prev) 686 * 687 * The 44x core does not have an FPU. 688 */ 689#ifndef CONFIG_PPC_FPU 690_GLOBAL(giveup_fpu) 691 blr 692#endif 693 694_GLOBAL(set_context) 695 696#ifdef CONFIG_BDI_SWITCH 697 /* Context switch the PTE pointer for the Abatron BDI2000. 698 * The PGDIR is the second parameter. 699 */ 700 lis r5, abatron_pteptrs@h 701 ori r5, r5, abatron_pteptrs@l 702 stw r4, 0x4(r5) 703#endif 704 mtspr SPRN_PID,r3 705 isync /* Force context change */ 706 blr 707 708/* 709 * We put a few things here that have to be page-aligned. This stuff 710 * goes at the beginning of the data segment, which is page-aligned. 711 */ 712 .data 713 .align 12 714 .globl sdata 715sdata: 716 .globl empty_zero_page 717empty_zero_page: 718 .space 4096 719 720/* 721 * To support >32-bit physical addresses, we use an 8KB pgdir. 722 */ 723 .globl swapper_pg_dir 724swapper_pg_dir: 725 .space 8192 726 727/* Reserved 4k for the critical exception stack & 4k for the machine 728 * check stack per CPU for kernel mode exceptions */ 729 .section .bss 730 .align 12 731exception_stack_bottom: 732 .space BOOKE_EXCEPTION_STACK_SIZE 733 .globl exception_stack_top 734exception_stack_top: 735 736/* 737 * Room for two PTE pointers, usually the kernel and current user pointers 738 * to their respective root page table. 739 */ 740abatron_pteptrs: 741 .space 8 742