@@ -417,24 +417,137 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
417
417
BUG_ON (lpar_rc != H_SUCCESS );
418
418
}
419
419
420
+
421
+ /*
422
+ * As defined in the PAPR's section 14.5.4.1.8
423
+ * The control mask doesn't include the returned reference and change bit from
424
+ * the processed PTE.
425
+ */
426
+ #define HBLKR_AVPN 0x0100000000000000UL
427
+ #define HBLKR_CTRL_MASK 0xf800000000000000UL
428
+ #define HBLKR_CTRL_SUCCESS 0x8000000000000000UL
429
+ #define HBLKR_CTRL_ERRNOTFOUND 0x8800000000000000UL
430
+ #define HBLKR_CTRL_ERRBUSY 0xa000000000000000UL
431
+
432
+ /**
433
+ * H_BLOCK_REMOVE caller.
434
+ * @idx should point to the latest @param entry set with a PTEX.
435
+ * If PTE cannot be processed because another CPUs has already locked that
436
+ * group, those entries are put back in @param starting at index 1.
437
+ * If entries has to be retried and @retry_busy is set to true, these entries
438
+ * are retried until success. If @retry_busy is set to false, the returned
439
+ * is the number of entries yet to process.
440
+ */
441
+ static unsigned long call_block_remove (unsigned long idx , unsigned long * param ,
442
+ bool retry_busy )
443
+ {
444
+ unsigned long i , rc , new_idx ;
445
+ unsigned long retbuf [PLPAR_HCALL9_BUFSIZE ];
446
+
447
+ if (idx < 2 ) {
448
+ pr_warn ("Unexpected empty call to H_BLOCK_REMOVE" );
449
+ return 0 ;
450
+ }
451
+ again :
452
+ new_idx = 0 ;
453
+ if (idx > PLPAR_HCALL9_BUFSIZE ) {
454
+ pr_err ("Too many PTEs (%lu) for H_BLOCK_REMOVE" , idx );
455
+ idx = PLPAR_HCALL9_BUFSIZE ;
456
+ } else if (idx < PLPAR_HCALL9_BUFSIZE )
457
+ param [idx ] = HBR_END ;
458
+
459
+ rc = plpar_hcall9 (H_BLOCK_REMOVE , retbuf ,
460
+ param [0 ], /* AVA */
461
+ param [1 ], param [2 ], param [3 ], param [4 ], /* TS0-7 */
462
+ param [5 ], param [6 ], param [7 ], param [8 ]);
463
+ if (rc == H_SUCCESS )
464
+ return 0 ;
465
+
466
+ BUG_ON (rc != H_PARTIAL );
467
+
468
+ /* Check that the unprocessed entries were 'not found' or 'busy' */
469
+ for (i = 0 ; i < idx - 1 ; i ++ ) {
470
+ unsigned long ctrl = retbuf [i ] & HBLKR_CTRL_MASK ;
471
+
472
+ if (ctrl == HBLKR_CTRL_ERRBUSY ) {
473
+ param [++ new_idx ] = param [i + 1 ];
474
+ continue ;
475
+ }
476
+
477
+ BUG_ON (ctrl != HBLKR_CTRL_SUCCESS
478
+ && ctrl != HBLKR_CTRL_ERRNOTFOUND );
479
+ }
480
+
481
+ /*
482
+ * If there were entries found busy, retry these entries if requested,
483
+ * of if all the entries have to be retried.
484
+ */
485
+ if (new_idx && (retry_busy || new_idx == (PLPAR_HCALL9_BUFSIZE - 1 ))) {
486
+ idx = new_idx + 1 ;
487
+ goto again ;
488
+ }
489
+
490
+ return new_idx ;
491
+ }
492
+
420
493
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
421
494
/*
422
495
* Limit iterations holding pSeries_lpar_tlbie_lock to 3. We also need
423
496
* to make sure that we avoid bouncing the hypervisor tlbie lock.
424
497
*/
425
498
#define PPC64_HUGE_HPTE_BATCH 12
426
499
427
- static void __pSeries_lpar_hugepage_invalidate (unsigned long * slot ,
428
- unsigned long * vpn , int count ,
429
- int psize , int ssize )
500
+ static void hugepage_block_invalidate (unsigned long * slot , unsigned long * vpn ,
501
+ int count , int psize , int ssize )
430
502
{
431
503
unsigned long param [PLPAR_HCALL9_BUFSIZE ];
432
- int i = 0 , pix = 0 , rc ;
433
- unsigned long flags = 0 ;
434
- int lock_tlbie = !mmu_has_feature (MMU_FTR_LOCKLESS_TLBIE );
504
+ unsigned long shift , current_vpgb , vpgb ;
505
+ int i , pix = 0 ;
435
506
436
- if (lock_tlbie )
437
- spin_lock_irqsave (& pSeries_lpar_tlbie_lock , flags );
507
+ shift = mmu_psize_defs [psize ].shift ;
508
+
509
+ for (i = 0 ; i < count ; i ++ ) {
510
+ /*
511
+ * Shifting 3 bits more on the right to get a
512
+ * 8 pages aligned virtual addresse.
513
+ */
514
+ vpgb = (vpn [i ] >> (shift - VPN_SHIFT + 3 ));
515
+ if (!pix || vpgb != current_vpgb ) {
516
+ /*
517
+ * Need to start a new 8 pages block, flush
518
+ * the current one if needed.
519
+ */
520
+ if (pix )
521
+ (void )call_block_remove (pix , param , true);
522
+ current_vpgb = vpgb ;
523
+ param [0 ] = hpte_encode_avpn (vpn [i ], psize , ssize );
524
+ pix = 1 ;
525
+ }
526
+
527
+ param [pix ++ ] = HBR_REQUEST | HBLKR_AVPN | slot [i ];
528
+ if (pix == PLPAR_HCALL9_BUFSIZE ) {
529
+ pix = call_block_remove (pix , param , false);
530
+ /*
531
+ * pix = 0 means that all the entries were
532
+ * removed, we can start a new block.
533
+ * Otherwise, this means that there are entries
534
+ * to retry, and pix points to latest one, so
535
+ * we should increment it and try to continue
536
+ * the same block.
537
+ */
538
+ if (pix )
539
+ pix ++ ;
540
+ }
541
+ }
542
+ if (pix )
543
+ (void )call_block_remove (pix , param , true);
544
+ }
545
+
546
+ static void hugepage_bulk_invalidate (unsigned long * slot , unsigned long * vpn ,
547
+ int count , int psize , int ssize )
548
+ {
549
+ unsigned long param [PLPAR_HCALL9_BUFSIZE ];
550
+ int i = 0 , pix = 0 , rc ;
438
551
439
552
for (i = 0 ; i < count ; i ++ ) {
440
553
@@ -462,6 +575,23 @@ static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot,
462
575
param [6 ], param [7 ]);
463
576
BUG_ON (rc != H_SUCCESS );
464
577
}
578
+ }
579
+
580
+ static inline void __pSeries_lpar_hugepage_invalidate (unsigned long * slot ,
581
+ unsigned long * vpn ,
582
+ int count , int psize ,
583
+ int ssize )
584
+ {
585
+ unsigned long flags = 0 ;
586
+ int lock_tlbie = !mmu_has_feature (MMU_FTR_LOCKLESS_TLBIE );
587
+
588
+ if (lock_tlbie )
589
+ spin_lock_irqsave (& pSeries_lpar_tlbie_lock , flags );
590
+
591
+ if (firmware_has_feature (FW_FEATURE_BLOCK_REMOVE ))
592
+ hugepage_block_invalidate (slot , vpn , count , psize , ssize );
593
+ else
594
+ hugepage_bulk_invalidate (slot , vpn , count , psize , ssize );
465
595
466
596
if (lock_tlbie )
467
597
spin_unlock_irqrestore (& pSeries_lpar_tlbie_lock , flags );
@@ -564,6 +694,68 @@ static inline unsigned long compute_slot(real_pte_t pte,
564
694
return slot ;
565
695
}
566
696
697
+ /**
698
+ * The hcall H_BLOCK_REMOVE implies that the virtual pages to processed are
699
+ * "all within the same naturally aligned 8 page virtual address block".
700
+ */
701
+ static void do_block_remove (unsigned long number , struct ppc64_tlb_batch * batch ,
702
+ unsigned long * param )
703
+ {
704
+ unsigned long vpn ;
705
+ unsigned long i , pix = 0 ;
706
+ unsigned long index , shift , slot , current_vpgb , vpgb ;
707
+ real_pte_t pte ;
708
+ int psize , ssize ;
709
+
710
+ psize = batch -> psize ;
711
+ ssize = batch -> ssize ;
712
+
713
+ for (i = 0 ; i < number ; i ++ ) {
714
+ vpn = batch -> vpn [i ];
715
+ pte = batch -> pte [i ];
716
+ pte_iterate_hashed_subpages (pte , psize , vpn , index , shift ) {
717
+ /*
718
+ * Shifting 3 bits more on the right to get a
719
+ * 8 pages aligned virtual addresse.
720
+ */
721
+ vpgb = (vpn >> (shift - VPN_SHIFT + 3 ));
722
+ if (!pix || vpgb != current_vpgb ) {
723
+ /*
724
+ * Need to start a new 8 pages block, flush
725
+ * the current one if needed.
726
+ */
727
+ if (pix )
728
+ (void )call_block_remove (pix , param ,
729
+ true);
730
+ current_vpgb = vpgb ;
731
+ param [0 ] = hpte_encode_avpn (vpn , psize ,
732
+ ssize );
733
+ pix = 1 ;
734
+ }
735
+
736
+ slot = compute_slot (pte , vpn , index , shift , ssize );
737
+ param [pix ++ ] = HBR_REQUEST | HBLKR_AVPN | slot ;
738
+
739
+ if (pix == PLPAR_HCALL9_BUFSIZE ) {
740
+ pix = call_block_remove (pix , param , false);
741
+ /*
742
+ * pix = 0 means that all the entries were
743
+ * removed, we can start a new block.
744
+ * Otherwise, this means that there are entries
745
+ * to retry, and pix points to latest one, so
746
+ * we should increment it and try to continue
747
+ * the same block.
748
+ */
749
+ if (pix )
750
+ pix ++ ;
751
+ }
752
+ } pte_iterate_hashed_end ();
753
+ }
754
+
755
+ if (pix )
756
+ (void )call_block_remove (pix , param , true);
757
+ }
758
+
567
759
/*
568
760
* Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
569
761
* lock.
@@ -583,6 +775,11 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
583
775
if (lock_tlbie )
584
776
spin_lock_irqsave (& pSeries_lpar_tlbie_lock , flags );
585
777
778
+ if (firmware_has_feature (FW_FEATURE_BLOCK_REMOVE )) {
779
+ do_block_remove (number , batch , param );
780
+ goto out ;
781
+ }
782
+
586
783
psize = batch -> psize ;
587
784
ssize = batch -> ssize ;
588
785
pix = 0 ;
@@ -621,6 +818,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
621
818
BUG_ON (rc != H_SUCCESS );
622
819
}
623
820
821
+ out :
624
822
if (lock_tlbie )
625
823
spin_unlock_irqrestore (& pSeries_lpar_tlbie_lock , flags );
626
824
}
0 commit comments