Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/iommu/iommufd.c
26302 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES */
3
#include <asm/unistd.h>
4
#include <stdlib.h>
5
#include <sys/capability.h>
6
#include <sys/mman.h>
7
#include <sys/eventfd.h>
8
9
#define __EXPORTED_HEADERS__
10
#include <linux/vfio.h>
11
12
#include "iommufd_utils.h"
13
14
static unsigned long HUGEPAGE_SIZE;
15
16
#define MOCK_PAGE_SIZE (PAGE_SIZE / 2)
17
#define MOCK_HUGE_PAGE_SIZE (512 * MOCK_PAGE_SIZE)
18
19
static unsigned long get_huge_page_size(void)
20
{
21
char buf[80];
22
int ret;
23
int fd;
24
25
fd = open("/sys/kernel/mm/transparent_hugepage/hpage_pmd_size",
26
O_RDONLY);
27
if (fd < 0)
28
return 2 * 1024 * 1024;
29
30
ret = read(fd, buf, sizeof(buf));
31
close(fd);
32
if (ret <= 0 || ret == sizeof(buf))
33
return 2 * 1024 * 1024;
34
buf[ret] = 0;
35
return strtoul(buf, NULL, 10);
36
}
37
38
static __attribute__((constructor)) void setup_sizes(void)
39
{
40
void *vrc;
41
int rc;
42
43
PAGE_SIZE = sysconf(_SC_PAGE_SIZE);
44
HUGEPAGE_SIZE = get_huge_page_size();
45
46
BUFFER_SIZE = PAGE_SIZE * 16;
47
rc = posix_memalign(&buffer, HUGEPAGE_SIZE, BUFFER_SIZE);
48
assert(!rc);
49
assert(buffer);
50
assert((uintptr_t)buffer % HUGEPAGE_SIZE == 0);
51
vrc = mmap(buffer, BUFFER_SIZE, PROT_READ | PROT_WRITE,
52
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
53
assert(vrc == buffer);
54
55
mfd_buffer = memfd_mmap(BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
56
&mfd);
57
assert(mfd_buffer != MAP_FAILED);
58
assert(mfd > 0);
59
}
60
61
FIXTURE(iommufd)
62
{
63
int fd;
64
};
65
66
FIXTURE_SETUP(iommufd)
67
{
68
self->fd = open("/dev/iommu", O_RDWR);
69
ASSERT_NE(-1, self->fd);
70
}
71
72
FIXTURE_TEARDOWN(iommufd)
73
{
74
teardown_iommufd(self->fd, _metadata);
75
}
76
77
TEST_F(iommufd, simple_close)
78
{
79
}
80
81
TEST_F(iommufd, cmd_fail)
82
{
83
struct iommu_destroy cmd = { .size = sizeof(cmd), .id = 0 };
84
85
/* object id is invalid */
86
EXPECT_ERRNO(ENOENT, _test_ioctl_destroy(self->fd, 0));
87
/* Bad pointer */
88
EXPECT_ERRNO(EFAULT, ioctl(self->fd, IOMMU_DESTROY, NULL));
89
/* Unknown ioctl */
90
EXPECT_ERRNO(ENOTTY,
91
ioctl(self->fd, _IO(IOMMUFD_TYPE, IOMMUFD_CMD_BASE - 1),
92
&cmd));
93
}
94
95
TEST_F(iommufd, cmd_length)
96
{
97
#define TEST_LENGTH(_struct, _ioctl, _last) \
98
{ \
99
size_t min_size = offsetofend(struct _struct, _last); \
100
struct { \
101
struct _struct cmd; \
102
uint8_t extra; \
103
} cmd = { .cmd = { .size = min_size - 1 }, \
104
.extra = UINT8_MAX }; \
105
int old_errno; \
106
int rc; \
107
\
108
EXPECT_ERRNO(EINVAL, ioctl(self->fd, _ioctl, &cmd)); \
109
cmd.cmd.size = sizeof(struct _struct) + 1; \
110
EXPECT_ERRNO(E2BIG, ioctl(self->fd, _ioctl, &cmd)); \
111
cmd.cmd.size = sizeof(struct _struct); \
112
rc = ioctl(self->fd, _ioctl, &cmd); \
113
old_errno = errno; \
114
cmd.cmd.size = sizeof(struct _struct) + 1; \
115
cmd.extra = 0; \
116
if (rc) { \
117
EXPECT_ERRNO(old_errno, \
118
ioctl(self->fd, _ioctl, &cmd)); \
119
} else { \
120
ASSERT_EQ(0, ioctl(self->fd, _ioctl, &cmd)); \
121
} \
122
}
123
124
TEST_LENGTH(iommu_destroy, IOMMU_DESTROY, id);
125
TEST_LENGTH(iommu_hw_info, IOMMU_GET_HW_INFO, __reserved);
126
TEST_LENGTH(iommu_hwpt_alloc, IOMMU_HWPT_ALLOC, __reserved);
127
TEST_LENGTH(iommu_hwpt_invalidate, IOMMU_HWPT_INVALIDATE, __reserved);
128
TEST_LENGTH(iommu_ioas_alloc, IOMMU_IOAS_ALLOC, out_ioas_id);
129
TEST_LENGTH(iommu_ioas_iova_ranges, IOMMU_IOAS_IOVA_RANGES,
130
out_iova_alignment);
131
TEST_LENGTH(iommu_ioas_allow_iovas, IOMMU_IOAS_ALLOW_IOVAS,
132
allowed_iovas);
133
TEST_LENGTH(iommu_ioas_map, IOMMU_IOAS_MAP, iova);
134
TEST_LENGTH(iommu_ioas_copy, IOMMU_IOAS_COPY, src_iova);
135
TEST_LENGTH(iommu_ioas_unmap, IOMMU_IOAS_UNMAP, length);
136
TEST_LENGTH(iommu_option, IOMMU_OPTION, val64);
137
TEST_LENGTH(iommu_vfio_ioas, IOMMU_VFIO_IOAS, __reserved);
138
TEST_LENGTH(iommu_ioas_map_file, IOMMU_IOAS_MAP_FILE, iova);
139
TEST_LENGTH(iommu_viommu_alloc, IOMMU_VIOMMU_ALLOC, out_viommu_id);
140
TEST_LENGTH(iommu_vdevice_alloc, IOMMU_VDEVICE_ALLOC, virt_id);
141
TEST_LENGTH(iommu_ioas_change_process, IOMMU_IOAS_CHANGE_PROCESS,
142
__reserved);
143
#undef TEST_LENGTH
144
}
145
146
TEST_F(iommufd, cmd_ex_fail)
147
{
148
struct {
149
struct iommu_destroy cmd;
150
__u64 future;
151
} cmd = { .cmd = { .size = sizeof(cmd), .id = 0 } };
152
153
/* object id is invalid and command is longer */
154
EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_DESTROY, &cmd));
155
/* future area is non-zero */
156
cmd.future = 1;
157
EXPECT_ERRNO(E2BIG, ioctl(self->fd, IOMMU_DESTROY, &cmd));
158
/* Original command "works" */
159
cmd.cmd.size = sizeof(cmd.cmd);
160
EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_DESTROY, &cmd));
161
/* Short command fails */
162
cmd.cmd.size = sizeof(cmd.cmd) - 1;
163
EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_DESTROY, &cmd));
164
}
165
166
TEST_F(iommufd, global_options)
167
{
168
struct iommu_option cmd = {
169
.size = sizeof(cmd),
170
.option_id = IOMMU_OPTION_RLIMIT_MODE,
171
.op = IOMMU_OPTION_OP_GET,
172
.val64 = 1,
173
};
174
175
cmd.option_id = IOMMU_OPTION_RLIMIT_MODE;
176
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
177
ASSERT_EQ(0, cmd.val64);
178
179
/* This requires root */
180
cmd.op = IOMMU_OPTION_OP_SET;
181
cmd.val64 = 1;
182
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
183
cmd.val64 = 2;
184
EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_OPTION, &cmd));
185
186
cmd.op = IOMMU_OPTION_OP_GET;
187
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
188
ASSERT_EQ(1, cmd.val64);
189
190
cmd.op = IOMMU_OPTION_OP_SET;
191
cmd.val64 = 0;
192
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
193
194
cmd.op = IOMMU_OPTION_OP_GET;
195
cmd.option_id = IOMMU_OPTION_HUGE_PAGES;
196
EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_OPTION, &cmd));
197
cmd.op = IOMMU_OPTION_OP_SET;
198
EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_OPTION, &cmd));
199
}
200
201
static void drop_cap_ipc_lock(struct __test_metadata *_metadata)
202
{
203
cap_t caps;
204
cap_value_t cap_list[1] = { CAP_IPC_LOCK };
205
206
caps = cap_get_proc();
207
ASSERT_NE(caps, NULL);
208
ASSERT_NE(-1,
209
cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_CLEAR));
210
ASSERT_NE(-1, cap_set_proc(caps));
211
cap_free(caps);
212
}
213
214
static long get_proc_status_value(pid_t pid, const char *var)
215
{
216
FILE *fp;
217
char buf[80], tag[80];
218
long val = -1;
219
220
snprintf(buf, sizeof(buf), "/proc/%d/status", pid);
221
fp = fopen(buf, "r");
222
if (!fp)
223
return val;
224
225
while (fgets(buf, sizeof(buf), fp))
226
if (fscanf(fp, "%s %ld\n", tag, &val) == 2 && !strcmp(tag, var))
227
break;
228
229
fclose(fp);
230
return val;
231
}
232
233
static long get_vm_pinned(pid_t pid)
234
{
235
return get_proc_status_value(pid, "VmPin:");
236
}
237
238
static long get_vm_locked(pid_t pid)
239
{
240
return get_proc_status_value(pid, "VmLck:");
241
}
242
243
FIXTURE(change_process)
244
{
245
int fd;
246
uint32_t ioas_id;
247
};
248
249
FIXTURE_VARIANT(change_process)
250
{
251
int accounting;
252
};
253
254
FIXTURE_SETUP(change_process)
255
{
256
self->fd = open("/dev/iommu", O_RDWR);
257
ASSERT_NE(-1, self->fd);
258
259
drop_cap_ipc_lock(_metadata);
260
if (variant->accounting != IOPT_PAGES_ACCOUNT_NONE) {
261
struct iommu_option set_limit_cmd = {
262
.size = sizeof(set_limit_cmd),
263
.option_id = IOMMU_OPTION_RLIMIT_MODE,
264
.op = IOMMU_OPTION_OP_SET,
265
.val64 = (variant->accounting == IOPT_PAGES_ACCOUNT_MM),
266
};
267
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &set_limit_cmd));
268
}
269
270
test_ioctl_ioas_alloc(&self->ioas_id);
271
test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
272
}
273
274
FIXTURE_TEARDOWN(change_process)
275
{
276
teardown_iommufd(self->fd, _metadata);
277
}
278
279
FIXTURE_VARIANT_ADD(change_process, account_none)
280
{
281
.accounting = IOPT_PAGES_ACCOUNT_NONE,
282
};
283
284
FIXTURE_VARIANT_ADD(change_process, account_user)
285
{
286
.accounting = IOPT_PAGES_ACCOUNT_USER,
287
};
288
289
FIXTURE_VARIANT_ADD(change_process, account_mm)
290
{
291
.accounting = IOPT_PAGES_ACCOUNT_MM,
292
};
293
294
TEST_F(change_process, basic)
295
{
296
pid_t parent = getpid();
297
pid_t child;
298
__u64 iova;
299
struct iommu_ioas_change_process cmd = {
300
.size = sizeof(cmd),
301
};
302
303
/* Expect failure if non-file maps exist */
304
test_ioctl_ioas_map(buffer, PAGE_SIZE, &iova);
305
EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_IOAS_CHANGE_PROCESS, &cmd));
306
test_ioctl_ioas_unmap(iova, PAGE_SIZE);
307
308
/* Change process works in current process. */
309
test_ioctl_ioas_map_file(mfd, 0, PAGE_SIZE, &iova);
310
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_CHANGE_PROCESS, &cmd));
311
312
/* Change process works in another process */
313
child = fork();
314
if (!child) {
315
int nlock = PAGE_SIZE / 1024;
316
317
/* Parent accounts for locked memory before */
318
ASSERT_EQ(nlock, get_vm_pinned(parent));
319
if (variant->accounting == IOPT_PAGES_ACCOUNT_MM)
320
ASSERT_EQ(nlock, get_vm_locked(parent));
321
ASSERT_EQ(0, get_vm_pinned(getpid()));
322
ASSERT_EQ(0, get_vm_locked(getpid()));
323
324
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_CHANGE_PROCESS, &cmd));
325
326
/* Child accounts for locked memory after */
327
ASSERT_EQ(0, get_vm_pinned(parent));
328
ASSERT_EQ(0, get_vm_locked(parent));
329
ASSERT_EQ(nlock, get_vm_pinned(getpid()));
330
if (variant->accounting == IOPT_PAGES_ACCOUNT_MM)
331
ASSERT_EQ(nlock, get_vm_locked(getpid()));
332
333
exit(0);
334
}
335
ASSERT_NE(-1, child);
336
ASSERT_EQ(child, waitpid(child, NULL, 0));
337
}
338
339
FIXTURE(iommufd_ioas)
340
{
341
int fd;
342
uint32_t ioas_id;
343
uint32_t stdev_id;
344
uint32_t hwpt_id;
345
uint32_t device_id;
346
uint64_t base_iova;
347
uint32_t device_pasid_id;
348
};
349
350
FIXTURE_VARIANT(iommufd_ioas)
351
{
352
unsigned int mock_domains;
353
unsigned int memory_limit;
354
bool pasid_capable;
355
};
356
357
FIXTURE_SETUP(iommufd_ioas)
358
{
359
unsigned int i;
360
361
362
self->fd = open("/dev/iommu", O_RDWR);
363
ASSERT_NE(-1, self->fd);
364
test_ioctl_ioas_alloc(&self->ioas_id);
365
366
if (!variant->memory_limit) {
367
test_ioctl_set_default_memory_limit();
368
} else {
369
test_ioctl_set_temp_memory_limit(variant->memory_limit);
370
}
371
372
for (i = 0; i != variant->mock_domains; i++) {
373
test_cmd_mock_domain(self->ioas_id, &self->stdev_id,
374
&self->hwpt_id, &self->device_id);
375
test_cmd_dev_check_cache_all(self->device_id,
376
IOMMU_TEST_DEV_CACHE_DEFAULT);
377
self->base_iova = MOCK_APERTURE_START;
378
}
379
380
if (variant->pasid_capable)
381
test_cmd_mock_domain_flags(self->ioas_id,
382
MOCK_FLAGS_DEVICE_PASID,
383
NULL, NULL,
384
&self->device_pasid_id);
385
}
386
387
FIXTURE_TEARDOWN(iommufd_ioas)
388
{
389
test_ioctl_set_default_memory_limit();
390
teardown_iommufd(self->fd, _metadata);
391
}
392
393
FIXTURE_VARIANT_ADD(iommufd_ioas, no_domain)
394
{
395
};
396
397
FIXTURE_VARIANT_ADD(iommufd_ioas, mock_domain)
398
{
399
.mock_domains = 1,
400
.pasid_capable = true,
401
};
402
403
FIXTURE_VARIANT_ADD(iommufd_ioas, two_mock_domain)
404
{
405
.mock_domains = 2,
406
};
407
408
FIXTURE_VARIANT_ADD(iommufd_ioas, mock_domain_limit)
409
{
410
.mock_domains = 1,
411
.memory_limit = 16,
412
};
413
414
TEST_F(iommufd_ioas, ioas_auto_destroy)
415
{
416
}
417
418
TEST_F(iommufd_ioas, ioas_destroy)
419
{
420
if (self->stdev_id) {
421
/* IOAS cannot be freed while a device has a HWPT using it */
422
EXPECT_ERRNO(EBUSY,
423
_test_ioctl_destroy(self->fd, self->ioas_id));
424
} else {
425
/* Can allocate and manually free an IOAS table */
426
test_ioctl_destroy(self->ioas_id);
427
}
428
}
429
430
TEST_F(iommufd_ioas, alloc_hwpt_nested)
431
{
432
const uint32_t min_data_len =
433
offsetofend(struct iommu_hwpt_selftest, iotlb);
434
struct iommu_hwpt_selftest data = {
435
.iotlb = IOMMU_TEST_IOTLB_DEFAULT,
436
};
437
struct iommu_hwpt_invalidate_selftest inv_reqs[2] = {};
438
uint32_t nested_hwpt_id[2] = {};
439
uint32_t num_inv;
440
uint32_t parent_hwpt_id = 0;
441
uint32_t parent_hwpt_id_not_work = 0;
442
uint32_t test_hwpt_id = 0;
443
uint32_t iopf_hwpt_id;
444
uint32_t fault_id;
445
uint32_t fault_fd;
446
447
if (self->device_id) {
448
/* Negative tests */
449
test_err_hwpt_alloc(ENOENT, self->ioas_id, self->device_id, 0,
450
&test_hwpt_id);
451
test_err_hwpt_alloc(EINVAL, self->device_id, self->device_id, 0,
452
&test_hwpt_id);
453
test_err_hwpt_alloc(EOPNOTSUPP, self->device_id, self->ioas_id,
454
IOMMU_HWPT_ALLOC_NEST_PARENT |
455
IOMMU_HWPT_FAULT_ID_VALID,
456
&test_hwpt_id);
457
458
test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
459
IOMMU_HWPT_ALLOC_NEST_PARENT,
460
&parent_hwpt_id);
461
462
test_cmd_hwpt_alloc(self->device_id, self->ioas_id, 0,
463
&parent_hwpt_id_not_work);
464
465
/* Negative nested tests */
466
test_err_hwpt_alloc_nested(EINVAL, self->device_id,
467
parent_hwpt_id, 0,
468
&nested_hwpt_id[0],
469
IOMMU_HWPT_DATA_NONE, &data,
470
sizeof(data));
471
test_err_hwpt_alloc_nested(EOPNOTSUPP, self->device_id,
472
parent_hwpt_id, 0,
473
&nested_hwpt_id[0],
474
IOMMU_HWPT_DATA_SELFTEST + 1, &data,
475
sizeof(data));
476
test_err_hwpt_alloc_nested(EINVAL, self->device_id,
477
parent_hwpt_id, 0,
478
&nested_hwpt_id[0],
479
IOMMU_HWPT_DATA_SELFTEST, &data,
480
min_data_len - 1);
481
test_err_hwpt_alloc_nested(EFAULT, self->device_id,
482
parent_hwpt_id, 0,
483
&nested_hwpt_id[0],
484
IOMMU_HWPT_DATA_SELFTEST, NULL,
485
sizeof(data));
486
test_err_hwpt_alloc_nested(
487
EOPNOTSUPP, self->device_id, parent_hwpt_id,
488
IOMMU_HWPT_ALLOC_NEST_PARENT, &nested_hwpt_id[0],
489
IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data));
490
test_err_hwpt_alloc_nested(EINVAL, self->device_id,
491
parent_hwpt_id_not_work, 0,
492
&nested_hwpt_id[0],
493
IOMMU_HWPT_DATA_SELFTEST, &data,
494
sizeof(data));
495
496
/* Allocate two nested hwpts sharing one common parent hwpt */
497
test_ioctl_fault_alloc(&fault_id, &fault_fd);
498
test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id, 0,
499
&nested_hwpt_id[0],
500
IOMMU_HWPT_DATA_SELFTEST, &data,
501
sizeof(data));
502
test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id, 0,
503
&nested_hwpt_id[1],
504
IOMMU_HWPT_DATA_SELFTEST, &data,
505
sizeof(data));
506
test_err_hwpt_alloc_iopf(ENOENT, self->device_id, parent_hwpt_id,
507
UINT32_MAX, IOMMU_HWPT_FAULT_ID_VALID,
508
&iopf_hwpt_id, IOMMU_HWPT_DATA_SELFTEST,
509
&data, sizeof(data));
510
test_cmd_hwpt_alloc_iopf(self->device_id, parent_hwpt_id, fault_id,
511
IOMMU_HWPT_FAULT_ID_VALID, &iopf_hwpt_id,
512
IOMMU_HWPT_DATA_SELFTEST, &data,
513
sizeof(data));
514
test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[0],
515
IOMMU_TEST_IOTLB_DEFAULT);
516
test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[1],
517
IOMMU_TEST_IOTLB_DEFAULT);
518
519
/* Negative test: a nested hwpt on top of a nested hwpt */
520
test_err_hwpt_alloc_nested(EINVAL, self->device_id,
521
nested_hwpt_id[0], 0, &test_hwpt_id,
522
IOMMU_HWPT_DATA_SELFTEST, &data,
523
sizeof(data));
524
/* Negative test: parent hwpt now cannot be freed */
525
EXPECT_ERRNO(EBUSY,
526
_test_ioctl_destroy(self->fd, parent_hwpt_id));
527
528
/* hwpt_invalidate does not support a parent hwpt */
529
num_inv = 1;
530
test_err_hwpt_invalidate(EINVAL, parent_hwpt_id, inv_reqs,
531
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
532
sizeof(*inv_reqs), &num_inv);
533
assert(!num_inv);
534
535
/* Check data_type by passing zero-length array */
536
num_inv = 0;
537
test_cmd_hwpt_invalidate(nested_hwpt_id[0], inv_reqs,
538
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
539
sizeof(*inv_reqs), &num_inv);
540
assert(!num_inv);
541
542
/* Negative test: Invalid data_type */
543
num_inv = 1;
544
test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
545
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST_INVALID,
546
sizeof(*inv_reqs), &num_inv);
547
assert(!num_inv);
548
549
/* Negative test: structure size sanity */
550
num_inv = 1;
551
test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
552
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
553
sizeof(*inv_reqs) + 1, &num_inv);
554
assert(!num_inv);
555
556
num_inv = 1;
557
test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
558
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
559
1, &num_inv);
560
assert(!num_inv);
561
562
/* Negative test: invalid flag is passed */
563
num_inv = 1;
564
inv_reqs[0].flags = 0xffffffff;
565
test_err_hwpt_invalidate(EOPNOTSUPP, nested_hwpt_id[0], inv_reqs,
566
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
567
sizeof(*inv_reqs), &num_inv);
568
assert(!num_inv);
569
570
/* Negative test: invalid data_uptr when array is not empty */
571
num_inv = 1;
572
inv_reqs[0].flags = 0;
573
test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], NULL,
574
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
575
sizeof(*inv_reqs), &num_inv);
576
assert(!num_inv);
577
578
/* Negative test: invalid entry_len when array is not empty */
579
num_inv = 1;
580
inv_reqs[0].flags = 0;
581
test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
582
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
583
0, &num_inv);
584
assert(!num_inv);
585
586
/* Negative test: invalid iotlb_id */
587
num_inv = 1;
588
inv_reqs[0].flags = 0;
589
inv_reqs[0].iotlb_id = MOCK_NESTED_DOMAIN_IOTLB_ID_MAX + 1;
590
test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
591
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
592
sizeof(*inv_reqs), &num_inv);
593
assert(!num_inv);
594
595
/*
596
* Invalidate the 1st iotlb entry but fail the 2nd request
597
* due to invalid flags configuration in the 2nd request.
598
*/
599
num_inv = 2;
600
inv_reqs[0].flags = 0;
601
inv_reqs[0].iotlb_id = 0;
602
inv_reqs[1].flags = 0xffffffff;
603
inv_reqs[1].iotlb_id = 1;
604
test_err_hwpt_invalidate(EOPNOTSUPP, nested_hwpt_id[0], inv_reqs,
605
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
606
sizeof(*inv_reqs), &num_inv);
607
assert(num_inv == 1);
608
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 0, 0);
609
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 1,
610
IOMMU_TEST_IOTLB_DEFAULT);
611
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 2,
612
IOMMU_TEST_IOTLB_DEFAULT);
613
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 3,
614
IOMMU_TEST_IOTLB_DEFAULT);
615
616
/*
617
* Invalidate the 1st iotlb entry but fail the 2nd request
618
* due to invalid iotlb_id configuration in the 2nd request.
619
*/
620
num_inv = 2;
621
inv_reqs[0].flags = 0;
622
inv_reqs[0].iotlb_id = 0;
623
inv_reqs[1].flags = 0;
624
inv_reqs[1].iotlb_id = MOCK_NESTED_DOMAIN_IOTLB_ID_MAX + 1;
625
test_err_hwpt_invalidate(EINVAL, nested_hwpt_id[0], inv_reqs,
626
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
627
sizeof(*inv_reqs), &num_inv);
628
assert(num_inv == 1);
629
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 0, 0);
630
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 1,
631
IOMMU_TEST_IOTLB_DEFAULT);
632
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 2,
633
IOMMU_TEST_IOTLB_DEFAULT);
634
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 3,
635
IOMMU_TEST_IOTLB_DEFAULT);
636
637
/* Invalidate the 2nd iotlb entry and verify */
638
num_inv = 1;
639
inv_reqs[0].flags = 0;
640
inv_reqs[0].iotlb_id = 1;
641
test_cmd_hwpt_invalidate(nested_hwpt_id[0], inv_reqs,
642
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
643
sizeof(*inv_reqs), &num_inv);
644
assert(num_inv == 1);
645
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 0, 0);
646
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 1, 0);
647
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 2,
648
IOMMU_TEST_IOTLB_DEFAULT);
649
test_cmd_hwpt_check_iotlb(nested_hwpt_id[0], 3,
650
IOMMU_TEST_IOTLB_DEFAULT);
651
652
/* Invalidate the 3rd and 4th iotlb entries and verify */
653
num_inv = 2;
654
inv_reqs[0].flags = 0;
655
inv_reqs[0].iotlb_id = 2;
656
inv_reqs[1].flags = 0;
657
inv_reqs[1].iotlb_id = 3;
658
test_cmd_hwpt_invalidate(nested_hwpt_id[0], inv_reqs,
659
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
660
sizeof(*inv_reqs), &num_inv);
661
assert(num_inv == 2);
662
test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[0], 0);
663
664
/* Invalidate all iotlb entries for nested_hwpt_id[1] and verify */
665
num_inv = 1;
666
inv_reqs[0].flags = IOMMU_TEST_INVALIDATE_FLAG_ALL;
667
test_cmd_hwpt_invalidate(nested_hwpt_id[1], inv_reqs,
668
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
669
sizeof(*inv_reqs), &num_inv);
670
assert(num_inv == 1);
671
test_cmd_hwpt_check_iotlb_all(nested_hwpt_id[1], 0);
672
673
/* Attach device to nested_hwpt_id[0] that then will be busy */
674
test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[0]);
675
EXPECT_ERRNO(EBUSY,
676
_test_ioctl_destroy(self->fd, nested_hwpt_id[0]));
677
678
/* Switch from nested_hwpt_id[0] to nested_hwpt_id[1] */
679
test_cmd_mock_domain_replace(self->stdev_id, nested_hwpt_id[1]);
680
EXPECT_ERRNO(EBUSY,
681
_test_ioctl_destroy(self->fd, nested_hwpt_id[1]));
682
test_ioctl_destroy(nested_hwpt_id[0]);
683
684
/* Switch from nested_hwpt_id[1] to iopf_hwpt_id */
685
test_cmd_mock_domain_replace(self->stdev_id, iopf_hwpt_id);
686
EXPECT_ERRNO(EBUSY,
687
_test_ioctl_destroy(self->fd, iopf_hwpt_id));
688
/* Trigger an IOPF on the device */
689
test_cmd_trigger_iopf(self->device_id, fault_fd);
690
691
/* Detach from nested_hwpt_id[1] and destroy it */
692
test_cmd_mock_domain_replace(self->stdev_id, parent_hwpt_id);
693
test_ioctl_destroy(nested_hwpt_id[1]);
694
test_ioctl_destroy(iopf_hwpt_id);
695
696
/* Detach from the parent hw_pagetable and destroy it */
697
test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
698
test_ioctl_destroy(parent_hwpt_id);
699
test_ioctl_destroy(parent_hwpt_id_not_work);
700
close(fault_fd);
701
test_ioctl_destroy(fault_id);
702
} else {
703
test_err_hwpt_alloc(ENOENT, self->device_id, self->ioas_id, 0,
704
&parent_hwpt_id);
705
test_err_hwpt_alloc_nested(ENOENT, self->device_id,
706
parent_hwpt_id, 0,
707
&nested_hwpt_id[0],
708
IOMMU_HWPT_DATA_SELFTEST, &data,
709
sizeof(data));
710
test_err_hwpt_alloc_nested(ENOENT, self->device_id,
711
parent_hwpt_id, 0,
712
&nested_hwpt_id[1],
713
IOMMU_HWPT_DATA_SELFTEST, &data,
714
sizeof(data));
715
test_err_mock_domain_replace(ENOENT, self->stdev_id,
716
nested_hwpt_id[0]);
717
test_err_mock_domain_replace(ENOENT, self->stdev_id,
718
nested_hwpt_id[1]);
719
}
720
}
721
722
TEST_F(iommufd_ioas, hwpt_attach)
723
{
724
/* Create a device attached directly to a hwpt */
725
if (self->stdev_id) {
726
test_cmd_mock_domain(self->hwpt_id, NULL, NULL, NULL);
727
} else {
728
test_err_mock_domain(ENOENT, self->hwpt_id, NULL, NULL);
729
}
730
}
731
732
TEST_F(iommufd_ioas, ioas_area_destroy)
733
{
734
/* Adding an area does not change ability to destroy */
735
test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, self->base_iova);
736
if (self->stdev_id)
737
EXPECT_ERRNO(EBUSY,
738
_test_ioctl_destroy(self->fd, self->ioas_id));
739
else
740
test_ioctl_destroy(self->ioas_id);
741
}
742
743
TEST_F(iommufd_ioas, ioas_area_auto_destroy)
744
{
745
int i;
746
747
/* Can allocate and automatically free an IOAS table with many areas */
748
for (i = 0; i != 10; i++) {
749
test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE,
750
self->base_iova + i * PAGE_SIZE);
751
}
752
}
753
754
TEST_F(iommufd_ioas, get_hw_info)
755
{
756
struct iommu_test_hw_info buffer_exact;
757
struct iommu_test_hw_info_buffer_larger {
758
struct iommu_test_hw_info info;
759
uint64_t trailing_bytes;
760
} buffer_larger;
761
struct iommu_test_hw_info_buffer_smaller {
762
__u32 flags;
763
} buffer_smaller;
764
765
if (self->device_id) {
766
uint8_t max_pasid = 0;
767
768
/* Provide a zero-size user_buffer */
769
test_cmd_get_hw_info(self->device_id,
770
IOMMU_HW_INFO_TYPE_DEFAULT, NULL, 0);
771
/* Provide a user_buffer with exact size */
772
test_cmd_get_hw_info(self->device_id,
773
IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_exact,
774
sizeof(buffer_exact));
775
776
/* Request for a wrong data_type, and a correct one */
777
test_err_get_hw_info(EOPNOTSUPP, self->device_id,
778
IOMMU_HW_INFO_TYPE_SELFTEST + 1,
779
&buffer_exact, sizeof(buffer_exact));
780
test_cmd_get_hw_info(self->device_id,
781
IOMMU_HW_INFO_TYPE_SELFTEST, &buffer_exact,
782
sizeof(buffer_exact));
783
/*
784
* Provide a user_buffer with size larger than the exact size to check if
785
* kernel zero the trailing bytes.
786
*/
787
test_cmd_get_hw_info(self->device_id,
788
IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_larger,
789
sizeof(buffer_larger));
790
/*
791
* Provide a user_buffer with size smaller than the exact size to check if
792
* the fields within the size range still gets updated.
793
*/
794
test_cmd_get_hw_info(self->device_id,
795
IOMMU_HW_INFO_TYPE_DEFAULT,
796
&buffer_smaller, sizeof(buffer_smaller));
797
test_cmd_get_hw_info_pasid(self->device_id, &max_pasid);
798
ASSERT_EQ(0, max_pasid);
799
if (variant->pasid_capable) {
800
test_cmd_get_hw_info_pasid(self->device_pasid_id,
801
&max_pasid);
802
ASSERT_EQ(MOCK_PASID_WIDTH, max_pasid);
803
}
804
} else {
805
test_err_get_hw_info(ENOENT, self->device_id,
806
IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_exact,
807
sizeof(buffer_exact));
808
test_err_get_hw_info(ENOENT, self->device_id,
809
IOMMU_HW_INFO_TYPE_DEFAULT, &buffer_larger,
810
sizeof(buffer_larger));
811
}
812
}
813
814
TEST_F(iommufd_ioas, area)
815
{
816
int i;
817
818
/* Unmap fails if nothing is mapped */
819
for (i = 0; i != 10; i++)
820
test_err_ioctl_ioas_unmap(ENOENT, i * PAGE_SIZE, PAGE_SIZE);
821
822
/* Unmap works */
823
for (i = 0; i != 10; i++)
824
test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE,
825
self->base_iova + i * PAGE_SIZE);
826
for (i = 0; i != 10; i++)
827
test_ioctl_ioas_unmap(self->base_iova + i * PAGE_SIZE,
828
PAGE_SIZE);
829
830
/* Split fails */
831
test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE * 2,
832
self->base_iova + 16 * PAGE_SIZE);
833
test_err_ioctl_ioas_unmap(ENOENT, self->base_iova + 16 * PAGE_SIZE,
834
PAGE_SIZE);
835
test_err_ioctl_ioas_unmap(ENOENT, self->base_iova + 17 * PAGE_SIZE,
836
PAGE_SIZE);
837
838
/* Over map fails */
839
test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 2,
840
self->base_iova + 16 * PAGE_SIZE);
841
test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE,
842
self->base_iova + 16 * PAGE_SIZE);
843
test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE,
844
self->base_iova + 17 * PAGE_SIZE);
845
test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 2,
846
self->base_iova + 15 * PAGE_SIZE);
847
test_err_ioctl_ioas_map_fixed(EEXIST, buffer, PAGE_SIZE * 3,
848
self->base_iova + 15 * PAGE_SIZE);
849
850
/* unmap all works */
851
test_ioctl_ioas_unmap(0, UINT64_MAX);
852
853
/* Unmap all succeeds on an empty IOAS */
854
test_ioctl_ioas_unmap(0, UINT64_MAX);
855
}
856
857
TEST_F(iommufd_ioas, unmap_fully_contained_areas)
858
{
859
uint64_t unmap_len;
860
int i;
861
862
/* Give no_domain some space to rewind base_iova */
863
self->base_iova += 4 * PAGE_SIZE;
864
865
for (i = 0; i != 4; i++)
866
test_ioctl_ioas_map_fixed(buffer, 8 * PAGE_SIZE,
867
self->base_iova + i * 16 * PAGE_SIZE);
868
869
/* Unmap not fully contained area doesn't work */
870
test_err_ioctl_ioas_unmap(ENOENT, self->base_iova - 4 * PAGE_SIZE,
871
8 * PAGE_SIZE);
872
test_err_ioctl_ioas_unmap(ENOENT,
873
self->base_iova + 3 * 16 * PAGE_SIZE +
874
8 * PAGE_SIZE - 4 * PAGE_SIZE,
875
8 * PAGE_SIZE);
876
877
/* Unmap fully contained areas works */
878
ASSERT_EQ(0, _test_ioctl_ioas_unmap(self->fd, self->ioas_id,
879
self->base_iova - 4 * PAGE_SIZE,
880
3 * 16 * PAGE_SIZE + 8 * PAGE_SIZE +
881
4 * PAGE_SIZE,
882
&unmap_len));
883
ASSERT_EQ(32 * PAGE_SIZE, unmap_len);
884
}
885
886
TEST_F(iommufd_ioas, area_auto_iova)
887
{
888
struct iommu_test_cmd test_cmd = {
889
.size = sizeof(test_cmd),
890
.op = IOMMU_TEST_OP_ADD_RESERVED,
891
.id = self->ioas_id,
892
.add_reserved = { .start = PAGE_SIZE * 4,
893
.length = PAGE_SIZE * 100 },
894
};
895
struct iommu_iova_range ranges[1] = {};
896
struct iommu_ioas_allow_iovas allow_cmd = {
897
.size = sizeof(allow_cmd),
898
.ioas_id = self->ioas_id,
899
.num_iovas = 1,
900
.allowed_iovas = (uintptr_t)ranges,
901
};
902
__u64 iovas[10];
903
int i;
904
905
/* Simple 4k pages */
906
for (i = 0; i != 10; i++)
907
test_ioctl_ioas_map(buffer, PAGE_SIZE, &iovas[i]);
908
for (i = 0; i != 10; i++)
909
test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE);
910
911
/* Kernel automatically aligns IOVAs properly */
912
for (i = 0; i != 10; i++) {
913
size_t length = PAGE_SIZE * (i + 1);
914
915
if (self->stdev_id) {
916
test_ioctl_ioas_map(buffer, length, &iovas[i]);
917
} else {
918
test_ioctl_ioas_map((void *)(1UL << 31), length,
919
&iovas[i]);
920
}
921
EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
922
}
923
for (i = 0; i != 10; i++)
924
test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
925
926
/* Avoids a reserved region */
927
ASSERT_EQ(0,
928
ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
929
&test_cmd));
930
for (i = 0; i != 10; i++) {
931
size_t length = PAGE_SIZE * (i + 1);
932
933
test_ioctl_ioas_map(buffer, length, &iovas[i]);
934
EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
935
EXPECT_EQ(false,
936
iovas[i] > test_cmd.add_reserved.start &&
937
iovas[i] <
938
test_cmd.add_reserved.start +
939
test_cmd.add_reserved.length);
940
}
941
for (i = 0; i != 10; i++)
942
test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
943
944
/* Allowed region intersects with a reserved region */
945
ranges[0].start = PAGE_SIZE;
946
ranges[0].last = PAGE_SIZE * 600;
947
EXPECT_ERRNO(EADDRINUSE,
948
ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
949
950
/* Allocate from an allowed region */
951
if (self->stdev_id) {
952
ranges[0].start = MOCK_APERTURE_START + PAGE_SIZE;
953
ranges[0].last = MOCK_APERTURE_START + PAGE_SIZE * 600 - 1;
954
} else {
955
ranges[0].start = PAGE_SIZE * 200;
956
ranges[0].last = PAGE_SIZE * 600 - 1;
957
}
958
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
959
for (i = 0; i != 10; i++) {
960
size_t length = PAGE_SIZE * (i + 1);
961
962
test_ioctl_ioas_map(buffer, length, &iovas[i]);
963
EXPECT_EQ(0, iovas[i] % (1UL << (ffs(length) - 1)));
964
EXPECT_EQ(true, iovas[i] >= ranges[0].start);
965
EXPECT_EQ(true, iovas[i] <= ranges[0].last);
966
EXPECT_EQ(true, iovas[i] + length > ranges[0].start);
967
EXPECT_EQ(true, iovas[i] + length <= ranges[0].last + 1);
968
}
969
for (i = 0; i != 10; i++)
970
test_ioctl_ioas_unmap(iovas[i], PAGE_SIZE * (i + 1));
971
}
972
973
/* https://lore.kernel.org/r/[email protected] */
974
TEST_F(iommufd_ioas, reserved_overflow)
975
{
976
struct iommu_test_cmd test_cmd = {
977
.size = sizeof(test_cmd),
978
.op = IOMMU_TEST_OP_ADD_RESERVED,
979
.id = self->ioas_id,
980
.add_reserved.start = 6,
981
};
982
unsigned int map_len;
983
__u64 iova;
984
985
if (PAGE_SIZE == 4096) {
986
test_cmd.add_reserved.length = 0xffffffffffff8001;
987
map_len = 0x5000;
988
} else {
989
test_cmd.add_reserved.length =
990
0xffffffffffffffff - MOCK_PAGE_SIZE * 16;
991
map_len = MOCK_PAGE_SIZE * 10;
992
}
993
994
ASSERT_EQ(0,
995
ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
996
&test_cmd));
997
test_err_ioctl_ioas_map(ENOSPC, buffer, map_len, &iova);
998
}
999
1000
TEST_F(iommufd_ioas, area_allowed)
1001
{
1002
struct iommu_test_cmd test_cmd = {
1003
.size = sizeof(test_cmd),
1004
.op = IOMMU_TEST_OP_ADD_RESERVED,
1005
.id = self->ioas_id,
1006
.add_reserved = { .start = PAGE_SIZE * 4,
1007
.length = PAGE_SIZE * 100 },
1008
};
1009
struct iommu_iova_range ranges[1] = {};
1010
struct iommu_ioas_allow_iovas allow_cmd = {
1011
.size = sizeof(allow_cmd),
1012
.ioas_id = self->ioas_id,
1013
.num_iovas = 1,
1014
.allowed_iovas = (uintptr_t)ranges,
1015
};
1016
1017
/* Reserved intersects an allowed */
1018
allow_cmd.num_iovas = 1;
1019
ranges[0].start = self->base_iova;
1020
ranges[0].last = ranges[0].start + PAGE_SIZE * 600;
1021
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
1022
test_cmd.add_reserved.start = ranges[0].start + PAGE_SIZE;
1023
test_cmd.add_reserved.length = PAGE_SIZE;
1024
EXPECT_ERRNO(EADDRINUSE,
1025
ioctl(self->fd,
1026
_IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
1027
&test_cmd));
1028
allow_cmd.num_iovas = 0;
1029
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
1030
1031
/* Allowed intersects a reserved */
1032
ASSERT_EQ(0,
1033
ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
1034
&test_cmd));
1035
allow_cmd.num_iovas = 1;
1036
ranges[0].start = self->base_iova;
1037
ranges[0].last = ranges[0].start + PAGE_SIZE * 600;
1038
EXPECT_ERRNO(EADDRINUSE,
1039
ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd));
1040
}
1041
1042
TEST_F(iommufd_ioas, copy_area)
1043
{
1044
struct iommu_ioas_copy copy_cmd = {
1045
.size = sizeof(copy_cmd),
1046
.flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
1047
.dst_ioas_id = self->ioas_id,
1048
.src_ioas_id = self->ioas_id,
1049
.length = PAGE_SIZE,
1050
};
1051
1052
test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, self->base_iova);
1053
1054
/* Copy inside a single IOAS */
1055
copy_cmd.src_iova = self->base_iova;
1056
copy_cmd.dst_iova = self->base_iova + PAGE_SIZE;
1057
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
1058
1059
/* Copy between IOAS's */
1060
copy_cmd.src_iova = self->base_iova;
1061
copy_cmd.dst_iova = 0;
1062
test_ioctl_ioas_alloc(&copy_cmd.dst_ioas_id);
1063
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
1064
}
1065
1066
TEST_F(iommufd_ioas, iova_ranges)
1067
{
1068
struct iommu_test_cmd test_cmd = {
1069
.size = sizeof(test_cmd),
1070
.op = IOMMU_TEST_OP_ADD_RESERVED,
1071
.id = self->ioas_id,
1072
.add_reserved = { .start = PAGE_SIZE, .length = PAGE_SIZE },
1073
};
1074
struct iommu_iova_range *ranges = buffer;
1075
struct iommu_ioas_iova_ranges ranges_cmd = {
1076
.size = sizeof(ranges_cmd),
1077
.ioas_id = self->ioas_id,
1078
.num_iovas = BUFFER_SIZE / sizeof(*ranges),
1079
.allowed_iovas = (uintptr_t)ranges,
1080
};
1081
1082
/* Range can be read */
1083
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
1084
EXPECT_EQ(1, ranges_cmd.num_iovas);
1085
if (!self->stdev_id) {
1086
EXPECT_EQ(0, ranges[0].start);
1087
EXPECT_EQ(SIZE_MAX, ranges[0].last);
1088
EXPECT_EQ(1, ranges_cmd.out_iova_alignment);
1089
} else {
1090
EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
1091
EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
1092
EXPECT_EQ(MOCK_PAGE_SIZE, ranges_cmd.out_iova_alignment);
1093
}
1094
1095
/* Buffer too small */
1096
memset(ranges, 0, BUFFER_SIZE);
1097
ranges_cmd.num_iovas = 0;
1098
EXPECT_ERRNO(EMSGSIZE,
1099
ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
1100
EXPECT_EQ(1, ranges_cmd.num_iovas);
1101
EXPECT_EQ(0, ranges[0].start);
1102
EXPECT_EQ(0, ranges[0].last);
1103
1104
/* 2 ranges */
1105
ASSERT_EQ(0,
1106
ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ADD_RESERVED),
1107
&test_cmd));
1108
ranges_cmd.num_iovas = BUFFER_SIZE / sizeof(*ranges);
1109
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
1110
if (!self->stdev_id) {
1111
EXPECT_EQ(2, ranges_cmd.num_iovas);
1112
EXPECT_EQ(0, ranges[0].start);
1113
EXPECT_EQ(PAGE_SIZE - 1, ranges[0].last);
1114
EXPECT_EQ(PAGE_SIZE * 2, ranges[1].start);
1115
EXPECT_EQ(SIZE_MAX, ranges[1].last);
1116
} else {
1117
EXPECT_EQ(1, ranges_cmd.num_iovas);
1118
EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
1119
EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
1120
}
1121
1122
/* Buffer too small */
1123
memset(ranges, 0, BUFFER_SIZE);
1124
ranges_cmd.num_iovas = 1;
1125
if (!self->stdev_id) {
1126
EXPECT_ERRNO(EMSGSIZE, ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES,
1127
&ranges_cmd));
1128
EXPECT_EQ(2, ranges_cmd.num_iovas);
1129
EXPECT_EQ(0, ranges[0].start);
1130
EXPECT_EQ(PAGE_SIZE - 1, ranges[0].last);
1131
} else {
1132
ASSERT_EQ(0,
1133
ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd));
1134
EXPECT_EQ(1, ranges_cmd.num_iovas);
1135
EXPECT_EQ(MOCK_APERTURE_START, ranges[0].start);
1136
EXPECT_EQ(MOCK_APERTURE_LAST, ranges[0].last);
1137
}
1138
EXPECT_EQ(0, ranges[1].start);
1139
EXPECT_EQ(0, ranges[1].last);
1140
}
1141
1142
TEST_F(iommufd_ioas, access_domain_destory)
1143
{
1144
struct iommu_test_cmd access_cmd = {
1145
.size = sizeof(access_cmd),
1146
.op = IOMMU_TEST_OP_ACCESS_PAGES,
1147
.access_pages = { .iova = self->base_iova + PAGE_SIZE,
1148
.length = PAGE_SIZE},
1149
};
1150
size_t buf_size = 2 * HUGEPAGE_SIZE;
1151
uint8_t *buf;
1152
1153
buf = mmap(0, buf_size, PROT_READ | PROT_WRITE,
1154
MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1,
1155
0);
1156
ASSERT_NE(MAP_FAILED, buf);
1157
test_ioctl_ioas_map_fixed(buf, buf_size, self->base_iova);
1158
1159
test_cmd_create_access(self->ioas_id, &access_cmd.id,
1160
MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
1161
access_cmd.access_pages.uptr = (uintptr_t)buf + PAGE_SIZE;
1162
ASSERT_EQ(0,
1163
ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
1164
&access_cmd));
1165
1166
/* Causes a complicated unpin across a huge page boundary */
1167
if (self->stdev_id)
1168
test_ioctl_destroy(self->stdev_id);
1169
1170
test_cmd_destroy_access_pages(
1171
access_cmd.id, access_cmd.access_pages.out_access_pages_id);
1172
test_cmd_destroy_access(access_cmd.id);
1173
ASSERT_EQ(0, munmap(buf, buf_size));
1174
}
1175
1176
TEST_F(iommufd_ioas, access_pin)
1177
{
1178
struct iommu_test_cmd access_cmd = {
1179
.size = sizeof(access_cmd),
1180
.op = IOMMU_TEST_OP_ACCESS_PAGES,
1181
.access_pages = { .iova = MOCK_APERTURE_START,
1182
.length = BUFFER_SIZE,
1183
.uptr = (uintptr_t)buffer },
1184
};
1185
struct iommu_test_cmd check_map_cmd = {
1186
.size = sizeof(check_map_cmd),
1187
.op = IOMMU_TEST_OP_MD_CHECK_MAP,
1188
.check_map = { .iova = MOCK_APERTURE_START,
1189
.length = BUFFER_SIZE,
1190
.uptr = (uintptr_t)buffer },
1191
};
1192
uint32_t access_pages_id;
1193
unsigned int npages;
1194
1195
test_cmd_create_access(self->ioas_id, &access_cmd.id,
1196
MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
1197
1198
for (npages = 1; npages < BUFFER_SIZE / PAGE_SIZE; npages++) {
1199
uint32_t mock_stdev_id;
1200
uint32_t mock_hwpt_id;
1201
1202
access_cmd.access_pages.length = npages * PAGE_SIZE;
1203
1204
/* Single map/unmap */
1205
test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
1206
MOCK_APERTURE_START);
1207
ASSERT_EQ(0, ioctl(self->fd,
1208
_IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
1209
&access_cmd));
1210
test_cmd_destroy_access_pages(
1211
access_cmd.id,
1212
access_cmd.access_pages.out_access_pages_id);
1213
1214
/* Double user */
1215
ASSERT_EQ(0, ioctl(self->fd,
1216
_IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
1217
&access_cmd));
1218
access_pages_id = access_cmd.access_pages.out_access_pages_id;
1219
ASSERT_EQ(0, ioctl(self->fd,
1220
_IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
1221
&access_cmd));
1222
test_cmd_destroy_access_pages(
1223
access_cmd.id,
1224
access_cmd.access_pages.out_access_pages_id);
1225
test_cmd_destroy_access_pages(access_cmd.id, access_pages_id);
1226
1227
/* Add/remove a domain with a user */
1228
ASSERT_EQ(0, ioctl(self->fd,
1229
_IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
1230
&access_cmd));
1231
test_cmd_mock_domain(self->ioas_id, &mock_stdev_id,
1232
&mock_hwpt_id, NULL);
1233
check_map_cmd.id = mock_hwpt_id;
1234
ASSERT_EQ(0, ioctl(self->fd,
1235
_IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_MAP),
1236
&check_map_cmd));
1237
1238
test_ioctl_destroy(mock_stdev_id);
1239
test_cmd_destroy_access_pages(
1240
access_cmd.id,
1241
access_cmd.access_pages.out_access_pages_id);
1242
1243
test_ioctl_ioas_unmap(MOCK_APERTURE_START, BUFFER_SIZE);
1244
}
1245
test_cmd_destroy_access(access_cmd.id);
1246
}
1247
1248
TEST_F(iommufd_ioas, access_pin_unmap)
1249
{
1250
struct iommu_test_cmd access_pages_cmd = {
1251
.size = sizeof(access_pages_cmd),
1252
.op = IOMMU_TEST_OP_ACCESS_PAGES,
1253
.access_pages = { .iova = MOCK_APERTURE_START,
1254
.length = BUFFER_SIZE,
1255
.uptr = (uintptr_t)buffer },
1256
};
1257
1258
test_cmd_create_access(self->ioas_id, &access_pages_cmd.id,
1259
MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
1260
test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE, MOCK_APERTURE_START);
1261
ASSERT_EQ(0,
1262
ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
1263
&access_pages_cmd));
1264
1265
/* Trigger the unmap op */
1266
test_ioctl_ioas_unmap(MOCK_APERTURE_START, BUFFER_SIZE);
1267
1268
/* kernel removed the item for us */
1269
test_err_destroy_access_pages(
1270
ENOENT, access_pages_cmd.id,
1271
access_pages_cmd.access_pages.out_access_pages_id);
1272
}
1273
1274
static void check_access_rw(struct __test_metadata *_metadata, int fd,
1275
unsigned int access_id, uint64_t iova,
1276
unsigned int def_flags)
1277
{
1278
uint16_t tmp[32];
1279
struct iommu_test_cmd access_cmd = {
1280
.size = sizeof(access_cmd),
1281
.op = IOMMU_TEST_OP_ACCESS_RW,
1282
.id = access_id,
1283
.access_rw = { .uptr = (uintptr_t)tmp },
1284
};
1285
uint16_t *buffer16 = buffer;
1286
unsigned int i;
1287
void *tmp2;
1288
1289
for (i = 0; i != BUFFER_SIZE / sizeof(*buffer16); i++)
1290
buffer16[i] = rand();
1291
1292
for (access_cmd.access_rw.iova = iova + PAGE_SIZE - 50;
1293
access_cmd.access_rw.iova < iova + PAGE_SIZE + 50;
1294
access_cmd.access_rw.iova++) {
1295
for (access_cmd.access_rw.length = 1;
1296
access_cmd.access_rw.length < sizeof(tmp);
1297
access_cmd.access_rw.length++) {
1298
access_cmd.access_rw.flags = def_flags;
1299
ASSERT_EQ(0, ioctl(fd,
1300
_IOMMU_TEST_CMD(
1301
IOMMU_TEST_OP_ACCESS_RW),
1302
&access_cmd));
1303
ASSERT_EQ(0,
1304
memcmp(buffer + (access_cmd.access_rw.iova -
1305
iova),
1306
tmp, access_cmd.access_rw.length));
1307
1308
for (i = 0; i != ARRAY_SIZE(tmp); i++)
1309
tmp[i] = rand();
1310
access_cmd.access_rw.flags = def_flags |
1311
MOCK_ACCESS_RW_WRITE;
1312
ASSERT_EQ(0, ioctl(fd,
1313
_IOMMU_TEST_CMD(
1314
IOMMU_TEST_OP_ACCESS_RW),
1315
&access_cmd));
1316
ASSERT_EQ(0,
1317
memcmp(buffer + (access_cmd.access_rw.iova -
1318
iova),
1319
tmp, access_cmd.access_rw.length));
1320
}
1321
}
1322
1323
/* Multi-page test */
1324
tmp2 = malloc(BUFFER_SIZE);
1325
ASSERT_NE(NULL, tmp2);
1326
access_cmd.access_rw.iova = iova;
1327
access_cmd.access_rw.length = BUFFER_SIZE;
1328
access_cmd.access_rw.flags = def_flags;
1329
access_cmd.access_rw.uptr = (uintptr_t)tmp2;
1330
ASSERT_EQ(0, ioctl(fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW),
1331
&access_cmd));
1332
ASSERT_EQ(0, memcmp(buffer, tmp2, access_cmd.access_rw.length));
1333
free(tmp2);
1334
}
1335
1336
TEST_F(iommufd_ioas, access_rw)
1337
{
1338
__u32 access_id;
1339
__u64 iova;
1340
1341
test_cmd_create_access(self->ioas_id, &access_id, 0);
1342
test_ioctl_ioas_map(buffer, BUFFER_SIZE, &iova);
1343
check_access_rw(_metadata, self->fd, access_id, iova, 0);
1344
check_access_rw(_metadata, self->fd, access_id, iova,
1345
MOCK_ACCESS_RW_SLOW_PATH);
1346
test_ioctl_ioas_unmap(iova, BUFFER_SIZE);
1347
test_cmd_destroy_access(access_id);
1348
}
1349
1350
TEST_F(iommufd_ioas, access_rw_unaligned)
1351
{
1352
__u32 access_id;
1353
__u64 iova;
1354
1355
test_cmd_create_access(self->ioas_id, &access_id, 0);
1356
1357
/* Unaligned pages */
1358
iova = self->base_iova + MOCK_PAGE_SIZE;
1359
test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE, iova);
1360
check_access_rw(_metadata, self->fd, access_id, iova, 0);
1361
test_ioctl_ioas_unmap(iova, BUFFER_SIZE);
1362
test_cmd_destroy_access(access_id);
1363
}
1364
1365
TEST_F(iommufd_ioas, fork_gone)
1366
{
1367
__u32 access_id;
1368
pid_t child;
1369
1370
test_cmd_create_access(self->ioas_id, &access_id, 0);
1371
1372
/* Create a mapping with a different mm */
1373
child = fork();
1374
if (!child) {
1375
test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
1376
MOCK_APERTURE_START);
1377
exit(0);
1378
}
1379
ASSERT_NE(-1, child);
1380
ASSERT_EQ(child, waitpid(child, NULL, 0));
1381
1382
if (self->stdev_id) {
1383
/*
1384
* If a domain already existed then everything was pinned within
1385
* the fork, so this copies from one domain to another.
1386
*/
1387
test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
1388
check_access_rw(_metadata, self->fd, access_id,
1389
MOCK_APERTURE_START, 0);
1390
1391
} else {
1392
/*
1393
* Otherwise we need to actually pin pages which can't happen
1394
* since the fork is gone.
1395
*/
1396
test_err_mock_domain(EFAULT, self->ioas_id, NULL, NULL);
1397
}
1398
1399
test_cmd_destroy_access(access_id);
1400
}
1401
1402
TEST_F(iommufd_ioas, fork_present)
1403
{
1404
__u32 access_id;
1405
int pipefds[2];
1406
uint64_t tmp;
1407
pid_t child;
1408
int efd;
1409
1410
test_cmd_create_access(self->ioas_id, &access_id, 0);
1411
1412
ASSERT_EQ(0, pipe2(pipefds, O_CLOEXEC));
1413
efd = eventfd(0, EFD_CLOEXEC);
1414
ASSERT_NE(-1, efd);
1415
1416
/* Create a mapping with a different mm */
1417
child = fork();
1418
if (!child) {
1419
__u64 iova;
1420
uint64_t one = 1;
1421
1422
close(pipefds[1]);
1423
test_ioctl_ioas_map_fixed(buffer, BUFFER_SIZE,
1424
MOCK_APERTURE_START);
1425
if (write(efd, &one, sizeof(one)) != sizeof(one))
1426
exit(100);
1427
if (read(pipefds[0], &iova, 1) != 1)
1428
exit(100);
1429
exit(0);
1430
}
1431
close(pipefds[0]);
1432
ASSERT_NE(-1, child);
1433
ASSERT_EQ(8, read(efd, &tmp, sizeof(tmp)));
1434
1435
/* Read pages from the remote process */
1436
test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
1437
check_access_rw(_metadata, self->fd, access_id, MOCK_APERTURE_START, 0);
1438
1439
ASSERT_EQ(0, close(pipefds[1]));
1440
ASSERT_EQ(child, waitpid(child, NULL, 0));
1441
1442
test_cmd_destroy_access(access_id);
1443
}
1444
1445
TEST_F(iommufd_ioas, ioas_option_huge_pages)
1446
{
1447
struct iommu_option cmd = {
1448
.size = sizeof(cmd),
1449
.option_id = IOMMU_OPTION_HUGE_PAGES,
1450
.op = IOMMU_OPTION_OP_GET,
1451
.val64 = 3,
1452
.object_id = self->ioas_id,
1453
};
1454
1455
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1456
ASSERT_EQ(1, cmd.val64);
1457
1458
cmd.op = IOMMU_OPTION_OP_SET;
1459
cmd.val64 = 0;
1460
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1461
1462
cmd.op = IOMMU_OPTION_OP_GET;
1463
cmd.val64 = 3;
1464
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1465
ASSERT_EQ(0, cmd.val64);
1466
1467
cmd.op = IOMMU_OPTION_OP_SET;
1468
cmd.val64 = 2;
1469
EXPECT_ERRNO(EINVAL, ioctl(self->fd, IOMMU_OPTION, &cmd));
1470
1471
cmd.op = IOMMU_OPTION_OP_SET;
1472
cmd.val64 = 1;
1473
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1474
}
1475
1476
TEST_F(iommufd_ioas, ioas_iova_alloc)
1477
{
1478
unsigned int length;
1479
__u64 iova;
1480
1481
for (length = 1; length != PAGE_SIZE * 2; length++) {
1482
if (variant->mock_domains && (length % MOCK_PAGE_SIZE)) {
1483
test_err_ioctl_ioas_map(EINVAL, buffer, length, &iova);
1484
} else {
1485
test_ioctl_ioas_map(buffer, length, &iova);
1486
test_ioctl_ioas_unmap(iova, length);
1487
}
1488
}
1489
}
1490
1491
TEST_F(iommufd_ioas, ioas_align_change)
1492
{
1493
struct iommu_option cmd = {
1494
.size = sizeof(cmd),
1495
.option_id = IOMMU_OPTION_HUGE_PAGES,
1496
.op = IOMMU_OPTION_OP_SET,
1497
.object_id = self->ioas_id,
1498
/* 0 means everything must be aligned to PAGE_SIZE */
1499
.val64 = 0,
1500
};
1501
1502
/*
1503
* We cannot upgrade the alignment using OPTION_HUGE_PAGES when a domain
1504
* and map are present.
1505
*/
1506
if (variant->mock_domains)
1507
return;
1508
1509
/*
1510
* We can upgrade to PAGE_SIZE alignment when things are aligned right
1511
*/
1512
test_ioctl_ioas_map_fixed(buffer, PAGE_SIZE, MOCK_APERTURE_START);
1513
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1514
1515
/* Misalignment is rejected at map time */
1516
test_err_ioctl_ioas_map_fixed(EINVAL, buffer + MOCK_PAGE_SIZE,
1517
PAGE_SIZE,
1518
MOCK_APERTURE_START + PAGE_SIZE);
1519
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1520
1521
/* Reduce alignment */
1522
cmd.val64 = 1;
1523
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
1524
1525
/* Confirm misalignment is rejected during alignment upgrade */
1526
test_ioctl_ioas_map_fixed(buffer + MOCK_PAGE_SIZE, PAGE_SIZE,
1527
MOCK_APERTURE_START + PAGE_SIZE);
1528
cmd.val64 = 0;
1529
EXPECT_ERRNO(EADDRINUSE, ioctl(self->fd, IOMMU_OPTION, &cmd));
1530
1531
test_ioctl_ioas_unmap(MOCK_APERTURE_START + PAGE_SIZE, PAGE_SIZE);
1532
test_ioctl_ioas_unmap(MOCK_APERTURE_START, PAGE_SIZE);
1533
}
1534
1535
TEST_F(iommufd_ioas, copy_sweep)
1536
{
1537
struct iommu_ioas_copy copy_cmd = {
1538
.size = sizeof(copy_cmd),
1539
.flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
1540
.src_ioas_id = self->ioas_id,
1541
.dst_iova = MOCK_APERTURE_START,
1542
.length = MOCK_PAGE_SIZE,
1543
};
1544
unsigned int dst_ioas_id;
1545
uint64_t last_iova;
1546
uint64_t iova;
1547
1548
test_ioctl_ioas_alloc(&dst_ioas_id);
1549
copy_cmd.dst_ioas_id = dst_ioas_id;
1550
1551
if (variant->mock_domains)
1552
last_iova = MOCK_APERTURE_START + BUFFER_SIZE - 1;
1553
else
1554
last_iova = MOCK_APERTURE_START + BUFFER_SIZE - 2;
1555
1556
test_ioctl_ioas_map_fixed(buffer, last_iova - MOCK_APERTURE_START + 1,
1557
MOCK_APERTURE_START);
1558
1559
for (iova = MOCK_APERTURE_START - PAGE_SIZE; iova <= last_iova;
1560
iova += 511) {
1561
copy_cmd.src_iova = iova;
1562
if (iova < MOCK_APERTURE_START ||
1563
iova + copy_cmd.length - 1 > last_iova) {
1564
EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_IOAS_COPY,
1565
&copy_cmd));
1566
} else {
1567
ASSERT_EQ(0,
1568
ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
1569
test_ioctl_ioas_unmap_id(dst_ioas_id, copy_cmd.dst_iova,
1570
copy_cmd.length);
1571
}
1572
}
1573
1574
test_ioctl_destroy(dst_ioas_id);
1575
}
1576
1577
FIXTURE(iommufd_mock_domain)
1578
{
1579
int fd;
1580
uint32_t ioas_id;
1581
uint32_t hwpt_id;
1582
uint32_t hwpt_ids[2];
1583
uint32_t stdev_ids[2];
1584
uint32_t idev_ids[2];
1585
int mmap_flags;
1586
size_t mmap_buf_size;
1587
};
1588
1589
FIXTURE_VARIANT(iommufd_mock_domain)
1590
{
1591
unsigned int mock_domains;
1592
bool hugepages;
1593
bool file;
1594
};
1595
1596
FIXTURE_SETUP(iommufd_mock_domain)
1597
{
1598
unsigned int i;
1599
1600
self->fd = open("/dev/iommu", O_RDWR);
1601
ASSERT_NE(-1, self->fd);
1602
test_ioctl_ioas_alloc(&self->ioas_id);
1603
1604
ASSERT_GE(ARRAY_SIZE(self->hwpt_ids), variant->mock_domains);
1605
1606
for (i = 0; i != variant->mock_domains; i++) {
1607
test_cmd_mock_domain(self->ioas_id, &self->stdev_ids[i],
1608
&self->hwpt_ids[i], &self->idev_ids[i]);
1609
test_cmd_dev_check_cache_all(self->idev_ids[0],
1610
IOMMU_TEST_DEV_CACHE_DEFAULT);
1611
}
1612
self->hwpt_id = self->hwpt_ids[0];
1613
1614
self->mmap_flags = MAP_SHARED | MAP_ANONYMOUS;
1615
self->mmap_buf_size = PAGE_SIZE * 8;
1616
if (variant->hugepages) {
1617
/*
1618
* MAP_POPULATE will cause the kernel to fail mmap if THPs are
1619
* not available.
1620
*/
1621
self->mmap_flags |= MAP_HUGETLB | MAP_POPULATE;
1622
self->mmap_buf_size = HUGEPAGE_SIZE * 2;
1623
}
1624
}
1625
1626
FIXTURE_TEARDOWN(iommufd_mock_domain)
1627
{
1628
teardown_iommufd(self->fd, _metadata);
1629
}
1630
1631
FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain)
1632
{
1633
.mock_domains = 1,
1634
.hugepages = false,
1635
.file = false,
1636
};
1637
1638
FIXTURE_VARIANT_ADD(iommufd_mock_domain, two_domains)
1639
{
1640
.mock_domains = 2,
1641
.hugepages = false,
1642
.file = false,
1643
};
1644
1645
FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain_hugepage)
1646
{
1647
.mock_domains = 1,
1648
.hugepages = true,
1649
.file = false,
1650
};
1651
1652
FIXTURE_VARIANT_ADD(iommufd_mock_domain, two_domains_hugepage)
1653
{
1654
.mock_domains = 2,
1655
.hugepages = true,
1656
.file = false,
1657
};
1658
1659
FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain_file)
1660
{
1661
.mock_domains = 1,
1662
.hugepages = false,
1663
.file = true,
1664
};
1665
1666
FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain_file_hugepage)
1667
{
1668
.mock_domains = 1,
1669
.hugepages = true,
1670
.file = true,
1671
};
1672
1673
1674
/* Have the kernel check that the user pages made it to the iommu_domain */
1675
#define check_mock_iova(_ptr, _iova, _length) \
1676
({ \
1677
struct iommu_test_cmd check_map_cmd = { \
1678
.size = sizeof(check_map_cmd), \
1679
.op = IOMMU_TEST_OP_MD_CHECK_MAP, \
1680
.id = self->hwpt_id, \
1681
.check_map = { .iova = _iova, \
1682
.length = _length, \
1683
.uptr = (uintptr_t)(_ptr) }, \
1684
}; \
1685
ASSERT_EQ(0, \
1686
ioctl(self->fd, \
1687
_IOMMU_TEST_CMD(IOMMU_TEST_OP_MD_CHECK_MAP), \
1688
&check_map_cmd)); \
1689
if (self->hwpt_ids[1]) { \
1690
check_map_cmd.id = self->hwpt_ids[1]; \
1691
ASSERT_EQ(0, \
1692
ioctl(self->fd, \
1693
_IOMMU_TEST_CMD( \
1694
IOMMU_TEST_OP_MD_CHECK_MAP), \
1695
&check_map_cmd)); \
1696
} \
1697
})
1698
1699
static void
1700
test_basic_mmap(struct __test_metadata *_metadata,
1701
struct _test_data_iommufd_mock_domain *self,
1702
const struct _fixture_variant_iommufd_mock_domain *variant)
1703
{
1704
size_t buf_size = self->mmap_buf_size;
1705
uint8_t *buf;
1706
__u64 iova;
1707
1708
/* Simple one page map */
1709
test_ioctl_ioas_map(buffer, PAGE_SIZE, &iova);
1710
check_mock_iova(buffer, iova, PAGE_SIZE);
1711
1712
buf = mmap(0, buf_size, PROT_READ | PROT_WRITE, self->mmap_flags, -1,
1713
0);
1714
ASSERT_NE(MAP_FAILED, buf);
1715
1716
/* EFAULT half way through mapping */
1717
ASSERT_EQ(0, munmap(buf + buf_size / 2, buf_size / 2));
1718
test_err_ioctl_ioas_map(EFAULT, buf, buf_size, &iova);
1719
1720
/* EFAULT on first page */
1721
ASSERT_EQ(0, munmap(buf, buf_size / 2));
1722
test_err_ioctl_ioas_map(EFAULT, buf, buf_size, &iova);
1723
}
1724
1725
static void
1726
test_basic_file(struct __test_metadata *_metadata,
1727
struct _test_data_iommufd_mock_domain *self,
1728
const struct _fixture_variant_iommufd_mock_domain *variant)
1729
{
1730
size_t buf_size = self->mmap_buf_size;
1731
uint8_t *buf;
1732
__u64 iova;
1733
int mfd_tmp;
1734
int prot = PROT_READ | PROT_WRITE;
1735
1736
/* Simple one page map */
1737
test_ioctl_ioas_map_file(mfd, 0, PAGE_SIZE, &iova);
1738
check_mock_iova(mfd_buffer, iova, PAGE_SIZE);
1739
1740
buf = memfd_mmap(buf_size, prot, MAP_SHARED, &mfd_tmp);
1741
ASSERT_NE(MAP_FAILED, buf);
1742
1743
test_err_ioctl_ioas_map_file(EINVAL, mfd_tmp, 0, buf_size + 1, &iova);
1744
1745
ASSERT_EQ(0, ftruncate(mfd_tmp, 0));
1746
test_err_ioctl_ioas_map_file(EINVAL, mfd_tmp, 0, buf_size, &iova);
1747
1748
close(mfd_tmp);
1749
}
1750
1751
TEST_F(iommufd_mock_domain, basic)
1752
{
1753
if (variant->file)
1754
test_basic_file(_metadata, self, variant);
1755
else
1756
test_basic_mmap(_metadata, self, variant);
1757
}
1758
1759
TEST_F(iommufd_mock_domain, ro_unshare)
1760
{
1761
uint8_t *buf;
1762
__u64 iova;
1763
int fd;
1764
1765
fd = open("/proc/self/exe", O_RDONLY);
1766
ASSERT_NE(-1, fd);
1767
1768
buf = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
1769
ASSERT_NE(MAP_FAILED, buf);
1770
close(fd);
1771
1772
/*
1773
* There have been lots of changes to the "unshare" mechanism in
1774
* get_user_pages(), make sure it works right. The write to the page
1775
* after we map it for reading should not change the assigned PFN.
1776
*/
1777
ASSERT_EQ(0,
1778
_test_ioctl_ioas_map(self->fd, self->ioas_id, buf, PAGE_SIZE,
1779
&iova, IOMMU_IOAS_MAP_READABLE));
1780
check_mock_iova(buf, iova, PAGE_SIZE);
1781
memset(buf, 1, PAGE_SIZE);
1782
check_mock_iova(buf, iova, PAGE_SIZE);
1783
ASSERT_EQ(0, munmap(buf, PAGE_SIZE));
1784
}
1785
1786
TEST_F(iommufd_mock_domain, all_aligns)
1787
{
1788
size_t test_step = variant->hugepages ? (self->mmap_buf_size / 16) :
1789
MOCK_PAGE_SIZE;
1790
size_t buf_size = self->mmap_buf_size;
1791
unsigned int start;
1792
unsigned int end;
1793
uint8_t *buf;
1794
int prot = PROT_READ | PROT_WRITE;
1795
int mfd = -1;
1796
1797
if (variant->file)
1798
buf = memfd_mmap(buf_size, prot, MAP_SHARED, &mfd);
1799
else
1800
buf = mmap(0, buf_size, prot, self->mmap_flags, -1, 0);
1801
ASSERT_NE(MAP_FAILED, buf);
1802
if (variant->file)
1803
ASSERT_GT(mfd, 0);
1804
check_refs(buf, buf_size, 0);
1805
1806
/*
1807
* Map every combination of page size and alignment within a big region,
1808
* less for hugepage case as it takes so long to finish.
1809
*/
1810
for (start = 0; start < buf_size; start += test_step) {
1811
if (variant->hugepages)
1812
end = buf_size;
1813
else
1814
end = start + MOCK_PAGE_SIZE;
1815
for (; end < buf_size; end += MOCK_PAGE_SIZE) {
1816
size_t length = end - start;
1817
__u64 iova;
1818
1819
if (variant->file) {
1820
test_ioctl_ioas_map_file(mfd, start, length,
1821
&iova);
1822
} else {
1823
test_ioctl_ioas_map(buf + start, length, &iova);
1824
}
1825
check_mock_iova(buf + start, iova, length);
1826
check_refs(buf + start / PAGE_SIZE * PAGE_SIZE,
1827
end / PAGE_SIZE * PAGE_SIZE -
1828
start / PAGE_SIZE * PAGE_SIZE,
1829
1);
1830
1831
test_ioctl_ioas_unmap(iova, length);
1832
}
1833
}
1834
check_refs(buf, buf_size, 0);
1835
ASSERT_EQ(0, munmap(buf, buf_size));
1836
if (variant->file)
1837
close(mfd);
1838
}
1839
1840
TEST_F(iommufd_mock_domain, all_aligns_copy)
1841
{
1842
size_t test_step = variant->hugepages ? self->mmap_buf_size / 16 :
1843
MOCK_PAGE_SIZE;
1844
size_t buf_size = self->mmap_buf_size;
1845
unsigned int start;
1846
unsigned int end;
1847
uint8_t *buf;
1848
int prot = PROT_READ | PROT_WRITE;
1849
int mfd = -1;
1850
1851
if (variant->file)
1852
buf = memfd_mmap(buf_size, prot, MAP_SHARED, &mfd);
1853
else
1854
buf = mmap(0, buf_size, prot, self->mmap_flags, -1, 0);
1855
ASSERT_NE(MAP_FAILED, buf);
1856
if (variant->file)
1857
ASSERT_GT(mfd, 0);
1858
check_refs(buf, buf_size, 0);
1859
1860
/*
1861
* Map every combination of page size and alignment within a big region,
1862
* less for hugepage case as it takes so long to finish.
1863
*/
1864
for (start = 0; start < buf_size; start += test_step) {
1865
if (variant->hugepages)
1866
end = buf_size;
1867
else
1868
end = start + MOCK_PAGE_SIZE;
1869
for (; end < buf_size; end += MOCK_PAGE_SIZE) {
1870
size_t length = end - start;
1871
unsigned int old_id;
1872
uint32_t mock_stdev_id;
1873
__u64 iova;
1874
1875
if (variant->file) {
1876
test_ioctl_ioas_map_file(mfd, start, length,
1877
&iova);
1878
} else {
1879
test_ioctl_ioas_map(buf + start, length, &iova);
1880
}
1881
1882
/* Add and destroy a domain while the area exists */
1883
old_id = self->hwpt_ids[1];
1884
test_cmd_mock_domain(self->ioas_id, &mock_stdev_id,
1885
&self->hwpt_ids[1], NULL);
1886
1887
check_mock_iova(buf + start, iova, length);
1888
check_refs(buf + start / PAGE_SIZE * PAGE_SIZE,
1889
end / PAGE_SIZE * PAGE_SIZE -
1890
start / PAGE_SIZE * PAGE_SIZE,
1891
1);
1892
1893
test_ioctl_destroy(mock_stdev_id);
1894
self->hwpt_ids[1] = old_id;
1895
1896
test_ioctl_ioas_unmap(iova, length);
1897
}
1898
}
1899
check_refs(buf, buf_size, 0);
1900
ASSERT_EQ(0, munmap(buf, buf_size));
1901
if (variant->file)
1902
close(mfd);
1903
}
1904
1905
TEST_F(iommufd_mock_domain, user_copy)
1906
{
1907
void *buf = variant->file ? mfd_buffer : buffer;
1908
struct iommu_test_cmd access_cmd = {
1909
.size = sizeof(access_cmd),
1910
.op = IOMMU_TEST_OP_ACCESS_PAGES,
1911
.access_pages = { .length = BUFFER_SIZE,
1912
.uptr = (uintptr_t)buf },
1913
};
1914
struct iommu_ioas_copy copy_cmd = {
1915
.size = sizeof(copy_cmd),
1916
.flags = IOMMU_IOAS_MAP_FIXED_IOVA | IOMMU_IOAS_MAP_WRITEABLE,
1917
.dst_ioas_id = self->ioas_id,
1918
.dst_iova = MOCK_APERTURE_START,
1919
.length = BUFFER_SIZE,
1920
};
1921
struct iommu_ioas_unmap unmap_cmd = {
1922
.size = sizeof(unmap_cmd),
1923
.ioas_id = self->ioas_id,
1924
.iova = MOCK_APERTURE_START,
1925
.length = BUFFER_SIZE,
1926
};
1927
unsigned int new_ioas_id, ioas_id;
1928
1929
/* Pin the pages in an IOAS with no domains then copy to an IOAS with domains */
1930
test_ioctl_ioas_alloc(&ioas_id);
1931
if (variant->file) {
1932
test_ioctl_ioas_map_id_file(ioas_id, mfd, 0, BUFFER_SIZE,
1933
&copy_cmd.src_iova);
1934
} else {
1935
test_ioctl_ioas_map_id(ioas_id, buf, BUFFER_SIZE,
1936
&copy_cmd.src_iova);
1937
}
1938
test_cmd_create_access(ioas_id, &access_cmd.id,
1939
MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES);
1940
1941
access_cmd.access_pages.iova = copy_cmd.src_iova;
1942
ASSERT_EQ(0,
1943
ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
1944
&access_cmd));
1945
copy_cmd.src_ioas_id = ioas_id;
1946
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
1947
check_mock_iova(buf, MOCK_APERTURE_START, BUFFER_SIZE);
1948
1949
/* Now replace the ioas with a new one */
1950
test_ioctl_ioas_alloc(&new_ioas_id);
1951
if (variant->file) {
1952
test_ioctl_ioas_map_id_file(new_ioas_id, mfd, 0, BUFFER_SIZE,
1953
&copy_cmd.src_iova);
1954
} else {
1955
test_ioctl_ioas_map_id(new_ioas_id, buf, BUFFER_SIZE,
1956
&copy_cmd.src_iova);
1957
}
1958
test_cmd_access_replace_ioas(access_cmd.id, new_ioas_id);
1959
1960
/* Destroy the old ioas and cleanup copied mapping */
1961
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_UNMAP, &unmap_cmd));
1962
test_ioctl_destroy(ioas_id);
1963
1964
/* Then run the same test again with the new ioas */
1965
access_cmd.access_pages.iova = copy_cmd.src_iova;
1966
ASSERT_EQ(0,
1967
ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_PAGES),
1968
&access_cmd));
1969
copy_cmd.src_ioas_id = new_ioas_id;
1970
ASSERT_EQ(0, ioctl(self->fd, IOMMU_IOAS_COPY, &copy_cmd));
1971
check_mock_iova(buf, MOCK_APERTURE_START, BUFFER_SIZE);
1972
1973
test_cmd_destroy_access_pages(
1974
access_cmd.id, access_cmd.access_pages.out_access_pages_id);
1975
test_cmd_destroy_access(access_cmd.id);
1976
1977
test_ioctl_destroy(new_ioas_id);
1978
}
1979
1980
TEST_F(iommufd_mock_domain, replace)
1981
{
1982
uint32_t ioas_id;
1983
1984
test_ioctl_ioas_alloc(&ioas_id);
1985
1986
test_cmd_mock_domain_replace(self->stdev_ids[0], ioas_id);
1987
1988
/*
1989
* Replacing the IOAS causes the prior HWPT to be deallocated, thus we
1990
* should get enoent when we try to use it.
1991
*/
1992
if (variant->mock_domains == 1)
1993
test_err_mock_domain_replace(ENOENT, self->stdev_ids[0],
1994
self->hwpt_ids[0]);
1995
1996
test_cmd_mock_domain_replace(self->stdev_ids[0], ioas_id);
1997
if (variant->mock_domains >= 2) {
1998
test_cmd_mock_domain_replace(self->stdev_ids[0],
1999
self->hwpt_ids[1]);
2000
test_cmd_mock_domain_replace(self->stdev_ids[0],
2001
self->hwpt_ids[1]);
2002
test_cmd_mock_domain_replace(self->stdev_ids[0],
2003
self->hwpt_ids[0]);
2004
}
2005
2006
test_cmd_mock_domain_replace(self->stdev_ids[0], self->ioas_id);
2007
test_ioctl_destroy(ioas_id);
2008
}
2009
2010
TEST_F(iommufd_mock_domain, alloc_hwpt)
2011
{
2012
int i;
2013
2014
for (i = 0; i != variant->mock_domains; i++) {
2015
uint32_t hwpt_id[2];
2016
uint32_t stddev_id;
2017
2018
test_err_hwpt_alloc(EOPNOTSUPP,
2019
self->idev_ids[i], self->ioas_id,
2020
~IOMMU_HWPT_ALLOC_NEST_PARENT, &hwpt_id[0]);
2021
test_cmd_hwpt_alloc(self->idev_ids[i], self->ioas_id,
2022
0, &hwpt_id[0]);
2023
test_cmd_hwpt_alloc(self->idev_ids[i], self->ioas_id,
2024
IOMMU_HWPT_ALLOC_NEST_PARENT, &hwpt_id[1]);
2025
2026
/* Do a hw_pagetable rotation test */
2027
test_cmd_mock_domain_replace(self->stdev_ids[i], hwpt_id[0]);
2028
EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, hwpt_id[0]));
2029
test_cmd_mock_domain_replace(self->stdev_ids[i], hwpt_id[1]);
2030
EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, hwpt_id[1]));
2031
test_cmd_mock_domain_replace(self->stdev_ids[i], self->ioas_id);
2032
test_ioctl_destroy(hwpt_id[1]);
2033
2034
test_cmd_mock_domain(hwpt_id[0], &stddev_id, NULL, NULL);
2035
test_ioctl_destroy(stddev_id);
2036
test_ioctl_destroy(hwpt_id[0]);
2037
}
2038
}
2039
2040
FIXTURE(iommufd_dirty_tracking)
2041
{
2042
int fd;
2043
uint32_t ioas_id;
2044
uint32_t hwpt_id;
2045
uint32_t stdev_id;
2046
uint32_t idev_id;
2047
unsigned long page_size;
2048
unsigned long bitmap_size;
2049
void *bitmap;
2050
void *buffer;
2051
};
2052
2053
FIXTURE_VARIANT(iommufd_dirty_tracking)
2054
{
2055
unsigned long buffer_size;
2056
bool hugepages;
2057
};
2058
2059
FIXTURE_SETUP(iommufd_dirty_tracking)
2060
{
2061
size_t mmap_buffer_size;
2062
unsigned long size;
2063
int mmap_flags;
2064
void *vrc;
2065
int rc;
2066
2067
if (variant->buffer_size < MOCK_PAGE_SIZE) {
2068
SKIP(return,
2069
"Skipping buffer_size=%lu, less than MOCK_PAGE_SIZE=%lu",
2070
variant->buffer_size, MOCK_PAGE_SIZE);
2071
}
2072
2073
self->fd = open("/dev/iommu", O_RDWR);
2074
ASSERT_NE(-1, self->fd);
2075
2076
mmap_flags = MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED;
2077
mmap_buffer_size = variant->buffer_size;
2078
if (variant->hugepages) {
2079
/*
2080
* MAP_POPULATE will cause the kernel to fail mmap if THPs are
2081
* not available.
2082
*/
2083
mmap_flags |= MAP_HUGETLB | MAP_POPULATE;
2084
2085
/*
2086
* Allocation must be aligned to the HUGEPAGE_SIZE, because the
2087
* following mmap() will automatically align the length to be a
2088
* multiple of the underlying huge page size. Failing to do the
2089
* same at this allocation will result in a memory overwrite by
2090
* the mmap().
2091
*/
2092
if (mmap_buffer_size < HUGEPAGE_SIZE)
2093
mmap_buffer_size = HUGEPAGE_SIZE;
2094
}
2095
2096
rc = posix_memalign(&self->buffer, HUGEPAGE_SIZE, mmap_buffer_size);
2097
if (rc || !self->buffer) {
2098
SKIP(return, "Skipping buffer_size=%lu due to errno=%d",
2099
mmap_buffer_size, rc);
2100
}
2101
assert((uintptr_t)self->buffer % HUGEPAGE_SIZE == 0);
2102
vrc = mmap(self->buffer, mmap_buffer_size, PROT_READ | PROT_WRITE,
2103
mmap_flags, -1, 0);
2104
assert(vrc == self->buffer);
2105
2106
self->page_size = MOCK_PAGE_SIZE;
2107
self->bitmap_size = variant->buffer_size / self->page_size;
2108
2109
/* Provision with an extra (PAGE_SIZE) for the unaligned case */
2110
size = DIV_ROUND_UP(self->bitmap_size, BITS_PER_BYTE);
2111
rc = posix_memalign(&self->bitmap, PAGE_SIZE, size + PAGE_SIZE);
2112
assert(!rc);
2113
assert(self->bitmap);
2114
assert((uintptr_t)self->bitmap % PAGE_SIZE == 0);
2115
2116
test_ioctl_ioas_alloc(&self->ioas_id);
2117
/* Enable 1M mock IOMMU hugepages */
2118
if (variant->hugepages) {
2119
test_cmd_mock_domain_flags(self->ioas_id,
2120
MOCK_FLAGS_DEVICE_HUGE_IOVA,
2121
&self->stdev_id, &self->hwpt_id,
2122
&self->idev_id);
2123
} else {
2124
test_cmd_mock_domain(self->ioas_id, &self->stdev_id,
2125
&self->hwpt_id, &self->idev_id);
2126
}
2127
}
2128
2129
FIXTURE_TEARDOWN(iommufd_dirty_tracking)
2130
{
2131
free(self->buffer);
2132
free(self->bitmap);
2133
teardown_iommufd(self->fd, _metadata);
2134
}
2135
2136
FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty8k)
2137
{
2138
/* half of an u8 index bitmap */
2139
.buffer_size = 8UL * 1024UL,
2140
};
2141
2142
FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty16k)
2143
{
2144
/* one u8 index bitmap */
2145
.buffer_size = 16UL * 1024UL,
2146
};
2147
2148
FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty64k)
2149
{
2150
/* one u32 index bitmap */
2151
.buffer_size = 64UL * 1024UL,
2152
};
2153
2154
FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128k)
2155
{
2156
/* one u64 index bitmap */
2157
.buffer_size = 128UL * 1024UL,
2158
};
2159
2160
FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty320k)
2161
{
2162
/* two u64 index and trailing end bitmap */
2163
.buffer_size = 320UL * 1024UL,
2164
};
2165
2166
FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty64M)
2167
{
2168
/* 4K bitmap (64M IOVA range) */
2169
.buffer_size = 64UL * 1024UL * 1024UL,
2170
};
2171
2172
FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty64M_huge)
2173
{
2174
/* 4K bitmap (64M IOVA range) */
2175
.buffer_size = 64UL * 1024UL * 1024UL,
2176
.hugepages = true,
2177
};
2178
2179
FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128M)
2180
{
2181
/* 8K bitmap (128M IOVA range) */
2182
.buffer_size = 128UL * 1024UL * 1024UL,
2183
};
2184
2185
FIXTURE_VARIANT_ADD(iommufd_dirty_tracking, domain_dirty128M_huge)
2186
{
2187
/* 8K bitmap (128M IOVA range) */
2188
.buffer_size = 128UL * 1024UL * 1024UL,
2189
.hugepages = true,
2190
};
2191
2192
TEST_F(iommufd_dirty_tracking, enforce_dirty)
2193
{
2194
uint32_t ioas_id, stddev_id, idev_id;
2195
uint32_t hwpt_id, _hwpt_id;
2196
uint32_t dev_flags;
2197
2198
/* Regular case */
2199
dev_flags = MOCK_FLAGS_DEVICE_NO_DIRTY;
2200
test_cmd_hwpt_alloc(self->idev_id, self->ioas_id,
2201
IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
2202
test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
2203
test_err_mock_domain_flags(EINVAL, hwpt_id, dev_flags, &stddev_id,
2204
NULL);
2205
test_ioctl_destroy(stddev_id);
2206
test_ioctl_destroy(hwpt_id);
2207
2208
/* IOMMU device does not support dirty tracking */
2209
test_ioctl_ioas_alloc(&ioas_id);
2210
test_cmd_mock_domain_flags(ioas_id, dev_flags, &stddev_id, &_hwpt_id,
2211
&idev_id);
2212
test_err_hwpt_alloc(EOPNOTSUPP, idev_id, ioas_id,
2213
IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
2214
test_ioctl_destroy(stddev_id);
2215
}
2216
2217
TEST_F(iommufd_dirty_tracking, set_dirty_tracking)
2218
{
2219
uint32_t stddev_id;
2220
uint32_t hwpt_id;
2221
2222
test_cmd_hwpt_alloc(self->idev_id, self->ioas_id,
2223
IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
2224
test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
2225
test_cmd_set_dirty_tracking(hwpt_id, true);
2226
test_cmd_set_dirty_tracking(hwpt_id, false);
2227
2228
test_ioctl_destroy(stddev_id);
2229
test_ioctl_destroy(hwpt_id);
2230
}
2231
2232
TEST_F(iommufd_dirty_tracking, device_dirty_capability)
2233
{
2234
uint32_t caps = 0;
2235
uint32_t stddev_id;
2236
uint32_t hwpt_id;
2237
2238
test_cmd_hwpt_alloc(self->idev_id, self->ioas_id, 0, &hwpt_id);
2239
test_cmd_mock_domain(hwpt_id, &stddev_id, NULL, NULL);
2240
test_cmd_get_hw_capabilities(self->idev_id, caps);
2241
ASSERT_EQ(IOMMU_HW_CAP_DIRTY_TRACKING,
2242
caps & IOMMU_HW_CAP_DIRTY_TRACKING);
2243
2244
test_ioctl_destroy(stddev_id);
2245
test_ioctl_destroy(hwpt_id);
2246
}
2247
2248
TEST_F(iommufd_dirty_tracking, get_dirty_bitmap)
2249
{
2250
uint32_t page_size = MOCK_PAGE_SIZE;
2251
uint32_t hwpt_id;
2252
uint32_t ioas_id;
2253
2254
if (variant->hugepages)
2255
page_size = MOCK_HUGE_PAGE_SIZE;
2256
2257
test_ioctl_ioas_alloc(&ioas_id);
2258
test_ioctl_ioas_map_fixed_id(ioas_id, self->buffer,
2259
variant->buffer_size, MOCK_APERTURE_START);
2260
2261
test_cmd_hwpt_alloc(self->idev_id, ioas_id,
2262
IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
2263
2264
test_cmd_set_dirty_tracking(hwpt_id, true);
2265
2266
test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
2267
MOCK_APERTURE_START, self->page_size, page_size,
2268
self->bitmap, self->bitmap_size, 0, _metadata);
2269
2270
/* PAGE_SIZE unaligned bitmap */
2271
test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
2272
MOCK_APERTURE_START, self->page_size, page_size,
2273
self->bitmap + MOCK_PAGE_SIZE,
2274
self->bitmap_size, 0, _metadata);
2275
2276
/* u64 unaligned bitmap */
2277
test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
2278
MOCK_APERTURE_START, self->page_size, page_size,
2279
self->bitmap + 0xff1, self->bitmap_size, 0,
2280
_metadata);
2281
2282
test_ioctl_destroy(hwpt_id);
2283
}
2284
2285
TEST_F(iommufd_dirty_tracking, get_dirty_bitmap_no_clear)
2286
{
2287
uint32_t page_size = MOCK_PAGE_SIZE;
2288
uint32_t hwpt_id;
2289
uint32_t ioas_id;
2290
2291
if (variant->hugepages)
2292
page_size = MOCK_HUGE_PAGE_SIZE;
2293
2294
test_ioctl_ioas_alloc(&ioas_id);
2295
test_ioctl_ioas_map_fixed_id(ioas_id, self->buffer,
2296
variant->buffer_size, MOCK_APERTURE_START);
2297
2298
test_cmd_hwpt_alloc(self->idev_id, ioas_id,
2299
IOMMU_HWPT_ALLOC_DIRTY_TRACKING, &hwpt_id);
2300
2301
test_cmd_set_dirty_tracking(hwpt_id, true);
2302
2303
test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
2304
MOCK_APERTURE_START, self->page_size, page_size,
2305
self->bitmap, self->bitmap_size,
2306
IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
2307
_metadata);
2308
2309
/* Unaligned bitmap */
2310
test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
2311
MOCK_APERTURE_START, self->page_size, page_size,
2312
self->bitmap + MOCK_PAGE_SIZE,
2313
self->bitmap_size,
2314
IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
2315
_metadata);
2316
2317
/* u64 unaligned bitmap */
2318
test_mock_dirty_bitmaps(hwpt_id, variant->buffer_size,
2319
MOCK_APERTURE_START, self->page_size, page_size,
2320
self->bitmap + 0xff1, self->bitmap_size,
2321
IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR,
2322
_metadata);
2323
2324
test_ioctl_destroy(hwpt_id);
2325
}
2326
2327
/* VFIO compatibility IOCTLs */
2328
2329
TEST_F(iommufd, simple_ioctls)
2330
{
2331
ASSERT_EQ(VFIO_API_VERSION, ioctl(self->fd, VFIO_GET_API_VERSION));
2332
ASSERT_EQ(1, ioctl(self->fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU));
2333
}
2334
2335
TEST_F(iommufd, unmap_cmd)
2336
{
2337
struct vfio_iommu_type1_dma_unmap unmap_cmd = {
2338
.iova = MOCK_APERTURE_START,
2339
.size = PAGE_SIZE,
2340
};
2341
2342
unmap_cmd.argsz = 1;
2343
EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2344
2345
unmap_cmd.argsz = sizeof(unmap_cmd);
2346
unmap_cmd.flags = 1 << 31;
2347
EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2348
2349
unmap_cmd.flags = 0;
2350
EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2351
}
2352
2353
TEST_F(iommufd, map_cmd)
2354
{
2355
struct vfio_iommu_type1_dma_map map_cmd = {
2356
.iova = MOCK_APERTURE_START,
2357
.size = PAGE_SIZE,
2358
.vaddr = (__u64)buffer,
2359
};
2360
2361
map_cmd.argsz = 1;
2362
EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2363
2364
map_cmd.argsz = sizeof(map_cmd);
2365
map_cmd.flags = 1 << 31;
2366
EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2367
2368
/* Requires a domain to be attached */
2369
map_cmd.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
2370
EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2371
}
2372
2373
TEST_F(iommufd, info_cmd)
2374
{
2375
struct vfio_iommu_type1_info info_cmd = {};
2376
2377
/* Invalid argsz */
2378
info_cmd.argsz = 1;
2379
EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_GET_INFO, &info_cmd));
2380
2381
info_cmd.argsz = sizeof(info_cmd);
2382
EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_IOMMU_GET_INFO, &info_cmd));
2383
}
2384
2385
TEST_F(iommufd, set_iommu_cmd)
2386
{
2387
/* Requires a domain to be attached */
2388
EXPECT_ERRNO(ENODEV,
2389
ioctl(self->fd, VFIO_SET_IOMMU, VFIO_TYPE1v2_IOMMU));
2390
EXPECT_ERRNO(ENODEV, ioctl(self->fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU));
2391
}
2392
2393
TEST_F(iommufd, vfio_ioas)
2394
{
2395
struct iommu_vfio_ioas vfio_ioas_cmd = {
2396
.size = sizeof(vfio_ioas_cmd),
2397
.op = IOMMU_VFIO_IOAS_GET,
2398
};
2399
__u32 ioas_id;
2400
2401
/* ENODEV if there is no compat ioas */
2402
EXPECT_ERRNO(ENODEV, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
2403
2404
/* Invalid id for set */
2405
vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_SET;
2406
EXPECT_ERRNO(ENOENT, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
2407
2408
/* Valid id for set*/
2409
test_ioctl_ioas_alloc(&ioas_id);
2410
vfio_ioas_cmd.ioas_id = ioas_id;
2411
ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
2412
2413
/* Same id comes back from get */
2414
vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_GET;
2415
ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
2416
ASSERT_EQ(ioas_id, vfio_ioas_cmd.ioas_id);
2417
2418
/* Clear works */
2419
vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_CLEAR;
2420
ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
2421
vfio_ioas_cmd.op = IOMMU_VFIO_IOAS_GET;
2422
EXPECT_ERRNO(ENODEV, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
2423
}
2424
2425
FIXTURE(vfio_compat_mock_domain)
2426
{
2427
int fd;
2428
uint32_t ioas_id;
2429
};
2430
2431
FIXTURE_VARIANT(vfio_compat_mock_domain)
2432
{
2433
unsigned int version;
2434
};
2435
2436
FIXTURE_SETUP(vfio_compat_mock_domain)
2437
{
2438
struct iommu_vfio_ioas vfio_ioas_cmd = {
2439
.size = sizeof(vfio_ioas_cmd),
2440
.op = IOMMU_VFIO_IOAS_SET,
2441
};
2442
2443
self->fd = open("/dev/iommu", O_RDWR);
2444
ASSERT_NE(-1, self->fd);
2445
2446
/* Create what VFIO would consider a group */
2447
test_ioctl_ioas_alloc(&self->ioas_id);
2448
test_cmd_mock_domain(self->ioas_id, NULL, NULL, NULL);
2449
2450
/* Attach it to the vfio compat */
2451
vfio_ioas_cmd.ioas_id = self->ioas_id;
2452
ASSERT_EQ(0, ioctl(self->fd, IOMMU_VFIO_IOAS, &vfio_ioas_cmd));
2453
ASSERT_EQ(0, ioctl(self->fd, VFIO_SET_IOMMU, variant->version));
2454
}
2455
2456
FIXTURE_TEARDOWN(vfio_compat_mock_domain)
2457
{
2458
teardown_iommufd(self->fd, _metadata);
2459
}
2460
2461
FIXTURE_VARIANT_ADD(vfio_compat_mock_domain, Ver1v2)
2462
{
2463
.version = VFIO_TYPE1v2_IOMMU,
2464
};
2465
2466
FIXTURE_VARIANT_ADD(vfio_compat_mock_domain, Ver1v0)
2467
{
2468
.version = VFIO_TYPE1_IOMMU,
2469
};
2470
2471
TEST_F(vfio_compat_mock_domain, simple_close)
2472
{
2473
}
2474
2475
TEST_F(vfio_compat_mock_domain, option_huge_pages)
2476
{
2477
struct iommu_option cmd = {
2478
.size = sizeof(cmd),
2479
.option_id = IOMMU_OPTION_HUGE_PAGES,
2480
.op = IOMMU_OPTION_OP_GET,
2481
.val64 = 3,
2482
.object_id = self->ioas_id,
2483
};
2484
2485
ASSERT_EQ(0, ioctl(self->fd, IOMMU_OPTION, &cmd));
2486
if (variant->version == VFIO_TYPE1_IOMMU) {
2487
ASSERT_EQ(0, cmd.val64);
2488
} else {
2489
ASSERT_EQ(1, cmd.val64);
2490
}
2491
}
2492
2493
/*
2494
* Execute an ioctl command stored in buffer and check that the result does not
2495
* overflow memory.
2496
*/
2497
static bool is_filled(const void *buf, uint8_t c, size_t len)
2498
{
2499
const uint8_t *cbuf = buf;
2500
2501
for (; len; cbuf++, len--)
2502
if (*cbuf != c)
2503
return false;
2504
return true;
2505
}
2506
2507
#define ioctl_check_buf(fd, cmd) \
2508
({ \
2509
size_t _cmd_len = *(__u32 *)buffer; \
2510
\
2511
memset(buffer + _cmd_len, 0xAA, BUFFER_SIZE - _cmd_len); \
2512
ASSERT_EQ(0, ioctl(fd, cmd, buffer)); \
2513
ASSERT_EQ(true, is_filled(buffer + _cmd_len, 0xAA, \
2514
BUFFER_SIZE - _cmd_len)); \
2515
})
2516
2517
static void check_vfio_info_cap_chain(struct __test_metadata *_metadata,
2518
struct vfio_iommu_type1_info *info_cmd)
2519
{
2520
const struct vfio_info_cap_header *cap;
2521
2522
ASSERT_GE(info_cmd->argsz, info_cmd->cap_offset + sizeof(*cap));
2523
cap = buffer + info_cmd->cap_offset;
2524
while (true) {
2525
size_t cap_size;
2526
2527
if (cap->next)
2528
cap_size = (buffer + cap->next) - (void *)cap;
2529
else
2530
cap_size = (buffer + info_cmd->argsz) - (void *)cap;
2531
2532
switch (cap->id) {
2533
case VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE: {
2534
struct vfio_iommu_type1_info_cap_iova_range *data =
2535
(void *)cap;
2536
2537
ASSERT_EQ(1, data->header.version);
2538
ASSERT_EQ(1, data->nr_iovas);
2539
EXPECT_EQ(MOCK_APERTURE_START,
2540
data->iova_ranges[0].start);
2541
EXPECT_EQ(MOCK_APERTURE_LAST, data->iova_ranges[0].end);
2542
break;
2543
}
2544
case VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL: {
2545
struct vfio_iommu_type1_info_dma_avail *data =
2546
(void *)cap;
2547
2548
ASSERT_EQ(1, data->header.version);
2549
ASSERT_EQ(sizeof(*data), cap_size);
2550
break;
2551
}
2552
default:
2553
ASSERT_EQ(false, true);
2554
break;
2555
}
2556
if (!cap->next)
2557
break;
2558
2559
ASSERT_GE(info_cmd->argsz, cap->next + sizeof(*cap));
2560
ASSERT_GE(buffer + cap->next, (void *)cap);
2561
cap = buffer + cap->next;
2562
}
2563
}
2564
2565
TEST_F(vfio_compat_mock_domain, get_info)
2566
{
2567
struct vfio_iommu_type1_info *info_cmd = buffer;
2568
unsigned int i;
2569
size_t caplen;
2570
2571
/* Pre-cap ABI */
2572
*info_cmd = (struct vfio_iommu_type1_info){
2573
.argsz = offsetof(struct vfio_iommu_type1_info, cap_offset),
2574
};
2575
ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
2576
ASSERT_NE(0, info_cmd->iova_pgsizes);
2577
ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
2578
info_cmd->flags);
2579
2580
/* Read the cap chain size */
2581
*info_cmd = (struct vfio_iommu_type1_info){
2582
.argsz = sizeof(*info_cmd),
2583
};
2584
ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
2585
ASSERT_NE(0, info_cmd->iova_pgsizes);
2586
ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
2587
info_cmd->flags);
2588
ASSERT_EQ(0, info_cmd->cap_offset);
2589
ASSERT_LT(sizeof(*info_cmd), info_cmd->argsz);
2590
2591
/* Read the caps, kernel should never create a corrupted caps */
2592
caplen = info_cmd->argsz;
2593
for (i = sizeof(*info_cmd); i < caplen; i++) {
2594
*info_cmd = (struct vfio_iommu_type1_info){
2595
.argsz = i,
2596
};
2597
ioctl_check_buf(self->fd, VFIO_IOMMU_GET_INFO);
2598
ASSERT_EQ(VFIO_IOMMU_INFO_PGSIZES | VFIO_IOMMU_INFO_CAPS,
2599
info_cmd->flags);
2600
if (!info_cmd->cap_offset)
2601
continue;
2602
check_vfio_info_cap_chain(_metadata, info_cmd);
2603
}
2604
}
2605
2606
static void shuffle_array(unsigned long *array, size_t nelms)
2607
{
2608
unsigned int i;
2609
2610
/* Shuffle */
2611
for (i = 0; i != nelms; i++) {
2612
unsigned long tmp = array[i];
2613
unsigned int other = rand() % (nelms - i);
2614
2615
array[i] = array[other];
2616
array[other] = tmp;
2617
}
2618
}
2619
2620
TEST_F(vfio_compat_mock_domain, map)
2621
{
2622
struct vfio_iommu_type1_dma_map map_cmd = {
2623
.argsz = sizeof(map_cmd),
2624
.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
2625
.vaddr = (uintptr_t)buffer,
2626
.size = BUFFER_SIZE,
2627
.iova = MOCK_APERTURE_START,
2628
};
2629
struct vfio_iommu_type1_dma_unmap unmap_cmd = {
2630
.argsz = sizeof(unmap_cmd),
2631
.size = BUFFER_SIZE,
2632
.iova = MOCK_APERTURE_START,
2633
};
2634
unsigned long pages_iova[BUFFER_SIZE / PAGE_SIZE];
2635
unsigned int i;
2636
2637
/* Simple map/unmap */
2638
ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2639
ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2640
ASSERT_EQ(BUFFER_SIZE, unmap_cmd.size);
2641
2642
/* UNMAP_FLAG_ALL requires 0 iova/size */
2643
ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2644
unmap_cmd.flags = VFIO_DMA_UNMAP_FLAG_ALL;
2645
EXPECT_ERRNO(EINVAL, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2646
2647
unmap_cmd.iova = 0;
2648
unmap_cmd.size = 0;
2649
ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2650
ASSERT_EQ(BUFFER_SIZE, unmap_cmd.size);
2651
2652
/* Small pages */
2653
for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
2654
map_cmd.iova = pages_iova[i] =
2655
MOCK_APERTURE_START + i * PAGE_SIZE;
2656
map_cmd.vaddr = (uintptr_t)buffer + i * PAGE_SIZE;
2657
map_cmd.size = PAGE_SIZE;
2658
ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2659
}
2660
shuffle_array(pages_iova, ARRAY_SIZE(pages_iova));
2661
2662
unmap_cmd.flags = 0;
2663
unmap_cmd.size = PAGE_SIZE;
2664
for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
2665
unmap_cmd.iova = pages_iova[i];
2666
ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA, &unmap_cmd));
2667
}
2668
}
2669
2670
TEST_F(vfio_compat_mock_domain, huge_map)
2671
{
2672
size_t buf_size = HUGEPAGE_SIZE * 2;
2673
struct vfio_iommu_type1_dma_map map_cmd = {
2674
.argsz = sizeof(map_cmd),
2675
.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
2676
.size = buf_size,
2677
.iova = MOCK_APERTURE_START,
2678
};
2679
struct vfio_iommu_type1_dma_unmap unmap_cmd = {
2680
.argsz = sizeof(unmap_cmd),
2681
};
2682
unsigned long pages_iova[16];
2683
unsigned int i;
2684
void *buf;
2685
2686
/* Test huge pages and splitting */
2687
buf = mmap(0, buf_size, PROT_READ | PROT_WRITE,
2688
MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1,
2689
0);
2690
ASSERT_NE(MAP_FAILED, buf);
2691
map_cmd.vaddr = (uintptr_t)buf;
2692
ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_MAP_DMA, &map_cmd));
2693
2694
unmap_cmd.size = buf_size / ARRAY_SIZE(pages_iova);
2695
for (i = 0; i != ARRAY_SIZE(pages_iova); i++)
2696
pages_iova[i] = MOCK_APERTURE_START + (i * unmap_cmd.size);
2697
shuffle_array(pages_iova, ARRAY_SIZE(pages_iova));
2698
2699
/* type1 mode can cut up larger mappings, type1v2 always fails */
2700
for (i = 0; i != ARRAY_SIZE(pages_iova); i++) {
2701
unmap_cmd.iova = pages_iova[i];
2702
unmap_cmd.size = buf_size / ARRAY_SIZE(pages_iova);
2703
if (variant->version == VFIO_TYPE1_IOMMU) {
2704
ASSERT_EQ(0, ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA,
2705
&unmap_cmd));
2706
} else {
2707
EXPECT_ERRNO(ENOENT,
2708
ioctl(self->fd, VFIO_IOMMU_UNMAP_DMA,
2709
&unmap_cmd));
2710
}
2711
}
2712
}
2713
2714
FIXTURE(iommufd_viommu)
2715
{
2716
int fd;
2717
uint32_t ioas_id;
2718
uint32_t stdev_id;
2719
uint32_t hwpt_id;
2720
uint32_t nested_hwpt_id;
2721
uint32_t device_id;
2722
uint32_t viommu_id;
2723
};
2724
2725
FIXTURE_VARIANT(iommufd_viommu)
2726
{
2727
unsigned int viommu;
2728
};
2729
2730
FIXTURE_SETUP(iommufd_viommu)
2731
{
2732
self->fd = open("/dev/iommu", O_RDWR);
2733
ASSERT_NE(-1, self->fd);
2734
test_ioctl_ioas_alloc(&self->ioas_id);
2735
test_ioctl_set_default_memory_limit();
2736
2737
if (variant->viommu) {
2738
struct iommu_hwpt_selftest data = {
2739
.iotlb = IOMMU_TEST_IOTLB_DEFAULT,
2740
};
2741
2742
test_cmd_mock_domain(self->ioas_id, &self->stdev_id, NULL,
2743
&self->device_id);
2744
2745
/* Allocate a nesting parent hwpt */
2746
test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
2747
IOMMU_HWPT_ALLOC_NEST_PARENT,
2748
&self->hwpt_id);
2749
2750
/* Allocate a vIOMMU taking refcount of the parent hwpt */
2751
test_cmd_viommu_alloc(self->device_id, self->hwpt_id,
2752
IOMMU_VIOMMU_TYPE_SELFTEST, NULL, 0,
2753
&self->viommu_id);
2754
2755
/* Allocate a regular nested hwpt */
2756
test_cmd_hwpt_alloc_nested(self->device_id, self->viommu_id, 0,
2757
&self->nested_hwpt_id,
2758
IOMMU_HWPT_DATA_SELFTEST, &data,
2759
sizeof(data));
2760
}
2761
}
2762
2763
FIXTURE_TEARDOWN(iommufd_viommu)
2764
{
2765
teardown_iommufd(self->fd, _metadata);
2766
}
2767
2768
FIXTURE_VARIANT_ADD(iommufd_viommu, no_viommu)
2769
{
2770
.viommu = 0,
2771
};
2772
2773
FIXTURE_VARIANT_ADD(iommufd_viommu, mock_viommu)
2774
{
2775
.viommu = 1,
2776
};
2777
2778
TEST_F(iommufd_viommu, viommu_auto_destroy)
2779
{
2780
}
2781
2782
TEST_F(iommufd_viommu, viommu_negative_tests)
2783
{
2784
uint32_t device_id = self->device_id;
2785
uint32_t ioas_id = self->ioas_id;
2786
uint32_t hwpt_id;
2787
2788
if (self->device_id) {
2789
/* Negative test -- invalid hwpt (hwpt_id=0) */
2790
test_err_viommu_alloc(ENOENT, device_id, 0,
2791
IOMMU_VIOMMU_TYPE_SELFTEST, NULL, 0,
2792
NULL);
2793
2794
/* Negative test -- not a nesting parent hwpt */
2795
test_cmd_hwpt_alloc(device_id, ioas_id, 0, &hwpt_id);
2796
test_err_viommu_alloc(EINVAL, device_id, hwpt_id,
2797
IOMMU_VIOMMU_TYPE_SELFTEST, NULL, 0,
2798
NULL);
2799
test_ioctl_destroy(hwpt_id);
2800
2801
/* Negative test -- unsupported viommu type */
2802
test_err_viommu_alloc(EOPNOTSUPP, device_id, self->hwpt_id,
2803
0xdead, NULL, 0, NULL);
2804
EXPECT_ERRNO(EBUSY,
2805
_test_ioctl_destroy(self->fd, self->hwpt_id));
2806
EXPECT_ERRNO(EBUSY,
2807
_test_ioctl_destroy(self->fd, self->viommu_id));
2808
} else {
2809
test_err_viommu_alloc(ENOENT, self->device_id, self->hwpt_id,
2810
IOMMU_VIOMMU_TYPE_SELFTEST, NULL, 0,
2811
NULL);
2812
}
2813
}
2814
2815
TEST_F(iommufd_viommu, viommu_alloc_nested_iopf)
2816
{
2817
struct iommu_hwpt_selftest data = {
2818
.iotlb = IOMMU_TEST_IOTLB_DEFAULT,
2819
};
2820
uint32_t viommu_id = self->viommu_id;
2821
uint32_t dev_id = self->device_id;
2822
uint32_t iopf_hwpt_id;
2823
uint32_t fault_id;
2824
uint32_t fault_fd;
2825
uint32_t vdev_id;
2826
2827
if (!dev_id)
2828
SKIP(return, "Skipping test for variant no_viommu");
2829
2830
test_ioctl_fault_alloc(&fault_id, &fault_fd);
2831
test_err_hwpt_alloc_iopf(ENOENT, dev_id, viommu_id, UINT32_MAX,
2832
IOMMU_HWPT_FAULT_ID_VALID, &iopf_hwpt_id,
2833
IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data));
2834
test_err_hwpt_alloc_iopf(EOPNOTSUPP, dev_id, viommu_id, fault_id,
2835
IOMMU_HWPT_FAULT_ID_VALID | (1 << 31),
2836
&iopf_hwpt_id, IOMMU_HWPT_DATA_SELFTEST, &data,
2837
sizeof(data));
2838
test_cmd_hwpt_alloc_iopf(dev_id, viommu_id, fault_id,
2839
IOMMU_HWPT_FAULT_ID_VALID, &iopf_hwpt_id,
2840
IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data));
2841
2842
/* Must allocate vdevice before attaching to a nested hwpt */
2843
test_err_mock_domain_replace(ENOENT, self->stdev_id, iopf_hwpt_id);
2844
test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
2845
test_cmd_mock_domain_replace(self->stdev_id, iopf_hwpt_id);
2846
EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, iopf_hwpt_id));
2847
test_cmd_trigger_iopf(dev_id, fault_fd);
2848
2849
test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
2850
test_ioctl_destroy(iopf_hwpt_id);
2851
close(fault_fd);
2852
test_ioctl_destroy(fault_id);
2853
}
2854
2855
TEST_F(iommufd_viommu, viommu_alloc_with_data)
2856
{
2857
struct iommu_viommu_selftest data = {
2858
.in_data = 0xbeef,
2859
};
2860
uint32_t *test;
2861
2862
if (!self->device_id)
2863
SKIP(return, "Skipping test for variant no_viommu");
2864
2865
test_cmd_viommu_alloc(self->device_id, self->hwpt_id,
2866
IOMMU_VIOMMU_TYPE_SELFTEST, &data, sizeof(data),
2867
&self->viommu_id);
2868
ASSERT_EQ(data.out_data, data.in_data);
2869
2870
/* Negative mmap tests -- offset and length cannot be changed */
2871
test_err_mmap(ENXIO, data.out_mmap_length,
2872
data.out_mmap_offset + PAGE_SIZE);
2873
test_err_mmap(ENXIO, data.out_mmap_length,
2874
data.out_mmap_offset + PAGE_SIZE * 2);
2875
test_err_mmap(ENXIO, data.out_mmap_length / 2, data.out_mmap_offset);
2876
test_err_mmap(ENXIO, data.out_mmap_length * 2, data.out_mmap_offset);
2877
2878
/* Now do a correct mmap for a loopback test */
2879
test = mmap(NULL, data.out_mmap_length, PROT_READ | PROT_WRITE,
2880
MAP_SHARED, self->fd, data.out_mmap_offset);
2881
ASSERT_NE(MAP_FAILED, test);
2882
ASSERT_EQ(data.in_data, *test);
2883
2884
/* The owner of the mmap region should be blocked */
2885
EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, self->viommu_id));
2886
munmap(test, data.out_mmap_length);
2887
}
2888
2889
TEST_F(iommufd_viommu, vdevice_alloc)
2890
{
2891
uint32_t viommu_id = self->viommu_id;
2892
uint32_t dev_id = self->device_id;
2893
uint32_t vdev_id = 0;
2894
uint32_t veventq_id;
2895
uint32_t veventq_fd;
2896
int prev_seq = -1;
2897
2898
if (dev_id) {
2899
/* Must allocate vdevice before attaching to a nested hwpt */
2900
test_err_mock_domain_replace(ENOENT, self->stdev_id,
2901
self->nested_hwpt_id);
2902
2903
/* Allocate a vEVENTQ with veventq_depth=2 */
2904
test_cmd_veventq_alloc(viommu_id, IOMMU_VEVENTQ_TYPE_SELFTEST,
2905
&veventq_id, &veventq_fd);
2906
test_err_veventq_alloc(EEXIST, viommu_id,
2907
IOMMU_VEVENTQ_TYPE_SELFTEST, NULL, NULL);
2908
/* Set vdev_id to 0x99, unset it, and set to 0x88 */
2909
test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
2910
test_cmd_mock_domain_replace(self->stdev_id,
2911
self->nested_hwpt_id);
2912
test_cmd_trigger_vevents(dev_id, 1);
2913
test_cmd_read_vevents(veventq_fd, 1, 0x99, &prev_seq);
2914
test_err_vdevice_alloc(EEXIST, viommu_id, dev_id, 0x99,
2915
&vdev_id);
2916
test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
2917
test_ioctl_destroy(vdev_id);
2918
2919
/* Try again with 0x88 */
2920
test_cmd_vdevice_alloc(viommu_id, dev_id, 0x88, &vdev_id);
2921
test_cmd_mock_domain_replace(self->stdev_id,
2922
self->nested_hwpt_id);
2923
/* Trigger an overflow with three events */
2924
test_cmd_trigger_vevents(dev_id, 3);
2925
test_err_read_vevents(EOVERFLOW, veventq_fd, 3, 0x88,
2926
&prev_seq);
2927
/* Overflow must be gone after the previous reads */
2928
test_cmd_trigger_vevents(dev_id, 1);
2929
test_cmd_read_vevents(veventq_fd, 1, 0x88, &prev_seq);
2930
close(veventq_fd);
2931
test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
2932
test_ioctl_destroy(vdev_id);
2933
test_ioctl_destroy(veventq_id);
2934
} else {
2935
test_err_vdevice_alloc(ENOENT, viommu_id, dev_id, 0x99, NULL);
2936
}
2937
}
2938
2939
TEST_F(iommufd_viommu, vdevice_cache)
2940
{
2941
struct iommu_viommu_invalidate_selftest inv_reqs[2] = {};
2942
uint32_t viommu_id = self->viommu_id;
2943
uint32_t dev_id = self->device_id;
2944
uint32_t vdev_id = 0;
2945
uint32_t num_inv;
2946
2947
if (!dev_id)
2948
SKIP(return, "Skipping test for variant no_viommu");
2949
2950
test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
2951
2952
test_cmd_dev_check_cache_all(dev_id, IOMMU_TEST_DEV_CACHE_DEFAULT);
2953
2954
/* Check data_type by passing zero-length array */
2955
num_inv = 0;
2956
test_cmd_viommu_invalidate(viommu_id, inv_reqs, sizeof(*inv_reqs),
2957
&num_inv);
2958
assert(!num_inv);
2959
2960
/* Negative test: Invalid data_type */
2961
num_inv = 1;
2962
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
2963
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST_INVALID,
2964
sizeof(*inv_reqs), &num_inv);
2965
assert(!num_inv);
2966
2967
/* Negative test: structure size sanity */
2968
num_inv = 1;
2969
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
2970
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2971
sizeof(*inv_reqs) + 1, &num_inv);
2972
assert(!num_inv);
2973
2974
num_inv = 1;
2975
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
2976
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST, 1,
2977
&num_inv);
2978
assert(!num_inv);
2979
2980
/* Negative test: invalid flag is passed */
2981
num_inv = 1;
2982
inv_reqs[0].flags = 0xffffffff;
2983
inv_reqs[0].vdev_id = 0x99;
2984
test_err_viommu_invalidate(EOPNOTSUPP, viommu_id, inv_reqs,
2985
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2986
sizeof(*inv_reqs), &num_inv);
2987
assert(!num_inv);
2988
2989
/* Negative test: invalid data_uptr when array is not empty */
2990
num_inv = 1;
2991
inv_reqs[0].flags = 0;
2992
inv_reqs[0].vdev_id = 0x99;
2993
test_err_viommu_invalidate(EINVAL, viommu_id, NULL,
2994
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
2995
sizeof(*inv_reqs), &num_inv);
2996
assert(!num_inv);
2997
2998
/* Negative test: invalid entry_len when array is not empty */
2999
num_inv = 1;
3000
inv_reqs[0].flags = 0;
3001
inv_reqs[0].vdev_id = 0x99;
3002
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
3003
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST, 0,
3004
&num_inv);
3005
assert(!num_inv);
3006
3007
/* Negative test: invalid cache_id */
3008
num_inv = 1;
3009
inv_reqs[0].flags = 0;
3010
inv_reqs[0].vdev_id = 0x99;
3011
inv_reqs[0].cache_id = MOCK_DEV_CACHE_ID_MAX + 1;
3012
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
3013
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
3014
sizeof(*inv_reqs), &num_inv);
3015
assert(!num_inv);
3016
3017
/* Negative test: invalid vdev_id */
3018
num_inv = 1;
3019
inv_reqs[0].flags = 0;
3020
inv_reqs[0].vdev_id = 0x9;
3021
inv_reqs[0].cache_id = 0;
3022
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
3023
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
3024
sizeof(*inv_reqs), &num_inv);
3025
assert(!num_inv);
3026
3027
/*
3028
* Invalidate the 1st cache entry but fail the 2nd request
3029
* due to invalid flags configuration in the 2nd request.
3030
*/
3031
num_inv = 2;
3032
inv_reqs[0].flags = 0;
3033
inv_reqs[0].vdev_id = 0x99;
3034
inv_reqs[0].cache_id = 0;
3035
inv_reqs[1].flags = 0xffffffff;
3036
inv_reqs[1].vdev_id = 0x99;
3037
inv_reqs[1].cache_id = 1;
3038
test_err_viommu_invalidate(EOPNOTSUPP, viommu_id, inv_reqs,
3039
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
3040
sizeof(*inv_reqs), &num_inv);
3041
assert(num_inv == 1);
3042
test_cmd_dev_check_cache(dev_id, 0, 0);
3043
test_cmd_dev_check_cache(dev_id, 1, IOMMU_TEST_DEV_CACHE_DEFAULT);
3044
test_cmd_dev_check_cache(dev_id, 2, IOMMU_TEST_DEV_CACHE_DEFAULT);
3045
test_cmd_dev_check_cache(dev_id, 3, IOMMU_TEST_DEV_CACHE_DEFAULT);
3046
3047
/*
3048
* Invalidate the 1st cache entry but fail the 2nd request
3049
* due to invalid cache_id configuration in the 2nd request.
3050
*/
3051
num_inv = 2;
3052
inv_reqs[0].flags = 0;
3053
inv_reqs[0].vdev_id = 0x99;
3054
inv_reqs[0].cache_id = 0;
3055
inv_reqs[1].flags = 0;
3056
inv_reqs[1].vdev_id = 0x99;
3057
inv_reqs[1].cache_id = MOCK_DEV_CACHE_ID_MAX + 1;
3058
test_err_viommu_invalidate(EINVAL, viommu_id, inv_reqs,
3059
IOMMU_VIOMMU_INVALIDATE_DATA_SELFTEST,
3060
sizeof(*inv_reqs), &num_inv);
3061
assert(num_inv == 1);
3062
test_cmd_dev_check_cache(dev_id, 0, 0);
3063
test_cmd_dev_check_cache(dev_id, 1, IOMMU_TEST_DEV_CACHE_DEFAULT);
3064
test_cmd_dev_check_cache(dev_id, 2, IOMMU_TEST_DEV_CACHE_DEFAULT);
3065
test_cmd_dev_check_cache(dev_id, 3, IOMMU_TEST_DEV_CACHE_DEFAULT);
3066
3067
/* Invalidate the 2nd cache entry and verify */
3068
num_inv = 1;
3069
inv_reqs[0].flags = 0;
3070
inv_reqs[0].vdev_id = 0x99;
3071
inv_reqs[0].cache_id = 1;
3072
test_cmd_viommu_invalidate(viommu_id, inv_reqs, sizeof(*inv_reqs),
3073
&num_inv);
3074
assert(num_inv == 1);
3075
test_cmd_dev_check_cache(dev_id, 0, 0);
3076
test_cmd_dev_check_cache(dev_id, 1, 0);
3077
test_cmd_dev_check_cache(dev_id, 2, IOMMU_TEST_DEV_CACHE_DEFAULT);
3078
test_cmd_dev_check_cache(dev_id, 3, IOMMU_TEST_DEV_CACHE_DEFAULT);
3079
3080
/* Invalidate the 3rd and 4th cache entries and verify */
3081
num_inv = 2;
3082
inv_reqs[0].flags = 0;
3083
inv_reqs[0].vdev_id = 0x99;
3084
inv_reqs[0].cache_id = 2;
3085
inv_reqs[1].flags = 0;
3086
inv_reqs[1].vdev_id = 0x99;
3087
inv_reqs[1].cache_id = 3;
3088
test_cmd_viommu_invalidate(viommu_id, inv_reqs, sizeof(*inv_reqs),
3089
&num_inv);
3090
assert(num_inv == 2);
3091
test_cmd_dev_check_cache_all(dev_id, 0);
3092
3093
/* Invalidate all cache entries for nested_dev_id[1] and verify */
3094
num_inv = 1;
3095
inv_reqs[0].vdev_id = 0x99;
3096
inv_reqs[0].flags = IOMMU_TEST_INVALIDATE_FLAG_ALL;
3097
test_cmd_viommu_invalidate(viommu_id, inv_reqs, sizeof(*inv_reqs),
3098
&num_inv);
3099
assert(num_inv == 1);
3100
test_cmd_dev_check_cache_all(dev_id, 0);
3101
test_ioctl_destroy(vdev_id);
3102
}
3103
3104
TEST_F(iommufd_viommu, hw_queue)
3105
{
3106
__u64 iova = MOCK_APERTURE_START, iova2;
3107
uint32_t viommu_id = self->viommu_id;
3108
uint32_t hw_queue_id[2];
3109
3110
if (!viommu_id)
3111
SKIP(return, "Skipping test for variant no_viommu");
3112
3113
/* Fail IOMMU_HW_QUEUE_TYPE_DEFAULT */
3114
test_err_hw_queue_alloc(EOPNOTSUPP, viommu_id,
3115
IOMMU_HW_QUEUE_TYPE_DEFAULT, 0, iova, PAGE_SIZE,
3116
&hw_queue_id[0]);
3117
/* Fail queue addr and length */
3118
test_err_hw_queue_alloc(EINVAL, viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST,
3119
0, iova, 0, &hw_queue_id[0]);
3120
test_err_hw_queue_alloc(EOVERFLOW, viommu_id,
3121
IOMMU_HW_QUEUE_TYPE_SELFTEST, 0, ~(uint64_t)0,
3122
PAGE_SIZE, &hw_queue_id[0]);
3123
/* Fail missing iova */
3124
test_err_hw_queue_alloc(ENOENT, viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST,
3125
0, iova, PAGE_SIZE, &hw_queue_id[0]);
3126
3127
/* Map iova */
3128
test_ioctl_ioas_map(buffer, PAGE_SIZE, &iova);
3129
test_ioctl_ioas_map(buffer + PAGE_SIZE, PAGE_SIZE, &iova2);
3130
3131
/* Fail index=1 and =MAX; must start from index=0 */
3132
test_err_hw_queue_alloc(EIO, viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST, 1,
3133
iova, PAGE_SIZE, &hw_queue_id[0]);
3134
test_err_hw_queue_alloc(EINVAL, viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST,
3135
IOMMU_TEST_HW_QUEUE_MAX, iova, PAGE_SIZE,
3136
&hw_queue_id[0]);
3137
3138
/* Allocate index=0, declare ownership of the iova */
3139
test_cmd_hw_queue_alloc(viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST, 0,
3140
iova, PAGE_SIZE, &hw_queue_id[0]);
3141
/* Fail duplicated index */
3142
test_err_hw_queue_alloc(EEXIST, viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST,
3143
0, iova, PAGE_SIZE, &hw_queue_id[0]);
3144
/* Fail unmap, due to iova ownership */
3145
test_err_ioctl_ioas_unmap(EBUSY, iova, PAGE_SIZE);
3146
/* The 2nd page is not pinned, so it can be unmmap */
3147
test_ioctl_ioas_unmap(iova2, PAGE_SIZE);
3148
3149
/* Allocate index=1, with an unaligned case */
3150
test_cmd_hw_queue_alloc(viommu_id, IOMMU_HW_QUEUE_TYPE_SELFTEST, 1,
3151
iova + PAGE_SIZE / 2, PAGE_SIZE / 2,
3152
&hw_queue_id[1]);
3153
/* Fail to destroy, due to dependency */
3154
EXPECT_ERRNO(EBUSY, _test_ioctl_destroy(self->fd, hw_queue_id[0]));
3155
3156
/* Destroy in descending order */
3157
test_ioctl_destroy(hw_queue_id[1]);
3158
test_ioctl_destroy(hw_queue_id[0]);
3159
/* Now it can unmap the first page */
3160
test_ioctl_ioas_unmap(iova, PAGE_SIZE);
3161
}
3162
3163
TEST_F(iommufd_viommu, vdevice_tombstone)
3164
{
3165
uint32_t viommu_id = self->viommu_id;
3166
uint32_t dev_id = self->device_id;
3167
uint32_t vdev_id = 0;
3168
3169
if (!dev_id)
3170
SKIP(return, "Skipping test for variant no_viommu");
3171
3172
test_cmd_vdevice_alloc(viommu_id, dev_id, 0x99, &vdev_id);
3173
test_ioctl_destroy(self->stdev_id);
3174
EXPECT_ERRNO(ENOENT, _test_ioctl_destroy(self->fd, vdev_id));
3175
}
3176
3177
FIXTURE(iommufd_device_pasid)
3178
{
3179
int fd;
3180
uint32_t ioas_id;
3181
uint32_t hwpt_id;
3182
uint32_t stdev_id;
3183
uint32_t device_id;
3184
uint32_t no_pasid_stdev_id;
3185
uint32_t no_pasid_device_id;
3186
};
3187
3188
FIXTURE_VARIANT(iommufd_device_pasid)
3189
{
3190
bool pasid_capable;
3191
};
3192
3193
FIXTURE_SETUP(iommufd_device_pasid)
3194
{
3195
self->fd = open("/dev/iommu", O_RDWR);
3196
ASSERT_NE(-1, self->fd);
3197
test_ioctl_ioas_alloc(&self->ioas_id);
3198
3199
test_cmd_mock_domain_flags(self->ioas_id,
3200
MOCK_FLAGS_DEVICE_PASID,
3201
&self->stdev_id, &self->hwpt_id,
3202
&self->device_id);
3203
if (!variant->pasid_capable)
3204
test_cmd_mock_domain_flags(self->ioas_id, 0,
3205
&self->no_pasid_stdev_id, NULL,
3206
&self->no_pasid_device_id);
3207
}
3208
3209
FIXTURE_TEARDOWN(iommufd_device_pasid)
3210
{
3211
teardown_iommufd(self->fd, _metadata);
3212
}
3213
3214
FIXTURE_VARIANT_ADD(iommufd_device_pasid, no_pasid)
3215
{
3216
.pasid_capable = false,
3217
};
3218
3219
FIXTURE_VARIANT_ADD(iommufd_device_pasid, has_pasid)
3220
{
3221
.pasid_capable = true,
3222
};
3223
3224
TEST_F(iommufd_device_pasid, pasid_attach)
3225
{
3226
struct iommu_hwpt_selftest data = {
3227
.iotlb = IOMMU_TEST_IOTLB_DEFAULT,
3228
};
3229
uint32_t nested_hwpt_id[3] = {};
3230
uint32_t parent_hwpt_id = 0;
3231
uint32_t fault_id, fault_fd;
3232
uint32_t s2_hwpt_id = 0;
3233
uint32_t iopf_hwpt_id;
3234
uint32_t pasid = 100;
3235
uint32_t viommu_id;
3236
3237
/*
3238
* Negative, detach pasid without attaching, this is not expected.
3239
* But it should not result in failure anyway.
3240
*/
3241
test_cmd_pasid_detach(pasid);
3242
3243
/* Allocate two nested hwpts sharing one common parent hwpt */
3244
test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
3245
IOMMU_HWPT_ALLOC_NEST_PARENT,
3246
&parent_hwpt_id);
3247
test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id,
3248
IOMMU_HWPT_ALLOC_PASID,
3249
&nested_hwpt_id[0],
3250
IOMMU_HWPT_DATA_SELFTEST,
3251
&data, sizeof(data));
3252
test_cmd_hwpt_alloc_nested(self->device_id, parent_hwpt_id,
3253
IOMMU_HWPT_ALLOC_PASID,
3254
&nested_hwpt_id[1],
3255
IOMMU_HWPT_DATA_SELFTEST,
3256
&data, sizeof(data));
3257
3258
/* Fault related preparation */
3259
test_ioctl_fault_alloc(&fault_id, &fault_fd);
3260
test_cmd_hwpt_alloc_iopf(self->device_id, parent_hwpt_id, fault_id,
3261
IOMMU_HWPT_FAULT_ID_VALID | IOMMU_HWPT_ALLOC_PASID,
3262
&iopf_hwpt_id,
3263
IOMMU_HWPT_DATA_SELFTEST, &data,
3264
sizeof(data));
3265
3266
/* Allocate a regular nested hwpt based on viommu */
3267
test_cmd_viommu_alloc(self->device_id, parent_hwpt_id,
3268
IOMMU_VIOMMU_TYPE_SELFTEST, NULL, 0, &viommu_id);
3269
test_cmd_hwpt_alloc_nested(self->device_id, viommu_id,
3270
IOMMU_HWPT_ALLOC_PASID,
3271
&nested_hwpt_id[2],
3272
IOMMU_HWPT_DATA_SELFTEST, &data,
3273
sizeof(data));
3274
3275
test_cmd_hwpt_alloc(self->device_id, self->ioas_id,
3276
IOMMU_HWPT_ALLOC_PASID,
3277
&s2_hwpt_id);
3278
3279
/* Attach RID to non-pasid compat domain, */
3280
test_cmd_mock_domain_replace(self->stdev_id, parent_hwpt_id);
3281
/* then attach to pasid should fail */
3282
test_err_pasid_attach(EINVAL, pasid, s2_hwpt_id);
3283
3284
/* Attach RID to pasid compat domain, */
3285
test_cmd_mock_domain_replace(self->stdev_id, s2_hwpt_id);
3286
/* then attach to pasid should succeed, */
3287
test_cmd_pasid_attach(pasid, nested_hwpt_id[0]);
3288
/* but attach RID to non-pasid compat domain should fail now. */
3289
test_err_mock_domain_replace(EINVAL, self->stdev_id, parent_hwpt_id);
3290
/*
3291
* Detach hwpt from pasid 100, and check if the pasid 100
3292
* has null domain.
3293
*/
3294
test_cmd_pasid_detach(pasid);
3295
ASSERT_EQ(0,
3296
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3297
pasid, 0));
3298
/* RID is attached to pasid-comapt domain, pasid path is not used */
3299
3300
if (!variant->pasid_capable) {
3301
/*
3302
* PASID-compatible domain can be used by non-PASID-capable
3303
* device.
3304
*/
3305
test_cmd_mock_domain_replace(self->no_pasid_stdev_id, nested_hwpt_id[0]);
3306
test_cmd_mock_domain_replace(self->no_pasid_stdev_id, self->ioas_id);
3307
/*
3308
* Attach hwpt to pasid 100 of non-PASID-capable device,
3309
* should fail, no matter domain is pasid-comapt or not.
3310
*/
3311
EXPECT_ERRNO(EINVAL,
3312
_test_cmd_pasid_attach(self->fd, self->no_pasid_stdev_id,
3313
pasid, parent_hwpt_id));
3314
EXPECT_ERRNO(EINVAL,
3315
_test_cmd_pasid_attach(self->fd, self->no_pasid_stdev_id,
3316
pasid, s2_hwpt_id));
3317
}
3318
3319
/*
3320
* Attach non pasid compat hwpt to pasid-capable device, should
3321
* fail, and have null domain.
3322
*/
3323
test_err_pasid_attach(EINVAL, pasid, parent_hwpt_id);
3324
ASSERT_EQ(0,
3325
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3326
pasid, 0));
3327
3328
/*
3329
* Attach ioas to pasid 100, should fail, domain should
3330
* be null.
3331
*/
3332
test_err_pasid_attach(EINVAL, pasid, self->ioas_id);
3333
ASSERT_EQ(0,
3334
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3335
pasid, 0));
3336
3337
/*
3338
* Attach the s2_hwpt to pasid 100, should succeed, domain should
3339
* be valid.
3340
*/
3341
test_cmd_pasid_attach(pasid, s2_hwpt_id);
3342
ASSERT_EQ(0,
3343
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3344
pasid, s2_hwpt_id));
3345
3346
/*
3347
* Try attach pasid 100 with another hwpt, should FAIL
3348
* as attach does not allow overwrite, use REPLACE instead.
3349
*/
3350
test_err_pasid_attach(EBUSY, pasid, nested_hwpt_id[0]);
3351
3352
/*
3353
* Detach hwpt from pasid 100 for next test, should succeed,
3354
* and have null domain.
3355
*/
3356
test_cmd_pasid_detach(pasid);
3357
ASSERT_EQ(0,
3358
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3359
pasid, 0));
3360
3361
/*
3362
* Attach nested hwpt to pasid 100, should succeed, domain
3363
* should be valid.
3364
*/
3365
test_cmd_pasid_attach(pasid, nested_hwpt_id[0]);
3366
ASSERT_EQ(0,
3367
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3368
pasid, nested_hwpt_id[0]));
3369
3370
/* Attach to pasid 100 which has been attached, should fail. */
3371
test_err_pasid_attach(EBUSY, pasid, nested_hwpt_id[0]);
3372
3373
/* cleanup pasid 100 */
3374
test_cmd_pasid_detach(pasid);
3375
3376
/* Replace tests */
3377
3378
pasid = 200;
3379
/*
3380
* Replace pasid 200 without attaching it, should fail
3381
* with -EINVAL.
3382
*/
3383
test_err_pasid_replace(EINVAL, pasid, s2_hwpt_id);
3384
3385
/*
3386
* Attach the s2 hwpt to pasid 200, should succeed, domain should
3387
* be valid.
3388
*/
3389
test_cmd_pasid_attach(pasid, s2_hwpt_id);
3390
ASSERT_EQ(0,
3391
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3392
pasid, s2_hwpt_id));
3393
3394
/*
3395
* Replace pasid 200 with self->ioas_id, should fail
3396
* and domain should be the prior s2 hwpt.
3397
*/
3398
test_err_pasid_replace(EINVAL, pasid, self->ioas_id);
3399
ASSERT_EQ(0,
3400
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3401
pasid, s2_hwpt_id));
3402
3403
/*
3404
* Replace a nested hwpt for pasid 200, should succeed,
3405
* and have valid domain.
3406
*/
3407
test_cmd_pasid_replace(pasid, nested_hwpt_id[0]);
3408
ASSERT_EQ(0,
3409
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3410
pasid, nested_hwpt_id[0]));
3411
3412
/*
3413
* Replace with another nested hwpt for pasid 200, should
3414
* succeed, and have valid domain.
3415
*/
3416
test_cmd_pasid_replace(pasid, nested_hwpt_id[1]);
3417
ASSERT_EQ(0,
3418
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3419
pasid, nested_hwpt_id[1]));
3420
3421
/* cleanup pasid 200 */
3422
test_cmd_pasid_detach(pasid);
3423
3424
/* Negative Tests for pasid replace, use pasid 1024 */
3425
3426
/*
3427
* Attach the s2 hwpt to pasid 1024, should succeed, domain should
3428
* be valid.
3429
*/
3430
pasid = 1024;
3431
test_cmd_pasid_attach(pasid, s2_hwpt_id);
3432
ASSERT_EQ(0,
3433
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3434
pasid, s2_hwpt_id));
3435
3436
/*
3437
* Replace pasid 1024 with nested_hwpt_id[0], should fail,
3438
* but have the old valid domain. This is a designed
3439
* negative case. Normally, this shall succeed.
3440
*/
3441
test_err_pasid_replace(ENOMEM, pasid, nested_hwpt_id[0]);
3442
ASSERT_EQ(0,
3443
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3444
pasid, s2_hwpt_id));
3445
3446
/* cleanup pasid 1024 */
3447
test_cmd_pasid_detach(pasid);
3448
3449
/* Attach to iopf-capable hwpt */
3450
3451
/*
3452
* Attach an iopf hwpt to pasid 2048, should succeed, domain should
3453
* be valid.
3454
*/
3455
pasid = 2048;
3456
test_cmd_pasid_attach(pasid, iopf_hwpt_id);
3457
ASSERT_EQ(0,
3458
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3459
pasid, iopf_hwpt_id));
3460
3461
test_cmd_trigger_iopf_pasid(self->device_id, pasid, fault_fd);
3462
3463
/*
3464
* Replace with s2_hwpt_id for pasid 2048, should
3465
* succeed, and have valid domain.
3466
*/
3467
test_cmd_pasid_replace(pasid, s2_hwpt_id);
3468
ASSERT_EQ(0,
3469
test_cmd_pasid_check_hwpt(self->fd, self->stdev_id,
3470
pasid, s2_hwpt_id));
3471
3472
/* cleanup pasid 2048 */
3473
test_cmd_pasid_detach(pasid);
3474
3475
test_ioctl_destroy(iopf_hwpt_id);
3476
close(fault_fd);
3477
test_ioctl_destroy(fault_id);
3478
3479
/* Detach the s2_hwpt_id from RID */
3480
test_cmd_mock_domain_replace(self->stdev_id, self->ioas_id);
3481
}
3482
3483
TEST_HARNESS_MAIN
3484
3485