1
2
3
4
5
6
7
8
9
10
11
12
13
14#define _GNU_SOURCE
15#include <fcntl.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <sys/ioctl.h>
20
21#include "test_util.h"
22#include "kvm_util.h"
23
24#define VCPU_ID 5
25
26static void guest_code(void)
27{
28 for (;;) {
29 asm volatile ("diag 0,0,0x501");
30 asm volatile ("ahi 11,1");
31 }
32}
33
34#define REG_COMPARE(reg) \
35 TEST_ASSERT(left->reg == right->reg, \
36 "Register " #reg \
37 " values did not match: 0x%llx, 0x%llx\n", \
38 left->reg, right->reg)
39
40static void compare_regs(struct kvm_regs *left, struct kvm_sync_regs *right)
41{
42 int i;
43
44 for (i = 0; i < 16; i++)
45 REG_COMPARE(gprs[i]);
46}
47
48static void compare_sregs(struct kvm_sregs *left, struct kvm_sync_regs *right)
49{
50 int i;
51
52 for (i = 0; i < 16; i++)
53 REG_COMPARE(acrs[i]);
54
55 for (i = 0; i < 16; i++)
56 REG_COMPARE(crs[i]);
57}
58
59#undef REG_COMPARE
60
61#define TEST_SYNC_FIELDS (KVM_SYNC_GPRS|KVM_SYNC_ACRS|KVM_SYNC_CRS)
62#define INVALID_SYNC_FIELD 0x80000000
63
64int main(int argc, char *argv[])
65{
66 struct kvm_vm *vm;
67 struct kvm_run *run;
68 struct kvm_regs regs;
69 struct kvm_sregs sregs;
70 int rv, cap;
71
72
73 setbuf(stdout, NULL);
74
75 cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
76 if (!cap) {
77 fprintf(stderr, "CAP_SYNC_REGS not supported, skipping test\n");
78 exit(KSFT_SKIP);
79 }
80
81
82 vm = vm_create_default(VCPU_ID, 0, guest_code);
83
84 run = vcpu_state(vm, VCPU_ID);
85
86
87 run->kvm_valid_regs = TEST_SYNC_FIELDS;
88 rv = _vcpu_run(vm, VCPU_ID);
89 TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
90 TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC,
91 "Unexpected exit reason: %u (%s)\n",
92 run->exit_reason,
93 exit_reason_str(run->exit_reason));
94 TEST_ASSERT(run->s390_sieic.icptcode == 4 &&
95 (run->s390_sieic.ipa >> 8) == 0x83 &&
96 (run->s390_sieic.ipb >> 16) == 0x501,
97 "Unexpected interception code: ic=%u, ipa=0x%x, ipb=0x%x\n",
98 run->s390_sieic.icptcode, run->s390_sieic.ipa,
99 run->s390_sieic.ipb);
100
101 vcpu_regs_get(vm, VCPU_ID, ®s);
102 compare_regs(®s, &run->s.regs);
103
104 vcpu_sregs_get(vm, VCPU_ID, &sregs);
105 compare_sregs(&sregs, &run->s.regs);
106
107
108 run->s.regs.gprs[11] = 0xBAD1DEA;
109 run->s.regs.acrs[0] = 1 << 11;
110
111 run->kvm_valid_regs = TEST_SYNC_FIELDS;
112 run->kvm_dirty_regs = KVM_SYNC_GPRS | KVM_SYNC_ACRS;
113 rv = _vcpu_run(vm, VCPU_ID);
114 TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
115 TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC,
116 "Unexpected exit reason: %u (%s)\n",
117 run->exit_reason,
118 exit_reason_str(run->exit_reason));
119 TEST_ASSERT(run->s.regs.gprs[11] == 0xBAD1DEA + 1,
120 "r11 sync regs value incorrect 0x%llx.",
121 run->s.regs.gprs[11]);
122 TEST_ASSERT(run->s.regs.acrs[0] == 1 << 11,
123 "acr0 sync regs value incorrect 0x%llx.",
124 run->s.regs.acrs[0]);
125
126 vcpu_regs_get(vm, VCPU_ID, ®s);
127 compare_regs(®s, &run->s.regs);
128
129 vcpu_sregs_get(vm, VCPU_ID, &sregs);
130 compare_sregs(&sregs, &run->s.regs);
131
132
133
134
135 run->kvm_valid_regs = TEST_SYNC_FIELDS;
136 run->kvm_dirty_regs = 0;
137 run->s.regs.gprs[11] = 0xDEADBEEF;
138 rv = _vcpu_run(vm, VCPU_ID);
139 TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
140 TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC,
141 "Unexpected exit reason: %u (%s)\n",
142 run->exit_reason,
143 exit_reason_str(run->exit_reason));
144 TEST_ASSERT(run->s.regs.gprs[11] != 0xDEADBEEF,
145 "r11 sync regs value incorrect 0x%llx.",
146 run->s.regs.gprs[11]);
147
148 kvm_vm_free(vm);
149
150 return 0;
151}
152