1
1
// SPDX-License-Identifier: GPL-2.0-only
2
2
/* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES */
3
+ #include <asm/unistd.h>
3
4
#include <stdlib.h>
4
5
#include <sys/mman.h>
5
6
#include <sys/eventfd.h>
@@ -49,6 +50,9 @@ static __attribute__((constructor)) void setup_sizes(void)
49
50
vrc = mmap (buffer , BUFFER_SIZE , PROT_READ | PROT_WRITE ,
50
51
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED , -1 , 0 );
51
52
assert (vrc == buffer );
53
+
54
+ mfd_buffer = memfd_mmap (BUFFER_SIZE , PROT_READ | PROT_WRITE , MAP_SHARED ,
55
+ & mfd );
52
56
}
53
57
54
58
FIXTURE (iommufd )
@@ -128,6 +132,7 @@ TEST_F(iommufd, cmd_length)
128
132
TEST_LENGTH (iommu_ioas_unmap , IOMMU_IOAS_UNMAP , length );
129
133
TEST_LENGTH (iommu_option , IOMMU_OPTION , val64 );
130
134
TEST_LENGTH (iommu_vfio_ioas , IOMMU_VFIO_IOAS , __reserved );
135
+ TEST_LENGTH (iommu_ioas_map_file , IOMMU_IOAS_MAP_FILE , iova );
131
136
#undef TEST_LENGTH
132
137
}
133
138
@@ -1372,6 +1377,7 @@ FIXTURE_VARIANT(iommufd_mock_domain)
1372
1377
{
1373
1378
unsigned int mock_domains ;
1374
1379
bool hugepages ;
1380
+ bool file ;
1375
1381
};
1376
1382
1377
1383
FIXTURE_SETUP (iommufd_mock_domain )
@@ -1410,26 +1416,45 @@ FIXTURE_VARIANT_ADD(iommufd_mock_domain, one_domain)
1410
1416
{
1411
1417
.mock_domains = 1 ,
1412
1418
.hugepages = false,
1419
+ .file = false,
1413
1420
};
1414
1421
1415
1422
FIXTURE_VARIANT_ADD (iommufd_mock_domain , two_domains )
1416
1423
{
1417
1424
.mock_domains = 2 ,
1418
1425
.hugepages = false,
1426
+ .file = false,
1419
1427
};
1420
1428
1421
1429
FIXTURE_VARIANT_ADD (iommufd_mock_domain , one_domain_hugepage )
1422
1430
{
1423
1431
.mock_domains = 1 ,
1424
1432
.hugepages = true,
1433
+ .file = false,
1425
1434
};
1426
1435
1427
1436
FIXTURE_VARIANT_ADD (iommufd_mock_domain , two_domains_hugepage )
1428
1437
{
1429
1438
.mock_domains = 2 ,
1430
1439
.hugepages = true,
1440
+ .file = false,
1441
+ };
1442
+
1443
+ FIXTURE_VARIANT_ADD (iommufd_mock_domain , one_domain_file )
1444
+ {
1445
+ .mock_domains = 1 ,
1446
+ .hugepages = false,
1447
+ .file = true,
1448
+ };
1449
+
1450
+ FIXTURE_VARIANT_ADD (iommufd_mock_domain , one_domain_file_hugepage )
1451
+ {
1452
+ .mock_domains = 1 ,
1453
+ .hugepages = true,
1454
+ .file = true,
1431
1455
};
1432
1456
1457
+
1433
1458
/* Have the kernel check that the user pages made it to the iommu_domain */
1434
1459
#define check_mock_iova (_ptr , _iova , _length ) \
1435
1460
({ \
@@ -1455,7 +1480,10 @@ FIXTURE_VARIANT_ADD(iommufd_mock_domain, two_domains_hugepage)
1455
1480
} \
1456
1481
})
1457
1482
1458
- TEST_F (iommufd_mock_domain , basic )
1483
+ static void
1484
+ test_basic_mmap (struct __test_metadata * _metadata ,
1485
+ struct _test_data_iommufd_mock_domain * self ,
1486
+ const struct _fixture_variant_iommufd_mock_domain * variant )
1459
1487
{
1460
1488
size_t buf_size = self -> mmap_buf_size ;
1461
1489
uint8_t * buf ;
@@ -1478,6 +1506,40 @@ TEST_F(iommufd_mock_domain, basic)
1478
1506
test_err_ioctl_ioas_map (EFAULT , buf , buf_size , & iova );
1479
1507
}
1480
1508
1509
+ static void
1510
+ test_basic_file (struct __test_metadata * _metadata ,
1511
+ struct _test_data_iommufd_mock_domain * self ,
1512
+ const struct _fixture_variant_iommufd_mock_domain * variant )
1513
+ {
1514
+ size_t buf_size = self -> mmap_buf_size ;
1515
+ uint8_t * buf ;
1516
+ __u64 iova ;
1517
+ int mfd_tmp ;
1518
+ int prot = PROT_READ | PROT_WRITE ;
1519
+
1520
+ /* Simple one page map */
1521
+ test_ioctl_ioas_map_file (mfd , 0 , PAGE_SIZE , & iova );
1522
+ check_mock_iova (mfd_buffer , iova , PAGE_SIZE );
1523
+
1524
+ buf = memfd_mmap (buf_size , prot , MAP_SHARED , & mfd_tmp );
1525
+ ASSERT_NE (MAP_FAILED , buf );
1526
+
1527
+ test_err_ioctl_ioas_map_file (EINVAL , mfd_tmp , 0 , buf_size + 1 , & iova );
1528
+
1529
+ ASSERT_EQ (0 , ftruncate (mfd_tmp , 0 ));
1530
+ test_err_ioctl_ioas_map_file (EINVAL , mfd_tmp , 0 , buf_size , & iova );
1531
+
1532
+ close (mfd_tmp );
1533
+ }
1534
+
1535
+ TEST_F (iommufd_mock_domain , basic )
1536
+ {
1537
+ if (variant -> file )
1538
+ test_basic_file (_metadata , self , variant );
1539
+ else
1540
+ test_basic_mmap (_metadata , self , variant );
1541
+ }
1542
+
1481
1543
TEST_F (iommufd_mock_domain , ro_unshare )
1482
1544
{
1483
1545
uint8_t * buf ;
@@ -1513,9 +1575,13 @@ TEST_F(iommufd_mock_domain, all_aligns)
1513
1575
unsigned int start ;
1514
1576
unsigned int end ;
1515
1577
uint8_t * buf ;
1578
+ int prot = PROT_READ | PROT_WRITE ;
1579
+ int mfd ;
1516
1580
1517
- buf = mmap (0 , buf_size , PROT_READ | PROT_WRITE , self -> mmap_flags , -1 ,
1518
- 0 );
1581
+ if (variant -> file )
1582
+ buf = memfd_mmap (buf_size , prot , MAP_SHARED , & mfd );
1583
+ else
1584
+ buf = mmap (0 , buf_size , prot , self -> mmap_flags , -1 , 0 );
1519
1585
ASSERT_NE (MAP_FAILED , buf );
1520
1586
check_refs (buf , buf_size , 0 );
1521
1587
@@ -1532,7 +1598,12 @@ TEST_F(iommufd_mock_domain, all_aligns)
1532
1598
size_t length = end - start ;
1533
1599
__u64 iova ;
1534
1600
1535
- test_ioctl_ioas_map (buf + start , length , & iova );
1601
+ if (variant -> file ) {
1602
+ test_ioctl_ioas_map_file (mfd , start , length ,
1603
+ & iova );
1604
+ } else {
1605
+ test_ioctl_ioas_map (buf + start , length , & iova );
1606
+ }
1536
1607
check_mock_iova (buf + start , iova , length );
1537
1608
check_refs (buf + start / PAGE_SIZE * PAGE_SIZE ,
1538
1609
end / PAGE_SIZE * PAGE_SIZE -
@@ -1544,6 +1615,8 @@ TEST_F(iommufd_mock_domain, all_aligns)
1544
1615
}
1545
1616
check_refs (buf , buf_size , 0 );
1546
1617
ASSERT_EQ (0 , munmap (buf , buf_size ));
1618
+ if (variant -> file )
1619
+ close (mfd );
1547
1620
}
1548
1621
1549
1622
TEST_F (iommufd_mock_domain , all_aligns_copy )
@@ -1554,9 +1627,13 @@ TEST_F(iommufd_mock_domain, all_aligns_copy)
1554
1627
unsigned int start ;
1555
1628
unsigned int end ;
1556
1629
uint8_t * buf ;
1630
+ int prot = PROT_READ | PROT_WRITE ;
1631
+ int mfd ;
1557
1632
1558
- buf = mmap (0 , buf_size , PROT_READ | PROT_WRITE , self -> mmap_flags , -1 ,
1559
- 0 );
1633
+ if (variant -> file )
1634
+ buf = memfd_mmap (buf_size , prot , MAP_SHARED , & mfd );
1635
+ else
1636
+ buf = mmap (0 , buf_size , prot , self -> mmap_flags , -1 , 0 );
1560
1637
ASSERT_NE (MAP_FAILED , buf );
1561
1638
check_refs (buf , buf_size , 0 );
1562
1639
@@ -1575,7 +1652,12 @@ TEST_F(iommufd_mock_domain, all_aligns_copy)
1575
1652
uint32_t mock_stdev_id ;
1576
1653
__u64 iova ;
1577
1654
1578
- test_ioctl_ioas_map (buf + start , length , & iova );
1655
+ if (variant -> file ) {
1656
+ test_ioctl_ioas_map_file (mfd , start , length ,
1657
+ & iova );
1658
+ } else {
1659
+ test_ioctl_ioas_map (buf + start , length , & iova );
1660
+ }
1579
1661
1580
1662
/* Add and destroy a domain while the area exists */
1581
1663
old_id = self -> hwpt_ids [1 ];
@@ -1596,15 +1678,18 @@ TEST_F(iommufd_mock_domain, all_aligns_copy)
1596
1678
}
1597
1679
check_refs (buf , buf_size , 0 );
1598
1680
ASSERT_EQ (0 , munmap (buf , buf_size ));
1681
+ if (variant -> file )
1682
+ close (mfd );
1599
1683
}
1600
1684
1601
1685
TEST_F (iommufd_mock_domain , user_copy )
1602
1686
{
1687
+ void * buf = variant -> file ? mfd_buffer : buffer ;
1603
1688
struct iommu_test_cmd access_cmd = {
1604
1689
.size = sizeof (access_cmd ),
1605
1690
.op = IOMMU_TEST_OP_ACCESS_PAGES ,
1606
1691
.access_pages = { .length = BUFFER_SIZE ,
1607
- .uptr = (uintptr_t )buffer },
1692
+ .uptr = (uintptr_t )buf },
1608
1693
};
1609
1694
struct iommu_ioas_copy copy_cmd = {
1610
1695
.size = sizeof (copy_cmd ),
@@ -1623,9 +1708,13 @@ TEST_F(iommufd_mock_domain, user_copy)
1623
1708
1624
1709
/* Pin the pages in an IOAS with no domains then copy to an IOAS with domains */
1625
1710
test_ioctl_ioas_alloc (& ioas_id );
1626
- test_ioctl_ioas_map_id (ioas_id , buffer , BUFFER_SIZE ,
1627
- & copy_cmd .src_iova );
1628
-
1711
+ if (variant -> file ) {
1712
+ test_ioctl_ioas_map_id_file (ioas_id , mfd , 0 , BUFFER_SIZE ,
1713
+ & copy_cmd .src_iova );
1714
+ } else {
1715
+ test_ioctl_ioas_map_id (ioas_id , buf , BUFFER_SIZE ,
1716
+ & copy_cmd .src_iova );
1717
+ }
1629
1718
test_cmd_create_access (ioas_id , & access_cmd .id ,
1630
1719
MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES );
1631
1720
@@ -1635,12 +1724,17 @@ TEST_F(iommufd_mock_domain, user_copy)
1635
1724
& access_cmd ));
1636
1725
copy_cmd .src_ioas_id = ioas_id ;
1637
1726
ASSERT_EQ (0 , ioctl (self -> fd , IOMMU_IOAS_COPY , & copy_cmd ));
1638
- check_mock_iova (buffer , MOCK_APERTURE_START , BUFFER_SIZE );
1727
+ check_mock_iova (buf , MOCK_APERTURE_START , BUFFER_SIZE );
1639
1728
1640
1729
/* Now replace the ioas with a new one */
1641
1730
test_ioctl_ioas_alloc (& new_ioas_id );
1642
- test_ioctl_ioas_map_id (new_ioas_id , buffer , BUFFER_SIZE ,
1643
- & copy_cmd .src_iova );
1731
+ if (variant -> file ) {
1732
+ test_ioctl_ioas_map_id_file (new_ioas_id , mfd , 0 , BUFFER_SIZE ,
1733
+ & copy_cmd .src_iova );
1734
+ } else {
1735
+ test_ioctl_ioas_map_id (new_ioas_id , buf , BUFFER_SIZE ,
1736
+ & copy_cmd .src_iova );
1737
+ }
1644
1738
test_cmd_access_replace_ioas (access_cmd .id , new_ioas_id );
1645
1739
1646
1740
/* Destroy the old ioas and cleanup copied mapping */
@@ -1654,7 +1748,7 @@ TEST_F(iommufd_mock_domain, user_copy)
1654
1748
& access_cmd ));
1655
1749
copy_cmd .src_ioas_id = new_ioas_id ;
1656
1750
ASSERT_EQ (0 , ioctl (self -> fd , IOMMU_IOAS_COPY , & copy_cmd ));
1657
- check_mock_iova (buffer , MOCK_APERTURE_START , BUFFER_SIZE );
1751
+ check_mock_iova (buf , MOCK_APERTURE_START , BUFFER_SIZE );
1658
1752
1659
1753
test_cmd_destroy_access_pages (
1660
1754
access_cmd .id , access_cmd .access_pages .out_access_pages_id );
0 commit comments