KVM: PPC: Book3S HV: Prevent POWER7/8 TLB flush flushing SLB
commit cf0b0e3712f7af90006f8317ff27278094c2c128 upstream. The POWER9 ERAT flush instruction is a SLBIA with IH=7, which is a reserved value on POWER7/8. On POWER8 this invalidates the SLB entries above index 0, similarly to SLBIA IH=0. If the SLB entries are invalidated, and then the guest is bypassed, the host SLB does not get re-loaded, so the bolted entries above 0 will be lost. This can result in kernel stack access causing a SLB fault. Kernel stack access causing a SLB fault was responsible for the infamous mega bug (search "Fix SLB reload bug"). Although since commit48e7b76957
("powerpc/64s/hash: Convert SLB miss handlers to C") that starts using the kernel stack in the SLB miss handler, it might only result in an infinite loop of SLB faults. In any case it's a bug. Fix this by only executing the instruction on >= POWER9 where IH=7 is defined not to invalidate the SLB. POWER7/8 don't require this ERAT flush. Fixes:5008711259
("KVM: PPC: Book3S HV: Invalidate ERAT when flushing guest TLB entries") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20211119031627.577853-1-npiggin@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
bfed9c2f2f
commit
b777c866aa
@@ -867,6 +867,7 @@ static void flush_guest_tlb(struct kvm *kvm)
|
|||||||
"r" (0) : "memory");
|
"r" (0) : "memory");
|
||||||
}
|
}
|
||||||
asm volatile("ptesync": : :"memory");
|
asm volatile("ptesync": : :"memory");
|
||||||
|
// POWER9 congruence-class TLBIEL leaves ERAT. Flush it now.
|
||||||
asm volatile(PPC_RADIX_INVALIDATE_ERAT_GUEST : : :"memory");
|
asm volatile(PPC_RADIX_INVALIDATE_ERAT_GUEST : : :"memory");
|
||||||
} else {
|
} else {
|
||||||
for (set = 0; set < kvm->arch.tlb_sets; ++set) {
|
for (set = 0; set < kvm->arch.tlb_sets; ++set) {
|
||||||
@@ -877,7 +878,9 @@ static void flush_guest_tlb(struct kvm *kvm)
|
|||||||
rb += PPC_BIT(51); /* increment set number */
|
rb += PPC_BIT(51); /* increment set number */
|
||||||
}
|
}
|
||||||
asm volatile("ptesync": : :"memory");
|
asm volatile("ptesync": : :"memory");
|
||||||
asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory");
|
// POWER9 congruence-class TLBIEL leaves ERAT. Flush it now.
|
||||||
|
if (cpu_has_feature(CPU_FTR_ARCH_300))
|
||||||
|
asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user