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