1 // SPDX-License-Identifier: GPL-2.0-only
3 * Test for s390x KVM_CAP_SYNC_REGS
5 * Based on the same test for x86:
6 * Copyright (C) 2018, Google LLC.
9 * Copyright (C) 2019, Red Hat, Inc.
11 * Test expected behavior of the KVM_CAP_SYNC_REGS functionality.
14 #define _GNU_SOURCE /* for program_invocation_short_name */
19 #include <sys/ioctl.h>
21 #include "test_util.h"
26 static void guest_code(void)
29 * We embed diag 501 here instead of doing a ucall to avoid that
30 * the compiler has messed with r11 at the time of the ucall.
39 #define REG_COMPARE(reg) \
40 TEST_ASSERT(left->reg == right->reg, \
42 " values did not match: 0x%llx, 0x%llx\n", \
43 left->reg, right->reg)
45 static void compare_regs(struct kvm_regs
*left
, struct kvm_sync_regs
*right
)
49 for (i
= 0; i
< 16; i
++)
53 static void compare_sregs(struct kvm_sregs
*left
, struct kvm_sync_regs
*right
)
57 for (i
= 0; i
< 16; i
++)
60 for (i
= 0; i
< 16; i
++)
66 #define TEST_SYNC_FIELDS (KVM_SYNC_GPRS|KVM_SYNC_ACRS|KVM_SYNC_CRS)
67 #define INVALID_SYNC_FIELD 0x80000000
69 int main(int argc
, char *argv
[])
74 struct kvm_sregs sregs
;
77 /* Tell stdout not to buffer its content */
80 cap
= kvm_check_cap(KVM_CAP_SYNC_REGS
);
82 fprintf(stderr
, "CAP_SYNC_REGS not supported, skipping test\n");
87 vm
= vm_create_default(VCPU_ID
, 0, guest_code
);
89 run
= vcpu_state(vm
, VCPU_ID
);
91 /* Request reading invalid register set from VCPU. */
92 run
->kvm_valid_regs
= INVALID_SYNC_FIELD
;
93 rv
= _vcpu_run(vm
, VCPU_ID
);
94 TEST_ASSERT(rv
< 0 && errno
== EINVAL
,
95 "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
97 vcpu_state(vm
, VCPU_ID
)->kvm_valid_regs
= 0;
99 run
->kvm_valid_regs
= INVALID_SYNC_FIELD
| TEST_SYNC_FIELDS
;
100 rv
= _vcpu_run(vm
, VCPU_ID
);
101 TEST_ASSERT(rv
< 0 && errno
== EINVAL
,
102 "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
104 vcpu_state(vm
, VCPU_ID
)->kvm_valid_regs
= 0;
106 /* Request setting invalid register set into VCPU. */
107 run
->kvm_dirty_regs
= INVALID_SYNC_FIELD
;
108 rv
= _vcpu_run(vm
, VCPU_ID
);
109 TEST_ASSERT(rv
< 0 && errno
== EINVAL
,
110 "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
112 vcpu_state(vm
, VCPU_ID
)->kvm_dirty_regs
= 0;
114 run
->kvm_dirty_regs
= INVALID_SYNC_FIELD
| TEST_SYNC_FIELDS
;
115 rv
= _vcpu_run(vm
, VCPU_ID
);
116 TEST_ASSERT(rv
< 0 && errno
== EINVAL
,
117 "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
119 vcpu_state(vm
, VCPU_ID
)->kvm_dirty_regs
= 0;
121 /* Request and verify all valid register sets. */
122 run
->kvm_valid_regs
= TEST_SYNC_FIELDS
;
123 rv
= _vcpu_run(vm
, VCPU_ID
);
124 TEST_ASSERT(rv
== 0, "vcpu_run failed: %d\n", rv
);
125 TEST_ASSERT(run
->exit_reason
== KVM_EXIT_S390_SIEIC
,
126 "Unexpected exit reason: %u (%s)\n",
128 exit_reason_str(run
->exit_reason
));
129 TEST_ASSERT(run
->s390_sieic
.icptcode
== 4 &&
130 (run
->s390_sieic
.ipa
>> 8) == 0x83 &&
131 (run
->s390_sieic
.ipb
>> 16) == 0x501,
132 "Unexpected interception code: ic=%u, ipa=0x%x, ipb=0x%x\n",
133 run
->s390_sieic
.icptcode
, run
->s390_sieic
.ipa
,
134 run
->s390_sieic
.ipb
);
136 vcpu_regs_get(vm
, VCPU_ID
, ®s
);
137 compare_regs(®s
, &run
->s
.regs
);
139 vcpu_sregs_get(vm
, VCPU_ID
, &sregs
);
140 compare_sregs(&sregs
, &run
->s
.regs
);
142 /* Set and verify various register values */
143 run
->s
.regs
.gprs
[11] = 0xBAD1DEA;
144 run
->s
.regs
.acrs
[0] = 1 << 11;
146 run
->kvm_valid_regs
= TEST_SYNC_FIELDS
;
147 run
->kvm_dirty_regs
= KVM_SYNC_GPRS
| KVM_SYNC_ACRS
;
148 rv
= _vcpu_run(vm
, VCPU_ID
);
149 TEST_ASSERT(rv
== 0, "vcpu_run failed: %d\n", rv
);
150 TEST_ASSERT(run
->exit_reason
== KVM_EXIT_S390_SIEIC
,
151 "Unexpected exit reason: %u (%s)\n",
153 exit_reason_str(run
->exit_reason
));
154 TEST_ASSERT(run
->s
.regs
.gprs
[11] == 0xBAD1DEA + 1,
155 "r11 sync regs value incorrect 0x%llx.",
156 run
->s
.regs
.gprs
[11]);
157 TEST_ASSERT(run
->s
.regs
.acrs
[0] == 1 << 11,
158 "acr0 sync regs value incorrect 0x%llx.",
159 run
->s
.regs
.acrs
[0]);
161 vcpu_regs_get(vm
, VCPU_ID
, ®s
);
162 compare_regs(®s
, &run
->s
.regs
);
164 vcpu_sregs_get(vm
, VCPU_ID
, &sregs
);
165 compare_sregs(&sregs
, &run
->s
.regs
);
167 /* Clear kvm_dirty_regs bits, verify new s.regs values are
168 * overwritten with existing guest values.
170 run
->kvm_valid_regs
= TEST_SYNC_FIELDS
;
171 run
->kvm_dirty_regs
= 0;
172 run
->s
.regs
.gprs
[11] = 0xDEADBEEF;
173 rv
= _vcpu_run(vm
, VCPU_ID
);
174 TEST_ASSERT(rv
== 0, "vcpu_run failed: %d\n", rv
);
175 TEST_ASSERT(run
->exit_reason
== KVM_EXIT_S390_SIEIC
,
176 "Unexpected exit reason: %u (%s)\n",
178 exit_reason_str(run
->exit_reason
));
179 TEST_ASSERT(run
->s
.regs
.gprs
[11] != 0xDEADBEEF,
180 "r11 sync regs value incorrect 0x%llx.",
181 run
->s
.regs
.gprs
[11]);