This function processes a gib alert list. It is required to run when either a gib alert interruption has been received or a gisa that might be in the alert list is cleared or dropped. Signed-off-by: Michael Mueller <mimu@xxxxxxxxxxxxx> --- arch/s390/kvm/interrupt.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 487cad95e2c9..920c065ce1d3 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -2900,6 +2900,44 @@ static void nullify_gisa(struct kvm_s390_gisa *gisa) gisa->next_alert = (u32)(u64)gisa; } +/* + * Before processing, the gib alert list needs to be cut-off from + * the gib by means of function unlink_gib_alert_list(). If non NULL, + * the list is processed from its latest to oldest entry. + * + * Processing an gisa entry needs to wake-up a vcpu of the kvm this gisa + * belongs to. Thus, the pending guest interruption will be processed + * in SIE context. + * + * Whenever a gisa is cleared (e.g. on vm reset) or a gisa is dropped + * (e.g. on vm termination) it might be part of the gib alert list. + * Thus, these operations need to process the alert list as well. + */ +static void __maybe_unused process_gib_alert_list( + struct kvm_s390_gisa *gisa, + struct kvm_s390_gisa *gisa_to_nullify, + struct kvm_s390_gisa *gisa_to_drop) +{ + struct kvm_s390_gisa *next_alert; + struct kvm *kvm; + + for (; gisa; gisa = next_alert) { + next_alert = (struct kvm_s390_gisa *)(u64)gisa->next_alert; + /* unlink from alert list */ + gisa->next_alert = (u32)(u64)gisa; + /* skip if to clear or drop */ + if (gisa == gisa_to_nullify || + gisa == gisa_to_drop) + continue; + /* wake-up a vcpu of the kvm this gisa belongs to */ + kvm = container_of(gisa, struct sie_page2, gisa)->kvm; + __floating_irq_kick(kvm, KVM_S390_INT_IO(1, 0, 0, 0)); + } + + if (gisa_to_nullify) + nullify_gisa(gisa_to_nullify); +} + void kvm_s390_gisa_clear(struct kvm *kvm) { if (kvm->arch.gisa) { -- 2.17.0