Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/kvm/s390/user_operexec.c
38237 views
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 <[email protected]>
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
16
static void guest_code_instr0(void)
17
{
18
asm(".word 0x0000");
19
}
20
21
static 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
39
static void guest_code_user_operexec(void)
40
{
41
asm(".word 0x0807");
42
}
43
44
static 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 */
78
static 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
*/
118
static 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
127
int 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
}
141
142