diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc/kernel/misc.S |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/ppc/kernel/misc.S')
-rw-r--r-- | arch/ppc/kernel/misc.S | 1453 |
1 files changed, 1453 insertions, 0 deletions
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S new file mode 100644 index 000000000000..73f7c23b0dd4 --- /dev/null +++ b/arch/ppc/kernel/misc.S | |||
@@ -0,0 +1,1453 @@ | |||
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 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/config.h> | ||
16 | #include <linux/sys.h> | ||
17 | #include <asm/unistd.h> | ||
18 | #include <asm/errno.h> | ||
19 | #include <asm/processor.h> | ||
20 | #include <asm/page.h> | ||
21 | #include <asm/cache.h> | ||
22 | #include <asm/cputable.h> | ||
23 | #include <asm/mmu.h> | ||
24 | #include <asm/ppc_asm.h> | ||
25 | #include <asm/thread_info.h> | ||
26 | #include <asm/offsets.h> | ||
27 | |||
28 | .text | ||
29 | |||
30 | .align 5 | ||
31 | _GLOBAL(__delay) | ||
32 | cmpwi 0,r3,0 | ||
33 | mtctr r3 | ||
34 | beqlr | ||
35 | 1: bdnz 1b | ||
36 | blr | ||
37 | |||
38 | /* | ||
39 | * Returns (address we're running at) - (address we were linked at) | ||
40 | * for use before the text and data are mapped to KERNELBASE. | ||
41 | */ | ||
42 | _GLOBAL(reloc_offset) | ||
43 | mflr r0 | ||
44 | bl 1f | ||
45 | 1: mflr r3 | ||
46 | lis r4,1b@ha | ||
47 | addi r4,r4,1b@l | ||
48 | subf r3,r4,r3 | ||
49 | mtlr r0 | ||
50 | blr | ||
51 | |||
52 | /* | ||
53 | * add_reloc_offset(x) returns x + reloc_offset(). | ||
54 | */ | ||
55 | _GLOBAL(add_reloc_offset) | ||
56 | mflr r0 | ||
57 | bl 1f | ||
58 | 1: mflr r5 | ||
59 | lis r4,1b@ha | ||
60 | addi r4,r4,1b@l | ||
61 | subf r5,r4,r5 | ||
62 | add r3,r3,r5 | ||
63 | mtlr r0 | ||
64 | blr | ||
65 | |||
66 | /* | ||
67 | * sub_reloc_offset(x) returns x - reloc_offset(). | ||
68 | */ | ||
69 | _GLOBAL(sub_reloc_offset) | ||
70 | mflr r0 | ||
71 | bl 1f | ||
72 | 1: mflr r5 | ||
73 | lis r4,1b@ha | ||
74 | addi r4,r4,1b@l | ||
75 | subf r5,r4,r5 | ||
76 | subf r3,r5,r3 | ||
77 | mtlr r0 | ||
78 | blr | ||
79 | |||
80 | /* | ||
81 | * reloc_got2 runs through the .got2 section adding an offset | ||
82 | * to each entry. | ||
83 | */ | ||
84 | _GLOBAL(reloc_got2) | ||
85 | mflr r11 | ||
86 | lis r7,__got2_start@ha | ||
87 | addi r7,r7,__got2_start@l | ||
88 | lis r8,__got2_end@ha | ||
89 | addi r8,r8,__got2_end@l | ||
90 | subf r8,r7,r8 | ||
91 | srwi. r8,r8,2 | ||
92 | beqlr | ||
93 | mtctr r8 | ||
94 | bl 1f | ||
95 | 1: mflr r0 | ||
96 | lis r4,1b@ha | ||
97 | addi r4,r4,1b@l | ||
98 | subf r0,r4,r0 | ||
99 | add r7,r0,r7 | ||
100 | 2: lwz r0,0(r7) | ||
101 | add r0,r0,r3 | ||
102 | stw r0,0(r7) | ||
103 | addi r7,r7,4 | ||
104 | bdnz 2b | ||
105 | mtlr r11 | ||
106 | blr | ||
107 | |||
108 | /* | ||
109 | * identify_cpu, | ||
110 | * called with r3 = data offset and r4 = CPU number | ||
111 | * doesn't change r3 | ||
112 | */ | ||
113 | _GLOBAL(identify_cpu) | ||
114 | addis r8,r3,cpu_specs@ha | ||
115 | addi r8,r8,cpu_specs@l | ||
116 | mfpvr r7 | ||
117 | 1: | ||
118 | lwz r5,CPU_SPEC_PVR_MASK(r8) | ||
119 | and r5,r5,r7 | ||
120 | lwz r6,CPU_SPEC_PVR_VALUE(r8) | ||
121 | cmplw 0,r6,r5 | ||
122 | beq 1f | ||
123 | addi r8,r8,CPU_SPEC_ENTRY_SIZE | ||
124 | b 1b | ||
125 | 1: | ||
126 | addis r6,r3,cur_cpu_spec@ha | ||
127 | addi r6,r6,cur_cpu_spec@l | ||
128 | slwi r4,r4,2 | ||
129 | sub r8,r8,r3 | ||
130 | stwx r8,r4,r6 | ||
131 | blr | ||
132 | |||
133 | /* | ||
134 | * do_cpu_ftr_fixups - goes through the list of CPU feature fixups | ||
135 | * and writes nop's over sections of code that don't apply for this cpu. | ||
136 | * r3 = data offset (not changed) | ||
137 | */ | ||
138 | _GLOBAL(do_cpu_ftr_fixups) | ||
139 | /* Get CPU 0 features */ | ||
140 | addis r6,r3,cur_cpu_spec@ha | ||
141 | addi r6,r6,cur_cpu_spec@l | ||
142 | lwz r4,0(r6) | ||
143 | add r4,r4,r3 | ||
144 | lwz r4,CPU_SPEC_FEATURES(r4) | ||
145 | |||
146 | /* Get the fixup table */ | ||
147 | addis r6,r3,__start___ftr_fixup@ha | ||
148 | addi r6,r6,__start___ftr_fixup@l | ||
149 | addis r7,r3,__stop___ftr_fixup@ha | ||
150 | addi r7,r7,__stop___ftr_fixup@l | ||
151 | |||
152 | /* Do the fixup */ | ||
153 | 1: cmplw 0,r6,r7 | ||
154 | bgelr | ||
155 | addi r6,r6,16 | ||
156 | lwz r8,-16(r6) /* mask */ | ||
157 | and r8,r8,r4 | ||
158 | lwz r9,-12(r6) /* value */ | ||
159 | cmplw 0,r8,r9 | ||
160 | beq 1b | ||
161 | lwz r8,-8(r6) /* section begin */ | ||
162 | lwz r9,-4(r6) /* section end */ | ||
163 | subf. r9,r8,r9 | ||
164 | beq 1b | ||
165 | /* write nops over the section of code */ | ||
166 | /* todo: if large section, add a branch at the start of it */ | ||
167 | srwi r9,r9,2 | ||
168 | mtctr r9 | ||
169 | add r8,r8,r3 | ||
170 | lis r0,0x60000000@h /* nop */ | ||
171 | 3: stw r0,0(r8) | ||
172 | andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l | ||
173 | beq 2f | ||
174 | dcbst 0,r8 /* suboptimal, but simpler */ | ||
175 | sync | ||
176 | icbi 0,r8 | ||
177 | 2: addi r8,r8,4 | ||
178 | bdnz 3b | ||
179 | sync /* additional sync needed on g4 */ | ||
180 | isync | ||
181 | b 1b | ||
182 | |||
183 | /* | ||
184 | * call_setup_cpu - call the setup_cpu function for this cpu | ||
185 | * r3 = data offset, r24 = cpu number | ||
186 | * | ||
187 | * Setup function is called with: | ||
188 | * r3 = data offset | ||
189 | * r4 = CPU number | ||
190 | * r5 = ptr to CPU spec (relocated) | ||
191 | */ | ||
192 | _GLOBAL(call_setup_cpu) | ||
193 | addis r5,r3,cur_cpu_spec@ha | ||
194 | addi r5,r5,cur_cpu_spec@l | ||
195 | slwi r4,r24,2 | ||
196 | lwzx r5,r4,r5 | ||
197 | add r5,r5,r3 | ||
198 | lwz r6,CPU_SPEC_SETUP(r5) | ||
199 | add r6,r6,r3 | ||
200 | mtctr r6 | ||
201 | mr r4,r24 | ||
202 | bctr | ||
203 | |||
204 | #if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx) | ||
205 | |||
206 | /* This gets called by via-pmu.c to switch the PLL selection | ||
207 | * on 750fx CPU. This function should really be moved to some | ||
208 | * other place (as most of the cpufreq code in via-pmu | ||
209 | */ | ||
210 | _GLOBAL(low_choose_750fx_pll) | ||
211 | /* Clear MSR:EE */ | ||
212 | mfmsr r7 | ||
213 | rlwinm r0,r7,0,17,15 | ||
214 | mtmsr r0 | ||
215 | |||
216 | /* If switching to PLL1, disable HID0:BTIC */ | ||
217 | cmplwi cr0,r3,0 | ||
218 | beq 1f | ||
219 | mfspr r5,SPRN_HID0 | ||
220 | rlwinm r5,r5,0,27,25 | ||
221 | sync | ||
222 | mtspr SPRN_HID0,r5 | ||
223 | isync | ||
224 | sync | ||
225 | |||
226 | 1: | ||
227 | /* Calc new HID1 value */ | ||
228 | mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */ | ||
229 | rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */ | ||
230 | rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */ | ||
231 | or r4,r4,r5 | ||
232 | mtspr SPRN_HID1,r4 | ||
233 | |||
234 | /* Store new HID1 image */ | ||
235 | rlwinm r6,r1,0,0,18 | ||
236 | lwz r6,TI_CPU(r6) | ||
237 | slwi r6,r6,2 | ||
238 | addis r6,r6,nap_save_hid1@ha | ||
239 | stw r4,nap_save_hid1@l(r6) | ||
240 | |||
241 | /* If switching to PLL0, enable HID0:BTIC */ | ||
242 | cmplwi cr0,r3,0 | ||
243 | bne 1f | ||
244 | mfspr r5,SPRN_HID0 | ||
245 | ori r5,r5,HID0_BTIC | ||
246 | sync | ||
247 | mtspr SPRN_HID0,r5 | ||
248 | isync | ||
249 | sync | ||
250 | |||
251 | 1: | ||
252 | /* Return */ | ||
253 | mtmsr r7 | ||
254 | blr | ||
255 | |||
256 | _GLOBAL(low_choose_7447a_dfs) | ||
257 | /* Clear MSR:EE */ | ||
258 | mfmsr r7 | ||
259 | rlwinm r0,r7,0,17,15 | ||
260 | mtmsr r0 | ||
261 | |||
262 | /* Calc new HID1 value */ | ||
263 | mfspr r4,SPRN_HID1 | ||
264 | insrwi r4,r3,1,9 /* insert parameter into bit 9 */ | ||
265 | sync | ||
266 | mtspr SPRN_HID1,r4 | ||
267 | sync | ||
268 | isync | ||
269 | |||
270 | /* Return */ | ||
271 | mtmsr r7 | ||
272 | blr | ||
273 | |||
274 | #endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */ | ||
275 | |||
276 | /* void local_save_flags_ptr(unsigned long *flags) */ | ||
277 | _GLOBAL(local_save_flags_ptr) | ||
278 | mfmsr r4 | ||
279 | stw r4,0(r3) | ||
280 | blr | ||
281 | /* | ||
282 | * Need these nops here for taking over save/restore to | ||
283 | * handle lost intrs | ||
284 | * -- Cort | ||
285 | */ | ||
286 | nop | ||
287 | nop | ||
288 | nop | ||
289 | nop | ||
290 | nop | ||
291 | nop | ||
292 | nop | ||
293 | nop | ||
294 | nop | ||
295 | nop | ||
296 | nop | ||
297 | nop | ||
298 | nop | ||
299 | nop | ||
300 | nop | ||
301 | nop | ||
302 | nop | ||
303 | _GLOBAL(local_save_flags_ptr_end) | ||
304 | |||
305 | /* void local_irq_restore(unsigned long flags) */ | ||
306 | _GLOBAL(local_irq_restore) | ||
307 | /* | ||
308 | * Just set/clear the MSR_EE bit through restore/flags but do not | ||
309 | * change anything else. This is needed by the RT system and makes | ||
310 | * sense anyway. | ||
311 | * -- Cort | ||
312 | */ | ||
313 | mfmsr r4 | ||
314 | /* Copy all except the MSR_EE bit from r4 (current MSR value) | ||
315 | to r3. This is the sort of thing the rlwimi instruction is | ||
316 | designed for. -- paulus. */ | ||
317 | rlwimi r3,r4,0,17,15 | ||
318 | /* Check if things are setup the way we want _already_. */ | ||
319 | cmpw 0,r3,r4 | ||
320 | beqlr | ||
321 | 1: SYNC | ||
322 | mtmsr r3 | ||
323 | SYNC | ||
324 | blr | ||
325 | nop | ||
326 | nop | ||
327 | nop | ||
328 | nop | ||
329 | nop | ||
330 | nop | ||
331 | nop | ||
332 | nop | ||
333 | nop | ||
334 | nop | ||
335 | nop | ||
336 | nop | ||
337 | nop | ||
338 | nop | ||
339 | nop | ||
340 | nop | ||
341 | nop | ||
342 | nop | ||
343 | nop | ||
344 | _GLOBAL(local_irq_restore_end) | ||
345 | |||
346 | _GLOBAL(local_irq_disable) | ||
347 | mfmsr r0 /* Get current interrupt state */ | ||
348 | rlwinm r3,r0,16+1,32-1,31 /* Extract old value of 'EE' */ | ||
349 | rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ | ||
350 | SYNC /* Some chip revs have problems here... */ | ||
351 | mtmsr r0 /* Update machine state */ | ||
352 | blr /* Done */ | ||
353 | /* | ||
354 | * Need these nops here for taking over save/restore to | ||
355 | * handle lost intrs | ||
356 | * -- Cort | ||
357 | */ | ||
358 | nop | ||
359 | nop | ||
360 | nop | ||
361 | nop | ||
362 | nop | ||
363 | nop | ||
364 | nop | ||
365 | nop | ||
366 | nop | ||
367 | nop | ||
368 | nop | ||
369 | nop | ||
370 | nop | ||
371 | nop | ||
372 | nop | ||
373 | _GLOBAL(local_irq_disable_end) | ||
374 | |||
375 | _GLOBAL(local_irq_enable) | ||
376 | mfmsr r3 /* Get current state */ | ||
377 | ori r3,r3,MSR_EE /* Turn on 'EE' bit */ | ||
378 | SYNC /* Some chip revs have problems here... */ | ||
379 | mtmsr r3 /* Update machine state */ | ||
380 | blr | ||
381 | /* | ||
382 | * Need these nops here for taking over save/restore to | ||
383 | * handle lost intrs | ||
384 | * -- Cort | ||
385 | */ | ||
386 | nop | ||
387 | nop | ||
388 | nop | ||
389 | nop | ||
390 | nop | ||
391 | nop | ||
392 | nop | ||
393 | nop | ||
394 | nop | ||
395 | nop | ||
396 | nop | ||
397 | nop | ||
398 | nop | ||
399 | nop | ||
400 | nop | ||
401 | nop | ||
402 | _GLOBAL(local_irq_enable_end) | ||
403 | |||
404 | /* | ||
405 | * complement mask on the msr then "or" some values on. | ||
406 | * _nmask_and_or_msr(nmask, value_to_or) | ||
407 | */ | ||
408 | _GLOBAL(_nmask_and_or_msr) | ||
409 | mfmsr r0 /* Get current msr */ | ||
410 | andc r0,r0,r3 /* And off the bits set in r3 (first parm) */ | ||
411 | or r0,r0,r4 /* Or on the bits in r4 (second parm) */ | ||
412 | SYNC /* Some chip revs have problems here... */ | ||
413 | mtmsr r0 /* Update machine state */ | ||
414 | isync | ||
415 | blr /* Done */ | ||
416 | |||
417 | |||
418 | /* | ||
419 | * Flush MMU TLB | ||
420 | */ | ||
421 | _GLOBAL(_tlbia) | ||
422 | #if defined(CONFIG_40x) | ||
423 | sync /* Flush to memory before changing mapping */ | ||
424 | tlbia | ||
425 | isync /* Flush shadow TLB */ | ||
426 | #elif defined(CONFIG_44x) | ||
427 | li r3,0 | ||
428 | sync | ||
429 | |||
430 | /* Load high watermark */ | ||
431 | lis r4,tlb_44x_hwater@ha | ||
432 | lwz r5,tlb_44x_hwater@l(r4) | ||
433 | |||
434 | 1: tlbwe r3,r3,PPC44x_TLB_PAGEID | ||
435 | addi r3,r3,1 | ||
436 | cmpw 0,r3,r5 | ||
437 | ble 1b | ||
438 | |||
439 | isync | ||
440 | #elif defined(CONFIG_FSL_BOOKE) | ||
441 | /* Invalidate all entries in TLB0 */ | ||
442 | li r3, 0x04 | ||
443 | tlbivax 0,3 | ||
444 | /* Invalidate all entries in TLB1 */ | ||
445 | li r3, 0x0c | ||
446 | tlbivax 0,3 | ||
447 | /* Invalidate all entries in TLB2 */ | ||
448 | li r3, 0x14 | ||
449 | tlbivax 0,3 | ||
450 | /* Invalidate all entries in TLB3 */ | ||
451 | li r3, 0x1c | ||
452 | tlbivax 0,3 | ||
453 | msync | ||
454 | #ifdef CONFIG_SMP | ||
455 | tlbsync | ||
456 | #endif /* CONFIG_SMP */ | ||
457 | #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */ | ||
458 | #if defined(CONFIG_SMP) | ||
459 | rlwinm r8,r1,0,0,18 | ||
460 | lwz r8,TI_CPU(r8) | ||
461 | oris r8,r8,10 | ||
462 | mfmsr r10 | ||
463 | SYNC | ||
464 | rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ | ||
465 | rlwinm r0,r0,0,28,26 /* clear DR */ | ||
466 | mtmsr r0 | ||
467 | SYNC_601 | ||
468 | isync | ||
469 | lis r9,mmu_hash_lock@h | ||
470 | ori r9,r9,mmu_hash_lock@l | ||
471 | tophys(r9,r9) | ||
472 | 10: lwarx r7,0,r9 | ||
473 | cmpwi 0,r7,0 | ||
474 | bne- 10b | ||
475 | stwcx. r8,0,r9 | ||
476 | bne- 10b | ||
477 | sync | ||
478 | tlbia | ||
479 | sync | ||
480 | TLBSYNC | ||
481 | li r0,0 | ||
482 | stw r0,0(r9) /* clear mmu_hash_lock */ | ||
483 | mtmsr r10 | ||
484 | SYNC_601 | ||
485 | isync | ||
486 | #else /* CONFIG_SMP */ | ||
487 | sync | ||
488 | tlbia | ||
489 | sync | ||
490 | #endif /* CONFIG_SMP */ | ||
491 | #endif /* ! defined(CONFIG_40x) */ | ||
492 | blr | ||
493 | |||
494 | /* | ||
495 | * Flush MMU TLB for a particular address | ||
496 | */ | ||
497 | _GLOBAL(_tlbie) | ||
498 | #if defined(CONFIG_40x) | ||
499 | tlbsx. r3, 0, r3 | ||
500 | bne 10f | ||
501 | sync | ||
502 | /* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear. | ||
503 | * Since 25 is the V bit in the TLB_TAG, loading this value will invalidate | ||
504 | * the TLB entry. */ | ||
505 | tlbwe r3, r3, TLB_TAG | ||
506 | isync | ||
507 | 10: | ||
508 | #elif defined(CONFIG_44x) | ||
509 | mfspr r4,SPRN_MMUCR | ||
510 | mfspr r5,SPRN_PID /* Get PID */ | ||
511 | rlwimi r4,r5,0,24,31 /* Set TID */ | ||
512 | mtspr SPRN_MMUCR,r4 | ||
513 | |||
514 | tlbsx. r3, 0, r3 | ||
515 | bne 10f | ||
516 | sync | ||
517 | /* There are only 64 TLB entries, so r3 < 64, | ||
518 | * which means bit 22, is clear. Since 22 is | ||
519 | * the V bit in the TLB_PAGEID, loading this | ||
520 | * value will invalidate the TLB entry. | ||
521 | */ | ||
522 | tlbwe r3, r3, PPC44x_TLB_PAGEID | ||
523 | isync | ||
524 | 10: | ||
525 | #elif defined(CONFIG_FSL_BOOKE) | ||
526 | rlwinm r4, r3, 0, 0, 19 | ||
527 | ori r5, r4, 0x08 /* TLBSEL = 1 */ | ||
528 | ori r6, r4, 0x10 /* TLBSEL = 2 */ | ||
529 | ori r7, r4, 0x18 /* TLBSEL = 3 */ | ||
530 | tlbivax 0, r4 | ||
531 | tlbivax 0, r5 | ||
532 | tlbivax 0, r6 | ||
533 | tlbivax 0, r7 | ||
534 | msync | ||
535 | #if defined(CONFIG_SMP) | ||
536 | tlbsync | ||
537 | #endif /* CONFIG_SMP */ | ||
538 | #else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */ | ||
539 | #if defined(CONFIG_SMP) | ||
540 | rlwinm r8,r1,0,0,18 | ||
541 | lwz r8,TI_CPU(r8) | ||
542 | oris r8,r8,11 | ||
543 | mfmsr r10 | ||
544 | SYNC | ||
545 | rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ | ||
546 | rlwinm r0,r0,0,28,26 /* clear DR */ | ||
547 | mtmsr r0 | ||
548 | SYNC_601 | ||
549 | isync | ||
550 | lis r9,mmu_hash_lock@h | ||
551 | ori r9,r9,mmu_hash_lock@l | ||
552 | tophys(r9,r9) | ||
553 | 10: lwarx r7,0,r9 | ||
554 | cmpwi 0,r7,0 | ||
555 | bne- 10b | ||
556 | stwcx. r8,0,r9 | ||
557 | bne- 10b | ||
558 | eieio | ||
559 | tlbie r3 | ||
560 | sync | ||
561 | TLBSYNC | ||
562 | li r0,0 | ||
563 | stw r0,0(r9) /* clear mmu_hash_lock */ | ||
564 | mtmsr r10 | ||
565 | SYNC_601 | ||
566 | isync | ||
567 | #else /* CONFIG_SMP */ | ||
568 | tlbie r3 | ||
569 | sync | ||
570 | #endif /* CONFIG_SMP */ | ||
571 | #endif /* ! CONFIG_40x */ | ||
572 | blr | ||
573 | |||
574 | /* | ||
575 | * Flush instruction cache. | ||
576 | * This is a no-op on the 601. | ||
577 | */ | ||
578 | _GLOBAL(flush_instruction_cache) | ||
579 | #if defined(CONFIG_8xx) | ||
580 | isync | ||
581 | lis r5, IDC_INVALL@h | ||
582 | mtspr SPRN_IC_CST, r5 | ||
583 | #elif defined(CONFIG_4xx) | ||
584 | #ifdef CONFIG_403GCX | ||
585 | li r3, 512 | ||
586 | mtctr r3 | ||
587 | lis r4, KERNELBASE@h | ||
588 | 1: iccci 0, r4 | ||
589 | addi r4, r4, 16 | ||
590 | bdnz 1b | ||
591 | #else | ||
592 | lis r3, KERNELBASE@h | ||
593 | iccci 0,r3 | ||
594 | #endif | ||
595 | #elif CONFIG_FSL_BOOKE | ||
596 | mfspr r3,SPRN_L1CSR1 | ||
597 | ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR | ||
598 | mtspr SPRN_L1CSR1,r3 | ||
599 | #else | ||
600 | mfspr r3,SPRN_PVR | ||
601 | rlwinm r3,r3,16,16,31 | ||
602 | cmpwi 0,r3,1 | ||
603 | beqlr /* for 601, do nothing */ | ||
604 | /* 603/604 processor - use invalidate-all bit in HID0 */ | ||
605 | mfspr r3,SPRN_HID0 | ||
606 | ori r3,r3,HID0_ICFI | ||
607 | mtspr SPRN_HID0,r3 | ||
608 | #endif /* CONFIG_8xx/4xx */ | ||
609 | isync | ||
610 | blr | ||
611 | |||
612 | /* | ||
613 | * Write any modified data cache blocks out to memory | ||
614 | * and invalidate the corresponding instruction cache blocks. | ||
615 | * This is a no-op on the 601. | ||
616 | * | ||
617 | * flush_icache_range(unsigned long start, unsigned long stop) | ||
618 | */ | ||
619 | _GLOBAL(flush_icache_range) | ||
620 | BEGIN_FTR_SECTION | ||
621 | blr /* for 601, do nothing */ | ||
622 | END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) | ||
623 | li r5,L1_CACHE_LINE_SIZE-1 | ||
624 | andc r3,r3,r5 | ||
625 | subf r4,r3,r4 | ||
626 | add r4,r4,r5 | ||
627 | srwi. r4,r4,LG_L1_CACHE_LINE_SIZE | ||
628 | beqlr | ||
629 | mtctr r4 | ||
630 | mr r6,r3 | ||
631 | 1: dcbst 0,r3 | ||
632 | addi r3,r3,L1_CACHE_LINE_SIZE | ||
633 | bdnz 1b | ||
634 | sync /* wait for dcbst's to get to ram */ | ||
635 | mtctr r4 | ||
636 | 2: icbi 0,r6 | ||
637 | addi r6,r6,L1_CACHE_LINE_SIZE | ||
638 | bdnz 2b | ||
639 | sync /* additional sync needed on g4 */ | ||
640 | isync | ||
641 | blr | ||
642 | /* | ||
643 | * Write any modified data cache blocks out to memory. | ||
644 | * Does not invalidate the corresponding cache lines (especially for | ||
645 | * any corresponding instruction cache). | ||
646 | * | ||
647 | * clean_dcache_range(unsigned long start, unsigned long stop) | ||
648 | */ | ||
649 | _GLOBAL(clean_dcache_range) | ||
650 | li r5,L1_CACHE_LINE_SIZE-1 | ||
651 | andc r3,r3,r5 | ||
652 | subf r4,r3,r4 | ||
653 | add r4,r4,r5 | ||
654 | srwi. r4,r4,LG_L1_CACHE_LINE_SIZE | ||
655 | beqlr | ||
656 | mtctr r4 | ||
657 | |||
658 | 1: dcbst 0,r3 | ||
659 | addi r3,r3,L1_CACHE_LINE_SIZE | ||
660 | bdnz 1b | ||
661 | sync /* wait for dcbst's to get to ram */ | ||
662 | blr | ||
663 | |||
664 | /* | ||
665 | * Write any modified data cache blocks out to memory and invalidate them. | ||
666 | * Does not invalidate the corresponding instruction cache blocks. | ||
667 | * | ||
668 | * flush_dcache_range(unsigned long start, unsigned long stop) | ||
669 | */ | ||
670 | _GLOBAL(flush_dcache_range) | ||
671 | li r5,L1_CACHE_LINE_SIZE-1 | ||
672 | andc r3,r3,r5 | ||
673 | subf r4,r3,r4 | ||
674 | add r4,r4,r5 | ||
675 | srwi. r4,r4,LG_L1_CACHE_LINE_SIZE | ||
676 | beqlr | ||
677 | mtctr r4 | ||
678 | |||
679 | 1: dcbf 0,r3 | ||
680 | addi r3,r3,L1_CACHE_LINE_SIZE | ||
681 | bdnz 1b | ||
682 | sync /* wait for dcbst's to get to ram */ | ||
683 | blr | ||
684 | |||
685 | /* | ||
686 | * Like above, but invalidate the D-cache. This is used by the 8xx | ||
687 | * to invalidate the cache so the PPC core doesn't get stale data | ||
688 | * from the CPM (no cache snooping here :-). | ||
689 | * | ||
690 | * invalidate_dcache_range(unsigned long start, unsigned long stop) | ||
691 | */ | ||
692 | _GLOBAL(invalidate_dcache_range) | ||
693 | li r5,L1_CACHE_LINE_SIZE-1 | ||
694 | andc r3,r3,r5 | ||
695 | subf r4,r3,r4 | ||
696 | add r4,r4,r5 | ||
697 | srwi. r4,r4,LG_L1_CACHE_LINE_SIZE | ||
698 | beqlr | ||
699 | mtctr r4 | ||
700 | |||
701 | 1: dcbi 0,r3 | ||
702 | addi r3,r3,L1_CACHE_LINE_SIZE | ||
703 | bdnz 1b | ||
704 | sync /* wait for dcbi's to get to ram */ | ||
705 | blr | ||
706 | |||
707 | #ifdef CONFIG_NOT_COHERENT_CACHE | ||
708 | /* | ||
709 | * 40x cores have 8K or 16K dcache and 32 byte line size. | ||
710 | * 44x has a 32K dcache and 32 byte line size. | ||
711 | * 8xx has 1, 2, 4, 8K variants. | ||
712 | * For now, cover the worst case of the 44x. | ||
713 | * Must be called with external interrupts disabled. | ||
714 | */ | ||
715 | #define CACHE_NWAYS 64 | ||
716 | #define CACHE_NLINES 16 | ||
717 | |||
718 | _GLOBAL(flush_dcache_all) | ||
719 | li r4, (2 * CACHE_NWAYS * CACHE_NLINES) | ||
720 | mtctr r4 | ||
721 | lis r5, KERNELBASE@h | ||
722 | 1: lwz r3, 0(r5) /* Load one word from every line */ | ||
723 | addi r5, r5, L1_CACHE_LINE_SIZE | ||
724 | bdnz 1b | ||
725 | blr | ||
726 | #endif /* CONFIG_NOT_COHERENT_CACHE */ | ||
727 | |||
728 | /* | ||
729 | * Flush a particular page from the data cache to RAM. | ||
730 | * Note: this is necessary because the instruction cache does *not* | ||
731 | * snoop from the data cache. | ||
732 | * This is a no-op on the 601 which has a unified cache. | ||
733 | * | ||
734 | * void __flush_dcache_icache(void *page) | ||
735 | */ | ||
736 | _GLOBAL(__flush_dcache_icache) | ||
737 | BEGIN_FTR_SECTION | ||
738 | blr /* for 601, do nothing */ | ||
739 | END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) | ||
740 | rlwinm r3,r3,0,0,19 /* Get page base address */ | ||
741 | li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */ | ||
742 | mtctr r4 | ||
743 | mr r6,r3 | ||
744 | 0: dcbst 0,r3 /* Write line to ram */ | ||
745 | addi r3,r3,L1_CACHE_LINE_SIZE | ||
746 | bdnz 0b | ||
747 | sync | ||
748 | mtctr r4 | ||
749 | 1: icbi 0,r6 | ||
750 | addi r6,r6,L1_CACHE_LINE_SIZE | ||
751 | bdnz 1b | ||
752 | sync | ||
753 | isync | ||
754 | blr | ||
755 | |||
756 | /* | ||
757 | * Flush a particular page from the data cache to RAM, identified | ||
758 | * by its physical address. We turn off the MMU so we can just use | ||
759 | * the physical address (this may be a highmem page without a kernel | ||
760 | * mapping). | ||
761 | * | ||
762 | * void __flush_dcache_icache_phys(unsigned long physaddr) | ||
763 | */ | ||
764 | _GLOBAL(__flush_dcache_icache_phys) | ||
765 | BEGIN_FTR_SECTION | ||
766 | blr /* for 601, do nothing */ | ||
767 | END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) | ||
768 | mfmsr r10 | ||
769 | rlwinm r0,r10,0,28,26 /* clear DR */ | ||
770 | mtmsr r0 | ||
771 | isync | ||
772 | rlwinm r3,r3,0,0,19 /* Get page base address */ | ||
773 | li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */ | ||
774 | mtctr r4 | ||
775 | mr r6,r3 | ||
776 | 0: dcbst 0,r3 /* Write line to ram */ | ||
777 | addi r3,r3,L1_CACHE_LINE_SIZE | ||
778 | bdnz 0b | ||
779 | sync | ||
780 | mtctr r4 | ||
781 | 1: icbi 0,r6 | ||
782 | addi r6,r6,L1_CACHE_LINE_SIZE | ||
783 | bdnz 1b | ||
784 | sync | ||
785 | mtmsr r10 /* restore DR */ | ||
786 | isync | ||
787 | blr | ||
788 | |||
789 | /* | ||
790 | * Clear pages using the dcbz instruction, which doesn't cause any | ||
791 | * memory traffic (except to write out any cache lines which get | ||
792 | * displaced). This only works on cacheable memory. | ||
793 | * | ||
794 | * void clear_pages(void *page, int order) ; | ||
795 | */ | ||
796 | _GLOBAL(clear_pages) | ||
797 | li r0,4096/L1_CACHE_LINE_SIZE | ||
798 | slw r0,r0,r4 | ||
799 | mtctr r0 | ||
800 | #ifdef CONFIG_8xx | ||
801 | li r4, 0 | ||
802 | 1: stw r4, 0(r3) | ||
803 | stw r4, 4(r3) | ||
804 | stw r4, 8(r3) | ||
805 | stw r4, 12(r3) | ||
806 | #else | ||
807 | 1: dcbz 0,r3 | ||
808 | #endif | ||
809 | addi r3,r3,L1_CACHE_LINE_SIZE | ||
810 | bdnz 1b | ||
811 | blr | ||
812 | |||
813 | /* | ||
814 | * Copy a whole page. We use the dcbz instruction on the destination | ||
815 | * to reduce memory traffic (it eliminates the unnecessary reads of | ||
816 | * the destination into cache). This requires that the destination | ||
817 | * is cacheable. | ||
818 | */ | ||
819 | #define COPY_16_BYTES \ | ||
820 | lwz r6,4(r4); \ | ||
821 | lwz r7,8(r4); \ | ||
822 | lwz r8,12(r4); \ | ||
823 | lwzu r9,16(r4); \ | ||
824 | stw r6,4(r3); \ | ||
825 | stw r7,8(r3); \ | ||
826 | stw r8,12(r3); \ | ||
827 | stwu r9,16(r3) | ||
828 | |||
829 | _GLOBAL(copy_page) | ||
830 | addi r3,r3,-4 | ||
831 | addi r4,r4,-4 | ||
832 | |||
833 | #ifdef CONFIG_8xx | ||
834 | /* don't use prefetch on 8xx */ | ||
835 | li r0,4096/L1_CACHE_LINE_SIZE | ||
836 | mtctr r0 | ||
837 | 1: COPY_16_BYTES | ||
838 | bdnz 1b | ||
839 | blr | ||
840 | |||
841 | #else /* not 8xx, we can prefetch */ | ||
842 | li r5,4 | ||
843 | |||
844 | #if MAX_COPY_PREFETCH > 1 | ||
845 | li r0,MAX_COPY_PREFETCH | ||
846 | li r11,4 | ||
847 | mtctr r0 | ||
848 | 11: dcbt r11,r4 | ||
849 | addi r11,r11,L1_CACHE_LINE_SIZE | ||
850 | bdnz 11b | ||
851 | #else /* MAX_COPY_PREFETCH == 1 */ | ||
852 | dcbt r5,r4 | ||
853 | li r11,L1_CACHE_LINE_SIZE+4 | ||
854 | #endif /* MAX_COPY_PREFETCH */ | ||
855 | li r0,4096/L1_CACHE_LINE_SIZE - MAX_COPY_PREFETCH | ||
856 | crclr 4*cr0+eq | ||
857 | 2: | ||
858 | mtctr r0 | ||
859 | 1: | ||
860 | dcbt r11,r4 | ||
861 | dcbz r5,r3 | ||
862 | COPY_16_BYTES | ||
863 | #if L1_CACHE_LINE_SIZE >= 32 | ||
864 | COPY_16_BYTES | ||
865 | #if L1_CACHE_LINE_SIZE >= 64 | ||
866 | COPY_16_BYTES | ||
867 | COPY_16_BYTES | ||
868 | #if L1_CACHE_LINE_SIZE >= 128 | ||
869 | COPY_16_BYTES | ||
870 | COPY_16_BYTES | ||
871 | COPY_16_BYTES | ||
872 | COPY_16_BYTES | ||
873 | #endif | ||
874 | #endif | ||
875 | #endif | ||
876 | bdnz 1b | ||
877 | beqlr | ||
878 | crnot 4*cr0+eq,4*cr0+eq | ||
879 | li r0,MAX_COPY_PREFETCH | ||
880 | li r11,4 | ||
881 | b 2b | ||
882 | #endif /* CONFIG_8xx */ | ||
883 | |||
884 | /* | ||
885 | * void atomic_clear_mask(atomic_t mask, atomic_t *addr) | ||
886 | * void atomic_set_mask(atomic_t mask, atomic_t *addr); | ||
887 | */ | ||
888 | _GLOBAL(atomic_clear_mask) | ||
889 | 10: lwarx r5,0,r4 | ||
890 | andc r5,r5,r3 | ||
891 | PPC405_ERR77(0,r4) | ||
892 | stwcx. r5,0,r4 | ||
893 | bne- 10b | ||
894 | blr | ||
895 | _GLOBAL(atomic_set_mask) | ||
896 | 10: lwarx r5,0,r4 | ||
897 | or r5,r5,r3 | ||
898 | PPC405_ERR77(0,r4) | ||
899 | stwcx. r5,0,r4 | ||
900 | bne- 10b | ||
901 | blr | ||
902 | |||
903 | /* | ||
904 | * I/O string operations | ||
905 | * | ||
906 | * insb(port, buf, len) | ||
907 | * outsb(port, buf, len) | ||
908 | * insw(port, buf, len) | ||
909 | * outsw(port, buf, len) | ||
910 | * insl(port, buf, len) | ||
911 | * outsl(port, buf, len) | ||
912 | * insw_ns(port, buf, len) | ||
913 | * outsw_ns(port, buf, len) | ||
914 | * insl_ns(port, buf, len) | ||
915 | * outsl_ns(port, buf, len) | ||
916 | * | ||
917 | * The *_ns versions don't do byte-swapping. | ||
918 | */ | ||
919 | _GLOBAL(_insb) | ||
920 | cmpwi 0,r5,0 | ||
921 | mtctr r5 | ||
922 | subi r4,r4,1 | ||
923 | blelr- | ||
924 | 00: lbz r5,0(r3) | ||
925 | eieio | ||
926 | stbu r5,1(r4) | ||
927 | bdnz 00b | ||
928 | blr | ||
929 | |||
930 | _GLOBAL(_outsb) | ||
931 | cmpwi 0,r5,0 | ||
932 | mtctr r5 | ||
933 | subi r4,r4,1 | ||
934 | blelr- | ||
935 | 00: lbzu r5,1(r4) | ||
936 | stb r5,0(r3) | ||
937 | eieio | ||
938 | bdnz 00b | ||
939 | blr | ||
940 | |||
941 | _GLOBAL(_insw) | ||
942 | cmpwi 0,r5,0 | ||
943 | mtctr r5 | ||
944 | subi r4,r4,2 | ||
945 | blelr- | ||
946 | 00: lhbrx r5,0,r3 | ||
947 | eieio | ||
948 | sthu r5,2(r4) | ||
949 | bdnz 00b | ||
950 | blr | ||
951 | |||
952 | _GLOBAL(_outsw) | ||
953 | cmpwi 0,r5,0 | ||
954 | mtctr r5 | ||
955 | subi r4,r4,2 | ||
956 | blelr- | ||
957 | 00: lhzu r5,2(r4) | ||
958 | eieio | ||
959 | sthbrx r5,0,r3 | ||
960 | bdnz 00b | ||
961 | blr | ||
962 | |||
963 | _GLOBAL(_insl) | ||
964 | cmpwi 0,r5,0 | ||
965 | mtctr r5 | ||
966 | subi r4,r4,4 | ||
967 | blelr- | ||
968 | 00: lwbrx r5,0,r3 | ||
969 | eieio | ||
970 | stwu r5,4(r4) | ||
971 | bdnz 00b | ||
972 | blr | ||
973 | |||
974 | _GLOBAL(_outsl) | ||
975 | cmpwi 0,r5,0 | ||
976 | mtctr r5 | ||
977 | subi r4,r4,4 | ||
978 | blelr- | ||
979 | 00: lwzu r5,4(r4) | ||
980 | stwbrx r5,0,r3 | ||
981 | eieio | ||
982 | bdnz 00b | ||
983 | blr | ||
984 | |||
985 | _GLOBAL(__ide_mm_insw) | ||
986 | _GLOBAL(_insw_ns) | ||
987 | cmpwi 0,r5,0 | ||
988 | mtctr r5 | ||
989 | subi r4,r4,2 | ||
990 | blelr- | ||
991 | 00: lhz r5,0(r3) | ||
992 | eieio | ||
993 | sthu r5,2(r4) | ||
994 | bdnz 00b | ||
995 | blr | ||
996 | |||
997 | _GLOBAL(__ide_mm_outsw) | ||
998 | _GLOBAL(_outsw_ns) | ||
999 | cmpwi 0,r5,0 | ||
1000 | mtctr r5 | ||
1001 | subi r4,r4,2 | ||
1002 | blelr- | ||
1003 | 00: lhzu r5,2(r4) | ||
1004 | sth r5,0(r3) | ||
1005 | eieio | ||
1006 | bdnz 00b | ||
1007 | blr | ||
1008 | |||
1009 | _GLOBAL(__ide_mm_insl) | ||
1010 | _GLOBAL(_insl_ns) | ||
1011 | cmpwi 0,r5,0 | ||
1012 | mtctr r5 | ||
1013 | subi r4,r4,4 | ||
1014 | blelr- | ||
1015 | 00: lwz r5,0(r3) | ||
1016 | eieio | ||
1017 | stwu r5,4(r4) | ||
1018 | bdnz 00b | ||
1019 | blr | ||
1020 | |||
1021 | _GLOBAL(__ide_mm_outsl) | ||
1022 | _GLOBAL(_outsl_ns) | ||
1023 | cmpwi 0,r5,0 | ||
1024 | mtctr r5 | ||
1025 | subi r4,r4,4 | ||
1026 | blelr- | ||
1027 | 00: lwzu r5,4(r4) | ||
1028 | stw r5,0(r3) | ||
1029 | eieio | ||
1030 | bdnz 00b | ||
1031 | blr | ||
1032 | |||
1033 | /* | ||
1034 | * Extended precision shifts. | ||
1035 | * | ||
1036 | * Updated to be valid for shift counts from 0 to 63 inclusive. | ||
1037 | * -- Gabriel | ||
1038 | * | ||
1039 | * R3/R4 has 64 bit value | ||
1040 | * R5 has shift count | ||
1041 | * result in R3/R4 | ||
1042 | * | ||
1043 | * ashrdi3: arithmetic right shift (sign propagation) | ||
1044 | * lshrdi3: logical right shift | ||
1045 | * ashldi3: left shift | ||
1046 | */ | ||
1047 | _GLOBAL(__ashrdi3) | ||
1048 | subfic r6,r5,32 | ||
1049 | srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count | ||
1050 | addi r7,r5,32 # could be xori, or addi with -32 | ||
1051 | slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count) | ||
1052 | rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0 | ||
1053 | sraw r7,r3,r7 # t2 = MSW >> (count-32) | ||
1054 | or r4,r4,r6 # LSW |= t1 | ||
1055 | slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2 | ||
1056 | sraw r3,r3,r5 # MSW = MSW >> count | ||
1057 | or r4,r4,r7 # LSW |= t2 | ||
1058 | blr | ||
1059 | |||
1060 | _GLOBAL(__ashldi3) | ||
1061 | subfic r6,r5,32 | ||
1062 | slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count | ||
1063 | addi r7,r5,32 # could be xori, or addi with -32 | ||
1064 | srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count) | ||
1065 | slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32) | ||
1066 | or r3,r3,r6 # MSW |= t1 | ||
1067 | slw r4,r4,r5 # LSW = LSW << count | ||
1068 | or r3,r3,r7 # MSW |= t2 | ||
1069 | blr | ||
1070 | |||
1071 | _GLOBAL(__lshrdi3) | ||
1072 | subfic r6,r5,32 | ||
1073 | srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count | ||
1074 | addi r7,r5,32 # could be xori, or addi with -32 | ||
1075 | slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count) | ||
1076 | srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32) | ||
1077 | or r4,r4,r6 # LSW |= t1 | ||
1078 | srw r3,r3,r5 # MSW = MSW >> count | ||
1079 | or r4,r4,r7 # LSW |= t2 | ||
1080 | blr | ||
1081 | |||
1082 | _GLOBAL(abs) | ||
1083 | srawi r4,r3,31 | ||
1084 | xor r3,r3,r4 | ||
1085 | sub r3,r3,r4 | ||
1086 | blr | ||
1087 | |||
1088 | _GLOBAL(_get_SP) | ||
1089 | mr r3,r1 /* Close enough */ | ||
1090 | blr | ||
1091 | |||
1092 | /* | ||
1093 | * These are used in the alignment trap handler when emulating | ||
1094 | * single-precision loads and stores. | ||
1095 | * We restore and save the fpscr so the task gets the same result | ||
1096 | * and exceptions as if the cpu had performed the load or store. | ||
1097 | */ | ||
1098 | |||
1099 | #if defined(CONFIG_4xx) || defined(CONFIG_E500) | ||
1100 | _GLOBAL(cvt_fd) | ||
1101 | lfs 0,0(r3) | ||
1102 | stfd 0,0(r4) | ||
1103 | blr | ||
1104 | |||
1105 | _GLOBAL(cvt_df) | ||
1106 | lfd 0,0(r3) | ||
1107 | stfs 0,0(r4) | ||
1108 | blr | ||
1109 | #else | ||
1110 | _GLOBAL(cvt_fd) | ||
1111 | lfd 0,-4(r5) /* load up fpscr value */ | ||
1112 | mtfsf 0xff,0 | ||
1113 | lfs 0,0(r3) | ||
1114 | stfd 0,0(r4) | ||
1115 | mffs 0 /* save new fpscr value */ | ||
1116 | stfd 0,-4(r5) | ||
1117 | blr | ||
1118 | |||
1119 | _GLOBAL(cvt_df) | ||
1120 | lfd 0,-4(r5) /* load up fpscr value */ | ||
1121 | mtfsf 0xff,0 | ||
1122 | lfd 0,0(r3) | ||
1123 | stfs 0,0(r4) | ||
1124 | mffs 0 /* save new fpscr value */ | ||
1125 | stfd 0,-4(r5) | ||
1126 | blr | ||
1127 | #endif | ||
1128 | |||
1129 | /* | ||
1130 | * Create a kernel thread | ||
1131 | * kernel_thread(fn, arg, flags) | ||
1132 | */ | ||
1133 | _GLOBAL(kernel_thread) | ||
1134 | stwu r1,-16(r1) | ||
1135 | stw r30,8(r1) | ||
1136 | stw r31,12(r1) | ||
1137 | mr r30,r3 /* function */ | ||
1138 | mr r31,r4 /* argument */ | ||
1139 | ori r3,r5,CLONE_VM /* flags */ | ||
1140 | oris r3,r3,CLONE_UNTRACED>>16 | ||
1141 | li r4,0 /* new sp (unused) */ | ||
1142 | li r0,__NR_clone | ||
1143 | sc | ||
1144 | cmpwi 0,r3,0 /* parent or child? */ | ||
1145 | bne 1f /* return if parent */ | ||
1146 | li r0,0 /* make top-level stack frame */ | ||
1147 | stwu r0,-16(r1) | ||
1148 | mtlr r30 /* fn addr in lr */ | ||
1149 | mr r3,r31 /* load arg and call fn */ | ||
1150 | blrl | ||
1151 | li r0,__NR_exit /* exit if function returns */ | ||
1152 | li r3,0 | ||
1153 | sc | ||
1154 | 1: lwz r30,8(r1) | ||
1155 | lwz r31,12(r1) | ||
1156 | addi r1,r1,16 | ||
1157 | blr | ||
1158 | |||
1159 | /* | ||
1160 | * This routine is just here to keep GCC happy - sigh... | ||
1161 | */ | ||
1162 | _GLOBAL(__main) | ||
1163 | blr | ||
1164 | |||
1165 | #define SYSCALL(name) \ | ||
1166 | _GLOBAL(name) \ | ||
1167 | li r0,__NR_##name; \ | ||
1168 | sc; \ | ||
1169 | bnslr; \ | ||
1170 | lis r4,errno@ha; \ | ||
1171 | stw r3,errno@l(r4); \ | ||
1172 | li r3,-1; \ | ||
1173 | blr | ||
1174 | |||
1175 | SYSCALL(execve) | ||
1176 | |||
1177 | /* Why isn't this a) automatic, b) written in 'C'? */ | ||
1178 | .data | ||
1179 | .align 4 | ||
1180 | _GLOBAL(sys_call_table) | ||
1181 | .long sys_restart_syscall /* 0 */ | ||
1182 | .long sys_exit | ||
1183 | .long ppc_fork | ||
1184 | .long sys_read | ||
1185 | .long sys_write | ||
1186 | .long sys_open /* 5 */ | ||
1187 | .long sys_close | ||
1188 | .long sys_waitpid | ||
1189 | .long sys_creat | ||
1190 | .long sys_link | ||
1191 | .long sys_unlink /* 10 */ | ||
1192 | .long sys_execve | ||
1193 | .long sys_chdir | ||
1194 | .long sys_time | ||
1195 | .long sys_mknod | ||
1196 | .long sys_chmod /* 15 */ | ||
1197 | .long sys_lchown | ||
1198 | .long sys_ni_syscall /* old break syscall holder */ | ||
1199 | .long sys_stat | ||
1200 | .long sys_lseek | ||
1201 | .long sys_getpid /* 20 */ | ||
1202 | .long sys_mount | ||
1203 | .long sys_oldumount | ||
1204 | .long sys_setuid | ||
1205 | .long sys_getuid | ||
1206 | .long sys_stime /* 25 */ | ||
1207 | .long sys_ptrace | ||
1208 | .long sys_alarm | ||
1209 | .long sys_fstat | ||
1210 | .long sys_pause | ||
1211 | .long sys_utime /* 30 */ | ||
1212 | .long sys_ni_syscall /* old stty syscall holder */ | ||
1213 | .long sys_ni_syscall /* old gtty syscall holder */ | ||
1214 | .long sys_access | ||
1215 | .long sys_nice | ||
1216 | .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ | ||
1217 | .long sys_sync | ||
1218 | .long sys_kill | ||
1219 | .long sys_rename | ||
1220 | .long sys_mkdir | ||
1221 | .long sys_rmdir /* 40 */ | ||
1222 | .long sys_dup | ||
1223 | .long sys_pipe | ||
1224 | .long sys_times | ||
1225 | .long sys_ni_syscall /* old prof syscall holder */ | ||
1226 | .long sys_brk /* 45 */ | ||
1227 | .long sys_setgid | ||
1228 | .long sys_getgid | ||
1229 | .long sys_signal | ||
1230 | .long sys_geteuid | ||
1231 | .long sys_getegid /* 50 */ | ||
1232 | .long sys_acct | ||
1233 | .long sys_umount /* recycled never used phys() */ | ||
1234 | .long sys_ni_syscall /* old lock syscall holder */ | ||
1235 | .long sys_ioctl | ||
1236 | .long sys_fcntl /* 55 */ | ||
1237 | .long sys_ni_syscall /* old mpx syscall holder */ | ||
1238 | .long sys_setpgid | ||
1239 | .long sys_ni_syscall /* old ulimit syscall holder */ | ||
1240 | .long sys_olduname | ||
1241 | .long sys_umask /* 60 */ | ||
1242 | .long sys_chroot | ||
1243 | .long sys_ustat | ||
1244 | .long sys_dup2 | ||
1245 | .long sys_getppid | ||
1246 | .long sys_getpgrp /* 65 */ | ||
1247 | .long sys_setsid | ||
1248 | .long sys_sigaction | ||
1249 | .long sys_sgetmask | ||
1250 | .long sys_ssetmask | ||
1251 | .long sys_setreuid /* 70 */ | ||
1252 | .long sys_setregid | ||
1253 | .long ppc_sigsuspend | ||
1254 | .long sys_sigpending | ||
1255 | .long sys_sethostname | ||
1256 | .long sys_setrlimit /* 75 */ | ||
1257 | .long sys_old_getrlimit | ||
1258 | .long sys_getrusage | ||
1259 | .long sys_gettimeofday | ||
1260 | .long sys_settimeofday | ||
1261 | .long sys_getgroups /* 80 */ | ||
1262 | .long sys_setgroups | ||
1263 | .long ppc_select | ||
1264 | .long sys_symlink | ||
1265 | .long sys_lstat | ||
1266 | .long sys_readlink /* 85 */ | ||
1267 | .long sys_uselib | ||
1268 | .long sys_swapon | ||
1269 | .long sys_reboot | ||
1270 | .long old_readdir | ||
1271 | .long sys_mmap /* 90 */ | ||
1272 | .long sys_munmap | ||
1273 | .long sys_truncate | ||
1274 | .long sys_ftruncate | ||
1275 | .long sys_fchmod | ||
1276 | .long sys_fchown /* 95 */ | ||
1277 | .long sys_getpriority | ||
1278 | .long sys_setpriority | ||
1279 | .long sys_ni_syscall /* old profil syscall holder */ | ||
1280 | .long sys_statfs | ||
1281 | .long sys_fstatfs /* 100 */ | ||
1282 | .long sys_ni_syscall | ||
1283 | .long sys_socketcall | ||
1284 | .long sys_syslog | ||
1285 | .long sys_setitimer | ||
1286 | .long sys_getitimer /* 105 */ | ||
1287 | .long sys_newstat | ||
1288 | .long sys_newlstat | ||
1289 | .long sys_newfstat | ||
1290 | .long sys_uname | ||
1291 | .long sys_ni_syscall /* 110 */ | ||
1292 | .long sys_vhangup | ||
1293 | .long sys_ni_syscall /* old 'idle' syscall */ | ||
1294 | .long sys_ni_syscall | ||
1295 | .long sys_wait4 | ||
1296 | .long sys_swapoff /* 115 */ | ||
1297 | .long sys_sysinfo | ||
1298 | .long sys_ipc | ||
1299 | .long sys_fsync | ||
1300 | .long sys_sigreturn | ||
1301 | .long ppc_clone /* 120 */ | ||
1302 | .long sys_setdomainname | ||
1303 | .long sys_newuname | ||
1304 | .long sys_ni_syscall | ||
1305 | .long sys_adjtimex | ||
1306 | .long sys_mprotect /* 125 */ | ||
1307 | .long sys_sigprocmask | ||
1308 | .long sys_ni_syscall /* old sys_create_module */ | ||
1309 | .long sys_init_module | ||
1310 | .long sys_delete_module | ||
1311 | .long sys_ni_syscall /* old sys_get_kernel_syms */ /* 130 */ | ||
1312 | .long sys_quotactl | ||
1313 | .long sys_getpgid | ||
1314 | .long sys_fchdir | ||
1315 | .long sys_bdflush | ||
1316 | .long sys_sysfs /* 135 */ | ||
1317 | .long sys_personality | ||
1318 | .long sys_ni_syscall /* for afs_syscall */ | ||
1319 | .long sys_setfsuid | ||
1320 | .long sys_setfsgid | ||
1321 | .long sys_llseek /* 140 */ | ||
1322 | .long sys_getdents | ||
1323 | .long ppc_select | ||
1324 | .long sys_flock | ||
1325 | .long sys_msync | ||
1326 | .long sys_readv /* 145 */ | ||
1327 | .long sys_writev | ||
1328 | .long sys_getsid | ||
1329 | .long sys_fdatasync | ||
1330 | .long sys_sysctl | ||
1331 | .long sys_mlock /* 150 */ | ||
1332 | .long sys_munlock | ||
1333 | .long sys_mlockall | ||
1334 | .long sys_munlockall | ||
1335 | .long sys_sched_setparam | ||
1336 | .long sys_sched_getparam /* 155 */ | ||
1337 | .long sys_sched_setscheduler | ||
1338 | .long sys_sched_getscheduler | ||
1339 | .long sys_sched_yield | ||
1340 | .long sys_sched_get_priority_max | ||
1341 | .long sys_sched_get_priority_min /* 160 */ | ||
1342 | .long sys_sched_rr_get_interval | ||
1343 | .long sys_nanosleep | ||
1344 | .long sys_mremap | ||
1345 | .long sys_setresuid | ||
1346 | .long sys_getresuid /* 165 */ | ||
1347 | .long sys_ni_syscall /* old sys_query_module */ | ||
1348 | .long sys_poll | ||
1349 | .long sys_nfsservctl | ||
1350 | .long sys_setresgid | ||
1351 | .long sys_getresgid /* 170 */ | ||
1352 | .long sys_prctl | ||
1353 | .long sys_rt_sigreturn | ||
1354 | .long sys_rt_sigaction | ||
1355 | .long sys_rt_sigprocmask | ||
1356 | .long sys_rt_sigpending /* 175 */ | ||
1357 | .long sys_rt_sigtimedwait | ||
1358 | .long sys_rt_sigqueueinfo | ||
1359 | .long ppc_rt_sigsuspend | ||
1360 | .long sys_pread64 | ||
1361 | .long sys_pwrite64 /* 180 */ | ||
1362 | .long sys_chown | ||
1363 | .long sys_getcwd | ||
1364 | .long sys_capget | ||
1365 | .long sys_capset | ||
1366 | .long sys_sigaltstack /* 185 */ | ||
1367 | .long sys_sendfile | ||
1368 | .long sys_ni_syscall /* streams1 */ | ||
1369 | .long sys_ni_syscall /* streams2 */ | ||
1370 | .long ppc_vfork | ||
1371 | .long sys_getrlimit /* 190 */ | ||
1372 | .long sys_readahead | ||
1373 | .long sys_mmap2 | ||
1374 | .long sys_truncate64 | ||
1375 | .long sys_ftruncate64 | ||
1376 | .long sys_stat64 /* 195 */ | ||
1377 | .long sys_lstat64 | ||
1378 | .long sys_fstat64 | ||
1379 | .long sys_pciconfig_read | ||
1380 | .long sys_pciconfig_write | ||
1381 | .long sys_pciconfig_iobase /* 200 */ | ||
1382 | .long sys_ni_syscall /* 201 - reserved - MacOnLinux - new */ | ||
1383 | .long sys_getdents64 | ||
1384 | .long sys_pivot_root | ||
1385 | .long sys_fcntl64 | ||
1386 | .long sys_madvise /* 205 */ | ||
1387 | .long sys_mincore | ||
1388 | .long sys_gettid | ||
1389 | .long sys_tkill | ||
1390 | .long sys_setxattr | ||
1391 | .long sys_lsetxattr /* 210 */ | ||
1392 | .long sys_fsetxattr | ||
1393 | .long sys_getxattr | ||
1394 | .long sys_lgetxattr | ||
1395 | .long sys_fgetxattr | ||
1396 | .long sys_listxattr /* 215 */ | ||
1397 | .long sys_llistxattr | ||
1398 | .long sys_flistxattr | ||
1399 | .long sys_removexattr | ||
1400 | .long sys_lremovexattr | ||
1401 | .long sys_fremovexattr /* 220 */ | ||
1402 | .long sys_futex | ||
1403 | .long sys_sched_setaffinity | ||
1404 | .long sys_sched_getaffinity | ||
1405 | .long sys_ni_syscall | ||
1406 | .long sys_ni_syscall /* 225 - reserved for Tux */ | ||
1407 | .long sys_sendfile64 | ||
1408 | .long sys_io_setup | ||
1409 | .long sys_io_destroy | ||
1410 | .long sys_io_getevents | ||
1411 | .long sys_io_submit /* 230 */ | ||
1412 | .long sys_io_cancel | ||
1413 | .long sys_set_tid_address | ||
1414 | .long sys_fadvise64 | ||
1415 | .long sys_exit_group | ||
1416 | .long sys_lookup_dcookie /* 235 */ | ||
1417 | .long sys_epoll_create | ||
1418 | .long sys_epoll_ctl | ||
1419 | .long sys_epoll_wait | ||
1420 | .long sys_remap_file_pages | ||
1421 | .long sys_timer_create /* 240 */ | ||
1422 | .long sys_timer_settime | ||
1423 | .long sys_timer_gettime | ||
1424 | .long sys_timer_getoverrun | ||
1425 | .long sys_timer_delete | ||
1426 | .long sys_clock_settime /* 245 */ | ||
1427 | .long sys_clock_gettime | ||
1428 | .long sys_clock_getres | ||
1429 | .long sys_clock_nanosleep | ||
1430 | .long ppc_swapcontext | ||
1431 | .long sys_tgkill /* 250 */ | ||
1432 | .long sys_utimes | ||
1433 | .long sys_statfs64 | ||
1434 | .long sys_fstatfs64 | ||
1435 | .long ppc_fadvise64_64 | ||
1436 | .long sys_ni_syscall /* 255 - rtas (used on ppc64) */ | ||
1437 | .long sys_debug_setcontext | ||
1438 | .long sys_ni_syscall /* 257 reserved for vserver */ | ||
1439 | .long sys_ni_syscall /* 258 reserved for new sys_remap_file_pages */ | ||
1440 | .long sys_ni_syscall /* 259 reserved for new sys_mbind */ | ||
1441 | .long sys_ni_syscall /* 260 reserved for new sys_get_mempolicy */ | ||
1442 | .long sys_ni_syscall /* 261 reserved for new sys_set_mempolicy */ | ||
1443 | .long sys_mq_open | ||
1444 | .long sys_mq_unlink | ||
1445 | .long sys_mq_timedsend | ||
1446 | .long sys_mq_timedreceive /* 265 */ | ||
1447 | .long sys_mq_notify | ||
1448 | .long sys_mq_getsetattr | ||
1449 | .long sys_ni_syscall /* 268 reserved for sys_kexec_load */ | ||
1450 | .long sys_add_key | ||
1451 | .long sys_request_key /* 270 */ | ||
1452 | .long sys_keyctl | ||
1453 | .long sys_waitid | ||