tools/testing/selftests/kvm/s390/user_operexec.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/s390/user_operexec.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/s390/user_operexec.c
Extension
.c
Size
3464 bytes
Lines
141
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/* Test operation exception forwarding.
 *
 * Copyright IBM Corp. 2025
 *
 * Authors:
 *  Janosch Frank <frankja@linux.ibm.com>
 */
#include "kselftest.h"
#include "kvm_util.h"
#include "test_util.h"
#include "sie.h"

#include <linux/kvm.h>

static void guest_code_instr0(void)
{
	asm(".word 0x0000");
}

static void test_user_instr0(void)
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm;
	int rc;

	vm = vm_create_with_one_vcpu(&vcpu, guest_code_instr0);
	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_INSTR0, 0);
	TEST_ASSERT_EQ(0, rc);

	vcpu_run(vcpu);
	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
	TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, ICPT_OPEREXC);
	TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0);

	kvm_vm_free(vm);
}

static void guest_code_user_operexec(void)
{
	asm(".word 0x0807");
}

static void test_user_operexec(void)
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm;
	int rc;

	vm = vm_create_with_one_vcpu(&vcpu, guest_code_user_operexec);
	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_OPEREXEC, 0);
	TEST_ASSERT_EQ(0, rc);

	vcpu_run(vcpu);
	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
	TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, ICPT_OPEREXC);
	TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0x0807);

	kvm_vm_free(vm);

	/*
	 * Since user_operexec is the superset it can be used for the
	 * 0 instruction.
	 */
	vm = vm_create_with_one_vcpu(&vcpu, guest_code_instr0);
	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_OPEREXEC, 0);
	TEST_ASSERT_EQ(0, rc);

	vcpu_run(vcpu);
	TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
	TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, ICPT_OPEREXC);
	TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0);

	kvm_vm_free(vm);
}

/* combine user_instr0 and user_operexec */
static void test_user_operexec_combined(void)
{
	struct kvm_vcpu *vcpu;
	struct kvm_vm *vm;
	int rc;

	vm = vm_create_with_one_vcpu(&vcpu, guest_code_user_operexec);
	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_INSTR0, 0);
	TEST_ASSERT_EQ(0, rc);
	rc = __vm_enable_cap(vm, KVM_CAP_S390_USER_OPEREXEC, 0);
	TEST_ASSERT_EQ(0, rc);

	vcpu_run(vcpu);

Annotation

Implementation Notes