Skip to content

Commit b5149e2

Browse files
npigginmpe
authored andcommitted
KVM: PPC: Book3S PR: Disable SCV when AIL could be disabled
PR KVM does not support running with AIL enabled, and SCV does is not supported with AIL disabled. Fix this by ensuring the SCV facility is disabled with FSCR while a CPU could be running with AIL=0. The PowerNV host supports disabling AIL on a per-CPU basis, so SCV just needs to be disabled when a vCPU is being run. The pSeries machine can only switch AIL on a system-wide basis, so it must disable SCV support at boot if the configuration can potentially run a PR KVM guest. Also ensure a the FSCR[SCV] bit can not be enabled when emulating mtFSCR for the guest. SCV is not emulated for the PR guest at the moment, this just fixes the host crashes. Alternatives considered and rejected: - SCV support can not be disabled by PR KVM after boot, because it is advertised to userspace with HWCAP. - AIL can not be disabled on a per-CPU basis. At least when running on pseries it is a per-LPAR setting. - Support for real-mode SCV vectors will not be added because they are at 0x17000 so making such a large fixed head space causes immediate value limits to be exceeded, requiring a lot rework and more code. - Disabling SCV for any PR KVM possible kernel will cause a slowdown when not using PR KVM. - A boot time option to disable SCV to use PR KVM is user-hostile. - System call instruction emulation for SCV facility unavailable instructions is too complex and old emulation code was subtly broken and removed. Signed-off-by: Nicholas Piggin <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Reviewed-by: Fabiano Rosas <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 04a5b0e commit b5149e2

File tree

4 files changed

+58
-9
lines changed

4 files changed

+58
-9
lines changed

arch/powerpc/kernel/exceptions-64s.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,10 @@ __start_interrupts:
809809
* - MSR_EE|MSR_RI is clear (no reentrant exceptions)
810810
* - Standard kernel environment is set up (stack, paca, etc)
811811
*
812+
* KVM:
813+
* These interrupts do not elevate HV 0->1, so HV is not involved. PR KVM
814+
* ensures that FSCR[SCV] is disabled whenever it has to force AIL off.
815+
*
812816
* Call convention:
813817
*
814818
* syscall register convention is in Documentation/powerpc/syscall64-abi.rst

arch/powerpc/kernel/setup_64.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,34 @@ static void __init configure_exceptions(void)
197197

198198
/* Under a PAPR hypervisor, we need hypercalls */
199199
if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
200+
/*
201+
* - PR KVM does not support AIL mode interrupts in the host
202+
* while a PR guest is running.
203+
*
204+
* - SCV system call interrupt vectors are only implemented for
205+
* AIL mode interrupts.
206+
*
207+
* - On pseries, AIL mode can only be enabled and disabled
208+
* system-wide so when a PR VM is created on a pseries host,
209+
* all CPUs of the host are set to AIL=0 mode.
210+
*
211+
* - Therefore host CPUs must not execute scv while a PR VM
212+
* exists.
213+
*
214+
* - SCV support can not be disabled dynamically because the
215+
* feature is advertised to host userspace. Disabling the
216+
* facility and emulating it would be possible but is not
217+
* implemented.
218+
*
219+
* - So SCV support is blanket disabled if PR KVM could possibly
220+
* run. That is, PR support compiled in, booting on pseries
221+
* with hash MMU.
222+
*/
223+
if (IS_ENABLED(CONFIG_KVM_BOOK3S_PR_POSSIBLE) && !radix_enabled()) {
224+
init_task.thread.fscr &= ~FSCR_SCV;
225+
cur_cpu_spec->cpu_user_features2 &= ~PPC_FEATURE2_SCV;
226+
}
227+
200228
/* Enable AIL if possible */
201229
if (!pseries_enable_reloc_on_exc()) {
202230
init_task.thread.fscr &= ~FSCR_SCV;

arch/powerpc/kvm/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,21 @@ config KVM_BOOK3S_64_PR
112112
guest in user mode (problem state) and emulating all
113113
privileged instructions and registers.
114114

115+
This is only available for hash MMU mode and only supports
116+
guests that use hash MMU mode.
117+
115118
This is not as fast as using hypervisor mode, but works on
116119
machines where hypervisor mode is not available or not usable,
117120
and can emulate processors that are different from the host
118121
processor, including emulating 32-bit processors on a 64-bit
119122
host.
120123

124+
Selecting this option will cause the SCV facility to be
125+
disabled when the kernel is booted on the pseries platform in
126+
hash MMU mode (regardless of PR VMs running). When any PR VMs
127+
are running, "AIL" mode is disabled which may slow interrupts
128+
and system calls on the host.
129+
121130
config KVM_BOOK3S_HV_EXIT_TIMING
122131
bool "Detailed timing for hypervisor real-mode code"
123132
depends on KVM_BOOK3S_HV_POSSIBLE && DEBUG_FS

arch/powerpc/kvm/book3s_pr.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,15 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
137137
svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
138138
svcpu->in_use = 0;
139139
svcpu_put(svcpu);
140-
#endif
141140

142141
/* Disable AIL if supported */
143-
if (cpu_has_feature(CPU_FTR_HVMODE) &&
144-
cpu_has_feature(CPU_FTR_ARCH_207S))
145-
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_AIL);
142+
if (cpu_has_feature(CPU_FTR_HVMODE)) {
143+
if (cpu_has_feature(CPU_FTR_ARCH_207S))
144+
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_AIL);
145+
if (cpu_has_feature(CPU_FTR_ARCH_300) && (current->thread.fscr & FSCR_SCV))
146+
mtspr(SPRN_FSCR, mfspr(SPRN_FSCR) & ~FSCR_SCV);
147+
}
148+
#endif
146149

147150
vcpu->cpu = smp_processor_id();
148151
#ifdef CONFIG_PPC_BOOK3S_32
@@ -165,6 +168,14 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
165168
memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
166169
to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
167170
svcpu_put(svcpu);
171+
172+
/* Enable AIL if supported */
173+
if (cpu_has_feature(CPU_FTR_HVMODE)) {
174+
if (cpu_has_feature(CPU_FTR_ARCH_207S))
175+
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_AIL_3);
176+
if (cpu_has_feature(CPU_FTR_ARCH_300) && (current->thread.fscr & FSCR_SCV))
177+
mtspr(SPRN_FSCR, mfspr(SPRN_FSCR) | FSCR_SCV);
178+
}
168179
#endif
169180

170181
if (kvmppc_is_split_real(vcpu))
@@ -174,11 +185,6 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
174185
kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
175186
kvmppc_save_tm_pr(vcpu);
176187

177-
/* Enable AIL if supported */
178-
if (cpu_has_feature(CPU_FTR_HVMODE) &&
179-
cpu_has_feature(CPU_FTR_ARCH_207S))
180-
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_AIL_3);
181-
182188
vcpu->cpu = -1;
183189
}
184190

@@ -1037,6 +1043,8 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac)
10371043

10381044
void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr)
10391045
{
1046+
if (fscr & FSCR_SCV)
1047+
fscr &= ~FSCR_SCV; /* SCV must not be enabled */
10401048
if ((vcpu->arch.fscr & FSCR_TAR) && !(fscr & FSCR_TAR)) {
10411049
/* TAR got dropped, drop it in shadow too */
10421050
kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);

0 commit comments

Comments
 (0)