forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/arch/powerpc/kernel/misc_32.S
....@@ -1,20 +1,10 @@
1
+/* SPDX-License-Identifier: GPL-2.0-or-later */
12 /*
23 * This file contains miscellaneous low-level functions.
34 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
45 *
56 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
67 * and Paul Mackerras.
7
- *
8
- * kexec bits:
9
- * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
10
- * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
11
- * PPC44x port. Copyright (C) 2011, IBM Corporation
12
- * Author: Suzuki Poulose <suzuki@in.ibm.com>
13
- *
14
- * This program is free software; you can redistribute it and/or
15
- * modify it under the terms of the GNU General Public License
16
- * as published by the Free Software Foundation; either version
17
- * 2 of the License, or (at your option) any later version.
188 *
199 */
2010
....@@ -30,7 +20,6 @@
3020 #include <asm/thread_info.h>
3121 #include <asm/asm-offsets.h>
3222 #include <asm/processor.h>
33
-#include <asm/kexec.h>
3423 #include <asm/bug.h>
3524 #include <asm/ptrace.h>
3625 #include <asm/export.h>
....@@ -42,16 +31,14 @@
4231 * We store the saved ksp_limit in the unused part
4332 * of the STACK_FRAME_OVERHEAD
4433 */
45
-#ifndef CONFIG_PREEMPT_RT_FULL
4634 _GLOBAL(call_do_softirq)
4735 mflr r0
4836 stw r0,4(r1)
4937 lwz r10,THREAD+KSP_LIMIT(r2)
50
- addi r11,r3,THREAD_INFO_GAP
38
+ stw r3, THREAD+KSP_LIMIT(r2)
5139 stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
5240 mr r1,r3
5341 stw r10,8(r1)
54
- stw r11,THREAD+KSP_LIMIT(r2)
5542 bl __do_softirq
5643 lwz r10,8(r1)
5744 lwz r1,0(r1)
....@@ -59,20 +46,18 @@
5946 stw r10,THREAD+KSP_LIMIT(r2)
6047 mtlr r0
6148 blr
62
-#endif
6349
6450 /*
65
- * void call_do_irq(struct pt_regs *regs, struct thread_info *irqtp);
51
+ * void call_do_irq(struct pt_regs *regs, void *sp);
6652 */
6753 _GLOBAL(call_do_irq)
6854 mflr r0
6955 stw r0,4(r1)
7056 lwz r10,THREAD+KSP_LIMIT(r2)
71
- addi r11,r4,THREAD_INFO_GAP
57
+ stw r4, THREAD+KSP_LIMIT(r2)
7258 stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
7359 mr r1,r4
7460 stw r10,8(r1)
75
- stw r11,THREAD+KSP_LIMIT(r2)
7661 bl __do_irq
7762 lwz r10,8(r1)
7863 lwz r1,0(r1)
....@@ -155,7 +140,7 @@
155140 mtctr r5
156141 bctr
157142
158
-#if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx)
143
+#if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_PPC_BOOK3S_32)
159144
160145 /* This gets called by via-pmu.c to switch the PLL selection
161146 * on 750fx CPU. This function should really be moved to some
....@@ -185,10 +170,13 @@
185170 or r4,r4,r5
186171 mtspr SPRN_HID1,r4
187172
173
+#ifdef CONFIG_SMP
188174 /* Store new HID1 image */
189
- CURRENT_THREAD_INFO(r6, r1)
190
- lwz r6,TI_CPU(r6)
175
+ lwz r6,TASK_CPU(r2)
191176 slwi r6,r6,2
177
+#else
178
+ li r6, 0
179
+#endif
192180 addis r6,r6,nap_save_hid1@ha
193181 stw r4,nap_save_hid1@l(r6)
194182
....@@ -225,20 +213,7 @@
225213 mtmsr r7
226214 blr
227215
228
-#endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */
229
-
230
-/*
231
- * complement mask on the msr then "or" some values on.
232
- * _nmask_and_or_msr(nmask, value_to_or)
233
- */
234
-_GLOBAL(_nmask_and_or_msr)
235
- mfmsr r0 /* Get current msr */
236
- andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
237
- or r0,r0,r4 /* Or on the bits in r4 (second parm) */
238
- SYNC /* Some chip revs have problems here... */
239
- mtmsr r0 /* Update machine state */
240
- isync
241
- blr /* Done */
216
+#endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_PPC_BOOK3S_32 */
242217
243218 #ifdef CONFIG_40x
244219
....@@ -258,6 +233,7 @@
258233 sync
259234 isync
260235 blr
236
+_ASM_NOKPROBE_SYMBOL(real_readb)
261237
262238 /*
263239 * Do an IO access in real mode
....@@ -275,171 +251,9 @@
275251 sync
276252 isync
277253 blr
254
+_ASM_NOKPROBE_SYMBOL(real_writeb)
278255
279256 #endif /* CONFIG_40x */
280
-
281
-
282
-/*
283
- * Flush instruction cache.
284
- * This is a no-op on the 601.
285
- */
286
-#ifndef CONFIG_PPC_8xx
287
-_GLOBAL(flush_instruction_cache)
288
-#if defined(CONFIG_4xx)
289
-#ifdef CONFIG_403GCX
290
- li r3, 512
291
- mtctr r3
292
- lis r4, KERNELBASE@h
293
-1: iccci 0, r4
294
- addi r4, r4, 16
295
- bdnz 1b
296
-#else
297
- lis r3, KERNELBASE@h
298
- iccci 0,r3
299
-#endif
300
-#elif defined(CONFIG_FSL_BOOKE)
301
-BEGIN_FTR_SECTION
302
- mfspr r3,SPRN_L1CSR0
303
- ori r3,r3,L1CSR0_CFI|L1CSR0_CLFC
304
- /* msync; isync recommended here */
305
- mtspr SPRN_L1CSR0,r3
306
- isync
307
- blr
308
-END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
309
- mfspr r3,SPRN_L1CSR1
310
- ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
311
- mtspr SPRN_L1CSR1,r3
312
-#else
313
- mfspr r3,SPRN_PVR
314
- rlwinm r3,r3,16,16,31
315
- cmpwi 0,r3,1
316
- beqlr /* for 601, do nothing */
317
- /* 603/604 processor - use invalidate-all bit in HID0 */
318
- mfspr r3,SPRN_HID0
319
- ori r3,r3,HID0_ICFI
320
- mtspr SPRN_HID0,r3
321
-#endif /* CONFIG_4xx */
322
- isync
323
- blr
324
-EXPORT_SYMBOL(flush_instruction_cache)
325
-#endif /* CONFIG_PPC_8xx */
326
-
327
-/*
328
- * Write any modified data cache blocks out to memory
329
- * and invalidate the corresponding instruction cache blocks.
330
- * This is a no-op on the 601.
331
- *
332
- * flush_icache_range(unsigned long start, unsigned long stop)
333
- */
334
-_GLOBAL(flush_icache_range)
335
-BEGIN_FTR_SECTION
336
- PURGE_PREFETCHED_INS
337
- blr /* for 601, do nothing */
338
-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
339
- rlwinm r3,r3,0,0,31 - L1_CACHE_SHIFT
340
- subf r4,r3,r4
341
- addi r4,r4,L1_CACHE_BYTES - 1
342
- srwi. r4,r4,L1_CACHE_SHIFT
343
- beqlr
344
- mtctr r4
345
- mr r6,r3
346
-1: dcbst 0,r3
347
- addi r3,r3,L1_CACHE_BYTES
348
- bdnz 1b
349
- sync /* wait for dcbst's to get to ram */
350
-#ifndef CONFIG_44x
351
- mtctr r4
352
-2: icbi 0,r6
353
- addi r6,r6,L1_CACHE_BYTES
354
- bdnz 2b
355
-#else
356
- /* Flash invalidate on 44x because we are passed kmapped addresses and
357
- this doesn't work for userspace pages due to the virtually tagged
358
- icache. Sigh. */
359
- iccci 0, r0
360
-#endif
361
- sync /* additional sync needed on g4 */
362
- isync
363
- blr
364
-_ASM_NOKPROBE_SYMBOL(flush_icache_range)
365
-EXPORT_SYMBOL(flush_icache_range)
366
-
367
-/*
368
- * Flush a particular page from the data cache to RAM.
369
- * Note: this is necessary because the instruction cache does *not*
370
- * snoop from the data cache.
371
- * This is a no-op on the 601 which has a unified cache.
372
- *
373
- * void __flush_dcache_icache(void *page)
374
- */
375
-_GLOBAL(__flush_dcache_icache)
376
-BEGIN_FTR_SECTION
377
- PURGE_PREFETCHED_INS
378
- blr
379
-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
380
- rlwinm r3,r3,0,0,31-PAGE_SHIFT /* Get page base address */
381
- li r4,PAGE_SIZE/L1_CACHE_BYTES /* Number of lines in a page */
382
- mtctr r4
383
- mr r6,r3
384
-0: dcbst 0,r3 /* Write line to ram */
385
- addi r3,r3,L1_CACHE_BYTES
386
- bdnz 0b
387
- sync
388
-#ifdef CONFIG_44x
389
- /* We don't flush the icache on 44x. Those have a virtual icache
390
- * and we don't have access to the virtual address here (it's
391
- * not the page vaddr but where it's mapped in user space). The
392
- * flushing of the icache on these is handled elsewhere, when
393
- * a change in the address space occurs, before returning to
394
- * user space
395
- */
396
-BEGIN_MMU_FTR_SECTION
397
- blr
398
-END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_44x)
399
-#endif /* CONFIG_44x */
400
- mtctr r4
401
-1: icbi 0,r6
402
- addi r6,r6,L1_CACHE_BYTES
403
- bdnz 1b
404
- sync
405
- isync
406
- blr
407
-
408
-#ifndef CONFIG_BOOKE
409
-/*
410
- * Flush a particular page from the data cache to RAM, identified
411
- * by its physical address. We turn off the MMU so we can just use
412
- * the physical address (this may be a highmem page without a kernel
413
- * mapping).
414
- *
415
- * void __flush_dcache_icache_phys(unsigned long physaddr)
416
- */
417
-_GLOBAL(__flush_dcache_icache_phys)
418
-BEGIN_FTR_SECTION
419
- PURGE_PREFETCHED_INS
420
- blr /* for 601, do nothing */
421
-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
422
- mfmsr r10
423
- rlwinm r0,r10,0,28,26 /* clear DR */
424
- mtmsr r0
425
- isync
426
- rlwinm r3,r3,0,0,31-PAGE_SHIFT /* Get page base address */
427
- li r4,PAGE_SIZE/L1_CACHE_BYTES /* Number of lines in a page */
428
- mtctr r4
429
- mr r6,r3
430
-0: dcbst 0,r3 /* Write line to ram */
431
- addi r3,r3,L1_CACHE_BYTES
432
- bdnz 0b
433
- sync
434
- mtctr r4
435
-1: icbi 0,r6
436
- addi r6,r6,L1_CACHE_BYTES
437
- bdnz 1b
438
- sync
439
- mtmsr r10 /* restore DR */
440
- isync
441
- blr
442
-#endif /* CONFIG_BOOKE */
443257
444258 /*
445259 * Copy a whole page. We use the dcbz instruction on the destination
....@@ -458,7 +272,12 @@
458272 stwu r9,16(r3)
459273
460274 _GLOBAL(copy_page)
275
+ rlwinm r5, r3, 0, L1_CACHE_BYTES - 1
461276 addi r3,r3,-4
277
+
278
+0: twnei r5, 0 /* WARN if r3 is not cache aligned */
279
+ EMIT_BUG_ENTRY 0b,__FILE__,__LINE__, BUGFLAG_WARNING
280
+
462281 addi r4,r4,-4
463282
464283 li r5,4
....@@ -601,7 +420,7 @@
601420 #ifdef CONFIG_SMP
602421 _GLOBAL(start_secondary_resume)
603422 /* Reset stack */
604
- CURRENT_THREAD_INFO(r1, r1)
423
+ rlwinm r1, r1, 0, 0, 31 - THREAD_SHIFT
605424 addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
606425 li r3,0
607426 stw r3,0(r1) /* Zero the stack frame pointer */
....@@ -614,488 +433,3 @@
614433 */
615434 _GLOBAL(__main)
616435 blr
617
-
618
-#ifdef CONFIG_KEXEC_CORE
619
- /*
620
- * Must be relocatable PIC code callable as a C function.
621
- */
622
- .globl relocate_new_kernel
623
-relocate_new_kernel:
624
- /* r3 = page_list */
625
- /* r4 = reboot_code_buffer */
626
- /* r5 = start_address */
627
-
628
-#ifdef CONFIG_FSL_BOOKE
629
-
630
- mr r29, r3
631
- mr r30, r4
632
- mr r31, r5
633
-
634
-#define ENTRY_MAPPING_KEXEC_SETUP
635
-#include "fsl_booke_entry_mapping.S"
636
-#undef ENTRY_MAPPING_KEXEC_SETUP
637
-
638
- mr r3, r29
639
- mr r4, r30
640
- mr r5, r31
641
-
642
- li r0, 0
643
-#elif defined(CONFIG_44x)
644
-
645
- /* Save our parameters */
646
- mr r29, r3
647
- mr r30, r4
648
- mr r31, r5
649
-
650
-#ifdef CONFIG_PPC_47x
651
- /* Check for 47x cores */
652
- mfspr r3,SPRN_PVR
653
- srwi r3,r3,16
654
- cmplwi cr0,r3,PVR_476FPE@h
655
- beq setup_map_47x
656
- cmplwi cr0,r3,PVR_476@h
657
- beq setup_map_47x
658
- cmplwi cr0,r3,PVR_476_ISS@h
659
- beq setup_map_47x
660
-#endif /* CONFIG_PPC_47x */
661
-
662
-/*
663
- * Code for setting up 1:1 mapping for PPC440x for KEXEC
664
- *
665
- * We cannot switch off the MMU on PPC44x.
666
- * So we:
667
- * 1) Invalidate all the mappings except the one we are running from.
668
- * 2) Create a tmp mapping for our code in the other address space(TS) and
669
- * jump to it. Invalidate the entry we started in.
670
- * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS.
671
- * 4) Jump to the 1:1 mapping in original TS.
672
- * 5) Invalidate the tmp mapping.
673
- *
674
- * - Based on the kexec support code for FSL BookE
675
- *
676
- */
677
-
678
- /*
679
- * Load the PID with kernel PID (0).
680
- * Also load our MSR_IS and TID to MMUCR for TLB search.
681
- */
682
- li r3, 0
683
- mtspr SPRN_PID, r3
684
- mfmsr r4
685
- andi. r4,r4,MSR_IS@l
686
- beq wmmucr
687
- oris r3,r3,PPC44x_MMUCR_STS@h
688
-wmmucr:
689
- mtspr SPRN_MMUCR,r3
690
- sync
691
-
692
- /*
693
- * Invalidate all the TLB entries except the current entry
694
- * where we are running from
695
- */
696
- bl 0f /* Find our address */
697
-0: mflr r5 /* Make it accessible */
698
- tlbsx r23,0,r5 /* Find entry we are in */
699
- li r4,0 /* Start at TLB entry 0 */
700
- li r3,0 /* Set PAGEID inval value */
701
-1: cmpw r23,r4 /* Is this our entry? */
702
- beq skip /* If so, skip the inval */
703
- tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */
704
-skip:
705
- addi r4,r4,1 /* Increment */
706
- cmpwi r4,64 /* Are we done? */
707
- bne 1b /* If not, repeat */
708
- isync
709
-
710
- /* Create a temp mapping and jump to it */
711
- andi. r6, r23, 1 /* Find the index to use */
712
- addi r24, r6, 1 /* r24 will contain 1 or 2 */
713
-
714
- mfmsr r9 /* get the MSR */
715
- rlwinm r5, r9, 27, 31, 31 /* Extract the MSR[IS] */
716
- xori r7, r5, 1 /* Use the other address space */
717
-
718
- /* Read the current mapping entries */
719
- tlbre r3, r23, PPC44x_TLB_PAGEID
720
- tlbre r4, r23, PPC44x_TLB_XLAT
721
- tlbre r5, r23, PPC44x_TLB_ATTRIB
722
-
723
- /* Save our current XLAT entry */
724
- mr r25, r4
725
-
726
- /* Extract the TLB PageSize */
727
- li r10, 1 /* r10 will hold PageSize */
728
- rlwinm r11, r3, 0, 24, 27 /* bits 24-27 */
729
-
730
- /* XXX: As of now we use 256M, 4K pages */
731
- cmpwi r11, PPC44x_TLB_256M
732
- bne tlb_4k
733
- rotlwi r10, r10, 28 /* r10 = 256M */
734
- b write_out
735
-tlb_4k:
736
- cmpwi r11, PPC44x_TLB_4K
737
- bne default
738
- rotlwi r10, r10, 12 /* r10 = 4K */
739
- b write_out
740
-default:
741
- rotlwi r10, r10, 10 /* r10 = 1K */
742
-
743
-write_out:
744
- /*
745
- * Write out the tmp 1:1 mapping for this code in other address space
746
- * Fixup EPN = RPN , TS=other address space
747
- */
748
- insrwi r3, r7, 1, 23 /* Bit 23 is TS for PAGEID field */
749
-
750
- /* Write out the tmp mapping entries */
751
- tlbwe r3, r24, PPC44x_TLB_PAGEID
752
- tlbwe r4, r24, PPC44x_TLB_XLAT
753
- tlbwe r5, r24, PPC44x_TLB_ATTRIB
754
-
755
- subi r11, r10, 1 /* PageOffset Mask = PageSize - 1 */
756
- not r10, r11 /* Mask for PageNum */
757
-
758
- /* Switch to other address space in MSR */
759
- insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */
760
-
761
- bl 1f
762
-1: mflr r8
763
- addi r8, r8, (2f-1b) /* Find the target offset */
764
-
765
- /* Jump to the tmp mapping */
766
- mtspr SPRN_SRR0, r8
767
- mtspr SPRN_SRR1, r9
768
- rfi
769
-
770
-2:
771
- /* Invalidate the entry we were executing from */
772
- li r3, 0
773
- tlbwe r3, r23, PPC44x_TLB_PAGEID
774
-
775
- /* attribute fields. rwx for SUPERVISOR mode */
776
- li r5, 0
777
- ori r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
778
-
779
- /* Create 1:1 mapping in 256M pages */
780
- xori r7, r7, 1 /* Revert back to Original TS */
781
-
782
- li r8, 0 /* PageNumber */
783
- li r6, 3 /* TLB Index, start at 3 */
784
-
785
-next_tlb:
786
- rotlwi r3, r8, 28 /* Create EPN (bits 0-3) */
787
- mr r4, r3 /* RPN = EPN */
788
- ori r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */
789
- insrwi r3, r7, 1, 23 /* Set TS from r7 */
790
-
791
- tlbwe r3, r6, PPC44x_TLB_PAGEID /* PageID field : EPN, V, SIZE */
792
- tlbwe r4, r6, PPC44x_TLB_XLAT /* Address translation : RPN */
793
- tlbwe r5, r6, PPC44x_TLB_ATTRIB /* Attributes */
794
-
795
- addi r8, r8, 1 /* Increment PN */
796
- addi r6, r6, 1 /* Increment TLB Index */
797
- cmpwi r8, 8 /* Are we done ? */
798
- bne next_tlb
799
- isync
800
-
801
- /* Jump to the new mapping 1:1 */
802
- li r9,0
803
- insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */
804
-
805
- bl 1f
806
-1: mflr r8
807
- and r8, r8, r11 /* Get our offset within page */
808
- addi r8, r8, (2f-1b)
809
-
810
- and r5, r25, r10 /* Get our target PageNum */
811
- or r8, r8, r5 /* Target jump address */
812
-
813
- mtspr SPRN_SRR0, r8
814
- mtspr SPRN_SRR1, r9
815
- rfi
816
-2:
817
- /* Invalidate the tmp entry we used */
818
- li r3, 0
819
- tlbwe r3, r24, PPC44x_TLB_PAGEID
820
- sync
821
- b ppc44x_map_done
822
-
823
-#ifdef CONFIG_PPC_47x
824
-
825
- /* 1:1 mapping for 47x */
826
-
827
-setup_map_47x:
828
-
829
- /*
830
- * Load the kernel pid (0) to PID and also to MMUCR[TID].
831
- * Also set the MSR IS->MMUCR STS
832
- */
833
- li r3, 0
834
- mtspr SPRN_PID, r3 /* Set PID */
835
- mfmsr r4 /* Get MSR */
836
- andi. r4, r4, MSR_IS@l /* TS=1? */
837
- beq 1f /* If not, leave STS=0 */
838
- oris r3, r3, PPC47x_MMUCR_STS@h /* Set STS=1 */
839
-1: mtspr SPRN_MMUCR, r3 /* Put MMUCR */
840
- sync
841
-
842
- /* Find the entry we are running from */
843
- bl 2f
844
-2: mflr r23
845
- tlbsx r23, 0, r23
846
- tlbre r24, r23, 0 /* TLB Word 0 */
847
- tlbre r25, r23, 1 /* TLB Word 1 */
848
- tlbre r26, r23, 2 /* TLB Word 2 */
849
-
850
-
851
- /*
852
- * Invalidates all the tlb entries by writing to 256 RPNs(r4)
853
- * of 4k page size in all 4 ways (0-3 in r3).
854
- * This would invalidate the entire UTLB including the one we are
855
- * running from. However the shadow TLB entries would help us
856
- * to continue the execution, until we flush them (rfi/isync).
857
- */
858
- addis r3, 0, 0x8000 /* specify the way */
859
- addi r4, 0, 0 /* TLB Word0 = (EPN=0, VALID = 0) */
860
- addi r5, 0, 0
861
- b clear_utlb_entry
862
-
863
- /* Align the loop to speed things up. from head_44x.S */
864
- .align 6
865
-
866
-clear_utlb_entry:
867
-
868
- tlbwe r4, r3, 0
869
- tlbwe r5, r3, 1
870
- tlbwe r5, r3, 2
871
- addis r3, r3, 0x2000 /* Increment the way */
872
- cmpwi r3, 0
873
- bne clear_utlb_entry
874
- addis r3, 0, 0x8000
875
- addis r4, r4, 0x100 /* Increment the EPN */
876
- cmpwi r4, 0
877
- bne clear_utlb_entry
878
-
879
- /* Create the entries in the other address space */
880
- mfmsr r5
881
- rlwinm r7, r5, 27, 31, 31 /* Get the TS (Bit 26) from MSR */
882
- xori r7, r7, 1 /* r7 = !TS */
883
-
884
- insrwi r24, r7, 1, 21 /* Change the TS in the saved TLB word 0 */
885
-
886
- /*
887
- * write out the TLB entries for the tmp mapping
888
- * Use way '0' so that we could easily invalidate it later.
889
- */
890
- lis r3, 0x8000 /* Way '0' */
891
-
892
- tlbwe r24, r3, 0
893
- tlbwe r25, r3, 1
894
- tlbwe r26, r3, 2
895
-
896
- /* Update the msr to the new TS */
897
- insrwi r5, r7, 1, 26
898
-
899
- bl 1f
900
-1: mflr r6
901
- addi r6, r6, (2f-1b)
902
-
903
- mtspr SPRN_SRR0, r6
904
- mtspr SPRN_SRR1, r5
905
- rfi
906
-
907
- /*
908
- * Now we are in the tmp address space.
909
- * Create a 1:1 mapping for 0-2GiB in the original TS.
910
- */
911
-2:
912
- li r3, 0
913
- li r4, 0 /* TLB Word 0 */
914
- li r5, 0 /* TLB Word 1 */
915
- li r6, 0
916
- ori r6, r6, PPC47x_TLB2_S_RWX /* TLB word 2 */
917
-
918
- li r8, 0 /* PageIndex */
919
-
920
- xori r7, r7, 1 /* revert back to original TS */
921
-
922
-write_utlb:
923
- rotlwi r5, r8, 28 /* RPN = PageIndex * 256M */
924
- /* ERPN = 0 as we don't use memory above 2G */
925
-
926
- mr r4, r5 /* EPN = RPN */
927
- ori r4, r4, (PPC47x_TLB0_VALID | PPC47x_TLB0_256M)
928
- insrwi r4, r7, 1, 21 /* Insert the TS to Word 0 */
929
-
930
- tlbwe r4, r3, 0 /* Write out the entries */
931
- tlbwe r5, r3, 1
932
- tlbwe r6, r3, 2
933
- addi r8, r8, 1
934
- cmpwi r8, 8 /* Have we completed ? */
935
- bne write_utlb
936
-
937
- /* make sure we complete the TLB write up */
938
- isync
939
-
940
- /*
941
- * Prepare to jump to the 1:1 mapping.
942
- * 1) Extract page size of the tmp mapping
943
- * DSIZ = TLB_Word0[22:27]
944
- * 2) Calculate the physical address of the address
945
- * to jump to.
946
- */
947
- rlwinm r10, r24, 0, 22, 27
948
-
949
- cmpwi r10, PPC47x_TLB0_4K
950
- bne 0f
951
- li r10, 0x1000 /* r10 = 4k */
952
- bl 1f
953
-
954
-0:
955
- /* Defaults to 256M */
956
- lis r10, 0x1000
957
-
958
- bl 1f
959
-1: mflr r4
960
- addi r4, r4, (2f-1b) /* virtual address of 2f */
961
-
962
- subi r11, r10, 1 /* offsetmask = Pagesize - 1 */
963
- not r10, r11 /* Pagemask = ~(offsetmask) */
964
-
965
- and r5, r25, r10 /* Physical page */
966
- and r6, r4, r11 /* offset within the current page */
967
-
968
- or r5, r5, r6 /* Physical address for 2f */
969
-
970
- /* Switch the TS in MSR to the original one */
971
- mfmsr r8
972
- insrwi r8, r7, 1, 26
973
-
974
- mtspr SPRN_SRR1, r8
975
- mtspr SPRN_SRR0, r5
976
- rfi
977
-
978
-2:
979
- /* Invalidate the tmp mapping */
980
- lis r3, 0x8000 /* Way '0' */
981
-
982
- clrrwi r24, r24, 12 /* Clear the valid bit */
983
- tlbwe r24, r3, 0
984
- tlbwe r25, r3, 1
985
- tlbwe r26, r3, 2
986
-
987
- /* Make sure we complete the TLB write and flush the shadow TLB */
988
- isync
989
-
990
-#endif
991
-
992
-ppc44x_map_done:
993
-
994
-
995
- /* Restore the parameters */
996
- mr r3, r29
997
- mr r4, r30
998
- mr r5, r31
999
-
1000
- li r0, 0
1001
-#else
1002
- li r0, 0
1003
-
1004
- /*
1005
- * Set Machine Status Register to a known status,
1006
- * switch the MMU off and jump to 1: in a single step.
1007
- */
1008
-
1009
- mr r8, r0
1010
- ori r8, r8, MSR_RI|MSR_ME
1011
- mtspr SPRN_SRR1, r8
1012
- addi r8, r4, 1f - relocate_new_kernel
1013
- mtspr SPRN_SRR0, r8
1014
- sync
1015
- rfi
1016
-
1017
-1:
1018
-#endif
1019
- /* from this point address translation is turned off */
1020
- /* and interrupts are disabled */
1021
-
1022
- /* set a new stack at the bottom of our page... */
1023
- /* (not really needed now) */
1024
- addi r1, r4, KEXEC_CONTROL_PAGE_SIZE - 8 /* for LR Save+Back Chain */
1025
- stw r0, 0(r1)
1026
-
1027
- /* Do the copies */
1028
- li r6, 0 /* checksum */
1029
- mr r0, r3
1030
- b 1f
1031
-
1032
-0: /* top, read another word for the indirection page */
1033
- lwzu r0, 4(r3)
1034
-
1035
-1:
1036
- /* is it a destination page? (r8) */
1037
- rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
1038
- beq 2f
1039
-
1040
- rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */
1041
- b 0b
1042
-
1043
-2: /* is it an indirection page? (r3) */
1044
- rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
1045
- beq 2f
1046
-
1047
- rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */
1048
- subi r3, r3, 4
1049
- b 0b
1050
-
1051
-2: /* are we done? */
1052
- rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
1053
- beq 2f
1054
- b 3f
1055
-
1056
-2: /* is it a source page? (r9) */
1057
- rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
1058
- beq 0b
1059
-
1060
- rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */
1061
-
1062
- li r7, PAGE_SIZE / 4
1063
- mtctr r7
1064
- subi r9, r9, 4
1065
- subi r8, r8, 4
1066
-9:
1067
- lwzu r0, 4(r9) /* do the copy */
1068
- xor r6, r6, r0
1069
- stwu r0, 4(r8)
1070
- dcbst 0, r8
1071
- sync
1072
- icbi 0, r8
1073
- bdnz 9b
1074
-
1075
- addi r9, r9, 4
1076
- addi r8, r8, 4
1077
- b 0b
1078
-
1079
-3:
1080
-
1081
- /* To be certain of avoiding problems with self-modifying code
1082
- * execute a serializing instruction here.
1083
- */
1084
- isync
1085
- sync
1086
-
1087
- mfspr r3, SPRN_PIR /* current core we are running on */
1088
- mr r4, r5 /* load physical address of chunk called */
1089
-
1090
- /* jump to the entry point, usually the setup routine */
1091
- mtlr r5
1092
- blrl
1093
-
1094
-1: b 1b
1095
-
1096
-relocate_new_kernel_end:
1097
-
1098
- .globl relocate_new_kernel_size
1099
-relocate_new_kernel_size:
1100
- .long relocate_new_kernel_end - relocate_new_kernel
1101
-#endif