Re: [PATCH 1/2] KVM: s390: Fix lpsw/e breaking event handling

Heiko Carstens
2026-04-15T10:59:33Z

On Mon, Mar 23, 2026 at 03:35:22PM +0000, Janosch Frank wrote:
> LPSW and LPSWE need to set the gbea on completion but currently don't.
> Time to fix this up.
>
> LPSWEY was designed to not set the bear.
>
> Fixes: 48a3e950f4cee ("KVM: s390: Add support for machine checks.")
> Reported-by: Christian Borntraeger <borntraeger@linux.ibm.com>
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> ---
> arch/s390/kvm/priv.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
> index a3250ad83a8e..cc0553da14cb 100644
> --- a/arch/s390/kvm/priv.c
> +++ b/arch/s390/kvm/priv.c
> @@ -714,12 +714,13 @@ int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu)
> {
> psw_t *gpsw = &vcpu->arch.sie_block->gpsw;
> psw32_t new_psw;
> - u64 addr;
> + u64 addr, iaddr;
> int rc;
> u8 ar;
>
> vcpu->stat.instruction_lpsw++;
>
> + iaddr = gpsw->addr - kvm_s390_get_ilen(vcpu);
> if (gpsw->mask & PSW_MASK_PSTATE)
> return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
>
> @@ -737,18 +738,20 @@ int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu)
> gpsw->addr = new_psw.addr & ~PSW32_ADDR_AMODE;
> if (!is_valid_psw(gpsw))
> return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
> + vcpu->arch.sie_block->gbea = iaddr;
> return 0;

This doesn't look correct to me: even if there is an early specification
exception the PSW is still replaced, and hence the breaking event address
needs to be updated. Read: the gbea assignment should be moved before
the is_valid_psw() check.

> static int handle_lpswe(struct kvm_vcpu *vcpu)
> {
> psw_t new_psw;
> - u64 addr;
> + u64 addr, iaddr;
> int rc;

This breaks reverse x-mas style. :)

> @@ -761,6 +764,7 @@ static int handle_lpswe(struct kvm_vcpu *vcpu)
> vcpu->arch.sie_block->gpsw = new_psw;
> if (!is_valid_psw(&vcpu->arch.sie_block->gpsw))
> return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
> + vcpu->arch.sie_block->gbea = iaddr;
> return 0;

Like above, I believe this is not correct.