KVM: PPC: Book3S HV: Prevent POWER7/8 TLB flush flushing SLB

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 commit
48e7b7695745 ("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: 500871125920 ("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

authored by Nicholas Piggin and committed by Michael Ellerman cf0b0e37 13605725

+4 -1
+4 -1
arch/powerpc/kvm/book3s_hv_builtin.c
··· 695 695 "r" (0) : "memory"); 696 696 } 697 697 asm volatile("ptesync": : :"memory"); 698 + // POWER9 congruence-class TLBIEL leaves ERAT. Flush it now. 698 699 asm volatile(PPC_RADIX_INVALIDATE_ERAT_GUEST : : :"memory"); 699 700 } else { 700 701 for (set = 0; set < kvm->arch.tlb_sets; ++set) { ··· 706 705 rb += PPC_BIT(51); /* increment set number */ 707 706 } 708 707 asm volatile("ptesync": : :"memory"); 709 - asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory"); 708 + // POWER9 congruence-class TLBIEL leaves ERAT. Flush it now. 709 + if (cpu_has_feature(CPU_FTR_ARCH_300)) 710 + asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory"); 710 711 } 711 712 } 712 713