staticinlineunsignedlong ___tlbie(unsignedlong vpn, int psize, int apsize, int ssize)
{ unsignedlong va; unsignedint penc; unsignedlong sllp;
/* *Weneed14to65bitsofvaforatlibeof4Kpage *WithvpnweignorethelowerVPN_SHIFTbitsalready. *Andtoptwobitsarealreadyignoredbecausewecan *onlyaccomodate76bitsina64bitvpnwithaVPN_SHIFT *of12.
*/
va = vpn << VPN_SHIFT; /* *cleartop16bitsof64bitva,nonSLSsegment *Olderversionsofthearchitecture(2.02andearler)requirethe *maskingofthetop16bits.
*/ if (mmu_has_feature(MMU_FTR_TLBIE_CROP_VA))
va &= ~(0xffffULL << 48);
switch (psize) { case MMU_PAGE_4K: /* clear out bits after (52) [0....52.....63] */
va &= ~((1ul << (64 - 52)) - 1);
va |= ssize << 8;
sllp = get_sllp_encoding(apsize);
va |= sllp << 5; asmvolatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2)
: : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
: "memory"); break; default: /* We need 14 to 14 + i bits of va */
penc = mmu_psize_defs[psize].penc[apsize];
va &= ~((1ul << mmu_psize_defs[apsize].shift) - 1);
va |= penc << 12;
va |= ssize << 8; /* *AVALbits: *Wedon'tneedallthebits,butrestofthebits *mustbeignoredbytheprocessor. *vpncoverupto65bitsofva.(0...65)andweneed *58..64bitsofva.
*/
va |= (vpn & 0xfe); /* AVAL */
va |= 1; /* L */ asmvolatile(ASM_FTR_IFCLR("tlbie %0,1", PPC_TLBIE(%1,%0), %2)
: : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
: "memory"); break;
} return va;
}
staticinlinevoid fixup_tlbie_vpn(unsignedlong vpn, int psize, int apsize, int ssize)
{ if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) { /* Radix flush for a hash guest */
if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) { /* Need the extra ptesync to ensure we don't reorder tlbie*/ asmvolatile("ptesync": : :"memory");
___tlbie(vpn, psize, apsize, ssize);
}
}
staticinlinevoid __tlbie(unsignedlong vpn, int psize, int apsize, int ssize)
{ unsignedlong rb;
staticinlinevoid __tlbiel(unsignedlong vpn, int psize, int apsize, int ssize)
{ unsignedlong va; unsignedint penc; unsignedlong sllp;
/* VPN_SHIFT can be atmost 12 */
va = vpn << VPN_SHIFT; /* *cleartop16bitsof64bitva,nonSLSsegment *Olderversionsofthearchitecture(2.02andearler)requirethe *maskingofthetop16bits.
*/ if (mmu_has_feature(MMU_FTR_TLBIE_CROP_VA))
va &= ~(0xffffULL << 48);
switch (psize) { case MMU_PAGE_4K: /* clear out bits after(52) [0....52.....63] */
va &= ~((1ul << (64 - 52)) - 1);
va |= ssize << 8;
sllp = get_sllp_encoding(apsize);
va |= sllp << 5; asmvolatile(ASM_FTR_IFSET("tlbiel %0", PPC_TLBIEL_v205(%0, 0), %1)
: : "r" (va), "i" (CPU_FTR_ARCH_206)
: "memory"); break; default: /* We need 14 to 14 + i bits of va */
penc = mmu_psize_defs[psize].penc[apsize];
va &= ~((1ul << mmu_psize_defs[apsize].shift) - 1);
va |= penc << 12;
va |= ssize << 8; /* *AVALbits: *Wedon'tneedallthebits,butrestofthebits *mustbeignoredbytheprocessor. *vpncoverupto65bitsofva.(0...65)andweneed *58..64bitsofva.
*/
va |= (vpn & 0xfe);
va |= 1; /* L */ asmvolatile(ASM_FTR_IFSET("tlbiel %0", PPC_TLBIEL_v205(%0, 1), %1)
: : "r" (va), "i" (CPU_FTR_ARCH_206)
: "memory"); break;
}
trace_tlbie(0, 1, va, 0, 0, 0, 0);
}
staticinlinevoid tlbie(unsignedlong vpn, int psize, int apsize, int ssize, int local)
{ unsignedint use_local = local && mmu_has_feature(MMU_FTR_TLBIEL); int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
for (i = 0; i < HPTES_PER_GROUP; i++) { if (! (be64_to_cpu(hptep->v) & HPTE_V_VALID)) { /* retry with lock held */
native_lock_hpte(hptep); if (! (be64_to_cpu(hptep->v) & HPTE_V_VALID)) break;
native_unlock_hpte(hptep);
}
hptep++;
}
if (i == HPTES_PER_GROUP) {
local_irq_restore(flags); return -1;
}
hptep->r = cpu_to_be64(hpte_r); /* Guarantee the second dword is visible before the valid bit */
eieio(); /* *Nowsetthefirstdwordincludingthevalidbit *NOTE:thisalsounlocksthehpte
*/
release_hpte_lock();
hptep->v = cpu_to_be64(hpte_v);
__asm__ __volatile__ ("ptesync" : : : "memory");
local_irq_restore(flags);
return i | (!!(vflags & HPTE_V_SECONDARY) << 3);
}
staticlong native_hpte_remove(unsignedlong hpte_group)
{ unsignedlong hpte_v, flags; struct hash_pte *hptep; int i; int slot_offset;
local_irq_save(flags);
DBG_LOW(" remove(group=%lx)\n", hpte_group);
/* pick a random entry to start at */
slot_offset = mftb() & 0x7;
for (i = 0; i < HPTES_PER_GROUP; i++) {
hptep = htab_address + hpte_group + slot_offset;
hpte_v = be64_to_cpu(hptep->v);
if ((hpte_v & HPTE_V_VALID) && !(hpte_v & HPTE_V_BOLTED)) { /* retry with lock held */
native_lock_hpte(hptep);
hpte_v = be64_to_cpu(hptep->v); if ((hpte_v & HPTE_V_VALID)
&& !(hpte_v & HPTE_V_BOLTED)) break;
native_unlock_hpte(hptep);
}
slot_offset++;
slot_offset &= 0x7;
}
if (i == HPTES_PER_GROUP) {
i = -1; goto out;
}
/* Invalidate the hpte. NOTE: this also unlocks it */
release_hpte_lock();
hptep->v = 0;
out:
local_irq_restore(flags); return i;
}
staticlong native_hpte_updatepp(unsignedlong slot, unsignedlong newpp, unsignedlong vpn, int bpsize, int apsize, int ssize, unsignedlong flags)
{ struct hash_pte *hptep = htab_address + slot; unsignedlong hpte_v, want_v; int ret = 0, local = 0; unsignedlong irqflags;
/* Even if we miss, we need to invalidate the TLB */ if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) { /* recheck with locks held */
native_lock_hpte(hptep);
hpte_v = hpte_get_old_v(hptep);
if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) { /* Invalidate the hpte. NOTE: this also unlocks it */
release_hpte_lock();
hptep->v = 0;
} else
native_unlock_hpte(hptep);
} /* *Weneedtodotlbinvalidateforalltheaddress,tlbie *instructioncomparesentry_VAintlbwiththeVAspecified *here
*/
tlbie(vpn, psize, actual_psize, ssize, local);
}
local_irq_restore(flags);
} #else staticvoid native_hugepage_invalidate(unsignedlong vsid, unsignedlong addr, unsignedchar *hpte_slot_array, int psize, int ssize, int local)
{
WARN(1, "%s called without THP support\n", __func__);
} #endif
staticvoid hpte_decode(struct hash_pte *hpte, unsignedlong slot, int *psize, int *apsize, int *ssize, unsignedlong *vpn)
{ unsignedlong avpn, pteg, vpi; unsignedlong hpte_v = be64_to_cpu(hpte->v); unsignedlong hpte_r = be64_to_cpu(hpte->r); unsignedlong vsid, seg_off; int size, a_size, shift; /* Look at the 8 bit LP value */ unsignedint lp = (hpte_r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
if (cpu_has_feature(CPU_FTR_ARCH_300)) {
hpte_v = hpte_new_to_old_v(hpte_v, hpte_r);
hpte_r = hpte_new_to_old_r(hpte_r);
} if (!(hpte_v & HPTE_V_LARGE)) {
size = MMU_PAGE_4K;
a_size = MMU_PAGE_4K;
} else {
size = hpte_page_sizes[lp] & 0xf;
a_size = hpte_page_sizes[lp] >> 4;
} /* This works for all page sizes, and for 256M and 1T segments */
*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
shift = mmu_psize_defs[size].shift;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.