All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christian Borntraeger <borntraeger@de.ibm.com>
To: Claudio Imbrenda <imbrenda@linux.ibm.com>, linux-kernel@vger.kernel.org
Cc: kvm@vger.kernel.org, linux-s390@vger.kernel.org,
	frankja@linux.ibm.com, david@kernel.org, seiden@linux.ibm.com,
	nrb@linux.ibm.com, schlameuss@linux.ibm.com, gra@linux.ibm.com
Subject: Re: [PATCH v1 03/11] KVM: s390: Fix get_all_floating_irqs()
Date: Wed, 12 Aug 2026 09:11:11 +0200	[thread overview]
Message-ID: <6cc80fa3-f506-4fff-970a-2cbd66d9ce49@de.ibm.com> (raw)
In-Reply-To: <20260811155641.219777-4-imbrenda@linux.ibm.com>

Am 11.08.26 um 17:56 schrieb Claudio Imbrenda:
> When attempting to report all pending floating interrupt to userspace,
> the GISA IPM bits are atomically tested and cleared, and the
> corresponding interrupt description is written in the output buffer. If
> the output buffer is too small, an error is returned to userspace, but
> the GISA IPM bits are now lost.
> 
> Fix by moving the GISA test at the end of the function, and keeping
> track of which bits have been cleared. In case of error, set the bits
> again, so they are not lost.
> 
> Fixes: 24160af6cb28 ("KVM: s390: add GISA interrupts to FLIC ioctl interface")
> Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>

this looks too complicated for a fix. Now what is the semantic of this?
This is used for migration purposes, and the doc says:

Documentation/virt/kvm/devices/s390_flic.rst

   KVM_DEV_FLIC_GET_ALL_IRQS
     Copies all floating interrupts into a buffer provided by userspace.
[...]
     All interrupts remain pending, i.e. are not deleted from the list of
     currently pending interrupts.
[...]

So even the success case is wrong. Why not simply add a new helper that
reads the GISA without clearing the bits?

static inline int gisa_test_ipm_gisc(struct kvm_s390_gisa *gisa, u32 gisc)
{
       return test_bit_inv(IPM_BIT_OFFSET + gisc, (unsigned long *) gisa);
}




> ---
>   arch/s390/kvm/interrupt.c | 93 ++++++++++++++++++---------------------
>   1 file changed, 44 insertions(+), 49 deletions(-)
> 
> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> index 6b3f97a7513b..30963e05e0e6 100644
> --- a/arch/s390/kvm/interrupt.c
> +++ b/arch/s390/kvm/interrupt.c
> @@ -2211,15 +2211,14 @@ void kvm_s390_clear_float_irqs(struct kvm *kvm)
>   static int get_all_floating_irqs(struct kvm *kvm, u8 __user *usrbuf, u64 len)
>   {
>   	struct kvm_s390_gisa_interrupt *gi = &kvm->arch.gisa_int;
> +	struct kvm_s390_irq *buf __free(kvfree) = NULL;
>   	struct kvm_s390_interrupt_info *inti;
>   	struct kvm_s390_float_interrupt *fi;
> -	struct kvm_s390_irq *buf;
>   	struct kvm_s390_irq *irq;
> +	unsigned int tmp = 0;
>   	int max_irqs;
> -	int ret = 0;
>   	int n = 0;
>   	int i;
> -	unsigned long flags;
>   
>   	if (len > KVM_S390_FLIC_MAX_BUFFER || len == 0)
>   		return -EINVAL;
> @@ -2235,14 +2234,48 @@ static int get_all_floating_irqs(struct kvm *kvm, u8 __user *usrbuf, u64 len)
>   
>   	max_irqs = len / sizeof(struct kvm_s390_irq);
>   
> +	fi = &kvm->arch.float_int;
> +	scoped_guard(spinlock_irqsave, &fi->lock) {
> +		for (i = 0; i < FIRQ_LIST_COUNT; i++) {
> +			list_for_each_entry(inti, &fi->lists[i], list) {
> +				/* signal userspace to try again */
> +				if (n == max_irqs)
> +					return -ENOMEM;
> +				inti_to_irq(inti, &buf[n]);
> +				n++;
> +			}
> +		}
> +		if (test_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs) ||
> +		    test_bit(IRQ_PEND_EXT_SERVICE_EV, &fi->pending_irqs)) {
> +			/* signal userspace to try again */
> +			if (n == max_irqs)
> +				return -ENOMEM;
> +			irq = (struct kvm_s390_irq *)&buf[n];
> +			irq->type = KVM_S390_INT_SERVICE;
> +			irq->u.ext = fi->srv_signal;
> +			n++;
> +		}
> +		if (test_bit(IRQ_PEND_MCHK_REP, &fi->pending_irqs)) {
> +			/* signal userspace to try again */
> +			if (n == max_irqs)
> +				return -ENOMEM;
> +			irq = (struct kvm_s390_irq *)&buf[n];
> +			irq->type = KVM_S390_MCHK;
> +			irq->u.mchk = fi->mchk;
> +			n++;
> +		}
> +	}
>   	if (gi->origin && gisa_get_ipm(gi->origin)) {
>   		for (i = 0; i <= MAX_ISC; i++) {
>   			if (n == max_irqs) {
> +				/* restore removed bits if returning failure */
> +				__atomic_or(tmp, (void *)&gi->origin->ipm);
>   				/* signal userspace to try again */
> -				ret = -ENOMEM;
> -				goto out_nolock;
> +				return -ENOMEM;
>   			}
>   			if (gisa_tac_ipm_gisc(gi->origin, i)) {
> +				/* set aside the bits we cleared */
> +				tmp |= 1 << (31 - i);
>   				irq = (struct kvm_s390_irq *) &buf[n];
>   				irq->type = KVM_S390_INT_IO(1, 0, 0, 0);
>   				irq->u.io.io_int_word = isc_to_int_word(i);
> @@ -2250,53 +2283,15 @@ static int get_all_floating_irqs(struct kvm *kvm, u8 __user *usrbuf, u64 len)
>   			}
>   		}
>   	}
> -	fi = &kvm->arch.float_int;
> -	spin_lock_irqsave(&fi->lock, flags);
> -	for (i = 0; i < FIRQ_LIST_COUNT; i++) {
> -		list_for_each_entry(inti, &fi->lists[i], list) {
> -			if (n == max_irqs) {
> -				/* signal userspace to try again */
> -				ret = -ENOMEM;
> -				goto out;
> -			}
> -			inti_to_irq(inti, &buf[n]);
> -			n++;
> -		}
> -	}
> -	if (test_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs) ||
> -	    test_bit(IRQ_PEND_EXT_SERVICE_EV, &fi->pending_irqs)) {
> -		if (n == max_irqs) {
> -			/* signal userspace to try again */
> -			ret = -ENOMEM;
> -			goto out;
> -		}
> -		irq = (struct kvm_s390_irq *) &buf[n];
> -		irq->type = KVM_S390_INT_SERVICE;
> -		irq->u.ext = fi->srv_signal;
> -		n++;
> -	}
> -	if (test_bit(IRQ_PEND_MCHK_REP, &fi->pending_irqs)) {
> -		if (n == max_irqs) {
> -				/* signal userspace to try again */
> -				ret = -ENOMEM;
> -				goto out;
> -		}
> -		irq = (struct kvm_s390_irq *) &buf[n];
> -		irq->type = KVM_S390_MCHK;
> -		irq->u.mchk = fi->mchk;
> -		n++;
> -}
>   
> -out:
> -	spin_unlock_irqrestore(&fi->lock, flags);
> -out_nolock:
> -	if (!ret && n > 0) {
> -		if (copy_to_user(usrbuf, buf, sizeof(struct kvm_s390_irq) * n))
> -			ret = -EFAULT;
> +	if (n > 0 && copy_to_user(usrbuf, buf, sizeof(struct kvm_s390_irq) * n)) {
> +		/* restore removed bits if returning failure */
> +		if (tmp)
> +			__atomic_or(tmp, (void *)&gi->origin->ipm);
> +		return -EFAULT;
>   	}
> -	vfree(buf);
>   
> -	return ret < 0 ? ret : n;
> +	return n;
>   }
>   
>   static int flic_ais_mode_get_all(struct kvm *kvm, struct kvm_device_attr *attr)


  reply	other threads:[~2026-08-12  7:11 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-11 15:56 [PATCH v1 00/11] KVM: s390: And then... even more fixes again Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 01/11] KVM: s390: Properly handle NULL pointer in dat_cond_set_storage_key() Claudio Imbrenda
2026-08-12  7:02   ` Christian Borntraeger
2026-08-12  8:06   ` Christoph Schlameuss
2026-08-11 15:56 ` [PATCH v1 02/11] KVM: s390: Use srcu in kvm_arch_vcpu_unlocked_ioctl() Claudio Imbrenda
2026-08-11 17:26   ` Christian Borntraeger
2026-08-11 18:01     ` Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 03/11] KVM: s390: Fix get_all_floating_irqs() Claudio Imbrenda
2026-08-12  7:11   ` Christian Borntraeger [this message]
2026-08-12  9:12     ` Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 04/11] KVM: s390: Fix dirty marking in adapter_indicators_set*() Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 05/11] KVM: s390: Fix pgste_get_trylock_multiple() Claudio Imbrenda
2026-08-11 17:07   ` Christian Borntraeger
2026-08-11 15:56 ` [PATCH v1 06/11] KVM: s390: Introduce extended topup for struct kvm_s390_mmu_cache Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 07/11] KVM: s390: Move all code into kvm_arch_prepare_memory_region() Claudio Imbrenda
2026-08-12  8:39   ` Christian Borntraeger
2026-08-11 15:56 ` [PATCH v1 08/11] KVM: s390: Fix IRQ injection with SIGP Stop and Store Status Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 09/11] KVM: s390: Fix kvm_s390_clear_pv_state() Claudio Imbrenda
2026-08-12  7:22   ` Christian Borntraeger
2026-08-12  8:07   ` Christian Borntraeger
2026-08-11 15:56 ` [PATCH v1 10/11] KVM: s390: Fix potential tiny kernel stack leak Claudio Imbrenda
2026-08-11 17:03   ` Christian Borntraeger
2026-08-11 15:56 ` [PATCH v1 11/11] KVM: s390: Fix _gaccess_shadow_fault() Claudio Imbrenda

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6cc80fa3-f506-4fff-970a-2cbd66d9ce49@de.ibm.com \
    --to=borntraeger@de.ibm.com \
    --cc=david@kernel.org \
    --cc=frankja@linux.ibm.com \
    --cc=gra@linux.ibm.com \
    --cc=imbrenda@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=nrb@linux.ibm.com \
    --cc=schlameuss@linux.ibm.com \
    --cc=seiden@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.