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