1 /* 2 * Intel IOMMU unit test. 3 * 4 * Copyright (C) 2016 Red Hat, Inc. 5 * 6 * Authors: 7 * Peter Xu <peterx@redhat.com>, 8 * 9 * This work is licensed under the terms of the GNU LGPL, version 2 or 10 * later. 11 */ 12 13 #include "intel-iommu.h" 14 #include "pci-edu.h" 15 16 #define VTD_TEST_DMAR_4B ("DMAR 4B memcpy test") 17 18 void vtd_test_dmar(struct pci_edu_dev *dev) 19 { 20 void *page = alloc_page(); 21 22 #define DMA_TEST_WORD (0x12345678) 23 /* Modify the first 4 bytes of the page */ 24 *(uint32_t *)page = DMA_TEST_WORD; 25 26 /* 27 * Map the newly allocated page into IOVA address 0 (size 4K) 28 * of the device address space. Root entry and context entry 29 * will be automatically created when needed. 30 */ 31 vtd_map_range(dev->pci_dev.bdf, 0, virt_to_phys(page), PAGE_SIZE); 32 33 /* 34 * DMA the first 4 bytes of the page to EDU device buffer 35 * offset 0. 36 */ 37 edu_dma(dev, 0, 4, 0, false); 38 39 /* 40 * DMA the first 4 bytes of EDU device buffer into the page 41 * with offset 4 (so it'll be using 4-7 bytes). 42 */ 43 edu_dma(dev, 4, 4, 0, true); 44 45 /* 46 * Check data match between 0-3 bytes and 4-7 bytes of the 47 * page. 48 */ 49 report(VTD_TEST_DMAR_4B, *((uint32_t *)page + 1) == DMA_TEST_WORD); 50 51 free_page(page); 52 } 53 54 int main(int argc, char *argv[]) 55 { 56 struct pci_edu_dev dev; 57 58 vtd_init(); 59 60 report("fault status check", vtd_readl(DMAR_FSTS_REG) == 0); 61 report("QI enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_QI); 62 report("DMAR table setup", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_ROOT); 63 report("IR table setup", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR_TABLE); 64 report("DMAR enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_DMAR); 65 report("IR enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR); 66 report("DMAR support 39 bits address width", 67 vtd_readq(DMAR_CAP_REG) & VTD_CAP_SAGAW); 68 report("DMAR support huge pages", vtd_readq(DMAR_CAP_REG) & VTD_CAP_SLLPS); 69 70 if (!edu_init(&dev)) { 71 printf("Please specify \"-device edu\" to do " 72 "further IOMMU tests.\n"); 73 report_skip(VTD_TEST_DMAR_4B); 74 } else 75 vtd_test_dmar(&dev); 76 77 return report_summary(); 78 } 79