Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[POWERPC] Make pSeries use the H_BULK_REMOVE hypervisor call

H_BULK_REMOVE lets us remove 4 entries from the MMU hash table with one
hypervisor call. This uses it in pSeries_lpar_hpte_invalidate so we
can tear down mappings with fewer hypervisor calls.

Signed-off-by: Paul Mackerras <paulus@samba.org>

+47 -5
+46 -5
arch/powerpc/platforms/pseries/lpar.c
··· 502 502 BUG_ON(lpar_rc != H_SUCCESS); 503 503 } 504 504 505 + /* Flag bits for H_BULK_REMOVE */ 506 + #define HBR_REQUEST 0x4000000000000000UL 507 + #define HBR_RESPONSE 0x8000000000000000UL 508 + #define HBR_END 0xc000000000000000UL 509 + #define HBR_AVPN 0x0200000000000000UL 510 + #define HBR_ANDCOND 0x0100000000000000UL 511 + 505 512 /* 506 513 * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie 507 514 * lock. 508 515 */ 509 516 static void pSeries_lpar_flush_hash_range(unsigned long number, int local) 510 517 { 511 - int i; 512 - unsigned long flags = 0; 518 + unsigned long i, pix, rc; 519 + unsigned long flags; 513 520 struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); 514 521 int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); 522 + unsigned long param[9]; 523 + unsigned long va; 524 + unsigned long hash, index, shift, hidx, slot; 525 + real_pte_t pte; 526 + int psize; 515 527 516 528 if (lock_tlbie) 517 529 spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); 518 530 519 - for (i = 0; i < number; i++) 520 - flush_hash_page(batch->vaddr[i], batch->pte[i], 521 - batch->psize, local); 531 + psize = batch->psize; 532 + pix = 0; 533 + for (i = 0; i < number; i++) { 534 + va = batch->vaddr[i]; 535 + pte = batch->pte[i]; 536 + pte_iterate_hashed_subpages(pte, psize, va, index, shift) { 537 + hash = hpt_hash(va, shift); 538 + hidx = __rpte_to_hidx(pte, index); 539 + if (hidx & _PTEIDX_SECONDARY) 540 + hash = ~hash; 541 + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; 542 + slot += hidx & _PTEIDX_GROUP_IX; 543 + param[pix] = HBR_REQUEST | HBR_AVPN | slot; 544 + param[pix+1] = hpte_encode_v(va, psize) & HPTE_V_AVPN; 545 + pix += 2; 546 + if (pix == 8) { 547 + rc = plpar_hcall9(H_BULK_REMOVE, param, 548 + param[0], param[1], param[2], 549 + param[3], param[4], param[5], 550 + param[6], param[7]); 551 + BUG_ON(rc != H_SUCCESS); 552 + pix = 0; 553 + } 554 + } pte_iterate_hashed_end(); 555 + } 556 + if (pix) { 557 + param[pix] = HBR_END; 558 + rc = plpar_hcall9(H_BULK_REMOVE, param, param[0], param[1], 559 + param[2], param[3], param[4], param[5], 560 + param[6], param[7]); 561 + BUG_ON(rc != H_SUCCESS); 562 + } 522 563 523 564 if (lock_tlbie) 524 565 spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
+1
include/asm-powerpc/hvcall.h
··· 168 168 #define H_FREE_LOGICAL_LAN 0x118 169 169 #define H_ADD_LOGICAL_LAN_BUFFER 0x11C 170 170 #define H_SEND_LOGICAL_LAN 0x120 171 + #define H_BULK_REMOVE 0x124 171 172 #define H_MULTICAST_CTRL 0x130 172 173 #define H_SET_XDABR 0x134 173 174 #define H_STUFF_TCE 0x138