1/* 2 * arch/powerpc/kernel/misc64.S 3 * 4 * This file contains miscellaneous low-level functions. 5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 6 * 7 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) 8 * and Paul Mackerras. 9 * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com) 10 * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 15 * 2 of the License, or (at your option) any later version. 16 * 17 */ 18 19#include <linux/config.h> 20#include <linux/sys.h> 21#include <asm/unistd.h> 22#include <asm/errno.h> 23#include <asm/processor.h> 24#include <asm/page.h> 25#include <asm/cache.h> 26#include <asm/ppc_asm.h> 27#include <asm/asm-offsets.h> 28#include <asm/cputable.h> 29#include <asm/thread_info.h> 30 31 .text 32 33/* 34 * Returns (address we are running at) - (address we were linked at) 35 * for use before the text and data are mapped to KERNELBASE. 36 */ 37 38_GLOBAL(reloc_offset) 39 mflr r0 40 bl 1f 411: mflr r3 42 LOADADDR(r4,1b) 43 subf r3,r4,r3 44 mtlr r0 45 blr 46 47/* 48 * add_reloc_offset(x) returns x + reloc_offset(). 49 */ 50_GLOBAL(add_reloc_offset) 51 mflr r0 52 bl 1f 531: mflr r5 54 LOADADDR(r4,1b) 55 subf r5,r4,r5 56 add r3,r3,r5 57 mtlr r0 58 blr 59 60_GLOBAL(get_msr) 61 mfmsr r3 62 blr 63 64_GLOBAL(get_dar) 65 mfdar r3 66 blr 67 68_GLOBAL(get_srr0) 69 mfsrr0 r3 70 blr 71 72_GLOBAL(get_srr1) 73 mfsrr1 r3 74 blr 75 76_GLOBAL(get_sp) 77 mr r3,r1 78 blr 79 80#ifdef CONFIG_IRQSTACKS 81_GLOBAL(call_do_softirq) 82 mflr r0 83 std r0,16(r1) 84 stdu r1,THREAD_SIZE-112(r3) 85 mr r1,r3 86 bl .__do_softirq 87 ld r1,0(r1) 88 ld r0,16(r1) 89 mtlr r0 90 blr 91 92_GLOBAL(call___do_IRQ) 93 mflr r0 94 std r0,16(r1) 95 stdu r1,THREAD_SIZE-112(r5) 96 mr r1,r5 97 bl .__do_IRQ 98 ld r1,0(r1) 99 ld r0,16(r1) 100 mtlr r0 101 blr 102#endif /* CONFIG_IRQSTACKS */ 103 104 /* 105 * To be called by C code which needs to do some operations with MMU 106 * disabled. Note that interrupts have to be disabled by the caller 107 * prior to calling us. The code called _MUST_ be in the RMO of course 108 * and part of the linear mapping as we don't attempt to translate the 109 * stack pointer at all. The function is called with the stack switched 110 * to this CPU emergency stack 111 * 112 * prototype is void *call_with_mmu_off(void *func, void *data); 113 * 114 * the called function is expected to be of the form 115 * 116 * void *called(void *data); 117 */ 118_GLOBAL(call_with_mmu_off) 119 mflr r0 /* get link, save it on stackframe */ 120 std r0,16(r1) 121 mr r1,r5 /* save old stack ptr */ 122 ld r1,PACAEMERGSP(r13) /* get emerg. stack */ 123 subi r1,r1,STACK_FRAME_OVERHEAD 124 std r0,16(r1) /* save link on emerg. stack */ 125 std r5,0(r1) /* save old stack ptr in backchain */ 126 ld r3,0(r3) /* get to real function ptr (assume same TOC) */ 127 bl 2f /* we need LR to return, continue at label 2 */ 128 129 ld r0,16(r1) /* we return here from the call, get LR and */ 130 ld r1,0(r1) /* .. old stack ptr */ 131 mtspr SPRN_SRR0,r0 /* and get back to virtual mode with these */ 132 mfmsr r4 133 ori r4,r4,MSR_IR|MSR_DR 134 mtspr SPRN_SRR1,r4 135 rfid 136 1372: mtspr SPRN_SRR0,r3 /* coming from above, enter real mode */ 138 mr r3,r4 /* get parameter */ 139 mfmsr r0 140 ori r0,r0,MSR_IR|MSR_DR 141 xori r0,r0,MSR_IR|MSR_DR 142 mtspr SPRN_SRR1,r0 143 rfid 144 145 146 .section ".toc","aw" 147PPC64_CACHES: 148 .tc ppc64_caches[TC],ppc64_caches 149 .section ".text" 150 151/* 152 * Write any modified data cache blocks out to memory 153 * and invalidate the corresponding instruction cache blocks. 154 * 155 * flush_icache_range(unsigned long start, unsigned long stop) 156 * 157 * flush all bytes from start through stop-1 inclusive 158 */ 159 160_KPROBE(__flush_icache_range) 161 162/* 163 * Flush the data cache to memory 164 * 165 * Different systems have different cache line sizes 166 * and in some cases i-cache and d-cache line sizes differ from 167 * each other. 168 */ 169 ld r10,PPC64_CACHES@toc(r2) 170 lwz r7,DCACHEL1LINESIZE(r10)/* Get cache line size */ 171 addi r5,r7,-1 172 andc r6,r3,r5 /* round low to line bdy */ 173 subf r8,r6,r4 /* compute length */ 174 add r8,r8,r5 /* ensure we get enough */ 175 lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ 176 srw. r8,r8,r9 /* compute line count */ 177 beqlr /* nothing to do? */ 178 mtctr r8 1791: dcbst 0,r6 180 add r6,r6,r7 181 bdnz 1b 182 sync 183 184/* Now invalidate the instruction cache */ 185 186 lwz r7,ICACHEL1LINESIZE(r10) /* Get Icache line size */ 187 addi r5,r7,-1 188 andc r6,r3,r5 /* round low to line bdy */ 189 subf r8,r6,r4 /* compute length */ 190 add r8,r8,r5 191 lwz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ 192 srw. r8,r8,r9 /* compute line count */ 193 beqlr /* nothing to do? */ 194 mtctr r8 1952: icbi 0,r6 196 add r6,r6,r7 197 bdnz 2b 198 isync 199 blr 200 .previous .text 201/* 202 * Like above, but only do the D-cache. 203 * 204 * flush_dcache_range(unsigned long start, unsigned long stop) 205 * 206 * flush all bytes from start to stop-1 inclusive 207 */ 208_GLOBAL(flush_dcache_range) 209 210/* 211 * Flush the data cache to memory 212 * 213 * Different systems have different cache line sizes 214 */ 215 ld r10,PPC64_CACHES@toc(r2) 216 lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ 217 addi r5,r7,-1 218 andc r6,r3,r5 /* round low to line bdy */ 219 subf r8,r6,r4 /* compute length */ 220 add r8,r8,r5 /* ensure we get enough */ 221 lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ 222 srw. r8,r8,r9 /* compute line count */ 223 beqlr /* nothing to do? */ 224 mtctr r8 2250: dcbst 0,r6 226 add r6,r6,r7 227 bdnz 0b 228 sync 229 blr 230 231/* 232 * Like above, but works on non-mapped physical addresses. 233 * Use only for non-LPAR setups ! It also assumes real mode 234 * is cacheable. Used for flushing out the DART before using 235 * it as uncacheable memory 236 * 237 * flush_dcache_phys_range(unsigned long start, unsigned long stop) 238 * 239 * flush all bytes from start to stop-1 inclusive 240 */ 241_GLOBAL(flush_dcache_phys_range) 242 ld r10,PPC64_CACHES@toc(r2) 243 lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ 244 addi r5,r7,-1 245 andc r6,r3,r5 /* round low to line bdy */ 246 subf r8,r6,r4 /* compute length */ 247 add r8,r8,r5 /* ensure we get enough */ 248 lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ 249 srw. r8,r8,r9 /* compute line count */ 250 beqlr /* nothing to do? */ 251 mfmsr r5 /* Disable MMU Data Relocation */ 252 ori r0,r5,MSR_DR 253 xori r0,r0,MSR_DR 254 sync 255 mtmsr r0 256 sync 257 isync 258 mtctr r8 2590: dcbst 0,r6 260 add r6,r6,r7 261 bdnz 0b 262 sync 263 isync 264 mtmsr r5 /* Re-enable MMU Data Relocation */ 265 sync 266 isync 267 blr 268 269_GLOBAL(flush_inval_dcache_range) 270 ld r10,PPC64_CACHES@toc(r2) 271 lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ 272 addi r5,r7,-1 273 andc r6,r3,r5 /* round low to line bdy */ 274 subf r8,r6,r4 /* compute length */ 275 add r8,r8,r5 /* ensure we get enough */ 276 lwz r9,DCACHEL1LOGLINESIZE(r10)/* Get log-2 of dcache line size */ 277 srw. r8,r8,r9 /* compute line count */ 278 beqlr /* nothing to do? */ 279 sync 280 isync 281 mtctr r8 2820: dcbf 0,r6 283 add r6,r6,r7 284 bdnz 0b 285 sync 286 isync 287 blr 288 289 290/* 291 * Flush a particular page from the data cache to RAM. 292 * Note: this is necessary because the instruction cache does *not* 293 * snoop from the data cache. 294 * 295 * void __flush_dcache_icache(void *page) 296 */ 297_GLOBAL(__flush_dcache_icache) 298/* 299 * Flush the data cache to memory 300 * 301 * Different systems have different cache line sizes 302 */ 303 304/* Flush the dcache */ 305 ld r7,PPC64_CACHES@toc(r2) 306 clrrdi r3,r3,PAGE_SHIFT /* Page align */ 307 lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ 308 lwz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ 309 mr r6,r3 310 mtctr r4 3110: dcbst 0,r6 312 add r6,r6,r5 313 bdnz 0b 314 sync 315 316/* Now invalidate the icache */ 317 318 lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ 319 lwz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */ 320 mtctr r4 3211: icbi 0,r3 322 add r3,r3,r5 323 bdnz 1b 324 isync 325 blr 326 327/* 328 * I/O string operations 329 * 330 * insb(port, buf, len) 331 * outsb(port, buf, len) 332 * insw(port, buf, len) 333 * outsw(port, buf, len) 334 * insl(port, buf, len) 335 * outsl(port, buf, len) 336 * insw_ns(port, buf, len) 337 * outsw_ns(port, buf, len) 338 * insl_ns(port, buf, len) 339 * outsl_ns(port, buf, len) 340 * 341 * The *_ns versions don't do byte-swapping. 342 */ 343_GLOBAL(_insb) 344 cmpwi 0,r5,0 345 mtctr r5 346 subi r4,r4,1 347 blelr- 34800: lbz r5,0(r3) 349 eieio 350 stbu r5,1(r4) 351 bdnz 00b 352 twi 0,r5,0 353 isync 354 blr 355 356_GLOBAL(_outsb) 357 cmpwi 0,r5,0 358 mtctr r5 359 subi r4,r4,1 360 blelr- 36100: lbzu r5,1(r4) 362 stb r5,0(r3) 363 bdnz 00b 364 sync 365 blr 366 367_GLOBAL(_insw) 368 cmpwi 0,r5,0 369 mtctr r5 370 subi r4,r4,2 371 blelr- 37200: lhbrx r5,0,r3 373 eieio 374 sthu r5,2(r4) 375 bdnz 00b 376 twi 0,r5,0 377 isync 378 blr 379 380_GLOBAL(_outsw) 381 cmpwi 0,r5,0 382 mtctr r5 383 subi r4,r4,2 384 blelr- 38500: lhzu r5,2(r4) 386 sthbrx r5,0,r3 387 bdnz 00b 388 sync 389 blr 390 391_GLOBAL(_insl) 392 cmpwi 0,r5,0 393 mtctr r5 394 subi r4,r4,4 395 blelr- 39600: lwbrx r5,0,r3 397 eieio 398 stwu r5,4(r4) 399 bdnz 00b 400 twi 0,r5,0 401 isync 402 blr 403 404_GLOBAL(_outsl) 405 cmpwi 0,r5,0 406 mtctr r5 407 subi r4,r4,4 408 blelr- 40900: lwzu r5,4(r4) 410 stwbrx r5,0,r3 411 bdnz 00b 412 sync 413 blr 414 415/* _GLOBAL(ide_insw) now in drivers/ide/ide-iops.c */ 416_GLOBAL(_insw_ns) 417 cmpwi 0,r5,0 418 mtctr r5 419 subi r4,r4,2 420 blelr- 42100: lhz r5,0(r3) 422 eieio 423 sthu r5,2(r4) 424 bdnz 00b 425 twi 0,r5,0 426 isync 427 blr 428 429/* _GLOBAL(ide_outsw) now in drivers/ide/ide-iops.c */ 430_GLOBAL(_outsw_ns) 431 cmpwi 0,r5,0 432 mtctr r5 433 subi r4,r4,2 434 blelr- 43500: lhzu r5,2(r4) 436 sth r5,0(r3) 437 bdnz 00b 438 sync 439 blr 440 441_GLOBAL(_insl_ns) 442 cmpwi 0,r5,0 443 mtctr r5 444 subi r4,r4,4 445 blelr- 44600: lwz r5,0(r3) 447 eieio 448 stwu r5,4(r4) 449 bdnz 00b 450 twi 0,r5,0 451 isync 452 blr 453 454_GLOBAL(_outsl_ns) 455 cmpwi 0,r5,0 456 mtctr r5 457 subi r4,r4,4 458 blelr- 45900: lwzu r5,4(r4) 460 stw r5,0(r3) 461 bdnz 00b 462 sync 463 blr 464 465/* 466 * identify_cpu and calls setup_cpu 467 * In: r3 = base of the cpu_specs array 468 * r4 = address of cur_cpu_spec 469 * r5 = relocation offset 470 */ 471_GLOBAL(identify_cpu) 472 mfpvr r7 4731: 474 lwz r8,CPU_SPEC_PVR_MASK(r3) 475 and r8,r8,r7 476 lwz r9,CPU_SPEC_PVR_VALUE(r3) 477 cmplw 0,r9,r8 478 beq 1f 479 addi r3,r3,CPU_SPEC_ENTRY_SIZE 480 b 1b 4811: 482 sub r0,r3,r5 483 std r0,0(r4) 484 ld r4,CPU_SPEC_SETUP(r3) 485 add r4,r4,r5 486 ld r4,0(r4) 487 add r4,r4,r5 488 mtctr r4 489 /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */ 490 mr r4,r3 491 mr r3,r5 492 bctr 493 494/* 495 * do_cpu_ftr_fixups - goes through the list of CPU feature fixups 496 * and writes nop's over sections of code that don't apply for this cpu. 497 * r3 = data offset (not changed) 498 */ 499_GLOBAL(do_cpu_ftr_fixups) 500 /* Get CPU 0 features */ 501 LOADADDR(r6,cur_cpu_spec) 502 sub r6,r6,r3 503 ld r4,0(r6) 504 sub r4,r4,r3 505 ld r4,CPU_SPEC_FEATURES(r4) 506 /* Get the fixup table */ 507 LOADADDR(r6,__start___ftr_fixup) 508 sub r6,r6,r3 509 LOADADDR(r7,__stop___ftr_fixup) 510 sub r7,r7,r3 511 /* Do the fixup */ 5121: cmpld r6,r7 513 bgelr 514 addi r6,r6,32 515 ld r8,-32(r6) /* mask */ 516 and r8,r8,r4 517 ld r9,-24(r6) /* value */ 518 cmpld r8,r9 519 beq 1b 520 ld r8,-16(r6) /* section begin */ 521 ld r9,-8(r6) /* section end */ 522 subf. r9,r8,r9 523 beq 1b 524 /* write nops over the section of code */ 525 /* todo: if large section, add a branch at the start of it */ 526 srwi r9,r9,2 527 mtctr r9 528 sub r8,r8,r3 529 lis r0,0x60000000@h /* nop */ 5303: stw r0,0(r8) 531 andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l 532 beq 2f 533 dcbst 0,r8 /* suboptimal, but simpler */ 534 sync 535 icbi 0,r8 5362: addi r8,r8,4 537 bdnz 3b 538 sync /* additional sync needed on g4 */ 539 isync 540 b 1b 541 542#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) 543/* 544 * Do an IO access in real mode 545 */ 546_GLOBAL(real_readb) 547 mfmsr r7 548 ori r0,r7,MSR_DR 549 xori r0,r0,MSR_DR 550 sync 551 mtmsrd r0 552 sync 553 isync 554 mfspr r6,SPRN_HID4 555 rldicl r5,r6,32,0 556 ori r5,r5,0x100 557 rldicl r5,r5,32,0 558 sync 559 mtspr SPRN_HID4,r5 560 isync 561 slbia 562 isync 563 lbz r3,0(r3) 564 sync 565 mtspr SPRN_HID4,r6 566 isync 567 slbia 568 isync 569 mtmsrd r7 570 sync 571 isync 572 blr 573 574 /* 575 * Do an IO access in real mode 576 */ 577_GLOBAL(real_writeb) 578 mfmsr r7 579 ori r0,r7,MSR_DR 580 xori r0,r0,MSR_DR 581 sync 582 mtmsrd r0 583 sync 584 isync 585 mfspr r6,SPRN_HID4 586 rldicl r5,r6,32,0 587 ori r5,r5,0x100 588 rldicl r5,r5,32,0 589 sync 590 mtspr SPRN_HID4,r5 591 isync 592 slbia 593 isync 594 stb r3,0(r4) 595 sync 596 mtspr SPRN_HID4,r6 597 isync 598 slbia 599 isync 600 mtmsrd r7 601 sync 602 isync 603 blr 604#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ 605 606/* 607 * SCOM access functions for 970 (FX only for now) 608 * 609 * unsigned long scom970_read(unsigned int address); 610 * void scom970_write(unsigned int address, unsigned long value); 611 * 612 * The address passed in is the 24 bits register address. This code 613 * is 970 specific and will not check the status bits, so you should 614 * know what you are doing. 615 */ 616_GLOBAL(scom970_read) 617 /* interrupts off */ 618 mfmsr r4 619 ori r0,r4,MSR_EE 620 xori r0,r0,MSR_EE 621 mtmsrd r0,1 622 623 /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits 624 * (including parity). On current CPUs they must be 0'd, 625 * and finally or in RW bit 626 */ 627 rlwinm r3,r3,8,0,15 628 ori r3,r3,0x8000 629 630 /* do the actual scom read */ 631 sync 632 mtspr SPRN_SCOMC,r3 633 isync 634 mfspr r3,SPRN_SCOMD 635 isync 636 mfspr r0,SPRN_SCOMC 637 isync 638 639 /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah 640 * that's the best we can do). Not implemented yet as we don't use 641 * the scom on any of the bogus CPUs yet, but may have to be done 642 * ultimately 643 */ 644 645 /* restore interrupts */ 646 mtmsrd r4,1 647 blr 648 649 650_GLOBAL(scom970_write) 651 /* interrupts off */ 652 mfmsr r5 653 ori r0,r5,MSR_EE 654 xori r0,r0,MSR_EE 655 mtmsrd r0,1 656 657 /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits 658 * (including parity). On current CPUs they must be 0'd. 659 */ 660 661 rlwinm r3,r3,8,0,15 662 663 sync 664 mtspr SPRN_SCOMD,r4 /* write data */ 665 isync 666 mtspr SPRN_SCOMC,r3 /* write command */ 667 isync 668 mfspr 3,SPRN_SCOMC 669 isync 670 671 /* restore interrupts */ 672 mtmsrd r5,1 673 blr 674 675 676/* 677 * Create a kernel thread 678 * kernel_thread(fn, arg, flags) 679 */ 680_GLOBAL(kernel_thread) 681 std r29,-24(r1) 682 std r30,-16(r1) 683 stdu r1,-STACK_FRAME_OVERHEAD(r1) 684 mr r29,r3 685 mr r30,r4 686 ori r3,r5,CLONE_VM /* flags */ 687 oris r3,r3,(CLONE_UNTRACED>>16) 688 li r4,0 /* new sp (unused) */ 689 li r0,__NR_clone 690 sc 691 cmpdi 0,r3,0 /* parent or child? */ 692 bne 1f /* return if parent */ 693 li r0,0 694 stdu r0,-STACK_FRAME_OVERHEAD(r1) 695 ld r2,8(r29) 696 ld r29,0(r29) 697 mtlr r29 /* fn addr in lr */ 698 mr r3,r30 /* load arg and call fn */ 699 blrl 700 li r0,__NR_exit /* exit after child exits */ 701 li r3,0 702 sc 7031: addi r1,r1,STACK_FRAME_OVERHEAD 704 ld r29,-24(r1) 705 ld r30,-16(r1) 706 blr 707 708/* 709 * disable_kernel_fp() 710 * Disable the FPU. 711 */ 712_GLOBAL(disable_kernel_fp) 713 mfmsr r3 714 rldicl r0,r3,(63-MSR_FP_LG),1 715 rldicl r3,r0,(MSR_FP_LG+1),0 716 mtmsrd r3 /* disable use of fpu now */ 717 isync 718 blr 719 720#ifdef CONFIG_ALTIVEC 721 722#if 0 /* this has no callers for now */ 723/* 724 * disable_kernel_altivec() 725 * Disable the VMX. 726 */ 727_GLOBAL(disable_kernel_altivec) 728 mfmsr r3 729 rldicl r0,r3,(63-MSR_VEC_LG),1 730 rldicl r3,r0,(MSR_VEC_LG+1),0 731 mtmsrd r3 /* disable use of VMX now */ 732 isync 733 blr 734#endif /* 0 */ 735 736/* 737 * giveup_altivec(tsk) 738 * Disable VMX for the task given as the argument, 739 * and save the vector registers in its thread_struct. 740 * Enables the VMX for use in the kernel on return. 741 */ 742_GLOBAL(giveup_altivec) 743 mfmsr r5 744 oris r5,r5,MSR_VEC@h 745 mtmsrd r5 /* enable use of VMX now */ 746 isync 747 cmpdi 0,r3,0 748 beqlr- /* if no previous owner, done */ 749 addi r3,r3,THREAD /* want THREAD of task */ 750 ld r5,PT_REGS(r3) 751 cmpdi 0,r5,0 752 SAVE_32VRS(0,r4,r3) 753 mfvscr vr0 754 li r4,THREAD_VSCR 755 stvx vr0,r4,r3 756 beq 1f 757 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) 758 lis r3,MSR_VEC@h 759 andc r4,r4,r3 /* disable FP for previous task */ 760 std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 7611: 762#ifndef CONFIG_SMP 763 li r5,0 764 ld r4,last_task_used_altivec@got(r2) 765 std r5,0(r4) 766#endif /* CONFIG_SMP */ 767 blr 768 769#endif /* CONFIG_ALTIVEC */ 770 771_GLOBAL(__setup_cpu_power3) 772 blr 773 774_GLOBAL(execve) 775 li r0,__NR_execve 776 sc 777 bnslr 778 neg r3,r3 779 blr 780 781/* kexec_wait(phys_cpu) 782 * 783 * wait for the flag to change, indicating this kernel is going away but 784 * the slave code for the next one is at addresses 0 to 100. 785 * 786 * This is used by all slaves. 787 * 788 * Physical (hardware) cpu id should be in r3. 789 */ 790_GLOBAL(kexec_wait) 791 bl 1f 7921: mflr r5 793 addi r5,r5,kexec_flag-1b 794 79599: HMT_LOW 796#ifdef CONFIG_KEXEC /* use no memory without kexec */ 797 lwz r4,0(r5) 798 cmpwi 0,r4,0 799 bnea 0x60 800#endif 801 b 99b 802 803/* this can be in text because we won't change it until we are 804 * running in real anyways 805 */ 806kexec_flag: 807 .long 0 808 809 810#ifdef CONFIG_KEXEC 811 812/* kexec_smp_wait(void) 813 * 814 * call with interrupts off 815 * note: this is a terminal routine, it does not save lr 816 * 817 * get phys id from paca 818 * set paca id to -1 to say we got here 819 * switch to real mode 820 * join other cpus in kexec_wait(phys_id) 821 */ 822_GLOBAL(kexec_smp_wait) 823 lhz r3,PACAHWCPUID(r13) 824 li r4,-1 825 sth r4,PACAHWCPUID(r13) /* let others know we left */ 826 bl real_mode 827 b .kexec_wait 828 829/* 830 * switch to real mode (turn mmu off) 831 * we use the early kernel trick that the hardware ignores bits 832 * 0 and 1 (big endian) of the effective address in real mode 833 * 834 * don't overwrite r3 here, it is live for kexec_wait above. 835 */ 836real_mode: /* assume normal blr return */ 8371: li r9,MSR_RI 838 li r10,MSR_DR|MSR_IR 839 mflr r11 /* return address to SRR0 */ 840 mfmsr r12 841 andc r9,r12,r9 842 andc r10,r12,r10 843 844 mtmsrd r9,1 845 mtspr SPRN_SRR1,r10 846 mtspr SPRN_SRR0,r11 847 rfid 848 849 850/* 851 * kexec_sequence(newstack, start, image, control, clear_all()) 852 * 853 * does the grungy work with stack switching and real mode switches 854 * also does simple calls to other code 855 */ 856 857_GLOBAL(kexec_sequence) 858 mflr r0 859 std r0,16(r1) 860 861 /* switch stacks to newstack -- &kexec_stack.stack */ 862 stdu r1,THREAD_SIZE-112(r3) 863 mr r1,r3 864 865 li r0,0 866 std r0,16(r1) 867 868 /* save regs for local vars on new stack. 869 * yes, we won't go back, but ... 870 */ 871 std r31,-8(r1) 872 std r30,-16(r1) 873 std r29,-24(r1) 874 std r28,-32(r1) 875 std r27,-40(r1) 876 std r26,-48(r1) 877 std r25,-56(r1) 878 879 stdu r1,-112-64(r1) 880 881 /* save args into preserved regs */ 882 mr r31,r3 /* newstack (both) */ 883 mr r30,r4 /* start (real) */ 884 mr r29,r5 /* image (virt) */ 885 mr r28,r6 /* control, unused */ 886 mr r27,r7 /* clear_all() fn desc */ 887 mr r26,r8 /* spare */ 888 lhz r25,PACAHWCPUID(r13) /* get our phys cpu from paca */ 889 890 /* disable interrupts, we are overwriting kernel data next */ 891 mfmsr r3 892 rlwinm r3,r3,0,17,15 893 mtmsrd r3,1 894 895 /* copy dest pages, flush whole dest image */ 896 mr r3,r29 897 bl .kexec_copy_flush /* (image) */ 898 899 /* turn off mmu */ 900 bl real_mode 901 902 /* clear out hardware hash page table and tlb */ 903 ld r5,0(r27) /* deref function descriptor */ 904 mtctr r5 905 bctrl /* ppc_md.hash_clear_all(void); */ 906 907/* 908 * kexec image calling is: 909 * the first 0x100 bytes of the entry point are copied to 0 910 * 911 * all slaves branch to slave = 0x60 (absolute) 912 * slave(phys_cpu_id); 913 * 914 * master goes to start = entry point 915 * start(phys_cpu_id, start, 0); 916 * 917 * 918 * a wrapper is needed to call existing kernels, here is an approximate 919 * description of one method: 920 * 921 * v2: (2.6.10) 922 * start will be near the boot_block (maybe 0x100 bytes before it?) 923 * it will have a 0x60, which will b to boot_block, where it will wait 924 * and 0 will store phys into struct boot-block and load r3 from there, 925 * copy kernel 0-0x100 and tell slaves to back down to 0x60 again 926 * 927 * v1: (2.6.9) 928 * boot block will have all cpus scanning device tree to see if they 929 * are the boot cpu ????? 930 * other device tree differences (prop sizes, va vs pa, etc)... 931 */ 932 933 /* copy 0x100 bytes starting at start to 0 */ 934 li r3,0 935 mr r4,r30 936 li r5,0x100 937 li r6,0 938 bl .copy_and_flush /* (dest, src, copy limit, start offset) */ 9391: /* assume normal blr return */ 940 941 /* release other cpus to the new kernel secondary start at 0x60 */ 942 mflr r5 943 li r6,1 944 stw r6,kexec_flag-1b(5) 945 mr r3,r25 # my phys cpu 946 mr r4,r30 # start, aka phys mem offset 947 mtlr 4 948 li r5,0 949 blr /* image->start(physid, image->start, 0); */ 950#endif /* CONFIG_KEXEC */ 951