Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iommufd: Move iommufd_sw_msi and related functions to driver.c

To provide the iommufd_sw_msi() to the iommu core that is under a different
Kconfig, move it and its related functions to driver.c. Then, stub it into
the iommu-priv header. The iommufd_sw_msi_install() continues to be used by
iommufd internal, so put it in the private header.

Note that iommufd_sw_msi() will be called in the iommu core, replacing the
sw_msi function pointer. Given that IOMMU_API is "bool" in Kconfig, change
IOMMUFD_DRIVER_CORE to "bool" as well.

Since this affects the module size, here is before-n-after size comparison:
[Before]
text data bss dec hex filename
18797 848 56 19701 4cf5 drivers/iommu/iommufd/device.o
722 44 0 766 2fe drivers/iommu/iommufd/driver.o
[After]
text data bss dec hex filename
17735 808 56 18599 48a7 drivers/iommu/iommufd/device.o
3020 180 0 3200 c80 drivers/iommu/iommufd/driver.o

Link: https://patch.msgid.link/r/374c159592dba7852bee20968f3f66fa0ee8ca93.1742871535.git.nicolinc@nvidia.com
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>

authored by

Nicolin Chen and committed by
Jason Gunthorpe
ec031e1b 6aa63a4e

+153 -126
+13
drivers/iommu/iommu-priv.h
··· 5 5 #define __LINUX_IOMMU_PRIV_H 6 6 7 7 #include <linux/iommu.h> 8 + #include <linux/msi.h> 8 9 9 10 static inline const struct iommu_ops *dev_iommu_ops(struct device *dev) 10 11 { ··· 44 43 int iommu_replace_group_handle(struct iommu_group *group, 45 44 struct iommu_domain *new_domain, 46 45 struct iommu_attach_handle *handle); 46 + 47 + #if IS_ENABLED(CONFIG_IOMMUFD_DRIVER_CORE) && IS_ENABLED(CONFIG_IRQ_MSI_IOMMU) 48 + int iommufd_sw_msi(struct iommu_domain *domain, struct msi_desc *desc, 49 + phys_addr_t msi_addr); 50 + #else /* !CONFIG_IOMMUFD_DRIVER_CORE || !CONFIG_IRQ_MSI_IOMMU */ 51 + static inline int iommufd_sw_msi(struct iommu_domain *domain, 52 + struct msi_desc *desc, phys_addr_t msi_addr) 53 + { 54 + return -EOPNOTSUPP; 55 + } 56 + #endif /* CONFIG_IOMMUFD_DRIVER_CORE && CONFIG_IRQ_MSI_IOMMU */ 57 + 47 58 #endif /* __LINUX_IOMMU_PRIV_H */
+1 -1
drivers/iommu/iommufd/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config IOMMUFD_DRIVER_CORE 3 - tristate 3 + bool 4 4 default (IOMMUFD_DRIVER || IOMMUFD) if IOMMUFD!=n 5 5 6 6 config IOMMUFD
+8 -123
drivers/iommu/iommufd/device.c
··· 5 5 #include <linux/iommufd.h> 6 6 #include <linux/slab.h> 7 7 #include <uapi/linux/iommufd.h> 8 - #include <linux/msi.h> 9 8 10 9 #include "../iommu-priv.h" 11 10 #include "io_pagetable.h" ··· 293 294 } 294 295 EXPORT_SYMBOL_NS_GPL(iommufd_device_to_id, "IOMMUFD"); 295 296 296 - /* 297 - * Get a iommufd_sw_msi_map for the msi physical address requested by the irq 298 - * layer. The mapping to IOVA is global to the iommufd file descriptor, every 299 - * domain that is attached to a device using the same MSI parameters will use 300 - * the same IOVA. 301 - */ 302 - static __maybe_unused struct iommufd_sw_msi_map * 303 - iommufd_sw_msi_get_map(struct iommufd_ctx *ictx, phys_addr_t msi_addr, 304 - phys_addr_t sw_msi_start) 305 - { 306 - struct iommufd_sw_msi_map *cur; 307 - unsigned int max_pgoff = 0; 308 - 309 - lockdep_assert_held(&ictx->sw_msi_lock); 310 - 311 - list_for_each_entry(cur, &ictx->sw_msi_list, sw_msi_item) { 312 - if (cur->sw_msi_start != sw_msi_start) 313 - continue; 314 - max_pgoff = max(max_pgoff, cur->pgoff + 1); 315 - if (cur->msi_addr == msi_addr) 316 - return cur; 317 - } 318 - 319 - if (ictx->sw_msi_id >= 320 - BITS_PER_BYTE * sizeof_field(struct iommufd_sw_msi_maps, bitmap)) 321 - return ERR_PTR(-EOVERFLOW); 322 - 323 - cur = kzalloc(sizeof(*cur), GFP_KERNEL); 324 - if (!cur) 325 - return ERR_PTR(-ENOMEM); 326 - 327 - cur->sw_msi_start = sw_msi_start; 328 - cur->msi_addr = msi_addr; 329 - cur->pgoff = max_pgoff; 330 - cur->id = ictx->sw_msi_id++; 331 - list_add_tail(&cur->sw_msi_item, &ictx->sw_msi_list); 332 - return cur; 333 - } 334 - 335 - static int iommufd_sw_msi_install(struct iommufd_ctx *ictx, 336 - struct iommufd_hwpt_paging *hwpt_paging, 337 - struct iommufd_sw_msi_map *msi_map) 338 - { 339 - unsigned long iova; 340 - 341 - lockdep_assert_held(&ictx->sw_msi_lock); 342 - 343 - iova = msi_map->sw_msi_start + msi_map->pgoff * PAGE_SIZE; 344 - if (!test_bit(msi_map->id, hwpt_paging->present_sw_msi.bitmap)) { 345 - int rc; 346 - 347 - rc = iommu_map(hwpt_paging->common.domain, iova, 348 - msi_map->msi_addr, PAGE_SIZE, 349 - IOMMU_WRITE | IOMMU_READ | IOMMU_MMIO, 350 - GFP_KERNEL_ACCOUNT); 351 - if (rc) 352 - return rc; 353 - __set_bit(msi_map->id, hwpt_paging->present_sw_msi.bitmap); 354 - } 355 - return 0; 356 - } 357 - 358 - /* 359 - * Called by the irq code if the platform translates the MSI address through the 360 - * IOMMU. msi_addr is the physical address of the MSI page. iommufd will 361 - * allocate a fd global iova for the physical page that is the same on all 362 - * domains and devices. 363 - */ 364 297 #ifdef CONFIG_IRQ_MSI_IOMMU 365 - int iommufd_sw_msi(struct iommu_domain *domain, struct msi_desc *desc, 366 - phys_addr_t msi_addr) 367 - { 368 - struct device *dev = msi_desc_to_dev(desc); 369 - struct iommufd_hwpt_paging *hwpt_paging; 370 - struct iommu_attach_handle *raw_handle; 371 - struct iommufd_attach_handle *handle; 372 - struct iommufd_sw_msi_map *msi_map; 373 - struct iommufd_ctx *ictx; 374 - unsigned long iova; 375 - int rc; 376 - 377 - /* 378 - * It is safe to call iommu_attach_handle_get() here because the iommu 379 - * core code invokes this under the group mutex which also prevents any 380 - * change of the attach handle for the duration of this function. 381 - */ 382 - iommu_group_mutex_assert(dev); 383 - 384 - raw_handle = 385 - iommu_attach_handle_get(dev->iommu_group, IOMMU_NO_PASID, 0); 386 - if (IS_ERR(raw_handle)) 387 - return 0; 388 - hwpt_paging = find_hwpt_paging(domain->iommufd_hwpt); 389 - 390 - handle = to_iommufd_handle(raw_handle); 391 - /* No IOMMU_RESV_SW_MSI means no change to the msi_msg */ 392 - if (handle->idev->igroup->sw_msi_start == PHYS_ADDR_MAX) 393 - return 0; 394 - 395 - ictx = handle->idev->ictx; 396 - guard(mutex)(&ictx->sw_msi_lock); 397 - /* 398 - * The input msi_addr is the exact byte offset of the MSI doorbell, we 399 - * assume the caller has checked that it is contained with a MMIO region 400 - * that is secure to map at PAGE_SIZE. 401 - */ 402 - msi_map = iommufd_sw_msi_get_map(handle->idev->ictx, 403 - msi_addr & PAGE_MASK, 404 - handle->idev->igroup->sw_msi_start); 405 - if (IS_ERR(msi_map)) 406 - return PTR_ERR(msi_map); 407 - 408 - rc = iommufd_sw_msi_install(ictx, hwpt_paging, msi_map); 409 - if (rc) 410 - return rc; 411 - __set_bit(msi_map->id, handle->idev->igroup->required_sw_msi.bitmap); 412 - 413 - iova = msi_map->sw_msi_start + msi_map->pgoff * PAGE_SIZE; 414 - msi_desc_set_iommu_msi_iova(desc, iova, PAGE_SHIFT); 415 - return 0; 416 - } 417 - #endif 418 - 419 298 static int iommufd_group_setup_msi(struct iommufd_group *igroup, 420 299 struct iommufd_hwpt_paging *hwpt_paging) 421 300 { ··· 320 443 } 321 444 return 0; 322 445 } 446 + #else 447 + static inline int 448 + iommufd_group_setup_msi(struct iommufd_group *igroup, 449 + struct iommufd_hwpt_paging *hwpt_paging) 450 + { 451 + return 0; 452 + } 453 + #endif 323 454 324 455 static int 325 456 iommufd_device_attach_reserved_iova(struct iommufd_device *idev,
+126
drivers/iommu/iommufd/driver.c
··· 121 121 } 122 122 EXPORT_SYMBOL_NS_GPL(iommufd_viommu_report_event, "IOMMUFD"); 123 123 124 + #ifdef CONFIG_IRQ_MSI_IOMMU 125 + /* 126 + * Get a iommufd_sw_msi_map for the msi physical address requested by the irq 127 + * layer. The mapping to IOVA is global to the iommufd file descriptor, every 128 + * domain that is attached to a device using the same MSI parameters will use 129 + * the same IOVA. 130 + */ 131 + static struct iommufd_sw_msi_map * 132 + iommufd_sw_msi_get_map(struct iommufd_ctx *ictx, phys_addr_t msi_addr, 133 + phys_addr_t sw_msi_start) 134 + { 135 + struct iommufd_sw_msi_map *cur; 136 + unsigned int max_pgoff = 0; 137 + 138 + lockdep_assert_held(&ictx->sw_msi_lock); 139 + 140 + list_for_each_entry(cur, &ictx->sw_msi_list, sw_msi_item) { 141 + if (cur->sw_msi_start != sw_msi_start) 142 + continue; 143 + max_pgoff = max(max_pgoff, cur->pgoff + 1); 144 + if (cur->msi_addr == msi_addr) 145 + return cur; 146 + } 147 + 148 + if (ictx->sw_msi_id >= 149 + BITS_PER_BYTE * sizeof_field(struct iommufd_sw_msi_maps, bitmap)) 150 + return ERR_PTR(-EOVERFLOW); 151 + 152 + cur = kzalloc(sizeof(*cur), GFP_KERNEL); 153 + if (!cur) 154 + return ERR_PTR(-ENOMEM); 155 + 156 + cur->sw_msi_start = sw_msi_start; 157 + cur->msi_addr = msi_addr; 158 + cur->pgoff = max_pgoff; 159 + cur->id = ictx->sw_msi_id++; 160 + list_add_tail(&cur->sw_msi_item, &ictx->sw_msi_list); 161 + return cur; 162 + } 163 + 164 + int iommufd_sw_msi_install(struct iommufd_ctx *ictx, 165 + struct iommufd_hwpt_paging *hwpt_paging, 166 + struct iommufd_sw_msi_map *msi_map) 167 + { 168 + unsigned long iova; 169 + 170 + lockdep_assert_held(&ictx->sw_msi_lock); 171 + 172 + iova = msi_map->sw_msi_start + msi_map->pgoff * PAGE_SIZE; 173 + if (!test_bit(msi_map->id, hwpt_paging->present_sw_msi.bitmap)) { 174 + int rc; 175 + 176 + rc = iommu_map(hwpt_paging->common.domain, iova, 177 + msi_map->msi_addr, PAGE_SIZE, 178 + IOMMU_WRITE | IOMMU_READ | IOMMU_MMIO, 179 + GFP_KERNEL_ACCOUNT); 180 + if (rc) 181 + return rc; 182 + __set_bit(msi_map->id, hwpt_paging->present_sw_msi.bitmap); 183 + } 184 + return 0; 185 + } 186 + EXPORT_SYMBOL_NS_GPL(iommufd_sw_msi_install, "IOMMUFD_INTERNAL"); 187 + 188 + /* 189 + * Called by the irq code if the platform translates the MSI address through the 190 + * IOMMU. msi_addr is the physical address of the MSI page. iommufd will 191 + * allocate a fd global iova for the physical page that is the same on all 192 + * domains and devices. 193 + */ 194 + int iommufd_sw_msi(struct iommu_domain *domain, struct msi_desc *desc, 195 + phys_addr_t msi_addr) 196 + { 197 + struct device *dev = msi_desc_to_dev(desc); 198 + struct iommufd_hwpt_paging *hwpt_paging; 199 + struct iommu_attach_handle *raw_handle; 200 + struct iommufd_attach_handle *handle; 201 + struct iommufd_sw_msi_map *msi_map; 202 + struct iommufd_ctx *ictx; 203 + unsigned long iova; 204 + int rc; 205 + 206 + /* 207 + * It is safe to call iommu_attach_handle_get() here because the iommu 208 + * core code invokes this under the group mutex which also prevents any 209 + * change of the attach handle for the duration of this function. 210 + */ 211 + iommu_group_mutex_assert(dev); 212 + 213 + raw_handle = 214 + iommu_attach_handle_get(dev->iommu_group, IOMMU_NO_PASID, 0); 215 + if (IS_ERR(raw_handle)) 216 + return 0; 217 + hwpt_paging = find_hwpt_paging(domain->iommufd_hwpt); 218 + 219 + handle = to_iommufd_handle(raw_handle); 220 + /* No IOMMU_RESV_SW_MSI means no change to the msi_msg */ 221 + if (handle->idev->igroup->sw_msi_start == PHYS_ADDR_MAX) 222 + return 0; 223 + 224 + ictx = handle->idev->ictx; 225 + guard(mutex)(&ictx->sw_msi_lock); 226 + /* 227 + * The input msi_addr is the exact byte offset of the MSI doorbell, we 228 + * assume the caller has checked that it is contained with a MMIO region 229 + * that is secure to map at PAGE_SIZE. 230 + */ 231 + msi_map = iommufd_sw_msi_get_map(handle->idev->ictx, 232 + msi_addr & PAGE_MASK, 233 + handle->idev->igroup->sw_msi_start); 234 + if (IS_ERR(msi_map)) 235 + return PTR_ERR(msi_map); 236 + 237 + rc = iommufd_sw_msi_install(ictx, hwpt_paging, msi_map); 238 + if (rc) 239 + return rc; 240 + __set_bit(msi_map->id, handle->idev->igroup->required_sw_msi.bitmap); 241 + 242 + iova = msi_map->sw_msi_start + msi_map->pgoff * PAGE_SIZE; 243 + msi_desc_set_iommu_msi_iova(desc, iova, PAGE_SHIFT); 244 + return 0; 245 + } 246 + EXPORT_SYMBOL_NS_GPL(iommufd_sw_msi, "IOMMUFD"); 247 + #endif 248 + 124 249 MODULE_DESCRIPTION("iommufd code shared with builtin modules"); 250 + MODULE_IMPORT_NS("IOMMUFD_INTERNAL"); 125 251 MODULE_LICENSE("GPL");
+5 -2
drivers/iommu/iommufd/iommufd_private.h
··· 32 32 DECLARE_BITMAP(bitmap, 64); 33 33 }; 34 34 35 - int iommufd_sw_msi(struct iommu_domain *domain, struct msi_desc *desc, 36 - phys_addr_t msi_addr); 35 + #ifdef CONFIG_IRQ_MSI_IOMMU 36 + int iommufd_sw_msi_install(struct iommufd_ctx *ictx, 37 + struct iommufd_hwpt_paging *hwpt_paging, 38 + struct iommufd_sw_msi_map *msi_map); 39 + #endif 37 40 38 41 struct iommufd_ctx { 39 42 struct file *file;