Merge branch 'upstream-16.11-stable' into 16.11.x
[deb_dpdk.git] / debian / patches / dpdk-dev-v3-eal-sPAPR-IOMMU-support-in-pci-probing-for-vfio-pci-in-ppc64le.patch
1 Description: eal: sPAPR IOMMU support in pci probing for vfio-pci in ppc64le
2
3     From: Gowrishankar Muthukrishnan <gowrishankar.m@linux.vnet.ibm.com>
4
5     Below changes adds pci probing support for vfio-pci devices in power8.
6
7     v3 - better validation for kernel not implementing few iocts called
8     v2 - kernel version checked and doc updated
9
10     Signed-off-by: Gowrishankar Muthukrishnan <gowrishankar.m@linux.vnet.ibm.com>
11
12 Note: can be dropped >=DPDK 17.05
13
14 Forwarded: yes, http://dpdk.org/dev/patchwork/patch/21482/
15 Original-Author: Gowrishankar Muthukrishnan <gowrishankar.m@linux.vnet.ibm.com>
16 Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/dpdk/+bug/1670689
17 Author: Christian Ehrhardt <christian.ehrhardt@canonical.com>
18 Last-Update: 2017-03-07
19
20 --- a/lib/librte_eal/linuxapp/eal/eal_vfio.c
21 +++ b/lib/librte_eal/linuxapp/eal/eal_vfio.c
22 @@ -50,12 +50,15 @@
23  static struct vfio_config vfio_cfg;
24  
25  static int vfio_type1_dma_map(int);
26 +static int vfio_spapr_dma_map(int);
27  static int vfio_noiommu_dma_map(int);
28  
29  /* IOMMU types we support */
30  static const struct vfio_iommu_type iommu_types[] = {
31         /* x86 IOMMU, otherwise known as type 1 */
32         { RTE_VFIO_TYPE1, "Type 1", &vfio_type1_dma_map},
33 +       /* ppc64 IOMMU, otherwise known as spapr */
34 +       { RTE_VFIO_SPAPR, "sPAPR", &vfio_spapr_dma_map},
35         /* IOMMU-less mode */
36         { RTE_VFIO_NOIOMMU, "No-IOMMU", &vfio_noiommu_dma_map},
37  };
38 @@ -537,6 +540,93 @@
39         }
40  
41         return 0;
42 +}
43 +
44 +static int
45 +vfio_spapr_dma_map(int vfio_container_fd)
46 +{
47 +       const struct rte_memseg *ms = rte_eal_get_physmem_layout();
48 +       int i, ret;
49 +
50 +       struct vfio_iommu_spapr_register_memory reg = {
51 +               .argsz = sizeof(reg),
52 +               .flags = 0
53 +       };
54 +       struct vfio_iommu_spapr_tce_info info = {
55 +               .argsz = sizeof(info),
56 +       };
57 +       struct vfio_iommu_spapr_tce_create create = {
58 +               .argsz = sizeof(create),
59 +       };
60 +       struct vfio_iommu_spapr_tce_remove remove = {
61 +               .argsz = sizeof(remove),
62 +       };
63 +
64 +       /* query spapr iommu info */
65 +       ret = ioctl(vfio_container_fd, VFIO_IOMMU_SPAPR_TCE_GET_INFO, &info);
66 +       if (ret) {
67 +               RTE_LOG(ERR, EAL, "  cannot get iommu info, "
68 +                               "error %i (%s)\n", errno, strerror(errno));
69 +               return -1;
70 +       }
71 +
72 +       /* remove default DMA of 32 bit window */
73 +       remove.start_addr = info.dma32_window_start;
74 +       ret = ioctl(vfio_container_fd, VFIO_IOMMU_SPAPR_TCE_REMOVE, &remove);
75 +       if (ret) {
76 +               RTE_LOG(ERR, EAL, "  cannot remove default DMA window, "
77 +                               "error %i (%s)\n", errno, strerror(errno));
78 +               return -1;
79 +       }
80 +
81 +       /* calculate window size based on number of hugepages configured */
82 +       create.window_size = rte_eal_get_physmem_size();
83 +       create.page_shift = __builtin_ctzll(ms->hugepage_sz);
84 +       create.levels = 2;
85 +
86 +       ret = ioctl(vfio_container_fd, VFIO_IOMMU_SPAPR_TCE_CREATE, &create);
87 +       if (ret) {
88 +               RTE_LOG(ERR, EAL, "  cannot create new DMA window, "
89 +                               "error %i (%s)\n", errno, strerror(errno));
90 +               return -1;
91 +       }
92 +
93 +       /* map all DPDK segments for DMA. use 1:1 PA to IOVA mapping */
94 +       for (i = 0; i < RTE_MAX_MEMSEG; i++) {
95 +               struct vfio_iommu_type1_dma_map dma_map;
96 +
97 +               if (ms[i].addr == NULL)
98 +                       break;
99 +
100 +               reg.vaddr = (uintptr_t) ms[i].addr;
101 +               reg.size = ms[i].len;
102 +               ret = ioctl(vfio_container_fd,
103 +                       VFIO_IOMMU_SPAPR_REGISTER_MEMORY, &reg);
104 +               if (ret) {
105 +                       RTE_LOG(ERR, EAL, "  cannot register vaddr for IOMMU, "
106 +                               "error %i (%s)\n", errno, strerror(errno));
107 +                       return -1;
108 +               }
109 +
110 +               memset(&dma_map, 0, sizeof(dma_map));
111 +               dma_map.argsz = sizeof(struct vfio_iommu_type1_dma_map);
112 +               dma_map.vaddr = ms[i].addr_64;
113 +               dma_map.size = ms[i].len;
114 +               dma_map.iova = ms[i].phys_addr;
115 +               dma_map.flags = VFIO_DMA_MAP_FLAG_READ |
116 +                                VFIO_DMA_MAP_FLAG_WRITE;
117 +
118 +               ret = ioctl(vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dma_map);
119 +
120 +               if (ret) {
121 +                       RTE_LOG(ERR, EAL, "  cannot set up DMA remapping, "
122 +                               "error %i (%s)\n", errno, strerror(errno));
123 +                       return -1;
124 +               }
125 +
126 +       }
127 +
128 +       return 0;
129  }
130  
131  static int
132 --- a/lib/librte_eal/linuxapp/eal/eal_vfio.h
133 +++ b/lib/librte_eal/linuxapp/eal/eal_vfio.h
134 @@ -54,6 +54,31 @@
135  
136  #define RTE_VFIO_TYPE1 VFIO_TYPE1_IOMMU
137  
138 +#ifndef VFIO_SPAPR_TCE_v2_IOMMU
139 +#define RTE_VFIO_SPAPR 7
140 +#define VFIO_IOMMU_SPAPR_REGISTER_MEMORY _IO(VFIO_TYPE, VFIO_BASE + 17)
141 +#define VFIO_IOMMU_SPAPR_TCE_CREATE _IO(VFIO_TYPE, VFIO_BASE + 19)
142 +#define VFIO_IOMMU_SPAPR_TCE_REMOVE _IO(VFIO_TYPE, VFIO_BASE + 20)
143 +struct vfio_iommu_spapr_register_memory {
144 +       uint32_t argsz;
145 +       uint32_t flags;
146 +       uint64_t vaddr;
147 +       uint64_t size;
148 +};
149 +struct vfio_iommu_spapr_tce_create {
150 +       uint32_t argsz;
151 +       uint32_t page_shift;
152 +       uint64_t window_size;
153 +       uint32_t levels;
154 +};
155 +struct vfio_iommu_spapr_tce_remove {
156 +       uint32_t argsz;
157 +       uint64_t start_addr;
158 +};
159 +#else
160 +#define RTE_VFIO_SPAPR VFIO_SPAPR_TCE_v2_IOMMU
161 +#endif
162 +
163  #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
164  #define RTE_VFIO_NOIOMMU 8
165  #else