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