File Index
Files and directories
Sign in
FILE

user_operexec.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/kvm/s390/user_operexec.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* Test operation exception forwarding.
  3 *
  4 * Copyright IBM Corp. 2025
  5 *
  6 * Authors:
  7 *  Janosch Frank <frankja@linux.ibm.com>
  8 */
  9#include "kselftest.h"
 10#include "kvm_util.h"
 11#include "test_util.h"
 12#include "sie.h"
 13
 14#include <linux/kvm.h>
 15
 16static void guest_code_instr0(void)
 17{
 18	asm(".word 0x0000");
 19}
 20
 21static void test_user_instr0(void)
 22{
 23	struct kvm_vcpu *vcpu;
 24	struct kvm_vm *vm;
 25	int rc;
 26
 27	vm = vm_create_with_one_vcpu(&vcpu, guest_code_instr0);
 28	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_INSTR0, 0);
 29	TEST_ASSERT_EQ(0, rc);
 30
 31	vcpu_run(vcpu);
 32	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
 33	TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, ICPT_OPEREXC);
 34	TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0);
 35
 36	kvm_vm_free(vm);
 37}
 38
 39static void guest_code_user_operexec(void)
 40{
 41	asm(".word 0x0807");
 42}
 43
 44static void test_user_operexec(void)
 45{
 46	struct kvm_vcpu *vcpu;
 47	struct kvm_vm *vm;
 48	int rc;
 49
 50	vm = vm_create_with_one_vcpu(&vcpu, guest_code_user_operexec);
 51	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_OPEREXEC, 0);
 52	TEST_ASSERT_EQ(0, rc);
 53
 54	vcpu_run(vcpu);
 55	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
 56	TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, ICPT_OPEREXC);
 57	TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0x0807);
 58
 59	kvm_vm_free(vm);
 60
 61	/*
 62	 * Since user_operexec is the superset it can be used for the
 63	 * 0 instruction.
 64	 */
 65	vm = vm_create_with_one_vcpu(&vcpu, guest_code_instr0);
 66	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_OPEREXEC, 0);
 67	TEST_ASSERT_EQ(0, rc);
 68
 69	vcpu_run(vcpu);
 70	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
 71	TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, ICPT_OPEREXC);
 72	TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0);
 73
 74	kvm_vm_free(vm);
 75}
 76
 77/* combine user_instr0 and user_operexec */
 78static void test_user_operexec_combined(void)
 79{
 80	struct kvm_vcpu *vcpu;
 81	struct kvm_vm *vm;
 82	int rc;
 83
 84	vm = vm_create_with_one_vcpu(&vcpu, guest_code_user_operexec);
 85	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_INSTR0, 0);
 86	TEST_ASSERT_EQ(0, rc);
 87	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_OPEREXEC, 0);
 88	TEST_ASSERT_EQ(0, rc);
 89
 90	vcpu_run(vcpu);
 91	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
 92	TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, ICPT_OPEREXC);
 93	TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0x0807);
 94
 95	kvm_vm_free(vm);
 96
 97	/* Reverse enablement order */
 98	vm = vm_create_with_one_vcpu(&vcpu, guest_code_user_operexec);
 99	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_OPEREXEC, 0);
100	TEST_ASSERT_EQ(0, rc);
101	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_INSTR0, 0);
102	TEST_ASSERT_EQ(0, rc);
103
104	vcpu_run(vcpu);
105	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
106	TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, ICPT_OPEREXC);
107	TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0x0807);
108
109	kvm_vm_free(vm);
110}
111
112/*
113 * Run all tests above.
114 *
115 * Enablement after VCPU has been added is automatically tested since
116 * we enable the capability after VCPU creation.
117 */
118static struct testdef {
119	const char *name;
120	void (*test)(void);
121} testlist[] = {
122	{ "instr0", test_user_instr0 },
123	{ "operexec", test_user_operexec },
124	{ "operexec_combined", test_user_operexec_combined},
125};
126
127int main(int argc, char *argv[])
128{
129	int idx;
130
131	TEST_REQUIRE(kvm_has_cap(KVM_CAP_S390_USER_INSTR0));
132
133	ksft_print_header();
134	ksft_set_plan(ARRAY_SIZE(testlist));
135	for (idx = 0; idx < ARRAY_SIZE(testlist); idx++) {
136		testlist[idx].test();
137		ksft_test_result_pass("%s\n", testlist[idx].name);
138	}
139	ksft_finished();
140}
~/ Read-only file preview.