Xen Test Framework
main.c
Go to the documentation of this file.
1
11#include <xtf.h>
12
13const char test_title[] = "Argo test";
14
15/*
16 * Xen enforces an upper limit of 16M for rings. 32 pages should suffice.
17 */
19#define TEST_RING_NPAGES (sizeof(ring_buffer) / PAGE_SIZE)
20
21static int probe_for_argo(domid_t own_domid)
22{
23 /* Attempt an Argo call to register a ring with invalid arguments */
25 .aport = 1,
26 .partner_id = own_domid,
27 .len = 1, /* A 1-byte ring is never allowed */
28 };
30
31 switch ( rc )
32 {
33 case -EINVAL: /* This is the response we are looking for */
34 return 0;
35
36 /* All below here are test exit conditions */
37 case -ENOSYS:
38 xtf_skip("Skip: Argo support has not been enabled in this hypervisor\n");
39 break;
40 case -EOPNOTSUPP:
41 xtf_skip("Skip: Argo is not enabled at runtime for this hypervisor\n");
42 break;
43 case -ENODEV:
44 xtf_skip("Skip: Argo is not enabled for this domain\n");
45 break;
46
47 case -EPERM:
48 xtf_failure("Fail: Ring registration by this domain is not permitted\n");
49 break;
50 case 0:
51 xtf_failure("Fail: An invalid ring register op was not rejected\n");
52 break;
53 default:
54 xtf_failure("Fail: Unknown error %d for invalid ring registration\n", rc);
55 break;
56 }
57
58 return -1;
59}
60
61/* notify: asks Xen for information about rings */
62static int
64 bool exists)
65{
66 struct {
69 } notify = {
70 .data = {
71 .nent = ARRAY_SIZE(notify.ents),
72 },
73 .ents = {
74 {
75 .ring = {
76 .domain_id = query_domid,
77 .aport = query_port,
78 },
79 },
80 },
81 };
82 int rc = hypercall_argo_op(XEN_ARGO_OP_notify, &notify, NULL, 0, 0);
83
84 if ( rc )
85 {
86 xtf_failure("Fail: Unexpected error code %d in notify test\n", rc);
87 return -1;
88 }
89
90 if ( !exists )
91 {
92 /* No currently-defined flags should be set for a non-existent ring */
93 if ( notify.ents[0].flags )
94 {
95 xtf_failure("Fail: Non-existent ring reported as existing\n");
96 return -1;
97 }
98 }
99 else
100 {
101 if ( !(notify.ents[0].flags & XEN_ARGO_RING_EXISTS) )
102 {
103 xtf_failure("Fail: Ring not reported as existing\n");
104 return -1;
105 }
106 }
107
108 return 0;
109}
110
111/* See the Argo Linux device driver for similar use of these macros */
112#define XEN_ARGO_ROUNDUP(x) ROUNDUP(x, XEN_ARGO_MSG_SLOT_SIZE)
113#define ARGO_RING_OVERHEAD 80
114#define TEST_RING_SIZE(npages) \
115 (XEN_ARGO_ROUNDUP((((PAGE_SIZE)*npages) - ARGO_RING_OVERHEAD)))
116
117static int
119{
120 unsigned int i;
122 .aport = aport,
123 .partner_id = own_domid,
125 };
127
128 for ( i = 0; i < TEST_RING_NPAGES; i++ )
129 gfns[i] = virt_to_gfn(ring_buffer + (i * PAGE_SIZE));
130
131 int rc = hypercall_argo_op(XEN_ARGO_OP_register_ring, &reg, &gfns,
133 switch ( rc )
134 {
135 case 0:
136 return 0;
137
138 case -ENODEV:
139 xtf_failure("Fail: Argo is not enabled for this domain\n");
140 break;
141 case -EFAULT:
142 xtf_failure("Fail: Memory fault performing register ring test\n");
143 break;
144 default:
145 xtf_failure("Fail: Unexpected error code %d in register ring test\n", rc);
146 break;
147 }
148 return -1;
149}
150
151static int
153 bool exists)
154{
156 .aport = aport,
157 .partner_id = partner_domid,
158 };
159 int rc = hypercall_argo_op(XEN_ARGO_OP_unregister_ring, &unreg, NULL, 0, 0);
160
161 switch ( rc )
162 {
163 case 0:
164 if ( exists )
165 return 0;
166 xtf_failure("Fail: Unexpected success unregistering non-existent ring\n");
167 return -1;
168
169 case -ENOENT:
170 if ( !exists )
171 return 0;
172 xtf_failure("Fail: Unexpected ring not found when unregistering \n");
173 return -1;
174
175 default:
176 xtf_failure("Fail: Unexpected error code %d in unregister ring test\n", rc);
177 break;
178 }
179 return -1;
180}
181
182static int
183test_sendv(domid_t src_domid, xen_argo_port_t src_aport,
184 domid_t dst_domid, xen_argo_port_t dst_aport,
185 const char *msg_text, size_t msg_len, unsigned int msg_type)
186{
187 xen_argo_send_addr_t send_addr = {
188 .src = {
189 .domain_id = src_domid,
190 .aport = src_aport,
191 },
192 .dst = {
193 .domain_id = dst_domid,
194 .aport = dst_aport,
195 },
196 };
197 xen_argo_iov_t iovs[] = {
198 {
199 .iov_hnd = _u(msg_text),
200 .iov_len = msg_len,
201 },
202 };
203 int rc = hypercall_argo_op(XEN_ARGO_OP_sendv, &send_addr,
204 iovs, ARRAY_SIZE(iovs), msg_type);
205
206 if ( rc < 0 )
207 {
208 xtf_failure("Fail: Unexpected error code %d in sendv test\n", rc);
209 return -1;
210 }
211
212 if ( (size_t)rc != msg_len )
213 {
214 xtf_failure("Fail: Unexpected message size %d written in sendv test\n", rc);
215 return -1;
216 }
217
218 return 0;
219}
220
221static int
223 xen_argo_port_t src_aport,
224 const char *sent_msg,
225 unsigned int sent_msg_len,
226 unsigned int sent_msg_type)
227{
228 int rc = 0;
230 struct xen_argo_ring_message_header *msg_hdr;
231 unsigned int sent_length;
232
233 if ( ringp->rx_ptr != 0 )
234 {
235 xtf_failure("Fail: Receive pointer non-zero after sendv: %u\n",
236 ringp->rx_ptr);
237 rc = -1;
238 }
239
240 if ( ringp->tx_ptr != XEN_ARGO_ROUNDUP(
241 sizeof(struct xen_argo_ring_message_header) + sent_msg_len) )
242 {
243 xtf_failure("Fail: Transmit pointer incorrect after sendv: %u\n",
244 ringp->rx_ptr);
245 rc = -1;
246 }
247
248 msg_hdr = (struct xen_argo_ring_message_header *)&(ringp->ring);
249
250 if ( msg_hdr->source.domain_id != src_domid )
251 {
252 xtf_failure("Fail: Source domain id incorrect: %u, expected %u\n",
253 msg_hdr->source.domain_id, src_domid);
254 rc = -1;
255 }
256
257 if ( msg_hdr->source.aport != src_aport )
258 {
259 xtf_failure("Fail: Source domain port incorrect: %u, expected %u\n",
260 msg_hdr->source.domain_id, src_aport);
261 rc = -1;
262 }
263
264 if ( msg_hdr->source.pad != 0 )
265 {
266 xtf_failure("Fail: Source padding incorrect: %u, expected zero\n",
267 msg_hdr->source.pad);
268 rc = -1;
269 }
270
271 if ( sent_msg_type != msg_hdr->message_type )
272 {
273 xtf_failure("Fail: Message type incorrect: %u sent, %u received\n",
274 sent_msg_type, msg_hdr->message_type);
275 rc = -1;
276 }
277
278 sent_length = sent_msg_len + sizeof(struct xen_argo_ring_message_header);
279 if ( sent_length != msg_hdr->len )
280 {
281 xtf_failure("Fail: Received message length incorrect: "
282 "%u sent is %u with header added, %u received\n",
283 sent_msg_len, sent_length, msg_hdr->len);
284 rc = -1;
285 }
286
287 if ( memcmp(msg_hdr->data, sent_msg, sent_msg_len) )
288 {
289 xtf_failure("Fail: Sent message got mangled\n");
290 rc = -1;
291 }
292
293 return rc;
294}
295
296static void clear_test_ring(void)
297{
298 memset(ring_buffer, 0, sizeof(ring_buffer));
299}
300
301void test_main(void)
302{
303 int own_domid;
304 xen_argo_port_t test_aport = 1;
305 const char simple_text[] = "A simple thing to send\n";
306 const unsigned int msg_type = 0x12345678;
307
308 own_domid = xtf_get_domid();
309 if ( own_domid < 0 )
310 return xtf_error("Error: could not determine domid of the test domain\n");
311
312 /* First test validates for Argo availability to gate further testing */
313 if ( probe_for_argo(own_domid) )
314 return;
315
316 if ( test_notify_for_one_ring(own_domid, test_aport, false) ||
317 test_unregister_ring(own_domid, test_aport, false) )
318 return;
319
321
322 if ( test_register_ring(own_domid, test_aport) ||
323 test_notify_for_one_ring(own_domid, test_aport, true) ||
324 test_unregister_ring(own_domid, test_aport, true) ||
325 test_notify_for_one_ring(own_domid, test_aport, false) ||
326 test_unregister_ring(own_domid, test_aport, false) )
327 return;
328
330
331 if ( test_register_ring(own_domid, test_aport) ||
332 test_sendv(own_domid, test_aport, own_domid, test_aport,
333 simple_text, strlen(simple_text), msg_type) ||
335 own_domid, test_aport, simple_text, strlen(simple_text), msg_type) ||
336 test_notify_for_one_ring(own_domid, test_aport, true) ||
337 test_unregister_ring(own_domid, test_aport, true) ||
338 test_unregister_ring(own_domid, test_aport, false) )
339 return;
340
342}
343
344/*
345 * Local variables:
346 * mode: C
347 * c-file-style: "BSD"
348 * c-basic-offset: 4
349 * tab-width: 4
350 * indent-tabs-mode: nil
351 * End:
352 */
#define TEST_RING_SIZE(npages)
Definition: main.c:114
static int test_register_ring(domid_t own_domid, xen_argo_port_t aport)
Definition: main.c:118
static int test_unregister_ring(domid_t partner_domid, xen_argo_port_t aport, bool exists)
Definition: main.c:152
static int inspect_ring_after_first_single_sendv(domid_t src_domid, xen_argo_port_t src_aport, const char *sent_msg, unsigned int sent_msg_len, unsigned int sent_msg_type)
Definition: main.c:222
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:301
static int test_sendv(domid_t src_domid, xen_argo_port_t src_aport, domid_t dst_domid, xen_argo_port_t dst_aport, const char *msg_text, size_t msg_len, unsigned int msg_type)
Definition: main.c:183
const char test_title[]
The title of the test.
Definition: main.c:13
#define TEST_RING_NPAGES
Definition: main.c:19
static int test_notify_for_one_ring(domid_t query_domid, xen_argo_port_t query_port, bool exists)
Definition: main.c:63
#define XEN_ARGO_ROUNDUP(x)
Definition: main.c:112
static uint8_t ring_buffer[32 *PAGE_SIZE]
Definition: main.c:18
static int probe_for_argo(domid_t own_domid)
Definition: main.c:21
static void clear_test_ring(void)
Definition: main.c:296
#define XEN_ARGO_RING_EXISTS
Definition: argo.h:66
#define XEN_ARGO_OP_notify
Definition: argo.h:207
#define XEN_ARGO_OP_unregister_ring
Definition: argo.h:150
#define XEN_ARGO_OP_register_ring
Definition: argo.h:129
#define XEN_ARGO_OP_sendv
Definition: argo.h:176
uint64_t xen_argo_gfn_t
Definition: argo.h:14
#define XEN_ARGO_REGISTER_FLAG_FAIL_EXIST
Definition: argo.h:138
uint32_t xen_argo_port_t
Definition: argo.h:11
#define __page_aligned_bss
Definition: compiler.h:37
#define ENOENT
Definition: errno.h:16
#define EINVAL
Definition: errno.h:33
#define EFAULT
Definition: errno.h:28
#define ENOSYS
Definition: errno.h:43
#define EOPNOTSUPP
Definition: errno.h:51
#define ENODEV
Definition: errno.h:32
#define EPERM
Definition: errno.h:15
static long hypercall_argo_op(unsigned int cmd, void *arg1, void *arg2, unsigned long arg3, unsigned long arg4)
Definition: hypercall.h:188
#define ARRAY_SIZE(a)
Definition: lib.h:8
int xtf_get_domid(void)
Obtain the current domid.
Definition: lib.c:102
#define memset(d, c, n)
Definition: libc.h:33
#define memcmp(s1, s2, n)
Definition: libc.h:39
#define strlen(s)
Definition: libc.h:18
static unsigned long virt_to_gfn(const void *va)
Definition: mm.h:100
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
#define PAGE_SIZE
Definition: page.h:11
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
#define NULL
Definition: stddef.h:12
__UINT8_TYPE__ uint8_t
Definition: stdint.h:14
uint16_t pad
Definition: argo.h:25
xen_argo_port_t aport
Definition: argo.h:23
domid_t domain_id
Definition: argo.h:24
unsigned long iov_hnd
Definition: argo.h:17
xen_argo_port_t aport
Definition: argo.h:47
struct xen_argo_addr source
Definition: argo.h:100
uint32_t rx_ptr
Definition: argo.h:35
uint8_t ring[]
Definition: argo.h:43
uint32_t tx_ptr
Definition: argo.h:37
struct xen_argo_addr src
Definition: argo.h:29
uint16_t domid_t
Definition: xen.h:66