diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2007-02-20 19:13:30 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-02-20 19:13:30 +0000 |
commit | 5a84d159061d914c8dd4aa372ac6e9529c2be453 (patch) | |
tree | 9b08af78085334af44414adafe0096276f8fe0ff /arch/powerpc/platforms/pseries/lpar.c | |
parent | e80a0e6e7ccdf64575d4384cb4172860422f5b81 (diff) | |
parent | 7d477a04a619e90ee08724e8f2d8803c6bdfcef8 (diff) | |
download | blackbird-op-linux-5a84d159061d914c8dd4aa372ac6e9529c2be453.tar.gz blackbird-op-linux-5a84d159061d914c8dd4aa372ac6e9529c2be453.zip |
Merge ARM fixes
Diffstat (limited to 'arch/powerpc/platforms/pseries/lpar.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 721436db3ef0..7496005566ef 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -502,23 +502,70 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, BUG_ON(lpar_rc != H_SUCCESS); } +/* Flag bits for H_BULK_REMOVE */ +#define HBR_REQUEST 0x4000000000000000UL +#define HBR_RESPONSE 0x8000000000000000UL +#define HBR_END 0xc000000000000000UL +#define HBR_AVPN 0x0200000000000000UL +#define HBR_ANDCOND 0x0100000000000000UL + /* * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie * lock. */ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) { - int i; + unsigned long i, pix, rc; unsigned long flags = 0; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE); + unsigned long param[9]; + unsigned long va; + unsigned long hash, index, shift, hidx, slot; + real_pte_t pte; + int psize; if (lock_tlbie) spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); - for (i = 0; i < number; i++) - flush_hash_page(batch->vaddr[i], batch->pte[i], - batch->psize, local); + psize = batch->psize; + pix = 0; + for (i = 0; i < number; i++) { + va = batch->vaddr[i]; + pte = batch->pte[i]; + pte_iterate_hashed_subpages(pte, psize, va, index, shift) { + hash = hpt_hash(va, shift); + hidx = __rpte_to_hidx(pte, index); + if (hidx & _PTEIDX_SECONDARY) + hash = ~hash; + slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; + slot += hidx & _PTEIDX_GROUP_IX; + if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) { + pSeries_lpar_hpte_invalidate(slot, va, psize, + local); + } else { + param[pix] = HBR_REQUEST | HBR_AVPN | slot; + param[pix+1] = hpte_encode_v(va, psize) & + HPTE_V_AVPN; + pix += 2; + if (pix == 8) { + rc = plpar_hcall9(H_BULK_REMOVE, param, + param[0], param[1], param[2], + param[3], param[4], param[5], + param[6], param[7]); + BUG_ON(rc != H_SUCCESS); + pix = 0; + } + } + } pte_iterate_hashed_end(); + } + if (pix) { + param[pix] = HBR_END; + rc = plpar_hcall9(H_BULK_REMOVE, param, param[0], param[1], + param[2], param[3], param[4], param[5], + param[6], param[7]); + BUG_ON(rc != H_SUCCESS); + } if (lock_tlbie) spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); |