diff options
author | Paul Mackerras <paulus@samba.org> | 2007-02-06 05:10:31 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-02-06 22:03:23 -0500 |
commit | f03e64f2ca6ee3d0b7824536b1940497701fe766 (patch) | |
tree | b91a2f5d29c7772f0b77a894fe745f3e67dd79bd | |
parent | e56a6e20f3029ed5c178dd0328bd688dbbc8272a (diff) |
[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>
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 51 | ||||
-rw-r--r-- | include/asm-powerpc/hvcall.h | 1 |
2 files changed, 47 insertions, 5 deletions
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 721436db3ef0..5a684fbd8f27 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -502,23 +502,64 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | |||
502 | BUG_ON(lpar_rc != H_SUCCESS); | 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 | * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie | 513 | * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie |
507 | * lock. | 514 | * lock. |
508 | */ | 515 | */ |
509 | static void pSeries_lpar_flush_hash_range(unsigned long number, int local) | 516 | static void pSeries_lpar_flush_hash_range(unsigned long number, int local) |
510 | { | 517 | { |
511 | int i; | 518 | unsigned long i, pix, rc; |
512 | unsigned long flags = 0; | 519 | unsigned long flags; |
513 | struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); | 520 | struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); |
514 | int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); | 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 | if (lock_tlbie) | 528 | if (lock_tlbie) |
517 | spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); | 529 | spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); |
518 | 530 | ||
519 | for (i = 0; i < number; i++) | 531 | psize = batch->psize; |
520 | flush_hash_page(batch->vaddr[i], batch->pte[i], | 532 | pix = 0; |
521 | batch->psize, local); | 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 | if (lock_tlbie) | 564 | if (lock_tlbie) |
524 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); | 565 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); |
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h index 7a500732b671..60977806d2f4 100644 --- a/include/asm-powerpc/hvcall.h +++ b/include/asm-powerpc/hvcall.h | |||
@@ -168,6 +168,7 @@ | |||
168 | #define H_FREE_LOGICAL_LAN 0x118 | 168 | #define H_FREE_LOGICAL_LAN 0x118 |
169 | #define H_ADD_LOGICAL_LAN_BUFFER 0x11C | 169 | #define H_ADD_LOGICAL_LAN_BUFFER 0x11C |
170 | #define H_SEND_LOGICAL_LAN 0x120 | 170 | #define H_SEND_LOGICAL_LAN 0x120 |
171 | #define H_BULK_REMOVE 0x124 | ||
171 | #define H_MULTICAST_CTRL 0x130 | 172 | #define H_MULTICAST_CTRL 0x130 |
172 | #define H_SET_XDABR 0x134 | 173 | #define H_SET_XDABR 0x134 |
173 | #define H_STUFF_TCE 0x138 | 174 | #define H_STUFF_TCE 0x138 |