On 2/18/26 01:11, Jason Gunthorpe wrote:
This type is required by iommufd and kvm as dmabuf importers.
Due to sensitivity about abusing physical addresses, restrict importers by using EXPORT_SYMBOL_FOR_MODULES(). Only iommufd can implement an importer, the kernel module loader will enforce this.
Allow anything to implement an exporter as there are use cases in DPDK/SPDK to connect GPU memory into VFIO/iommufd and it is hard to abuse the API as an exporter.
The physical address list exporter returns a physical address list in a simple kvalloc'd array of struct phys_vec.
As far as I can see that is still a pretty big NO-GO.
We have seen so many problems with direct physical address access by the importer that I clear don't want to repeat that performance.
My main question is why does IOMMUFD need the physical address in the first place?
If that is really strictly necessary then I strongly suggest to not touch drivers/dma-buf in any way, but only do this is private interface between iommufd and KVM.
Regards, Christian.
For now all entries are assumed to be MMIO and iommufd will map into the IOMMU using the IOMMU_MMIO flag.
Signed-off-by: Jason Gunthorpe jgg@nvidia.com
drivers/dma-buf/dma-buf-mapping.c | 63 +++++++++++++++++++++++++++++++ include/linux/dma-buf-mapping.h | 42 +++++++++++++++++++++ 2 files changed, 105 insertions(+)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c index baa96b37e2c6bd..d9d6b9b5bf05c6 100644 --- a/drivers/dma-buf/dma-buf-mapping.c +++ b/drivers/dma-buf/dma-buf-mapping.c @@ -349,3 +349,66 @@ struct dma_buf_mapping_type dma_buf_mapping_sgt_type = { .debugfs_dump = dma_buf_sgt_debugfs_dump, }; EXPORT_SYMBOL_NS_GPL(dma_buf_mapping_sgt_type, "DMA_BUF");
+static const struct dma_buf_mapping_pal_exp_ops * +to_pal_exp_ops(struct dma_buf_attachment *attach) +{
- return container_of(attach->map_type.exp_ops,
struct dma_buf_mapping_pal_exp_ops, ops);+}
+/**
- dma_buf_pal_map_phys - Obtain the physical address list for a PAL attachment
- @attach: The DMA-buf attachment
- Calls the exporter's map_phys() callback to retrieve the physical address
- list for the buffer. The caller must hold the dma-buf's reservation lock.
- This symbol is restricted to iommufd to prevent misuse.
- Returns the physical address list on success, or an ERR_PTR on failure.
- The returned list must be freed with dma_buf_pal_unmap_phys().
- */
+struct dma_buf_phys_list * +dma_buf_pal_map_phys(struct dma_buf_attachment *attach) +{
- dma_resv_assert_held(attach->dmabuf->resv);
- return to_pal_exp_ops(attach)->map_phys(attach);
+} +/*
- Restricted, iommufd is the only importer allowed to prevent misuse of this
- API.
- */
+EXPORT_SYMBOL_FOR_MODULES(dma_buf_pal_map_phys, "iommufd");
+/**
- dma_buf_pal_unmap_phys - Unmap a physical address list
- @attach: The DMA-buf attachment
- @phys: The physical address list returned by dma_buf_pal_map_phys()
- Returns the mapping back to the exporter. After this point the importer may
- not touch any of the addresses in any way.
- */
+void dma_buf_pal_unmap_phys(struct dma_buf_attachment *attach,
struct dma_buf_phys_list *phys)+{
- to_pal_exp_ops(attach)->unmap_phys(attach, phys);
+} +EXPORT_SYMBOL_NS_GPL(dma_buf_pal_unmap_phys, "DMA_BUF");
+static inline void +dma_buf_pal_finish_match(struct dma_buf_match_args *args,
const struct dma_buf_mapping_match *exp,const struct dma_buf_mapping_match *imp)+{
- args->attach->map_type = (struct dma_buf_mapping_match){
.type = &dma_buf_mapping_pal_type,.exp_ops = exp->exp_ops,- };
+}
+struct dma_buf_mapping_type dma_buf_mapping_pal_type = {
- .name = "Physical Address List",
- .finish_match = dma_buf_pal_finish_match,
+}; +EXPORT_SYMBOL_NS_GPL(dma_buf_mapping_pal_type, "DMA_BUF"); diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h index ac859b8913edcd..10831ce2e72851 100644 --- a/include/linux/dma-buf-mapping.h +++ b/include/linux/dma-buf-mapping.h @@ -269,4 +269,46 @@ DMA_BUF_EMAPPING_SGT_P2P(const struct dma_buf_mapping_sgt_exp_ops *exp_ops, .exporter_requires_p2p = DMA_SGT_NO_P2P, \ } }) +/*
- Physical Address List mapping type
- Use of the Physical Address List type is restricted to prevent abuse of the
- physical addresses API. Please check with the DMA BUF maintainers before
- trying to use it.
- */
+struct dma_buf_phys_list {
- size_t length;
- struct dma_buf_phys_vec phys[] __counted_by(length);
+};
+extern struct dma_buf_mapping_type dma_buf_mapping_pal_type;
+struct dma_buf_mapping_pal_exp_ops {
- struct dma_buf_mapping_exp_ops ops;
- struct dma_buf_phys_list *(*map_phys)(struct dma_buf_attachment *attach);
- void (*unmap_phys)(struct dma_buf_attachment *attach,
struct dma_buf_phys_list *phys);+};
+struct dma_buf_phys_list * +dma_buf_pal_map_phys(struct dma_buf_attachment *attach); +void dma_buf_pal_unmap_phys(struct dma_buf_attachment *attach,
struct dma_buf_phys_list *phys);+static inline struct dma_buf_mapping_match DMA_BUF_IMAPPING_PAL(void) +{
- return (struct dma_buf_mapping_match){
.type = &dma_buf_mapping_pal_type,- };
+}
+static inline struct dma_buf_mapping_match +DMA_BUF_EMAPPING_PAL(const struct dma_buf_mapping_pal_exp_ops *exp_ops) +{
- return (struct dma_buf_mapping_match){
.type = &dma_buf_mapping_pal_type,.exp_ops = &exp_ops->ops,- };
+}
#endif