Skip to content

Commit 0e6c0f3

Browse files
efarmangregkh
authored andcommitted
KVM: s390: Clarify SIGP orders versus STOP/RESTART
commit 812de04 upstream. With KVM_CAP_S390_USER_SIGP, there are only five Signal Processor orders (CONDITIONAL EMERGENCY SIGNAL, EMERGENCY SIGNAL, EXTERNAL CALL, SENSE, and SENSE RUNNING STATUS) which are intended for frequent use and thus are processed in-kernel. The remainder are sent to userspace with the KVM_CAP_S390_USER_SIGP capability. Of those, three orders (RESTART, STOP, and STOP AND STORE STATUS) have the potential to inject work back into the kernel, and thus are asynchronous. Let's look for those pending IRQs when processing one of the in-kernel SIGP orders, and return BUSY (CC2) if one is in process. This is in agreement with the Principles of Operation, which states that only one order can be "active" on a CPU at a time. Cc: stable@vger.kernel.org Suggested-by: David Hildenbrand <david@redhat.com> Signed-off-by: Eric Farman <farman@linux.ibm.com> Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com> Acked-by: David Hildenbrand <david@redhat.com> Link: https://lore.kernel.org/r/20211213210550.856213-2-farman@linux.ibm.com [borntraeger@linux.ibm.com: add stable tag] Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 413b427 commit 0e6c0f3

4 files changed

Lines changed: 43 additions & 2 deletions

File tree

arch/s390/kvm/interrupt.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,13 @@ int kvm_s390_is_stop_irq_pending(struct kvm_vcpu *vcpu)
21152115
return test_bit(IRQ_PEND_SIGP_STOP, &li->pending_irqs);
21162116
}
21172117

2118+
int kvm_s390_is_restart_irq_pending(struct kvm_vcpu *vcpu)
2119+
{
2120+
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
2121+
2122+
return test_bit(IRQ_PEND_RESTART, &li->pending_irqs);
2123+
}
2124+
21182125
void kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu)
21192126
{
21202127
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;

arch/s390/kvm/kvm-s390.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4588,10 +4588,15 @@ int kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu)
45884588
}
45894589
}
45904590

4591-
/* SIGP STOP and SIGP STOP AND STORE STATUS has been fully processed */
4591+
/*
4592+
* Set the VCPU to STOPPED and THEN clear the interrupt flag,
4593+
* now that the SIGP STOP and SIGP STOP AND STORE STATUS orders
4594+
* have been fully processed. This will ensure that the VCPU
4595+
* is kept BUSY if another VCPU is inquiring with SIGP SENSE.
4596+
*/
4597+
kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOPPED);
45924598
kvm_s390_clear_stop_irq(vcpu);
45934599

4594-
kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOPPED);
45954600
__disable_ibs_on_vcpu(vcpu);
45964601

45974602
for (i = 0; i < online_vcpus; i++) {

arch/s390/kvm/kvm-s390.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ void kvm_s390_destroy_adapters(struct kvm *kvm);
418418
int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu);
419419
extern struct kvm_device_ops kvm_flic_ops;
420420
int kvm_s390_is_stop_irq_pending(struct kvm_vcpu *vcpu);
421+
int kvm_s390_is_restart_irq_pending(struct kvm_vcpu *vcpu);
421422
void kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu);
422423
int kvm_s390_set_irq_state(struct kvm_vcpu *vcpu,
423424
void __user *buf, int len);

arch/s390/kvm/sigp.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,34 @@ static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
288288
if (!dst_vcpu)
289289
return SIGP_CC_NOT_OPERATIONAL;
290290

291+
/*
292+
* SIGP RESTART, SIGP STOP, and SIGP STOP AND STORE STATUS orders
293+
* are processed asynchronously. Until the affected VCPU finishes
294+
* its work and calls back into KVM to clear the (RESTART or STOP)
295+
* interrupt, we need to return any new non-reset orders "busy".
296+
*
297+
* This is important because a single VCPU could issue:
298+
* 1) SIGP STOP $DESTINATION
299+
* 2) SIGP SENSE $DESTINATION
300+
*
301+
* If the SIGP SENSE would not be rejected as "busy", it could
302+
* return an incorrect answer as to whether the VCPU is STOPPED
303+
* or OPERATING.
304+
*/
305+
if (order_code != SIGP_INITIAL_CPU_RESET &&
306+
order_code != SIGP_CPU_RESET) {
307+
/*
308+
* Lockless check. Both SIGP STOP and SIGP (RE)START
309+
* properly synchronize everything while processing
310+
* their orders, while the guest cannot observe a
311+
* difference when issuing other orders from two
312+
* different VCPUs.
313+
*/
314+
if (kvm_s390_is_stop_irq_pending(dst_vcpu) ||
315+
kvm_s390_is_restart_irq_pending(dst_vcpu))
316+
return SIGP_CC_BUSY;
317+
}
318+
291319
switch (order_code) {
292320
case SIGP_SENSE:
293321
vcpu->stat.instruction_sigp_sense++;

0 commit comments

Comments
 (0)