73
73
#define RPN_PATTERN 0x00f0
74
74
#endif
75
75
76
+ #define PAGE_SHIFT_512K 19
77
+ #define PAGE_SHIFT_8M 23
78
+
76
79
__HEAD
77
80
_ENTRY(_stext);
78
81
_ENTRY(_start);
@@ -322,7 +325,7 @@ SystemCall:
322
325
#endif
323
326
324
327
InstructionTLBMiss:
325
- #if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
328
+ #if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
326
329
mtspr SPRN_SPRG_SCRATCH2, r3
327
330
#endif
328
331
EXCEPTION_PROLOG_0
@@ -332,33 +335,45 @@ InstructionTLBMiss:
332
335
*/
333
336
mfspr r10, SPRN_SRR0 /* Get effective address of fault */
334
337
INVALIDATE_ADJACENT_PAGES_CPU15(r11, r10)
335
- #if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
336
338
/* Only modules will cause ITLB Misses as we always
337
339
* pin the first 8MB of kernel memory */
340
+ #if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
338
341
mfcr r3
342
+ #endif
343
+ #if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
339
344
IS_KERNEL(r11, r10)
340
345
#endif
341
346
mfspr r11, SPRN_M_TW /* Get level 1 table */
342
347
#if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
343
348
BRANCH_UNLESS_KERNEL(3f)
344
349
lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha
345
350
3:
346
- mtcr r3
347
351
#endif
348
352
/* Insert level 1 index */
349
353
rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2 ) << 1 ), (PAGE_SHIFT - 2 ) << 1 , 29
350
354
lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */
351
355
352
356
/* Extract level 2 index */
353
357
rlwinm r10, r10, 32 - (PAGE_SHIFT - 2 ), 32 - PAGE_SHIFT, 29
358
+ #ifdef CONFIG_HUGETLB_PAGE
359
+ mtcr r11
360
+ bt - 28 , 10f /* bit 28 = Large page (8M) */
361
+ bt - 29 , 20f /* bit 29 = Large page (8M or 512k) */
362
+ #endif
354
363
rlwimi r10, r11, 0 , 0 , 32 - PAGE_SHIFT - 1 /* Add level 2 base */
355
364
lwz r10, 0 (r10) /* Get the pte */
356
-
365
+ 4:
366
+ #if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
367
+ mtcr r3
368
+ #endif
357
369
/* Insert the APG into the TWC from the Linux PTE. */
358
370
rlwimi r11, r10, 0 , 25 , 26
359
371
/* Load the MI_TWC with the attributes for this "segment." */
360
372
MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */
361
373
374
+ #if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
375
+ rlwimi r10, r11, 1 , MI_SPS16K
376
+ #endif
362
377
#ifdef CONFIG_SWAP
363
378
rlwinm r11, r10, 32 -5 , _PAGE_PRESENT
364
379
and r11, r11, r10
@@ -371,16 +386,45 @@ InstructionTLBMiss:
371
386
* set. All other Linux PTE bits control the behavior
372
387
* of the MMU.
373
388
*/
389
+ #if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
390
+ rlwimi r10, r11, 0 , 0x0ff0 /* Set 24-27, clear 20-23 */
391
+ #else
374
392
rlwimi r10, r11, 0 , 0x0ff8 /* Set 24-27, clear 20-23,28 */
393
+ #endif
375
394
MTSPR_CPU6(SPRN_MI_RPN, r10, r3) /* Update TLB entry */
376
395
377
396
/* Restore registers */
378
- #if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
397
+ #if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
379
398
mfspr r3, SPRN_SPRG_SCRATCH2
380
399
#endif
381
400
EXCEPTION_EPILOG_0
382
401
rfi
383
402
403
+ #ifdef CONFIG_HUGETLB_PAGE
404
+ 10: /* 8M pages */
405
+ #ifdef CONFIG_PPC_16K_PAGES
406
+ /* Extract level 2 index */
407
+ rlwinm r10, r10, 32 - (PAGE_SHIFT_8M - PAGE_SHIFT), 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1 ), 29
408
+ /* Add level 2 base */
409
+ rlwimi r10, r11, 0 , 0 , 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1 ) - 1
410
+ #else
411
+ /* Level 2 base */
412
+ rlwinm r10, r11, 0 , ~HUGEPD_SHIFT_MASK
413
+ #endif
414
+ lwz r10, 0 (r10) /* Get the pte */
415
+ rlwinm r11, r11, 0 , 0xf
416
+ b 4b
417
+
418
+ 20: /* 512k pages */
419
+ /* Extract level 2 index */
420
+ rlwinm r10, r10, 32 - (PAGE_SHIFT_512K - PAGE_SHIFT), 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1 ), 29
421
+ /* Add level 2 base */
422
+ rlwimi r10, r11, 0 , 0 , 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1 ) - 1
423
+ lwz r10, 0 (r10) /* Get the pte */
424
+ rlwinm r11, r11, 0 , 0xf
425
+ b 4b
426
+ #endif
427
+
384
428
. = 0x1200
385
429
DataStoreTLBMiss:
386
430
mtspr SPRN_SPRG_SCRATCH2, r3
@@ -407,7 +451,6 @@ _ENTRY(DTLBMiss_jmp)
407
451
#endif
408
452
blt cr7, DTLBMissLinear
409
453
3:
410
- mtcr r3
411
454
mfspr r10, SPRN_MD_EPN
412
455
413
456
/* Insert level 1 index */
@@ -418,8 +461,15 @@ _ENTRY(DTLBMiss_jmp)
418
461
*/
419
462
/* Extract level 2 index */
420
463
rlwinm r10, r10, 32 - (PAGE_SHIFT - 2 ), 32 - PAGE_SHIFT, 29
464
+ #ifdef CONFIG_HUGETLB_PAGE
465
+ mtcr r11
466
+ bt - 28 , 10f /* bit 28 = Large page (8M) */
467
+ bt - 29 , 20f /* bit 29 = Large page (8M or 512k) */
468
+ #endif
421
469
rlwimi r10, r11, 0 , 0 , 32 - PAGE_SHIFT - 1 /* Add level 2 base */
422
470
lwz r10, 0 (r10) /* Get the pte */
471
+ 4:
472
+ mtcr r3
423
473
424
474
/* Insert the Guarded flag and APG into the TWC from the Linux PTE.
425
475
* It is bit 26-27 of both the Linux PTE and the TWC (at least
@@ -434,6 +484,11 @@ _ENTRY(DTLBMiss_jmp)
434
484
rlwimi r11, r10, 32 -5 , 30 , 30
435
485
MTSPR_CPU6(SPRN_MD_TWC, r11, r3)
436
486
487
+ /* In 4k pages mode, SPS (bit 28) in RPN must match PS[1] (bit 29)
488
+ * In 16k pages mode, SPS is always 1 */
489
+ #if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
490
+ rlwimi r10, r11, 1 , MD_SPS16K
491
+ #endif
437
492
/* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
438
493
* We also need to know if the insn is a load/store, so:
439
494
* Clear _PAGE_PRESENT and load that which will
@@ -455,7 +510,11 @@ _ENTRY(DTLBMiss_jmp)
455
510
* of the MMU.
456
511
*/
457
512
li r11, RPN_PATTERN
513
+ #if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
514
+ rlwimi r10, r11, 0 , 24 , 27 /* Set 24-27 */
515
+ #else
458
516
rlwimi r10, r11, 0 , 24 , 28 /* Set 24-27, clear 28 */
517
+ #endif
459
518
rlwimi r10, r11, 0 , 20 , 20 /* clear 20 */
460
519
MTSPR_CPU6(SPRN_MD_RPN, r10, r3) /* Update TLB entry */
461
520
@@ -465,6 +524,30 @@ _ENTRY(DTLBMiss_jmp)
465
524
EXCEPTION_EPILOG_0
466
525
rfi
467
526
527
+ #ifdef CONFIG_HUGETLB_PAGE
528
+ 10: /* 8M pages */
529
+ /* Extract level 2 index */
530
+ #ifdef CONFIG_PPC_16K_PAGES
531
+ rlwinm r10, r10, 32 - (PAGE_SHIFT_8M - PAGE_SHIFT), 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1 ), 29
532
+ /* Add level 2 base */
533
+ rlwimi r10, r11, 0 , 0 , 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1 ) - 1
534
+ #else
535
+ /* Level 2 base */
536
+ rlwinm r10, r11, 0 , ~HUGEPD_SHIFT_MASK
537
+ #endif
538
+ lwz r10, 0 (r10) /* Get the pte */
539
+ rlwinm r11, r11, 0 , 0xf
540
+ b 4b
541
+
542
+ 20: /* 512k pages */
543
+ /* Extract level 2 index */
544
+ rlwinm r10, r10, 32 - (PAGE_SHIFT_512K - PAGE_SHIFT), 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1 ), 29
545
+ /* Add level 2 base */
546
+ rlwimi r10, r11, 0 , 0 , 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1 ) - 1
547
+ lwz r10, 0 (r10) /* Get the pte */
548
+ rlwinm r11, r11, 0 , 0xf
549
+ b 4b
550
+ #endif
468
551
469
552
/* This is an instruction TLB error on the MPC8xx. This could be due
470
553
* to many reasons, such as executing guarded memory or illegal instruction
@@ -586,6 +669,9 @@ _ENTRY(FixupDAR_cmp)
586
669
/* Insert level 1 index */
587
670
3: rlwimi r11, r10, 32 - ((PAGE_SHIFT - 2 ) << 1 ), (PAGE_SHIFT - 2 ) << 1 , 29
588
671
lwz r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11) /* Get the level 1 entry */
672
+ mtcr r11
673
+ bt 28 ,200f /* bit 28 = Large page (8M) */
674
+ bt 29 ,202f /* bit 29 = Large page (8M or 512K) */
589
675
rlwinm r11, r11,0 ,0 ,19 /* Extract page descriptor page address */
590
676
/* Insert level 2 index */
591
677
rlwimi r11, r10, 32 - (PAGE_SHIFT - 2 ), 32 - PAGE_SHIFT, 29
@@ -611,6 +697,27 @@ _ENTRY(FixupDAR_cmp)
611
697
141: mfspr r10,SPRN_SPRG_SCRATCH2
612
698
b DARFixed /* Nope, go back to normal TLB processing */
613
699
700
+ /* concat physical page address(r11) and page offset(r10) */
701
+ 200:
702
+ #ifdef CONFIG_PPC_16K_PAGES
703
+ rlwinm r11, r11, 0 , 0 , 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1 ) - 1
704
+ rlwimi r11, r10, 32 - (PAGE_SHIFT_8M - 2 ), 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1 ), 29
705
+ #else
706
+ rlwinm r11, r10, 0 , ~HUGEPD_SHIFT_MASK
707
+ #endif
708
+ lwz r11, 0 (r11) /* Get the pte */
709
+ /* concat physical page address(r11) and page offset(r10) */
710
+ rlwimi r11, r10, 0 , 32 - PAGE_SHIFT_8M, 31
711
+ b 201b
712
+
713
+ 202:
714
+ rlwinm r11, r11, 0 , 0 , 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1 ) - 1
715
+ rlwimi r11, r10, 32 - (PAGE_SHIFT_512K - 2 ), 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1 ), 29
716
+ lwz r11, 0 (r11) /* Get the pte */
717
+ /* concat physical page address(r11) and page offset(r10) */
718
+ rlwimi r11, r10, 0 , 32 - PAGE_SHIFT_512K, 31
719
+ b 201b
720
+
614
721
144: mfspr r10, SPRN_DSISR
615
722
rlwinm r10, r10,0 ,7 ,5 /* Clear store bit for buggy dcbst insn */
616
723
mtspr SPRN_DSISR, r10
0 commit comments