public inbox for linux-s390@vger.kernel.org
 help / color / mirror / Atom feed
From: Janosch Frank <frankja@linux.ibm.com>
To: kvm@vger.kernel.org
Cc: linux-s390@vger.kernel.org, imbrenda@linux.ibm.com,
	borntraeger@linux.ibm.com
Subject: [PATCH 2/2] KVM: s390: selftests: Add load psw bear test
Date: Mon, 23 Mar 2026 15:35:23 +0000	[thread overview]
Message-ID: <20260323153637.3683-3-frankja@linux.ibm.com> (raw)
In-Reply-To: <20260323153637.3683-1-frankja@linux.ibm.com>

The bear is set for lpsw and lpswe but not for lpswey.

Load PSW and all of its variants are only emulated by KVM if there's a
pending machine check. Therefore the tests inject those but never open
the masks to receive them.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
 tools/testing/selftests/kvm/Makefile.kvm |   1 +
 tools/testing/selftests/kvm/s390/bear.c  | 184 +++++++++++++++++++++++
 2 files changed, 185 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/s390/bear.c

diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 6471fa214a9f..9afb6479dbee 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -207,6 +207,7 @@ TEST_GEN_PROGS_s390 += s390/user_operexec
 TEST_GEN_PROGS_s390 += s390/keyop
 TEST_GEN_PROGS_s390 += rseq_test
 TEST_GEN_PROGS_s390 += s390/irq_routing
+TEST_GEN_PROGS_s390 += s390/bear
 
 TEST_GEN_PROGS_riscv = $(TEST_GEN_PROGS_COMMON)
 TEST_GEN_PROGS_riscv += riscv/sbi_pmu_test
diff --git a/tools/testing/selftests/kvm/s390/bear.c b/tools/testing/selftests/kvm/s390/bear.c
new file mode 100644
index 000000000000..fee4999532ae
--- /dev/null
+++ b/tools/testing/selftests/kvm/s390/bear.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * LPSW(E|Y) bear tests.
+ * LPSW and LPSWE do set the bear but LPSWEY doesn't.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+#include "kselftest.h"
+#include "ucall_common.h"
+#include "facility.h"
+
+static void guest_lpswey(void)
+{
+	extern void lpswey_dest_addr(void);
+	u64 psw[2] = {0x0400000180000000ULL, (uintptr_t)lpswey_dest_addr};
+	u64 bear;
+
+	asm volatile (
+		"	larl	%%r3,lpswey_addr\n"
+		"lpswey_addr:\n"
+		"	.insn	siy,0xeb0000000071,%[psw],0\n"
+		"       nop\n"
+		"       nop\n"
+		".globl lpswey_dest_addr \n"
+		"lpswey_dest_addr:\n"
+		"       .insn   s,0xb2010000,%[bear]\n"
+		"	lg	%%r4, %[bear]\n"
+		"       nop\n"
+		"       nop\n"
+		: [bear] "=Q" (bear)
+		: [psw] "T" (psw)
+		: "cc", "r3", "r4"
+		);
+}
+
+static void guest_lpswe(void)
+{
+	extern void lpswe_dest_addr(void);
+	u64 psw[2] = {0x0400000180000000ULL, (uintptr_t)lpswe_dest_addr};
+	u64 bear;
+
+	asm volatile (
+		"	larl	%%r3,lpswe_addr\n"
+		"lpswe_addr:\n"
+		"       lpswe    %[psw]\n"
+		"       nop\n"
+		"       nop\n"
+		".globl lpswe_dest_addr\n"
+		"lpswe_dest_addr:\n"
+		"       .insn   s,0xb2010000,%[bear]\n"
+		"	lg	%%r4, %[bear]\n"
+		"       nop\n"
+		"       nop\n"
+		: [bear] "=Q" (bear)
+		: [psw] "Q" (psw)
+		: "cc", "r3", "r4"
+		);
+}
+
+static void guest_lpsw(void)
+{
+	extern void lpsw_dest_addr(void);
+	u64 psw_short = (0x0400000180000000ULL | BIT(63 - 12) |
+			 (uintptr_t)lpsw_dest_addr);
+	u64 bear;
+
+	asm volatile (
+		"	larl	%%r3,lpsw_addr\n"
+		"lpsw_addr:\n"
+		"       lpsw    %[psw]\n"
+		"       nop\n"
+		"       nop\n"
+		".globl lpsw_dest_addr\n"
+		"lpsw_dest_addr:\n"
+		"       .insn   s,0xb2010000,%[bear]\n"
+		"	lg	%%r4, %[bear]\n"
+		"       nop\n"
+		"       nop\n"
+		: [bear] "=Q" (bear)
+		: [psw] "Q" (psw_short)
+		: "cc", "r3", "r4"
+		);
+}
+
+/* A machine check forces KVM to emulate PSW loading */
+static void inject_mcheck(struct kvm_vcpu *vcpu)
+{
+	struct kvm_s390_irq irq = {};
+	int irqs;
+
+	irq.type = KVM_S390_MCHK;
+	/* External damage mcheck */
+	irq.u.mchk.cr14 = BIT(63 - 38);
+	irq.u.mchk.mcic = BIT(58);
+	irqs = __vcpu_ioctl(vcpu, KVM_S390_IRQ, &irq);
+	TEST_ASSERT(irqs >= 0, "Error injecting MCHECK errno %d", errno);
+}
+
+static void test_lpswey(void)
+{
+	struct kvm_vcpu *vcpu;
+	struct kvm_run *run;
+	struct kvm_vm *vm;
+
+	vm = vm_create_with_one_vcpu(&vcpu, guest_lpswey);
+	inject_mcheck(vcpu);
+	run = vcpu->run;
+	vcpu_run(vcpu);
+	ksft_test_result(run->s.regs.gprs[3] != run->s.regs.gprs[4],
+			 "emulation: lpswey bear does not match\n");
+	kvm_vm_free(vm);
+
+	vm = vm_create_with_one_vcpu(&vcpu, guest_lpswey);
+	run = vcpu->run;
+	vcpu_run(vcpu);
+	ksft_test_result(run->s.regs.gprs[3] &&
+			 run->s.regs.gprs[3] != run->s.regs.gprs[4],
+			 "interpretation: lpswey bear does not match\n");
+	kvm_vm_free(vm);
+}
+
+static void test_lpswe(void)
+{
+	struct kvm_vcpu *vcpu;
+	struct kvm_run *run;
+	struct kvm_vm *vm;
+
+	vm = vm_create_with_one_vcpu(&vcpu, guest_lpswe);
+	inject_mcheck(vcpu);
+	run = vcpu->run;
+	vcpu_run(vcpu);
+	ksft_test_result(run->s.regs.gprs[3] == run->s.regs.gprs[4],
+			 "emulation: lpswe bear matches\n");
+	kvm_vm_free(vm);
+
+	vm = vm_create_with_one_vcpu(&vcpu, guest_lpsw);
+	run = vcpu->run;
+	vcpu_run(vcpu);
+	ksft_test_result(run->s.regs.gprs[3] &&
+			 run->s.regs.gprs[3] == run->s.regs.gprs[4],
+			 "interpretation: lpswe bear matches\n");
+	kvm_vm_free(vm);
+}
+
+static void test_lpsw(void)
+{
+	struct kvm_vcpu *vcpu;
+	struct kvm_run *run;
+	struct kvm_vm *vm;
+
+	vm = vm_create_with_one_vcpu(&vcpu, guest_lpsw);
+	inject_mcheck(vcpu);
+	run = vcpu->run;
+	vcpu_run(vcpu);
+	ksft_test_result(run->s.regs.gprs[3] == run->s.regs.gprs[4],
+			 "emulation: lpsw bear matches\n");
+	kvm_vm_free(vm);
+
+	vm = vm_create_with_one_vcpu(&vcpu, guest_lpsw);
+	run = vcpu->run;
+	vcpu_run(vcpu);
+	ksft_test_result(run->s.regs.gprs[3] &&
+			 run->s.regs.gprs[3] == run->s.regs.gprs[4],
+			 "interpretation: lpsw bear matches\n");
+	kvm_vm_free(vm);
+}
+
+int main(int argc, char *argv[])
+{
+	TEST_REQUIRE(test_facility(193));
+
+	ksft_print_header();
+	ksft_set_plan(6);
+	test_lpsw();
+	test_lpswe();
+	test_lpswey();
+	ksft_finished();
+}
-- 
2.51.0


  parent reply	other threads:[~2026-03-23 15:36 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-23 15:35 [PATCH 0/2] KVM: s390: Fix lpsw/e breaking event handling Janosch Frank
2026-03-23 15:35 ` [PATCH 1/2] " Janosch Frank
2026-03-25  7:51   ` Christian Borntraeger
2026-03-25 12:00   ` Claudio Imbrenda
2026-03-23 15:35 ` Janosch Frank [this message]
2026-03-25  8:49   ` [PATCH 2/2] KVM: s390: selftests: Add load psw bear test Christian Borntraeger
2026-03-25 10:29   ` Christian Borntraeger
2026-03-25 13:15     ` Janosch Frank
2026-03-25 13:19   ` [PATCH v2] " Janosch Frank

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=20260323153637.3683-3-frankja@linux.ibm.com \
    --to=frankja@linux.ibm.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=imbrenda@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox