powerpc/mm: Update tlbiel loop on POWER10
With POWER10, single tlbiel instruction invalidates all the congruence class of the TLB and hence we need to issue only one tlbiel with SET=0. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20201007053305.232879-1-aneesh.kumar@linux.ibm.com
This commit is contained in:
Родитель
a7223f5bfc
Коммит
e80639405c
|
@ -4949,7 +4949,12 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
|
||||||
* Work out how many sets the TLB has, for the use of
|
* Work out how many sets the TLB has, for the use of
|
||||||
* the TLB invalidation loop in book3s_hv_rmhandlers.S.
|
* the TLB invalidation loop in book3s_hv_rmhandlers.S.
|
||||||
*/
|
*/
|
||||||
if (radix_enabled())
|
if (cpu_has_feature(CPU_FTR_ARCH_31)) {
|
||||||
|
/*
|
||||||
|
* P10 will flush all the congruence class with a single tlbiel
|
||||||
|
*/
|
||||||
|
kvm->arch.tlb_sets = 1;
|
||||||
|
} else if (radix_enabled())
|
||||||
kvm->arch.tlb_sets = POWER9_TLB_SETS_RADIX; /* 128 */
|
kvm->arch.tlb_sets = POWER9_TLB_SETS_RADIX; /* 128 */
|
||||||
else if (cpu_has_feature(CPU_FTR_ARCH_300))
|
else if (cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
kvm->arch.tlb_sets = POWER9_TLB_SETS_HASH; /* 256 */
|
kvm->arch.tlb_sets = POWER9_TLB_SETS_HASH; /* 256 */
|
||||||
|
|
|
@ -694,6 +694,7 @@ static void wait_for_sync(struct kvm_split_mode *sip, int phase)
|
||||||
|
|
||||||
void kvmhv_p9_set_lpcr(struct kvm_split_mode *sip)
|
void kvmhv_p9_set_lpcr(struct kvm_split_mode *sip)
|
||||||
{
|
{
|
||||||
|
int num_sets;
|
||||||
unsigned long rb, set;
|
unsigned long rb, set;
|
||||||
|
|
||||||
/* wait for every other thread to get to real mode */
|
/* wait for every other thread to get to real mode */
|
||||||
|
@ -704,11 +705,19 @@ void kvmhv_p9_set_lpcr(struct kvm_split_mode *sip)
|
||||||
mtspr(SPRN_LPID, sip->lpidr_req);
|
mtspr(SPRN_LPID, sip->lpidr_req);
|
||||||
isync();
|
isync();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* P10 will flush all the congruence class with a single tlbiel
|
||||||
|
*/
|
||||||
|
if (cpu_has_feature(CPU_FTR_ARCH_31))
|
||||||
|
num_sets = 1;
|
||||||
|
else
|
||||||
|
num_sets = POWER9_TLB_SETS_RADIX;
|
||||||
|
|
||||||
/* Invalidate the TLB on thread 0 */
|
/* Invalidate the TLB on thread 0 */
|
||||||
if (local_paca->kvm_hstate.tid == 0) {
|
if (local_paca->kvm_hstate.tid == 0) {
|
||||||
sip->do_set = 0;
|
sip->do_set = 0;
|
||||||
asm volatile("ptesync" : : : "memory");
|
asm volatile("ptesync" : : : "memory");
|
||||||
for (set = 0; set < POWER9_TLB_SETS_RADIX; ++set) {
|
for (set = 0; set < num_sets; ++set) {
|
||||||
rb = TLBIEL_INVAL_SET_LPID +
|
rb = TLBIEL_INVAL_SET_LPID +
|
||||||
(set << TLBIEL_INVAL_SET_SHIFT);
|
(set << TLBIEL_INVAL_SET_SHIFT);
|
||||||
asm volatile(PPC_TLBIEL(%0, %1, 0, 0, 0) : :
|
asm volatile(PPC_TLBIEL(%0, %1, 0, 0, 0) : :
|
||||||
|
|
|
@ -56,14 +56,21 @@ static void tlbiel_all_isa300(unsigned int num_sets, unsigned int is)
|
||||||
if (early_cpu_has_feature(CPU_FTR_HVMODE)) {
|
if (early_cpu_has_feature(CPU_FTR_HVMODE)) {
|
||||||
/* MSR[HV] should flush partition scope translations first. */
|
/* MSR[HV] should flush partition scope translations first. */
|
||||||
tlbiel_radix_set_isa300(0, is, 0, RIC_FLUSH_ALL, 0);
|
tlbiel_radix_set_isa300(0, is, 0, RIC_FLUSH_ALL, 0);
|
||||||
for (set = 1; set < num_sets; set++)
|
|
||||||
tlbiel_radix_set_isa300(set, is, 0, RIC_FLUSH_TLB, 0);
|
if (!early_cpu_has_feature(CPU_FTR_ARCH_31)) {
|
||||||
|
for (set = 1; set < num_sets; set++)
|
||||||
|
tlbiel_radix_set_isa300(set, is, 0,
|
||||||
|
RIC_FLUSH_TLB, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush process scoped entries. */
|
/* Flush process scoped entries. */
|
||||||
tlbiel_radix_set_isa300(0, is, 0, RIC_FLUSH_ALL, 1);
|
tlbiel_radix_set_isa300(0, is, 0, RIC_FLUSH_ALL, 1);
|
||||||
for (set = 1; set < num_sets; set++)
|
|
||||||
tlbiel_radix_set_isa300(set, is, 0, RIC_FLUSH_TLB, 1);
|
if (!early_cpu_has_feature(CPU_FTR_ARCH_31)) {
|
||||||
|
for (set = 1; set < num_sets; set++)
|
||||||
|
tlbiel_radix_set_isa300(set, is, 0, RIC_FLUSH_TLB, 1);
|
||||||
|
}
|
||||||
|
|
||||||
ppc_after_tlbiel_barrier();
|
ppc_after_tlbiel_barrier();
|
||||||
}
|
}
|
||||||
|
@ -300,9 +307,11 @@ static __always_inline void _tlbiel_pid(unsigned long pid, unsigned long ric)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For the remaining sets, just flush the TLB */
|
if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
|
||||||
for (set = 1; set < POWER9_TLB_SETS_RADIX ; set++)
|
/* For the remaining sets, just flush the TLB */
|
||||||
__tlbiel_pid(pid, set, RIC_FLUSH_TLB);
|
for (set = 1; set < POWER9_TLB_SETS_RADIX ; set++)
|
||||||
|
__tlbiel_pid(pid, set, RIC_FLUSH_TLB);
|
||||||
|
}
|
||||||
|
|
||||||
ppc_after_tlbiel_barrier();
|
ppc_after_tlbiel_barrier();
|
||||||
asm volatile(PPC_RADIX_INVALIDATE_ERAT_USER "; isync" : : :"memory");
|
asm volatile(PPC_RADIX_INVALIDATE_ERAT_USER "; isync" : : :"memory");
|
||||||
|
|
Загрузка…
Ссылка в новой задаче