@@ -417,24 +417,137 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
417417 BUG_ON (lpar_rc != H_SUCCESS );
418418}
419419
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+
420493#ifdef CONFIG_TRANSPARENT_HUGEPAGE
421494/*
422495 * Limit iterations holding pSeries_lpar_tlbie_lock to 3. We also need
423496 * to make sure that we avoid bouncing the hypervisor tlbie lock.
424497 */
425498#define PPC64_HUGE_HPTE_BATCH 12
426499
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 )
430502{
431503 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 ;
435506
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 ;
438551
439552 for (i = 0 ; i < count ; i ++ ) {
440553
@@ -462,6 +575,23 @@ static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot,
462575 param [6 ], param [7 ]);
463576 BUG_ON (rc != H_SUCCESS );
464577 }
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 );
465595
466596 if (lock_tlbie )
467597 spin_unlock_irqrestore (& pSeries_lpar_tlbie_lock , flags );
@@ -564,6 +694,68 @@ static inline unsigned long compute_slot(real_pte_t pte,
564694 return slot ;
565695}
566696
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+
567759/*
568760 * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
569761 * lock.
@@ -583,6 +775,11 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
583775 if (lock_tlbie )
584776 spin_lock_irqsave (& pSeries_lpar_tlbie_lock , flags );
585777
778+ if (firmware_has_feature (FW_FEATURE_BLOCK_REMOVE )) {
779+ do_block_remove (number , batch , param );
780+ goto out ;
781+ }
782+
586783 psize = batch -> psize ;
587784 ssize = batch -> ssize ;
588785 pix = 0 ;
@@ -621,6 +818,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
621818 BUG_ON (rc != H_SUCCESS );
622819 }
623820
821+ out :
624822 if (lock_tlbie )
625823 spin_unlock_irqrestore (& pSeries_lpar_tlbie_lock , flags );
626824}
0 commit comments