forked from ~ljy/RK356X_SDK_RELEASE

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