aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/head_8xx.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/head_8xx.S')
-rw-r--r--arch/powerpc/kernel/head_8xx.S70
1 files changed, 47 insertions, 23 deletions
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 3ef743fa5d7c..1f1a04b5c2a4 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -71,9 +71,6 @@ _ENTRY(_start);
71 * in the first level table, but that would require many changes to the 71 * in the first level table, but that would require many changes to the
72 * Linux page directory/table functions that I don't want to do right now. 72 * Linux page directory/table functions that I don't want to do right now.
73 * 73 *
74 * I used to use SPRG2 for a temporary register in the TLB handler, but it
75 * has since been put to other uses. I now use a hack to save a register
76 * and the CCR at memory location 0.....Someday I'll fix this.....
77 * -- Dan 74 * -- Dan
78 */ 75 */
79 .globl __start 76 .globl __start
@@ -302,8 +299,13 @@ InstructionTLBMiss:
302 DO_8xx_CPU6(0x3f80, r3) 299 DO_8xx_CPU6(0x3f80, r3)
303 mtspr SPRN_M_TW, r10 /* Save a couple of working registers */ 300 mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
304 mfcr r10 301 mfcr r10
302#ifdef CONFIG_8xx_CPU6
305 stw r10, 0(r0) 303 stw r10, 0(r0)
306 stw r11, 4(r0) 304 stw r11, 4(r0)
305#else
306 mtspr SPRN_DAR, r10
307 mtspr SPRN_SPRG2, r11
308#endif
307 mfspr r10, SPRN_SRR0 /* Get effective address of fault */ 309 mfspr r10, SPRN_SRR0 /* Get effective address of fault */
308#ifdef CONFIG_8xx_CPU15 310#ifdef CONFIG_8xx_CPU15
309 addi r11, r10, 0x1000 311 addi r11, r10, 0x1000
@@ -318,12 +320,16 @@ InstructionTLBMiss:
318 /* If we are faulting a kernel address, we have to use the 320 /* If we are faulting a kernel address, we have to use the
319 * kernel page tables. 321 * kernel page tables.
320 */ 322 */
323#ifdef CONFIG_MODULES
324 /* Only modules will cause ITLB Misses as we always
325 * pin the first 8MB of kernel memory */
321 andi. r11, r10, 0x0800 /* Address >= 0x80000000 */ 326 andi. r11, r10, 0x0800 /* Address >= 0x80000000 */
322 beq 3f 327 beq 3f
323 lis r11, swapper_pg_dir@h 328 lis r11, swapper_pg_dir@h
324 ori r11, r11, swapper_pg_dir@l 329 ori r11, r11, swapper_pg_dir@l
325 rlwimi r10, r11, 0, 2, 19 330 rlwimi r10, r11, 0, 2, 19
3263: 3313:
332#endif
327 lwz r11, 0(r10) /* Get the level 1 entry */ 333 lwz r11, 0(r10) /* Get the level 1 entry */
328 rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ 334 rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
329 beq 2f /* If zero, don't try to find a pte */ 335 beq 2f /* If zero, don't try to find a pte */
@@ -339,31 +345,35 @@ InstructionTLBMiss:
339 mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ 345 mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
340 lwz r10, 0(r11) /* Get the pte */ 346 lwz r10, 0(r11) /* Get the pte */
341 347
348#ifdef CONFIG_SWAP
342 andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT 349 andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT
343 cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT 350 cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT
344 bne- cr0, 2f 351 bne- cr0, 2f
345 352#endif
346 /* Clear PP lsb, 0x400 */
347 rlwinm r10, r10, 0, 22, 20
348
349 /* The Linux PTE won't go exactly into the MMU TLB. 353 /* The Linux PTE won't go exactly into the MMU TLB.
350 * Software indicator bits 22 and 28 must be clear. 354 * Software indicator bits 21 and 28 must be clear.
351 * Software indicator bits 24, 25, 26, and 27 must be 355 * Software indicator bits 24, 25, 26, and 27 must be
352 * set. All other Linux PTE bits control the behavior 356 * set. All other Linux PTE bits control the behavior
353 * of the MMU. 357 * of the MMU.
354 */ 358 */
355 li r11, 0x00f0 359 li r11, 0x00f0
356 rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ 360 rlwimi r10, r11, 0, 0x07f8 /* Set 24-27, clear 21-23,28 */
357 DO_8xx_CPU6(0x2d80, r3) 361 DO_8xx_CPU6(0x2d80, r3)
358 mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ 362 mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
359 363
360 mfspr r10, SPRN_M_TW /* Restore registers */ 364 /* Restore registers */
365#ifndef CONFIG_8xx_CPU6
366 mfspr r10, SPRN_DAR
367 mtcr r10
368 mtspr SPRN_DAR, r11 /* Tag DAR */
369 mfspr r11, SPRN_SPRG2
370#else
361 lwz r11, 0(r0) 371 lwz r11, 0(r0)
362 mtcr r11 372 mtcr r11
363 lwz r11, 4(r0) 373 lwz r11, 4(r0)
364#ifdef CONFIG_8xx_CPU6
365 lwz r3, 8(r0) 374 lwz r3, 8(r0)
366#endif 375#endif
376 mfspr r10, SPRN_M_TW
367 rfi 377 rfi
3682: 3782:
369 mfspr r11, SPRN_SRR1 379 mfspr r11, SPRN_SRR1
@@ -373,13 +383,20 @@ InstructionTLBMiss:
373 rlwinm r11, r11, 0, 0xffff 383 rlwinm r11, r11, 0, 0xffff
374 mtspr SPRN_SRR1, r11 384 mtspr SPRN_SRR1, r11
375 385
376 mfspr r10, SPRN_M_TW /* Restore registers */ 386 /* Restore registers */
387#ifndef CONFIG_8xx_CPU6
388 mfspr r10, SPRN_DAR
389 mtcr r10
390 li r11, 0x00f0
391 mtspr SPRN_DAR, r11 /* Tag DAR */
392 mfspr r11, SPRN_SPRG2
393#else
377 lwz r11, 0(r0) 394 lwz r11, 0(r0)
378 mtcr r11 395 mtcr r11
379 lwz r11, 4(r0) 396 lwz r11, 4(r0)
380#ifdef CONFIG_8xx_CPU6
381 lwz r3, 8(r0) 397 lwz r3, 8(r0)
382#endif 398#endif
399 mfspr r10, SPRN_M_TW
383 b InstructionAccess 400 b InstructionAccess
384 401
385 . = 0x1200 402 . = 0x1200
@@ -390,8 +407,13 @@ DataStoreTLBMiss:
390 DO_8xx_CPU6(0x3f80, r3) 407 DO_8xx_CPU6(0x3f80, r3)
391 mtspr SPRN_M_TW, r10 /* Save a couple of working registers */ 408 mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
392 mfcr r10 409 mfcr r10
410#ifdef CONFIG_8xx_CPU6
393 stw r10, 0(r0) 411 stw r10, 0(r0)
394 stw r11, 4(r0) 412 stw r11, 4(r0)
413#else
414 mtspr SPRN_DAR, r10
415 mtspr SPRN_SPRG2, r11
416#endif
395 mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */ 417 mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
396 418
397 /* If we are faulting a kernel address, we have to use the 419 /* If we are faulting a kernel address, we have to use the
@@ -438,15 +460,14 @@ DataStoreTLBMiss:
438 * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5)); 460 * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
439 * r10 = (r10 & ~PRESENT) | r11; 461 * r10 = (r10 & ~PRESENT) | r11;
440 */ 462 */
463#ifdef CONFIG_SWAP
441 rlwinm r11, r10, 32-5, _PAGE_PRESENT 464 rlwinm r11, r10, 32-5, _PAGE_PRESENT
442 and r11, r11, r10 465 and r11, r11, r10
443 rlwimi r10, r11, 0, _PAGE_PRESENT 466 rlwimi r10, r11, 0, _PAGE_PRESENT
444 467#endif
445 /* Honour kernel RO, User NA */ 468 /* Honour kernel RO, User NA */
446 /* 0x200 == Extended encoding, bit 22 */ 469 /* 0x200 == Extended encoding, bit 22 */
447 /* r11 = (r10 & _PAGE_USER) >> 2 */ 470 rlwimi r10, r10, 32-2, 0x200 /* Copy USER to bit 22, 0x200 */
448 rlwinm r11, r10, 32-2, 0x200
449 or r10, r11, r10
450 /* r11 = (r10 & _PAGE_RW) >> 1 */ 471 /* r11 = (r10 & _PAGE_RW) >> 1 */
451 rlwinm r11, r10, 32-1, 0x200 472 rlwinm r11, r10, 32-1, 0x200
452 or r10, r11, r10 473 or r10, r11, r10
@@ -460,18 +481,24 @@ DataStoreTLBMiss:
460 * of the MMU. 481 * of the MMU.
461 */ 482 */
4622: li r11, 0x00f0 4832: li r11, 0x00f0
463 mtspr SPRN_DAR,r11 /* Tag DAR */
464 rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ 484 rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
465 DO_8xx_CPU6(0x3d80, r3) 485 DO_8xx_CPU6(0x3d80, r3)
466 mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ 486 mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
467 487
468 mfspr r10, SPRN_M_TW /* Restore registers */ 488 /* Restore registers */
489#ifndef CONFIG_8xx_CPU6
490 mfspr r10, SPRN_DAR
491 mtcr r10
492 mtspr SPRN_DAR, r11 /* Tag DAR */
493 mfspr r11, SPRN_SPRG2
494#else
495 mtspr SPRN_DAR, r11 /* Tag DAR */
469 lwz r11, 0(r0) 496 lwz r11, 0(r0)
470 mtcr r11 497 mtcr r11
471 lwz r11, 4(r0) 498 lwz r11, 4(r0)
472#ifdef CONFIG_8xx_CPU6
473 lwz r3, 8(r0) 499 lwz r3, 8(r0)
474#endif 500#endif
501 mfspr r10, SPRN_M_TW
475 rfi 502 rfi
476 503
477/* This is an instruction TLB error on the MPC8xx. This could be due 504/* This is an instruction TLB error on the MPC8xx. This could be due
@@ -683,9 +710,6 @@ start_here:
683 tophys(r4,r2) 710 tophys(r4,r2)
684 addi r4,r4,THREAD /* init task's THREAD */ 711 addi r4,r4,THREAD /* init task's THREAD */
685 mtspr SPRN_SPRG_THREAD,r4 712 mtspr SPRN_SPRG_THREAD,r4
686 li r3,0
687 /* XXX What is that for ? SPRG2 appears otherwise unused on 8xx */
688 mtspr SPRN_SPRG2,r3 /* 0 => r1 has kernel sp */
689 713
690 /* stack */ 714 /* stack */
691 lis r1,init_thread_union@ha 715 lis r1,init_thread_union@ha