KVM: s390: selftests: Split memop tests
[linux-2.6-microblaze.git] / tools / testing / selftests / kvm / s390x / memop.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Test for s390x KVM_S390_MEM_OP
4  *
5  * Copyright (C) 2019, Red Hat, Inc.
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
12
13 #include "test_util.h"
14 #include "kvm_util.h"
15
16 #define VCPU_ID 1
17
18 static uint8_t mem1[65536];
19 static uint8_t mem2[65536];
20
21 struct test_default {
22         struct kvm_vm *kvm_vm;
23         struct kvm_run *run;
24         int size;
25 };
26
27 static struct test_default test_default_init(void *guest_code)
28 {
29         struct test_default t;
30
31         t.size = min((size_t)kvm_check_cap(KVM_CAP_S390_MEM_OP), sizeof(mem1));
32         t.kvm_vm = vm_create_default(VCPU_ID, 0, guest_code);
33         t.run = vcpu_state(t.kvm_vm, VCPU_ID);
34         return t;
35 }
36
37 static void guest_copy(void)
38 {
39         memcpy(&mem2, &mem1, sizeof(mem2));
40         GUEST_SYNC(0);
41 }
42
43 static void test_copy(void)
44 {
45         struct test_default t = test_default_init(guest_copy);
46         struct kvm_s390_mem_op ksmo;
47         int i;
48
49         for (i = 0; i < sizeof(mem1); i++)
50                 mem1[i] = i * i + i;
51
52         /* Set the first array */
53         ksmo.gaddr = addr_gva2gpa(t.kvm_vm, (uintptr_t)mem1);
54         ksmo.flags = 0;
55         ksmo.size = t.size;
56         ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE;
57         ksmo.buf = (uintptr_t)mem1;
58         ksmo.ar = 0;
59         vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
60
61         /* Let the guest code copy the first array to the second */
62         vcpu_run(t.kvm_vm, VCPU_ID);
63         TEST_ASSERT(t.run->exit_reason == KVM_EXIT_S390_SIEIC,
64                     "Unexpected exit reason: %u (%s)\n",
65                     t.run->exit_reason,
66                     exit_reason_str(t.run->exit_reason));
67
68         memset(mem2, 0xaa, sizeof(mem2));
69
70         /* Get the second array */
71         ksmo.gaddr = (uintptr_t)mem2;
72         ksmo.flags = 0;
73         ksmo.size = t.size;
74         ksmo.op = KVM_S390_MEMOP_LOGICAL_READ;
75         ksmo.buf = (uintptr_t)mem2;
76         ksmo.ar = 0;
77         vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
78
79         TEST_ASSERT(!memcmp(mem1, mem2, t.size),
80                     "Memory contents do not match!");
81
82         kvm_vm_free(t.kvm_vm);
83 }
84
85 static void guest_idle(void)
86 {
87         for (;;)
88                 GUEST_SYNC(0);
89 }
90
91 static void test_errors(void)
92 {
93         struct test_default t = test_default_init(guest_idle);
94         struct kvm_s390_mem_op ksmo;
95         int rv;
96
97         /* Check error conditions - first bad size: */
98         ksmo.gaddr = (uintptr_t)mem1;
99         ksmo.flags = 0;
100         ksmo.size = -1;
101         ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE;
102         ksmo.buf = (uintptr_t)mem1;
103         ksmo.ar = 0;
104         rv = _vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
105         TEST_ASSERT(rv == -1 && errno == E2BIG, "ioctl allows insane sizes");
106
107         /* Zero size: */
108         ksmo.gaddr = (uintptr_t)mem1;
109         ksmo.flags = 0;
110         ksmo.size = 0;
111         ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE;
112         ksmo.buf = (uintptr_t)mem1;
113         ksmo.ar = 0;
114         rv = _vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
115         TEST_ASSERT(rv == -1 && (errno == EINVAL || errno == ENOMEM),
116                     "ioctl allows 0 as size");
117
118         /* Bad flags: */
119         ksmo.gaddr = (uintptr_t)mem1;
120         ksmo.flags = -1;
121         ksmo.size = t.size;
122         ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE;
123         ksmo.buf = (uintptr_t)mem1;
124         ksmo.ar = 0;
125         rv = _vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
126         TEST_ASSERT(rv == -1 && errno == EINVAL, "ioctl allows all flags");
127
128         /* Bad operation: */
129         ksmo.gaddr = (uintptr_t)mem1;
130         ksmo.flags = 0;
131         ksmo.size = t.size;
132         ksmo.op = -1;
133         ksmo.buf = (uintptr_t)mem1;
134         ksmo.ar = 0;
135         rv = _vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
136         TEST_ASSERT(rv == -1 && errno == EINVAL, "ioctl allows bad operations");
137
138         /* Bad guest address: */
139         ksmo.gaddr = ~0xfffUL;
140         ksmo.flags = KVM_S390_MEMOP_F_CHECK_ONLY;
141         ksmo.size = t.size;
142         ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE;
143         ksmo.buf = (uintptr_t)mem1;
144         ksmo.ar = 0;
145         rv = _vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
146         TEST_ASSERT(rv > 0, "ioctl does not report bad guest memory access");
147
148         /* Bad host address: */
149         ksmo.gaddr = (uintptr_t)mem1;
150         ksmo.flags = 0;
151         ksmo.size = t.size;
152         ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE;
153         ksmo.buf = 0;
154         ksmo.ar = 0;
155         rv = _vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
156         TEST_ASSERT(rv == -1 && errno == EFAULT,
157                     "ioctl does not report bad host memory address");
158
159         /* Bad access register: */
160         t.run->psw_mask &= ~(3UL << (63 - 17));
161         t.run->psw_mask |= 1UL << (63 - 17);  /* Enable AR mode */
162         vcpu_run(t.kvm_vm, VCPU_ID);              /* To sync new state to SIE block */
163         ksmo.gaddr = (uintptr_t)mem1;
164         ksmo.flags = 0;
165         ksmo.size = t.size;
166         ksmo.op = KVM_S390_MEMOP_LOGICAL_WRITE;
167         ksmo.buf = (uintptr_t)mem1;
168         ksmo.ar = 17;
169         rv = _vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
170         TEST_ASSERT(rv == -1 && errno == EINVAL, "ioctl allows ARs > 15");
171         t.run->psw_mask &= ~(3UL << (63 - 17));   /* Disable AR mode */
172         vcpu_run(t.kvm_vm, VCPU_ID);                  /* Run to sync new state */
173
174         /* Check that the SIDA calls are rejected for non-protected guests */
175         ksmo.gaddr = 0;
176         ksmo.flags = 0;
177         ksmo.size = 8;
178         ksmo.op = KVM_S390_MEMOP_SIDA_READ;
179         ksmo.buf = (uintptr_t)mem1;
180         ksmo.sida_offset = 0x1c0;
181         rv = _vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
182         TEST_ASSERT(rv == -1 && errno == EINVAL,
183                     "ioctl does not reject SIDA_READ in non-protected mode");
184         ksmo.op = KVM_S390_MEMOP_SIDA_WRITE;
185         rv = _vcpu_ioctl(t.kvm_vm, VCPU_ID, KVM_S390_MEM_OP, &ksmo);
186         TEST_ASSERT(rv == -1 && errno == EINVAL,
187                     "ioctl does not reject SIDA_WRITE in non-protected mode");
188
189         kvm_vm_free(t.kvm_vm);
190 }
191
192 int main(int argc, char *argv[])
193 {
194         int memop_cap;
195
196         setbuf(stdout, NULL);   /* Tell stdout not to buffer its content */
197
198         memop_cap = kvm_check_cap(KVM_CAP_S390_MEM_OP);
199         if (!memop_cap) {
200                 print_skip("CAP_S390_MEM_OP not supported");
201                 exit(KSFT_SKIP);
202         }
203
204         test_copy();
205         test_errors();
206
207         return 0;
208 }