Skip to content

Commit 4ea3c64

Browse files
committed
Merge tag 'powerpc-5.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: - Fix KVM "lost kick" race, where an attempt to pull a vcpu out of the guest could be lost (or delayed until the next guest exit). - Disable SCV (system call vectored) when PR KVM guests could be run. - Fix KVM PR guests using SCV, by disallowing AIL != 0 for KVM PR guests. - Add a new KVM CAP to indicate if AIL == 3 is supported. - Fix a regression when hotplugging a CPU to a memoryless/cpuless node. - Make virt_addr_valid() stricter for 64-bit Book3E & 32-bit, which fixes crashes seen due to hardened usercopy. - Revert a change to max_mapnr which broke HIGHMEM. Thanks to Christophe Leroy, Fabiano Rosas, Kefeng Wang, Nicholas Piggin, and Srikar Dronamraju. * tag 'powerpc-5.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: Revert "powerpc: Set max_mapnr correctly" powerpc: Fix virt_addr_valid() for 64-bit Book3E & 32-bit KVM: PPC: Move kvmhv_on_pseries() into kvm_ppc.h powerpc/numa: Handle partially initialized numa nodes powerpc/64: Fix build failure with allyesconfig in book3s_64_entry.S KVM: PPC: Use KVM_CAP_PPC_AIL_MODE_3 KVM: PPC: Book3S PR: Disallow AIL != 0 KVM: PPC: Book3S PR: Disable SCV when AIL could be disabled KVM: PPC: Book3S HV P9: Fix "lost kick" race
2 parents 1519610 + 1ff5c8e commit 4ea3c64

File tree

15 files changed

+169
-35
lines changed

15 files changed

+169
-35
lines changed

arch/powerpc/include/asm/kvm_book3s_64.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,6 @@
1616
#include <asm/ppc-opcode.h>
1717
#include <asm/pte-walk.h>
1818

19-
#ifdef CONFIG_PPC_PSERIES
20-
static inline bool kvmhv_on_pseries(void)
21-
{
22-
return !cpu_has_feature(CPU_FTR_HVMODE);
23-
}
24-
#else
25-
static inline bool kvmhv_on_pseries(void)
26-
{
27-
return false;
28-
}
29-
#endif
30-
3119
/*
3220
* Structure for a nested guest, that is, for a guest that is managed by
3321
* one of our guests.

arch/powerpc/include/asm/kvm_ppc.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,18 @@ static inline bool kvm_hv_mode_active(void) { return false; }
586586

587587
#endif
588588

589+
#ifdef CONFIG_PPC_PSERIES
590+
static inline bool kvmhv_on_pseries(void)
591+
{
592+
return !cpu_has_feature(CPU_FTR_HVMODE);
593+
}
594+
#else
595+
static inline bool kvmhv_on_pseries(void)
596+
{
597+
return false;
598+
}
599+
#endif
600+
589601
#ifdef CONFIG_KVM_XICS
590602
static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
591603
{

arch/powerpc/include/asm/page.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,11 @@ static inline bool pfn_valid(unsigned long pfn)
132132
#define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
133133
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
134134

135-
#define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr))
135+
#define virt_addr_valid(vaddr) ({ \
136+
unsigned long _addr = (unsigned long)vaddr; \
137+
_addr >= PAGE_OFFSET && _addr < (unsigned long)high_memory && \
138+
pfn_valid(virt_to_pfn(_addr)); \
139+
})
136140

137141
/*
138142
* On Book-E parts we need __va to parse the device tree and we can't

arch/powerpc/include/asm/setup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@ void setup_panic(void);
2828
#define ARCH_PANIC_TIMEOUT 180
2929

3030
#ifdef CONFIG_PPC_PSERIES
31+
extern bool pseries_reloc_on_exception(void);
3132
extern bool pseries_enable_reloc_on_exc(void);
3233
extern void pseries_disable_reloc_on_exc(void);
3334
extern void pseries_big_endian_exceptions(void);
3435
void __init pseries_little_endian_exceptions(void);
3536
#else
37+
static inline bool pseries_reloc_on_exception(void) { return false; }
3638
static inline bool pseries_enable_reloc_on_exc(void) { return false; }
3739
static inline void pseries_disable_reloc_on_exc(void) {}
3840
static inline void pseries_big_endian_exceptions(void) {}

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
@@ -196,6 +196,34 @@ static void __init configure_exceptions(void)
196196

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,10 +414,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_DAWR1)
414414
*/
415415
ld r10,HSTATE_SCRATCH0(r13)
416416
cmpwi r10,BOOK3S_INTERRUPT_MACHINE_CHECK
417-
beq machine_check_common
417+
beq .Lcall_machine_check_common
418418

419419
cmpwi r10,BOOK3S_INTERRUPT_SYSTEM_RESET
420-
beq system_reset_common
420+
beq .Lcall_system_reset_common
421421

422422
b .
423+
424+
.Lcall_machine_check_common:
425+
b machine_check_common
426+
427+
.Lcall_system_reset_common:
428+
b system_reset_common
423429
#endif

arch/powerpc/kvm/book3s_hv.c

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,13 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
225225
int cpu;
226226
struct rcuwait *waitp;
227227

228+
/*
229+
* rcuwait_wake_up contains smp_mb() which orders prior stores that
230+
* create pending work vs below loads of cpu fields. The other side
231+
* is the barrier in vcpu run that orders setting the cpu fields vs
232+
* testing for pending work.
233+
*/
234+
228235
waitp = kvm_arch_vcpu_get_wait(vcpu);
229236
if (rcuwait_wake_up(waitp))
230237
++vcpu->stat.generic.halt_wakeup;
@@ -1089,7 +1096,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
10891096
break;
10901097
}
10911098
tvcpu->arch.prodded = 1;
1092-
smp_mb();
1099+
smp_mb(); /* This orders prodded store vs ceded load */
10931100
if (tvcpu->arch.ceded)
10941101
kvmppc_fast_vcpu_kick_hv(tvcpu);
10951102
break;
@@ -3766,6 +3773,14 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
37663773
pvc = core_info.vc[sub];
37673774
pvc->pcpu = pcpu + thr;
37683775
for_each_runnable_thread(i, vcpu, pvc) {
3776+
/*
3777+
* XXX: is kvmppc_start_thread called too late here?
3778+
* It updates vcpu->cpu and vcpu->arch.thread_cpu
3779+
* which are used by kvmppc_fast_vcpu_kick_hv(), but
3780+
* kick is called after new exceptions become available
3781+
* and exceptions are checked earlier than here, by
3782+
* kvmppc_core_prepare_to_enter.
3783+
*/
37693784
kvmppc_start_thread(vcpu, pvc);
37703785
kvmppc_create_dtl_entry(vcpu, pvc);
37713786
trace_kvm_guest_enter(vcpu);
@@ -4487,6 +4502,21 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
44874502
if (need_resched() || !kvm->arch.mmu_ready)
44884503
goto out;
44894504

4505+
vcpu->cpu = pcpu;
4506+
vcpu->arch.thread_cpu = pcpu;
4507+
vc->pcpu = pcpu;
4508+
local_paca->kvm_hstate.kvm_vcpu = vcpu;
4509+
local_paca->kvm_hstate.ptid = 0;
4510+
local_paca->kvm_hstate.fake_suspend = 0;
4511+
4512+
/*
4513+
* Orders set cpu/thread_cpu vs testing for pending interrupts and
4514+
* doorbells below. The other side is when these fields are set vs
4515+
* kvmppc_fast_vcpu_kick_hv reading the cpu/thread_cpu fields to
4516+
* kick a vCPU to notice the pending interrupt.
4517+
*/
4518+
smp_mb();
4519+
44904520
if (!nested) {
44914521
kvmppc_core_prepare_to_enter(vcpu);
44924522
if (test_bit(BOOK3S_IRQPRIO_EXTERNAL,
@@ -4506,13 +4536,6 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
45064536

45074537
tb = mftb();
45084538

4509-
vcpu->cpu = pcpu;
4510-
vcpu->arch.thread_cpu = pcpu;
4511-
vc->pcpu = pcpu;
4512-
local_paca->kvm_hstate.kvm_vcpu = vcpu;
4513-
local_paca->kvm_hstate.ptid = 0;
4514-
local_paca->kvm_hstate.fake_suspend = 0;
4515-
45164539
__kvmppc_create_dtl_entry(vcpu, pcpu, tb + vc->tb_offset, 0);
45174540

45184541
trace_kvm_guest_enter(vcpu);
@@ -4614,6 +4637,8 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
46144637
run->exit_reason = KVM_EXIT_INTR;
46154638
vcpu->arch.ret = -EINTR;
46164639
out:
4640+
vcpu->cpu = -1;
4641+
vcpu->arch.thread_cpu = -1;
46174642
powerpc_local_irq_pmu_restore(flags);
46184643
preempt_enable();
46194644
goto done;

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)