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