diff options
Diffstat (limited to 'arch/powerpc/kernel/head_8xx.S')
-rw-r--r-- | arch/powerpc/kernel/head_8xx.S | 123 |
1 files changed, 43 insertions, 80 deletions
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index d99aac0d69f1..9b53fe139bf6 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
@@ -319,36 +319,29 @@ InstructionTLBMiss: | |||
319 | * pin the first 8MB of kernel memory */ | 319 | * pin the first 8MB of kernel memory */ |
320 | andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ | 320 | andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ |
321 | #endif | 321 | #endif |
322 | mfspr r11, SPRN_M_TW /* Get level 1 table base address */ | 322 | mfspr r11, SPRN_M_TW /* Get level 1 table */ |
323 | #ifdef CONFIG_MODULES | 323 | #ifdef CONFIG_MODULES |
324 | beq 3f | 324 | beq 3f |
325 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@h | 325 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha |
326 | ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l | ||
327 | 3: | 326 | 3: |
328 | #endif | 327 | #endif |
329 | /* Extract level 1 index */ | 328 | /* Insert level 1 index */ |
330 | rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 | 329 | rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 |
331 | lwzx r11, r10, r11 /* Get the level 1 entry */ | 330 | lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */ |
332 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ | 331 | |
333 | beq 2f /* If zero, don't try to find a pte */ | 332 | /* Load the MI_TWC with the attributes for this "segment." */ |
334 | |||
335 | /* We have a pte table, so load the MI_TWC with the attributes | ||
336 | * for this "segment." | ||
337 | */ | ||
338 | MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */ | 333 | MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */ |
339 | mfspr r11, SPRN_SRR0 /* Get effective address of fault */ | 334 | rlwinm r11, r11,0,0,19 /* Extract page descriptor page address */ |
340 | /* Extract level 2 index */ | 335 | /* Extract level 2 index */ |
341 | rlwinm r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 | 336 | rlwinm r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 |
342 | lwzx r10, r10, r11 /* Get the pte */ | 337 | lwzx r10, r10, r11 /* Get the pte */ |
343 | 338 | ||
344 | #ifdef CONFIG_SWAP | 339 | #ifdef CONFIG_SWAP |
345 | andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT | 340 | rlwinm r11, r10, 32-5, _PAGE_PRESENT |
346 | cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT | 341 | and r11, r11, r10 |
347 | li r11, RPN_PATTERN | 342 | rlwimi r10, r11, 0, _PAGE_PRESENT |
348 | bne- cr0, 2f | ||
349 | #else | ||
350 | li r11, RPN_PATTERN | ||
351 | #endif | 343 | #endif |
344 | li r11, RPN_PATTERN | ||
352 | /* The Linux PTE won't go exactly into the MMU TLB. | 345 | /* The Linux PTE won't go exactly into the MMU TLB. |
353 | * Software indicator bits 21 and 28 must be clear. | 346 | * Software indicator bits 21 and 28 must be clear. |
354 | * Software indicator bits 24, 25, 26, and 27 must be | 347 | * Software indicator bits 24, 25, 26, and 27 must be |
@@ -366,21 +359,6 @@ InstructionTLBMiss: | |||
366 | mfspr r10, SPRN_SPRG_SCRATCH2 | 359 | mfspr r10, SPRN_SPRG_SCRATCH2 |
367 | EXCEPTION_EPILOG_0 | 360 | EXCEPTION_EPILOG_0 |
368 | rfi | 361 | rfi |
369 | 2: | ||
370 | mfspr r10, SPRN_SRR1 | ||
371 | /* clear all error bits as TLB Miss | ||
372 | * sets a few unconditionally | ||
373 | */ | ||
374 | rlwinm r10, r10, 0, 0xffff | ||
375 | mtspr SPRN_SRR1, r10 | ||
376 | |||
377 | /* Restore registers */ | ||
378 | #ifdef CONFIG_8xx_CPU6 | ||
379 | mfspr r3, SPRN_DAR | ||
380 | mtspr SPRN_DAR, r11 /* Tag DAR */ | ||
381 | #endif | ||
382 | mfspr r10, SPRN_SPRG_SCRATCH2 | ||
383 | b InstructionTLBError1 | ||
384 | 362 | ||
385 | . = 0x1200 | 363 | . = 0x1200 |
386 | DataStoreTLBMiss: | 364 | DataStoreTLBMiss: |
@@ -395,20 +373,16 @@ DataStoreTLBMiss: | |||
395 | * kernel page tables. | 373 | * kernel page tables. |
396 | */ | 374 | */ |
397 | andis. r11, r10, 0x8000 | 375 | andis. r11, r10, 0x8000 |
398 | mfspr r11, SPRN_M_TW /* Get level 1 table base address */ | 376 | mfspr r11, SPRN_M_TW /* Get level 1 table */ |
399 | beq 3f | 377 | beq 3f |
400 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@h | 378 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha |
401 | ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l | ||
402 | 3: | 379 | 3: |
403 | /* Extract level 1 index */ | 380 | /* Insert level 1 index */ |
404 | rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 | 381 | rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 |
405 | lwzx r11, r10, r11 /* Get the level 1 entry */ | 382 | lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */ |
406 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ | ||
407 | beq 2f /* If zero, don't try to find a pte */ | ||
408 | 383 | ||
409 | /* We have a pte table, so load fetch the pte from the table. | 384 | /* We have a pte table, so load fetch the pte from the table. |
410 | */ | 385 | */ |
411 | mfspr r10, SPRN_MD_EPN /* Get address of fault */ | ||
412 | /* Extract level 2 index */ | 386 | /* Extract level 2 index */ |
413 | rlwinm r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 | 387 | rlwinm r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 |
414 | rlwimi r10, r11, 0, 0, 32 - PAGE_SHIFT - 1 /* Add level 2 base */ | 388 | rlwimi r10, r11, 0, 0, 32 - PAGE_SHIFT - 1 /* Add level 2 base */ |
@@ -441,16 +415,13 @@ DataStoreTLBMiss: | |||
441 | and r11, r11, r10 | 415 | and r11, r11, r10 |
442 | rlwimi r10, r11, 0, _PAGE_PRESENT | 416 | rlwimi r10, r11, 0, _PAGE_PRESENT |
443 | #endif | 417 | #endif |
444 | /* invert RW */ | ||
445 | xori r10, r10, _PAGE_RW | ||
446 | |||
447 | /* The Linux PTE won't go exactly into the MMU TLB. | 418 | /* The Linux PTE won't go exactly into the MMU TLB. |
448 | * Software indicator bits 22 and 28 must be clear. | 419 | * Software indicator bits 22 and 28 must be clear. |
449 | * Software indicator bits 24, 25, 26, and 27 must be | 420 | * Software indicator bits 24, 25, 26, and 27 must be |
450 | * set. All other Linux PTE bits control the behavior | 421 | * set. All other Linux PTE bits control the behavior |
451 | * of the MMU. | 422 | * of the MMU. |
452 | */ | 423 | */ |
453 | 2: li r11, RPN_PATTERN | 424 | li r11, RPN_PATTERN |
454 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ | 425 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ |
455 | MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */ | 426 | MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */ |
456 | 427 | ||
@@ -469,10 +440,7 @@ DataStoreTLBMiss: | |||
469 | */ | 440 | */ |
470 | . = 0x1300 | 441 | . = 0x1300 |
471 | InstructionTLBError: | 442 | InstructionTLBError: |
472 | EXCEPTION_PROLOG_0 | 443 | EXCEPTION_PROLOG |
473 | InstructionTLBError1: | ||
474 | EXCEPTION_PROLOG_1 | ||
475 | EXCEPTION_PROLOG_2 | ||
476 | mr r4,r12 | 444 | mr r4,r12 |
477 | mr r5,r9 | 445 | mr r5,r9 |
478 | andis. r10,r5,0x4000 | 446 | andis. r10,r5,0x4000 |
@@ -532,30 +500,21 @@ DARFixed:/* Return from dcbx instruction bug workaround */ | |||
532 | /* define if you don't want to use self modifying code */ | 500 | /* define if you don't want to use self modifying code */ |
533 | #define NO_SELF_MODIFYING_CODE | 501 | #define NO_SELF_MODIFYING_CODE |
534 | FixupDAR:/* Entry point for dcbx workaround. */ | 502 | FixupDAR:/* Entry point for dcbx workaround. */ |
535 | #ifdef CONFIG_8xx_CPU6 | ||
536 | mtspr SPRN_DAR, r3 | ||
537 | #endif | ||
538 | mtspr SPRN_SPRG_SCRATCH2, r10 | 503 | mtspr SPRN_SPRG_SCRATCH2, r10 |
539 | /* fetch instruction from memory. */ | 504 | /* fetch instruction from memory. */ |
540 | mfspr r10, SPRN_SRR0 | 505 | mfspr r10, SPRN_SRR0 |
541 | andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ | 506 | andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ |
542 | mfspr r11, SPRN_M_TW /* Get level 1 table base address */ | 507 | mfspr r11, SPRN_M_TW /* Get level 1 table */ |
543 | beq- 3f /* Branch if user space */ | 508 | beq 3f |
544 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@h | 509 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha |
545 | ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l | 510 | /* Insert level 1 index */ |
546 | /* Extract level 1 index */ | 511 | 3: rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 |
547 | 3: rlwinm r10, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29 | 512 | lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */ |
548 | lwzx r11, r10, r11 /* Get the level 1 entry */ | 513 | rlwinm r11, r11,0,0,19 /* Extract page descriptor page address */ |
549 | rlwinm r10, r11,0,0,19 /* Extract page descriptor page address */ | 514 | /* Insert level 2 index */ |
550 | mfspr r11, SPRN_SRR0 /* Get effective address of fault */ | 515 | rlwimi r11, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 |
551 | /* Extract level 2 index */ | 516 | lwz r11, 0(r11) /* Get the pte */ |
552 | rlwinm r11, r11, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29 | ||
553 | lwzx r11, r10, r11 /* Get the pte */ | ||
554 | #ifdef CONFIG_8xx_CPU6 | ||
555 | mfspr r3, SPRN_DAR | ||
556 | #endif | ||
557 | /* concat physical page address(r11) and page offset(r10) */ | 517 | /* concat physical page address(r11) and page offset(r10) */ |
558 | mfspr r10, SPRN_SRR0 | ||
559 | rlwimi r11, r10, 0, 32 - PAGE_SHIFT, 31 | 518 | rlwimi r11, r10, 0, 32 - PAGE_SHIFT, 31 |
560 | lwz r11,0(r11) | 519 | lwz r11,0(r11) |
561 | /* Check if it really is a dcbx instruction. */ | 520 | /* Check if it really is a dcbx instruction. */ |
@@ -705,8 +664,7 @@ start_here: | |||
705 | * init's THREAD like the context switch code does, but this is | 664 | * init's THREAD like the context switch code does, but this is |
706 | * easier......until someone changes init's static structures. | 665 | * easier......until someone changes init's static structures. |
707 | */ | 666 | */ |
708 | lis r6, swapper_pg_dir@h | 667 | lis r6, swapper_pg_dir@ha |
709 | ori r6, r6, swapper_pg_dir@l | ||
710 | tophys(r6,r6) | 668 | tophys(r6,r6) |
711 | #ifdef CONFIG_8xx_CPU6 | 669 | #ifdef CONFIG_8xx_CPU6 |
712 | lis r4, cpu6_errata_word@h | 670 | lis r4, cpu6_errata_word@h |
@@ -885,23 +843,28 @@ _GLOBAL(set_context) | |||
885 | stw r4, 0x4(r5) | 843 | stw r4, 0x4(r5) |
886 | #endif | 844 | #endif |
887 | 845 | ||
846 | /* Register M_TW will contain base address of level 1 table minus the | ||
847 | * lower part of the kernel PGDIR base address, so that all accesses to | ||
848 | * level 1 table are done relative to lower part of kernel PGDIR base | ||
849 | * address. | ||
850 | */ | ||
851 | li r5, (swapper_pg_dir-PAGE_OFFSET)@l | ||
852 | sub r4, r4, r5 | ||
853 | tophys (r4, r4) | ||
888 | #ifdef CONFIG_8xx_CPU6 | 854 | #ifdef CONFIG_8xx_CPU6 |
889 | lis r6, cpu6_errata_word@h | 855 | lis r6, cpu6_errata_word@h |
890 | ori r6, r6, cpu6_errata_word@l | 856 | ori r6, r6, cpu6_errata_word@l |
891 | tophys (r4, r4) | ||
892 | li r7, 0x3f80 | 857 | li r7, 0x3f80 |
893 | stw r7, 12(r6) | 858 | stw r7, 12(r6) |
894 | lwz r7, 12(r6) | 859 | lwz r7, 12(r6) |
895 | mtspr SPRN_M_TW, r4 /* Update MMU base address */ | 860 | #endif |
861 | mtspr SPRN_M_TW, r4 /* Update pointeur to level 1 table */ | ||
862 | #ifdef CONFIG_8xx_CPU6 | ||
896 | li r7, 0x3380 | 863 | li r7, 0x3380 |
897 | stw r7, 12(r6) | 864 | stw r7, 12(r6) |
898 | lwz r7, 12(r6) | 865 | lwz r7, 12(r6) |
899 | mtspr SPRN_M_CASID, r3 /* Update context */ | ||
900 | #else | ||
901 | mtspr SPRN_M_CASID,r3 /* Update context */ | ||
902 | tophys (r4, r4) | ||
903 | mtspr SPRN_M_TW, r4 /* and pgd */ | ||
904 | #endif | 866 | #endif |
867 | mtspr SPRN_M_CASID, r3 /* Update context */ | ||
905 | SYNC | 868 | SYNC |
906 | blr | 869 | blr |
907 | 870 | ||