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