Merge tag 'drm-vc4-fixes-2016-09-14' of https://github.com/anholt/linux into drm...
[linux-2.6-block.git] / arch / powerpc / kernel / misc_32.S
CommitLineData
9994a338
PM
1/*
2 * This file contains miscellaneous low-level functions.
3 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
4 *
5 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
6 * and Paul Mackerras.
7 *
3d1229d6
ME
8 * kexec bits:
9 * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
10 * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
674bfa48
SP
11 * PPC44x port. Copyright (C) 2011, IBM Corporation
12 * Author: Suzuki Poulose <suzuki@in.ibm.com>
3d1229d6 13 *
9994a338
PM
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.
18 *
19 */
20
9994a338
PM
21#include <linux/sys.h>
22#include <asm/unistd.h>
23#include <asm/errno.h>
24#include <asm/reg.h>
25#include <asm/page.h>
26#include <asm/cache.h>
27#include <asm/cputable.h>
28#include <asm/mmu.h>
29#include <asm/ppc_asm.h>
30#include <asm/thread_info.h>
31#include <asm/asm-offsets.h>
3d1229d6
ME
32#include <asm/processor.h>
33#include <asm/kexec.h>
f048aace 34#include <asm/bug.h>
46f52210 35#include <asm/ptrace.h>
9994a338
PM
36
37 .text
38
cbc9565e
BH
39/*
40 * We store the saved ksp_limit in the unused part
41 * of the STACK_FRAME_OVERHEAD
42 */
85218827
KG
43_GLOBAL(call_do_softirq)
44 mflr r0
45 stw r0,4(r1)
cbc9565e
BH
46 lwz r10,THREAD+KSP_LIMIT(r2)
47 addi r11,r3,THREAD_INFO_GAP
85218827
KG
48 stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
49 mr r1,r3
cbc9565e
BH
50 stw r10,8(r1)
51 stw r11,THREAD+KSP_LIMIT(r2)
85218827 52 bl __do_softirq
cbc9565e 53 lwz r10,8(r1)
85218827
KG
54 lwz r1,0(r1)
55 lwz r0,4(r1)
cbc9565e 56 stw r10,THREAD+KSP_LIMIT(r2)
85218827
KG
57 mtlr r0
58 blr
59
1a18a664
KH
60/*
61 * void call_do_irq(struct pt_regs *regs, struct thread_info *irqtp);
62 */
0366a1c7 63_GLOBAL(call_do_irq)
85218827
KG
64 mflr r0
65 stw r0,4(r1)
cbc9565e 66 lwz r10,THREAD+KSP_LIMIT(r2)
1a18a664 67 addi r11,r4,THREAD_INFO_GAP
0366a1c7
BH
68 stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
69 mr r1,r4
cbc9565e
BH
70 stw r10,8(r1)
71 stw r11,THREAD+KSP_LIMIT(r2)
0366a1c7 72 bl __do_irq
cbc9565e 73 lwz r10,8(r1)
85218827
KG
74 lwz r1,0(r1)
75 lwz r0,4(r1)
cbc9565e 76 stw r10,THREAD+KSP_LIMIT(r2)
85218827
KG
77 mtlr r0
78 blr
85218827 79
f2783c15
PM
80/*
81 * This returns the high 64 bits of the product of two 64-bit numbers.
82 */
83_GLOBAL(mulhdu)
84 cmpwi r6,0
85 cmpwi cr1,r3,0
86 mr r10,r4
87 mulhwu r4,r4,r5
88 beq 1f
89 mulhwu r0,r10,r6
90 mullw r7,r10,r5
91 addc r7,r0,r7
92 addze r4,r4
931: beqlr cr1 /* all done if high part of A is 0 */
f2783c15 94 mullw r9,r3,r5
737b01fc 95 mulhwu r10,r3,r5
f2783c15 96 beq 2f
737b01fc
CL
97 mullw r0,r3,r6
98 mulhwu r8,r3,r6
f2783c15
PM
99 addc r7,r0,r7
100 adde r4,r4,r8
737b01fc 101 addze r10,r10
f2783c15 1022: addc r4,r4,r9
737b01fc 103 addze r3,r10
f2783c15
PM
104 blr
105
9994a338
PM
106/*
107 * reloc_got2 runs through the .got2 section adding an offset
108 * to each entry.
109 */
110_GLOBAL(reloc_got2)
111 mflr r11
112 lis r7,__got2_start@ha
113 addi r7,r7,__got2_start@l
114 lis r8,__got2_end@ha
115 addi r8,r8,__got2_end@l
116 subf r8,r7,r8
117 srwi. r8,r8,2
118 beqlr
119 mtctr r8
120 bl 1f
1211: mflr r0
122 lis r4,1b@ha
123 addi r4,r4,1b@l
124 subf r0,r4,r0
125 add r7,r0,r7
1262: lwz r0,0(r7)
127 add r0,r0,r3
128 stw r0,0(r7)
129 addi r7,r7,4
130 bdnz 2b
131 mtlr r11
132 blr
133
9994a338
PM
134/*
135 * call_setup_cpu - call the setup_cpu function for this cpu
136 * r3 = data offset, r24 = cpu number
137 *
138 * Setup function is called with:
139 * r3 = data offset
140 * r4 = ptr to CPU spec (relocated)
141 */
142_GLOBAL(call_setup_cpu)
143 addis r4,r3,cur_cpu_spec@ha
144 addi r4,r4,cur_cpu_spec@l
145 lwz r4,0(r4)
146 add r4,r4,r3
147 lwz r5,CPU_SPEC_SETUP(r4)
b26f100d 148 cmpwi 0,r5,0
9994a338
PM
149 add r5,r5,r3
150 beqlr
151 mtctr r5
152 bctr
153
154#if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx)
155
156/* This gets called by via-pmu.c to switch the PLL selection
157 * on 750fx CPU. This function should really be moved to some
158 * other place (as most of the cpufreq code in via-pmu
159 */
160_GLOBAL(low_choose_750fx_pll)
161 /* Clear MSR:EE */
162 mfmsr r7
163 rlwinm r0,r7,0,17,15
164 mtmsr r0
165
166 /* If switching to PLL1, disable HID0:BTIC */
167 cmplwi cr0,r3,0
168 beq 1f
169 mfspr r5,SPRN_HID0
170 rlwinm r5,r5,0,27,25
171 sync
172 mtspr SPRN_HID0,r5
173 isync
174 sync
175
1761:
177 /* Calc new HID1 value */
178 mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */
179 rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */
180 rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */
181 or r4,r4,r5
182 mtspr SPRN_HID1,r4
183
184 /* Store new HID1 image */
9778b696 185 CURRENT_THREAD_INFO(r6, r1)
9994a338
PM
186 lwz r6,TI_CPU(r6)
187 slwi r6,r6,2
188 addis r6,r6,nap_save_hid1@ha
189 stw r4,nap_save_hid1@l(r6)
190
191 /* If switching to PLL0, enable HID0:BTIC */
192 cmplwi cr0,r3,0
193 bne 1f
194 mfspr r5,SPRN_HID0
195 ori r5,r5,HID0_BTIC
196 sync
197 mtspr SPRN_HID0,r5
198 isync
199 sync
200
2011:
202 /* Return */
203 mtmsr r7
204 blr
205
206_GLOBAL(low_choose_7447a_dfs)
207 /* Clear MSR:EE */
208 mfmsr r7
209 rlwinm r0,r7,0,17,15
210 mtmsr r0
211
212 /* Calc new HID1 value */
213 mfspr r4,SPRN_HID1
214 insrwi r4,r3,1,9 /* insert parameter into bit 9 */
215 sync
216 mtspr SPRN_HID1,r4
217 sync
218 isync
219
220 /* Return */
221 mtmsr r7
222 blr
223
224#endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */
225
226/*
227 * complement mask on the msr then "or" some values on.
228 * _nmask_and_or_msr(nmask, value_to_or)
229 */
230_GLOBAL(_nmask_and_or_msr)
231 mfmsr r0 /* Get current msr */
232 andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
233 or r0,r0,r4 /* Or on the bits in r4 (second parm) */
234 SYNC /* Some chip revs have problems here... */
235 mtmsr r0 /* Update machine state */
236 isync
237 blr /* Done */
238
9dae8afd
BH
239#ifdef CONFIG_40x
240
241/*
242 * Do an IO access in real mode
243 */
244_GLOBAL(real_readb)
245 mfmsr r7
246 ori r0,r7,MSR_DR
247 xori r0,r0,MSR_DR
248 sync
249 mtmsr r0
250 sync
251 isync
252 lbz r3,0(r3)
253 sync
254 mtmsr r7
255 sync
256 isync
257 blr
258
259 /*
260 * Do an IO access in real mode
261 */
262_GLOBAL(real_writeb)
263 mfmsr r7
264 ori r0,r7,MSR_DR
265 xori r0,r0,MSR_DR
266 sync
267 mtmsr r0
268 sync
269 isync
270 stb r3,0(r4)
271 sync
272 mtmsr r7
273 sync
274 isync
275 blr
276
277#endif /* CONFIG_40x */
9994a338 278
0ba3418b 279
9994a338
PM
280/*
281 * Flush instruction cache.
282 * This is a no-op on the 601.
283 */
766d45cb 284#ifndef CONFIG_PPC_8xx
9994a338 285_GLOBAL(flush_instruction_cache)
766d45cb 286#if defined(CONFIG_4xx)
9994a338
PM
287#ifdef CONFIG_403GCX
288 li r3, 512
289 mtctr r3
290 lis r4, KERNELBASE@h
2911: 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 CONFIG_FSL_BOOKE
299BEGIN_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
4508dc21 306END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
9994a338
PM
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
766d45cb 319#endif /* CONFIG_4xx */
9994a338
PM
320 isync
321 blr
766d45cb 322#endif /* CONFIG_PPC_8xx */
9994a338
PM
323
324/*
325 * Write any modified data cache blocks out to memory
326 * and invalidate the corresponding instruction cache blocks.
327 * This is a no-op on the 601.
328 *
329 * flush_icache_range(unsigned long start, unsigned long stop)
330 */
3b04c300 331_KPROBE(flush_icache_range)
9994a338 332BEGIN_FTR_SECTION
0ce63670 333 PURGE_PREFETCHED_INS
9994a338 334 blr /* for 601, do nothing */
4508dc21 335END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
716fa91d 336 rlwinm r3,r3,0,0,31 - L1_CACHE_SHIFT
9994a338 337 subf r4,r3,r4
716fa91d 338 addi r4,r4,L1_CACHE_BYTES - 1
7dffb720 339 srwi. r4,r4,L1_CACHE_SHIFT
9994a338
PM
340 beqlr
341 mtctr r4
342 mr r6,r3
3431: dcbst 0,r3
7dffb720 344 addi r3,r3,L1_CACHE_BYTES
9994a338
PM
345 bdnz 1b
346 sync /* wait for dcbst's to get to ram */
14d75752 347#ifndef CONFIG_44x
9994a338
PM
348 mtctr r4
3492: icbi 0,r6
7dffb720 350 addi r6,r6,L1_CACHE_BYTES
9994a338 351 bdnz 2b
14d75752
JB
352#else
353 /* Flash invalidate on 44x because we are passed kmapped addresses and
354 this doesn't work for userspace pages due to the virtually tagged
355 icache. Sigh. */
356 iccci 0, r0
357#endif
9994a338
PM
358 sync /* additional sync needed on g4 */
359 isync
360 blr
9994a338
PM
361/*
362 * Flush a particular page from the data cache to RAM.
363 * Note: this is necessary because the instruction cache does *not*
364 * snoop from the data cache.
365 * This is a no-op on the 601 which has a unified cache.
366 *
367 * void __flush_dcache_icache(void *page)
368 */
369_GLOBAL(__flush_dcache_icache)
370BEGIN_FTR_SECTION
0ce63670 371 PURGE_PREFETCHED_INS
4508dc21
DG
372 blr
373END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
ca9153a3
IY
374 rlwinm r3,r3,0,0,31-PAGE_SHIFT /* Get page base address */
375 li r4,PAGE_SIZE/L1_CACHE_BYTES /* Number of lines in a page */
9994a338
PM
376 mtctr r4
377 mr r6,r3
3780: dcbst 0,r3 /* Write line to ram */
7dffb720 379 addi r3,r3,L1_CACHE_BYTES
9994a338
PM
380 bdnz 0b
381 sync
e7f75ad0 382#ifdef CONFIG_44x
b98ac05d
BH
383 /* We don't flush the icache on 44x. Those have a virtual icache
384 * and we don't have access to the virtual address here (it's
385 * not the page vaddr but where it's mapped in user space). The
386 * flushing of the icache on these is handled elsewhere, when
387 * a change in the address space occurs, before returning to
388 * user space
389 */
e7f75ad0
DK
390BEGIN_MMU_FTR_SECTION
391 blr
392END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_44x)
393#endif /* CONFIG_44x */
9994a338
PM
394 mtctr r4
3951: icbi 0,r6
7dffb720 396 addi r6,r6,L1_CACHE_BYTES
9994a338
PM
397 bdnz 1b
398 sync
399 isync
400 blr
401
e7f75ad0 402#ifndef CONFIG_BOOKE
9994a338
PM
403/*
404 * Flush a particular page from the data cache to RAM, identified
405 * by its physical address. We turn off the MMU so we can just use
406 * the physical address (this may be a highmem page without a kernel
407 * mapping).
408 *
409 * void __flush_dcache_icache_phys(unsigned long physaddr)
410 */
411_GLOBAL(__flush_dcache_icache_phys)
412BEGIN_FTR_SECTION
0ce63670 413 PURGE_PREFETCHED_INS
9994a338 414 blr /* for 601, do nothing */
4508dc21 415END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
9994a338
PM
416 mfmsr r10
417 rlwinm r0,r10,0,28,26 /* clear DR */
418 mtmsr r0
419 isync
ca9153a3
IY
420 rlwinm r3,r3,0,0,31-PAGE_SHIFT /* Get page base address */
421 li r4,PAGE_SIZE/L1_CACHE_BYTES /* Number of lines in a page */
9994a338
PM
422 mtctr r4
423 mr r6,r3
4240: dcbst 0,r3 /* Write line to ram */
7dffb720 425 addi r3,r3,L1_CACHE_BYTES
9994a338
PM
426 bdnz 0b
427 sync
428 mtctr r4
4291: icbi 0,r6
7dffb720 430 addi r6,r6,L1_CACHE_BYTES
9994a338
PM
431 bdnz 1b
432 sync
433 mtmsr r10 /* restore DR */
434 isync
435 blr
e7f75ad0 436#endif /* CONFIG_BOOKE */
9994a338 437
9994a338
PM
438/*
439 * Copy a whole page. We use the dcbz instruction on the destination
440 * to reduce memory traffic (it eliminates the unnecessary reads of
441 * the destination into cache). This requires that the destination
442 * is cacheable.
443 */
444#define COPY_16_BYTES \
445 lwz r6,4(r4); \
446 lwz r7,8(r4); \
447 lwz r8,12(r4); \
448 lwzu r9,16(r4); \
449 stw r6,4(r3); \
450 stw r7,8(r3); \
451 stw r8,12(r3); \
452 stwu r9,16(r3)
453
454_GLOBAL(copy_page)
455 addi r3,r3,-4
456 addi r4,r4,-4
457
9994a338
PM
458 li r5,4
459
460#if MAX_COPY_PREFETCH > 1
461 li r0,MAX_COPY_PREFETCH
462 li r11,4
463 mtctr r0
46411: dcbt r11,r4
7dffb720 465 addi r11,r11,L1_CACHE_BYTES
9994a338
PM
466 bdnz 11b
467#else /* MAX_COPY_PREFETCH == 1 */
468 dcbt r5,r4
7dffb720 469 li r11,L1_CACHE_BYTES+4
9994a338 470#endif /* MAX_COPY_PREFETCH */
ca9153a3 471 li r0,PAGE_SIZE/L1_CACHE_BYTES - MAX_COPY_PREFETCH
9994a338
PM
472 crclr 4*cr0+eq
4732:
474 mtctr r0
4751:
476 dcbt r11,r4
477 dcbz r5,r3
478 COPY_16_BYTES
7dffb720 479#if L1_CACHE_BYTES >= 32
9994a338 480 COPY_16_BYTES
7dffb720 481#if L1_CACHE_BYTES >= 64
9994a338
PM
482 COPY_16_BYTES
483 COPY_16_BYTES
7dffb720 484#if L1_CACHE_BYTES >= 128
9994a338
PM
485 COPY_16_BYTES
486 COPY_16_BYTES
487 COPY_16_BYTES
488 COPY_16_BYTES
489#endif
490#endif
491#endif
492 bdnz 1b
493 beqlr
494 crnot 4*cr0+eq,4*cr0+eq
495 li r0,MAX_COPY_PREFETCH
496 li r11,4
497 b 2b
9994a338 498
9994a338
PM
499/*
500 * Extended precision shifts.
501 *
502 * Updated to be valid for shift counts from 0 to 63 inclusive.
503 * -- Gabriel
504 *
505 * R3/R4 has 64 bit value
506 * R5 has shift count
507 * result in R3/R4
508 *
509 * ashrdi3: arithmetic right shift (sign propagation)
510 * lshrdi3: logical right shift
511 * ashldi3: left shift
512 */
513_GLOBAL(__ashrdi3)
514 subfic r6,r5,32
515 srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
516 addi r7,r5,32 # could be xori, or addi with -32
517 slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
518 rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
519 sraw r7,r3,r7 # t2 = MSW >> (count-32)
520 or r4,r4,r6 # LSW |= t1
521 slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
522 sraw r3,r3,r5 # MSW = MSW >> count
523 or r4,r4,r7 # LSW |= t2
524 blr
525
526_GLOBAL(__ashldi3)
527 subfic r6,r5,32
528 slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
529 addi r7,r5,32 # could be xori, or addi with -32
530 srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
531 slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
532 or r3,r3,r6 # MSW |= t1
533 slw r4,r4,r5 # LSW = LSW << count
534 or r3,r3,r7 # MSW |= t2
535 blr
536
537_GLOBAL(__lshrdi3)
538 subfic r6,r5,32
539 srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
540 addi r7,r5,32 # could be xori, or addi with -32
541 slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
542 srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
543 or r4,r4,r6 # LSW |= t1
544 srw r3,r3,r5 # MSW = MSW >> count
545 or r4,r4,r7 # LSW |= t2
546 blr
547
41b93b23
BB
548/*
549 * 64-bit comparison: __cmpdi2(s64 a, s64 b)
550 * Returns 0 if a < b, 1 if a == b, 2 if a > b.
551 */
552_GLOBAL(__cmpdi2)
553 cmpw r3,r5
554 li r3,1
555 bne 1f
556 cmplw r4,r6
557 beqlr
5581: li r3,0
559 bltlr
560 li r3,2
561 blr
95ff54f5
PM
562/*
563 * 64-bit comparison: __ucmpdi2(u64 a, u64 b)
564 * Returns 0 if a < b, 1 if a == b, 2 if a > b.
565 */
566_GLOBAL(__ucmpdi2)
567 cmplw r3,r5
568 li r3,1
569 bne 1f
570 cmplw r4,r6
571 beqlr
5721: li r3,0
573 bltlr
574 li r3,2
575 blr
576
ca9d7aea
DW
577_GLOBAL(__bswapdi2)
578 rotlwi r9,r4,8
579 rotlwi r10,r3,8
580 rlwimi r9,r4,24,0,7
581 rlwimi r10,r3,24,0,7
582 rlwimi r9,r4,24,16,23
583 rlwimi r10,r3,24,16,23
584 mr r3,r9
585 mr r4,r10
586 blr
587
69e3cea8
BH
588#ifdef CONFIG_SMP
589_GLOBAL(start_secondary_resume)
590 /* Reset stack */
9778b696 591 CURRENT_THREAD_INFO(r1, r1)
69e3cea8
BH
592 addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
593 li r3,0
6de06f31 594 stw r3,0(r1) /* Zero the stack frame pointer */
69e3cea8
BH
595 bl start_secondary
596 b .
597#endif /* CONFIG_SMP */
598
9994a338
PM
599/*
600 * This routine is just here to keep GCC happy - sigh...
601 */
602_GLOBAL(__main)
603 blr
3d1229d6
ME
604
605#ifdef CONFIG_KEXEC
606 /*
607 * Must be relocatable PIC code callable as a C function.
608 */
609 .globl relocate_new_kernel
610relocate_new_kernel:
611 /* r3 = page_list */
612 /* r4 = reboot_code_buffer */
613 /* r5 = start_address */
614
b3df895a
SAS
615#ifdef CONFIG_FSL_BOOKE
616
617 mr r29, r3
618 mr r30, r4
619 mr r31, r5
620
621#define ENTRY_MAPPING_KEXEC_SETUP
622#include "fsl_booke_entry_mapping.S"
623#undef ENTRY_MAPPING_KEXEC_SETUP
624
625 mr r3, r29
626 mr r4, r30
627 mr r5, r31
628
674bfa48 629 li r0, 0
68343020 630#elif defined(CONFIG_44x)
674bfa48 631
68343020
SP
632 /* Save our parameters */
633 mr r29, r3
634 mr r30, r4
635 mr r31, r5
636
637#ifdef CONFIG_PPC_47x
638 /* Check for 47x cores */
639 mfspr r3,SPRN_PVR
640 srwi r3,r3,16
4450022b
AP
641 cmplwi cr0,r3,PVR_476FPE@h
642 beq setup_map_47x
68343020
SP
643 cmplwi cr0,r3,PVR_476@h
644 beq setup_map_47x
645 cmplwi cr0,r3,PVR_476_ISS@h
646 beq setup_map_47x
647#endif /* CONFIG_PPC_47x */
648
674bfa48
SP
649/*
650 * Code for setting up 1:1 mapping for PPC440x for KEXEC
651 *
652 * We cannot switch off the MMU on PPC44x.
653 * So we:
654 * 1) Invalidate all the mappings except the one we are running from.
655 * 2) Create a tmp mapping for our code in the other address space(TS) and
656 * jump to it. Invalidate the entry we started in.
657 * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS.
658 * 4) Jump to the 1:1 mapping in original TS.
659 * 5) Invalidate the tmp mapping.
660 *
661 * - Based on the kexec support code for FSL BookE
674bfa48
SP
662 *
663 */
674bfa48 664
f13bfcc6
SP
665 /*
666 * Load the PID with kernel PID (0).
667 * Also load our MSR_IS and TID to MMUCR for TLB search.
668 */
669 li r3, 0
670 mtspr SPRN_PID, r3
674bfa48
SP
671 mfmsr r4
672 andi. r4,r4,MSR_IS@l
673 beq wmmucr
674 oris r3,r3,PPC44x_MMUCR_STS@h
675wmmucr:
676 mtspr SPRN_MMUCR,r3
677 sync
678
679 /*
680 * Invalidate all the TLB entries except the current entry
681 * where we are running from
682 */
683 bl 0f /* Find our address */
6840: mflr r5 /* Make it accessible */
685 tlbsx r23,0,r5 /* Find entry we are in */
686 li r4,0 /* Start at TLB entry 0 */
687 li r3,0 /* Set PAGEID inval value */
6881: cmpw r23,r4 /* Is this our entry? */
689 beq skip /* If so, skip the inval */
690 tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */
691skip:
692 addi r4,r4,1 /* Increment */
693 cmpwi r4,64 /* Are we done? */
694 bne 1b /* If not, repeat */
695 isync
696
697 /* Create a temp mapping and jump to it */
698 andi. r6, r23, 1 /* Find the index to use */
699 addi r24, r6, 1 /* r24 will contain 1 or 2 */
700
701 mfmsr r9 /* get the MSR */
702 rlwinm r5, r9, 27, 31, 31 /* Extract the MSR[IS] */
703 xori r7, r5, 1 /* Use the other address space */
704
705 /* Read the current mapping entries */
706 tlbre r3, r23, PPC44x_TLB_PAGEID
707 tlbre r4, r23, PPC44x_TLB_XLAT
708 tlbre r5, r23, PPC44x_TLB_ATTRIB
709
710 /* Save our current XLAT entry */
711 mr r25, r4
712
713 /* Extract the TLB PageSize */
714 li r10, 1 /* r10 will hold PageSize */
715 rlwinm r11, r3, 0, 24, 27 /* bits 24-27 */
716
717 /* XXX: As of now we use 256M, 4K pages */
718 cmpwi r11, PPC44x_TLB_256M
719 bne tlb_4k
720 rotlwi r10, r10, 28 /* r10 = 256M */
721 b write_out
722tlb_4k:
723 cmpwi r11, PPC44x_TLB_4K
724 bne default
725 rotlwi r10, r10, 12 /* r10 = 4K */
726 b write_out
727default:
728 rotlwi r10, r10, 10 /* r10 = 1K */
729
730write_out:
731 /*
732 * Write out the tmp 1:1 mapping for this code in other address space
733 * Fixup EPN = RPN , TS=other address space
734 */
735 insrwi r3, r7, 1, 23 /* Bit 23 is TS for PAGEID field */
736
737 /* Write out the tmp mapping entries */
738 tlbwe r3, r24, PPC44x_TLB_PAGEID
739 tlbwe r4, r24, PPC44x_TLB_XLAT
740 tlbwe r5, r24, PPC44x_TLB_ATTRIB
741
742 subi r11, r10, 1 /* PageOffset Mask = PageSize - 1 */
743 not r10, r11 /* Mask for PageNum */
744
745 /* Switch to other address space in MSR */
746 insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */
747
748 bl 1f
7491: mflr r8
750 addi r8, r8, (2f-1b) /* Find the target offset */
751
752 /* Jump to the tmp mapping */
753 mtspr SPRN_SRR0, r8
754 mtspr SPRN_SRR1, r9
755 rfi
756
7572:
758 /* Invalidate the entry we were executing from */
759 li r3, 0
760 tlbwe r3, r23, PPC44x_TLB_PAGEID
761
762 /* attribute fields. rwx for SUPERVISOR mode */
763 li r5, 0
764 ori r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
765
766 /* Create 1:1 mapping in 256M pages */
767 xori r7, r7, 1 /* Revert back to Original TS */
768
769 li r8, 0 /* PageNumber */
770 li r6, 3 /* TLB Index, start at 3 */
771
772next_tlb:
773 rotlwi r3, r8, 28 /* Create EPN (bits 0-3) */
774 mr r4, r3 /* RPN = EPN */
775 ori r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */
776 insrwi r3, r7, 1, 23 /* Set TS from r7 */
777
778 tlbwe r3, r6, PPC44x_TLB_PAGEID /* PageID field : EPN, V, SIZE */
779 tlbwe r4, r6, PPC44x_TLB_XLAT /* Address translation : RPN */
780 tlbwe r5, r6, PPC44x_TLB_ATTRIB /* Attributes */
781
782 addi r8, r8, 1 /* Increment PN */
783 addi r6, r6, 1 /* Increment TLB Index */
784 cmpwi r8, 8 /* Are we done ? */
785 bne next_tlb
786 isync
787
788 /* Jump to the new mapping 1:1 */
789 li r9,0
790 insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */
791
792 bl 1f
7931: mflr r8
794 and r8, r8, r11 /* Get our offset within page */
795 addi r8, r8, (2f-1b)
796
797 and r5, r25, r10 /* Get our target PageNum */
798 or r8, r8, r5 /* Target jump address */
799
800 mtspr SPRN_SRR0, r8
801 mtspr SPRN_SRR1, r9
802 rfi
8032:
804 /* Invalidate the tmp entry we used */
805 li r3, 0
806 tlbwe r3, r24, PPC44x_TLB_PAGEID
807 sync
68343020
SP
808 b ppc44x_map_done
809
810#ifdef CONFIG_PPC_47x
811
812 /* 1:1 mapping for 47x */
813
814setup_map_47x:
815
816 /*
817 * Load the kernel pid (0) to PID and also to MMUCR[TID].
818 * Also set the MSR IS->MMUCR STS
819 */
820 li r3, 0
821 mtspr SPRN_PID, r3 /* Set PID */
822 mfmsr r4 /* Get MSR */
823 andi. r4, r4, MSR_IS@l /* TS=1? */
824 beq 1f /* If not, leave STS=0 */
825 oris r3, r3, PPC47x_MMUCR_STS@h /* Set STS=1 */
8261: mtspr SPRN_MMUCR, r3 /* Put MMUCR */
827 sync
828
829 /* Find the entry we are running from */
830 bl 2f
8312: mflr r23
832 tlbsx r23, 0, r23
833 tlbre r24, r23, 0 /* TLB Word 0 */
834 tlbre r25, r23, 1 /* TLB Word 1 */
835 tlbre r26, r23, 2 /* TLB Word 2 */
836
837
838 /*
839 * Invalidates all the tlb entries by writing to 256 RPNs(r4)
840 * of 4k page size in all 4 ways (0-3 in r3).
841 * This would invalidate the entire UTLB including the one we are
842 * running from. However the shadow TLB entries would help us
843 * to continue the execution, until we flush them (rfi/isync).
844 */
845 addis r3, 0, 0x8000 /* specify the way */
846 addi r4, 0, 0 /* TLB Word0 = (EPN=0, VALID = 0) */
847 addi r5, 0, 0
848 b clear_utlb_entry
849
850 /* Align the loop to speed things up. from head_44x.S */
851 .align 6
852
853clear_utlb_entry:
854
855 tlbwe r4, r3, 0
856 tlbwe r5, r3, 1
857 tlbwe r5, r3, 2
858 addis r3, r3, 0x2000 /* Increment the way */
859 cmpwi r3, 0
860 bne clear_utlb_entry
861 addis r3, 0, 0x8000
862 addis r4, r4, 0x100 /* Increment the EPN */
863 cmpwi r4, 0
864 bne clear_utlb_entry
865
866 /* Create the entries in the other address space */
867 mfmsr r5
868 rlwinm r7, r5, 27, 31, 31 /* Get the TS (Bit 26) from MSR */
869 xori r7, r7, 1 /* r7 = !TS */
870
871 insrwi r24, r7, 1, 21 /* Change the TS in the saved TLB word 0 */
872
873 /*
874 * write out the TLB entries for the tmp mapping
875 * Use way '0' so that we could easily invalidate it later.
876 */
877 lis r3, 0x8000 /* Way '0' */
878
879 tlbwe r24, r3, 0
880 tlbwe r25, r3, 1
881 tlbwe r26, r3, 2
882
883 /* Update the msr to the new TS */
884 insrwi r5, r7, 1, 26
885
886 bl 1f
8871: mflr r6
888 addi r6, r6, (2f-1b)
889
890 mtspr SPRN_SRR0, r6
891 mtspr SPRN_SRR1, r5
892 rfi
893
894 /*
895 * Now we are in the tmp address space.
896 * Create a 1:1 mapping for 0-2GiB in the original TS.
897 */
8982:
899 li r3, 0
900 li r4, 0 /* TLB Word 0 */
901 li r5, 0 /* TLB Word 1 */
902 li r6, 0
903 ori r6, r6, PPC47x_TLB2_S_RWX /* TLB word 2 */
904
905 li r8, 0 /* PageIndex */
906
907 xori r7, r7, 1 /* revert back to original TS */
908
909write_utlb:
910 rotlwi r5, r8, 28 /* RPN = PageIndex * 256M */
911 /* ERPN = 0 as we don't use memory above 2G */
912
913 mr r4, r5 /* EPN = RPN */
914 ori r4, r4, (PPC47x_TLB0_VALID | PPC47x_TLB0_256M)
915 insrwi r4, r7, 1, 21 /* Insert the TS to Word 0 */
916
917 tlbwe r4, r3, 0 /* Write out the entries */
918 tlbwe r5, r3, 1
919 tlbwe r6, r3, 2
920 addi r8, r8, 1
921 cmpwi r8, 8 /* Have we completed ? */
922 bne write_utlb
923
924 /* make sure we complete the TLB write up */
925 isync
926
927 /*
928 * Prepare to jump to the 1:1 mapping.
929 * 1) Extract page size of the tmp mapping
930 * DSIZ = TLB_Word0[22:27]
931 * 2) Calculate the physical address of the address
932 * to jump to.
933 */
934 rlwinm r10, r24, 0, 22, 27
935
936 cmpwi r10, PPC47x_TLB0_4K
937 bne 0f
938 li r10, 0x1000 /* r10 = 4k */
939 bl 1f
940
9410:
942 /* Defaults to 256M */
943 lis r10, 0x1000
944
945 bl 1f
9461: mflr r4
947 addi r4, r4, (2f-1b) /* virtual address of 2f */
948
949 subi r11, r10, 1 /* offsetmask = Pagesize - 1 */
950 not r10, r11 /* Pagemask = ~(offsetmask) */
951
952 and r5, r25, r10 /* Physical page */
953 and r6, r4, r11 /* offset within the current page */
954
955 or r5, r5, r6 /* Physical address for 2f */
956
957 /* Switch the TS in MSR to the original one */
958 mfmsr r8
959 insrwi r8, r7, 1, 26
960
961 mtspr SPRN_SRR1, r8
962 mtspr SPRN_SRR0, r5
963 rfi
964
9652:
966 /* Invalidate the tmp mapping */
967 lis r3, 0x8000 /* Way '0' */
968
969 clrrwi r24, r24, 12 /* Clear the valid bit */
970 tlbwe r24, r3, 0
971 tlbwe r25, r3, 1
972 tlbwe r26, r3, 2
973
974 /* Make sure we complete the TLB write and flush the shadow TLB */
975 isync
976
977#endif
978
979ppc44x_map_done:
980
674bfa48
SP
981
982 /* Restore the parameters */
983 mr r3, r29
984 mr r4, r30
985 mr r5, r31
986
b3df895a
SAS
987 li r0, 0
988#else
3d1229d6
ME
989 li r0, 0
990
991 /*
992 * Set Machine Status Register to a known status,
993 * switch the MMU off and jump to 1: in a single step.
994 */
995
996 mr r8, r0
997 ori r8, r8, MSR_RI|MSR_ME
998 mtspr SPRN_SRR1, r8
999 addi r8, r4, 1f - relocate_new_kernel
1000 mtspr SPRN_SRR0, r8
1001 sync
1002 rfi
1003
10041:
b3df895a 1005#endif
3d1229d6
ME
1006 /* from this point address translation is turned off */
1007 /* and interrupts are disabled */
1008
1009 /* set a new stack at the bottom of our page... */
1010 /* (not really needed now) */
d9178f4c 1011 addi r1, r4, KEXEC_CONTROL_PAGE_SIZE - 8 /* for LR Save+Back Chain */
3d1229d6
ME
1012 stw r0, 0(r1)
1013
1014 /* Do the copies */
1015 li r6, 0 /* checksum */
1016 mr r0, r3
1017 b 1f
1018
10190: /* top, read another word for the indirection page */
1020 lwzu r0, 4(r3)
1021
10221:
1023 /* is it a destination page? (r8) */
1024 rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
1025 beq 2f
1026
1027 rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */
1028 b 0b
1029
10302: /* is it an indirection page? (r3) */
1031 rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
1032 beq 2f
1033
1034 rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */
1035 subi r3, r3, 4
1036 b 0b
1037
10382: /* are we done? */
1039 rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
1040 beq 2f
1041 b 3f
1042
10432: /* is it a source page? (r9) */
1044 rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
1045 beq 0b
1046
1047 rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */
1048
1049 li r7, PAGE_SIZE / 4
1050 mtctr r7
1051 subi r9, r9, 4
1052 subi r8, r8, 4
10539:
1054 lwzu r0, 4(r9) /* do the copy */
1055 xor r6, r6, r0
1056 stwu r0, 4(r8)
1057 dcbst 0, r8
1058 sync
1059 icbi 0, r8
1060 bdnz 9b
1061
1062 addi r9, r9, 4
1063 addi r8, r8, 4
1064 b 0b
1065
10663:
1067
1068 /* To be certain of avoiding problems with self-modifying code
1069 * execute a serializing instruction here.
1070 */
1071 isync
1072 sync
1073
4562c986
MM
1074 mfspr r3, SPRN_PIR /* current core we are running on */
1075 mr r4, r5 /* load physical address of chunk called */
1076
3d1229d6
ME
1077 /* jump to the entry point, usually the setup routine */
1078 mtlr r5
1079 blrl
1080
10811: b 1b
1082
1083relocate_new_kernel_end:
1084
1085 .globl relocate_new_kernel_size
1086relocate_new_kernel_size:
1087 .long relocate_new_kernel_end - relocate_new_kernel
1088#endif