diff options
| -rw-r--r-- | Documentation/dma-buf-sharing.txt | 109 | ||||
| -rw-r--r-- | drivers/base/dma-buf.c | 99 | ||||
| -rw-r--r-- | include/linux/dma-buf.h | 33 |
3 files changed, 233 insertions, 8 deletions
diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt index 3bbd5c51605a..ad86fb86c9a0 100644 --- a/Documentation/dma-buf-sharing.txt +++ b/Documentation/dma-buf-sharing.txt | |||
| @@ -29,13 +29,6 @@ The buffer-user | |||
| 29 | in memory, mapped into its own address space, so it can access the same area | 29 | in memory, mapped into its own address space, so it can access the same area |
| 30 | of memory. | 30 | of memory. |
| 31 | 31 | ||
| 32 | *IMPORTANT*: [see https://lkml.org/lkml/2011/12/20/211 for more details] | ||
| 33 | For this first version, A buffer shared using the dma_buf sharing API: | ||
| 34 | - *may* be exported to user space using "mmap" *ONLY* by exporter, outside of | ||
| 35 | this framework. | ||
| 36 | - with this new iteration of the dma-buf api cpu access from the kernel has been | ||
| 37 | enable, see below for the details. | ||
| 38 | |||
| 39 | dma-buf operations for device dma only | 32 | dma-buf operations for device dma only |
| 40 | -------------------------------------- | 33 | -------------------------------------- |
| 41 | 34 | ||
| @@ -300,6 +293,17 @@ Access to a dma_buf from the kernel context involves three steps: | |||
| 300 | Note that these calls need to always succeed. The exporter needs to complete | 293 | Note that these calls need to always succeed. The exporter needs to complete |
| 301 | any preparations that might fail in begin_cpu_access. | 294 | any preparations that might fail in begin_cpu_access. |
| 302 | 295 | ||
| 296 | For some cases the overhead of kmap can be too high, a vmap interface | ||
| 297 | is introduced. This interface should be used very carefully, as vmalloc | ||
| 298 | space is a limited resources on many architectures. | ||
| 299 | |||
| 300 | Interfaces: | ||
| 301 | void *dma_buf_vmap(struct dma_buf *dmabuf) | ||
| 302 | void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) | ||
| 303 | |||
| 304 | The vmap call can fail if there is no vmap support in the exporter, or if it | ||
| 305 | runs out of vmalloc space. Fallback to kmap should be implemented. | ||
| 306 | |||
| 303 | 3. Finish access | 307 | 3. Finish access |
| 304 | 308 | ||
| 305 | When the importer is done accessing the range specified in begin_cpu_access, | 309 | When the importer is done accessing the range specified in begin_cpu_access, |
| @@ -313,6 +317,83 @@ Access to a dma_buf from the kernel context involves three steps: | |||
| 313 | enum dma_data_direction dir); | 317 | enum dma_data_direction dir); |
| 314 | 318 | ||
| 315 | 319 | ||
| 320 | Direct Userspace Access/mmap Support | ||
| 321 | ------------------------------------ | ||
| 322 | |||
| 323 | Being able to mmap an export dma-buf buffer object has 2 main use-cases: | ||
| 324 | - CPU fallback processing in a pipeline and | ||
| 325 | - supporting existing mmap interfaces in importers. | ||
| 326 | |||
| 327 | 1. CPU fallback processing in a pipeline | ||
| 328 | |||
| 329 | In many processing pipelines it is sometimes required that the cpu can access | ||
| 330 | the data in a dma-buf (e.g. for thumbnail creation, snapshots, ...). To avoid | ||
| 331 | the need to handle this specially in userspace frameworks for buffer sharing | ||
| 332 | it's ideal if the dma_buf fd itself can be used to access the backing storage | ||
| 333 | from userspace using mmap. | ||
| 334 | |||
| 335 | Furthermore Android's ION framework already supports this (and is otherwise | ||
| 336 | rather similar to dma-buf from a userspace consumer side with using fds as | ||
| 337 | handles, too). So it's beneficial to support this in a similar fashion on | ||
| 338 | dma-buf to have a good transition path for existing Android userspace. | ||
| 339 | |||
| 340 | No special interfaces, userspace simply calls mmap on the dma-buf fd. | ||
| 341 | |||
| 342 | 2. Supporting existing mmap interfaces in exporters | ||
| 343 | |||
| 344 | Similar to the motivation for kernel cpu access it is again important that | ||
| 345 | the userspace code of a given importing subsystem can use the same interfaces | ||
| 346 | with a imported dma-buf buffer object as with a native buffer object. This is | ||
| 347 | especially important for drm where the userspace part of contemporary OpenGL, | ||
| 348 | X, and other drivers is huge, and reworking them to use a different way to | ||
| 349 | mmap a buffer rather invasive. | ||
| 350 | |||
| 351 | The assumption in the current dma-buf interfaces is that redirecting the | ||
| 352 | initial mmap is all that's needed. A survey of some of the existing | ||
| 353 | subsystems shows that no driver seems to do any nefarious thing like syncing | ||
| 354 | up with outstanding asynchronous processing on the device or allocating | ||
| 355 | special resources at fault time. So hopefully this is good enough, since | ||
| 356 | adding interfaces to intercept pagefaults and allow pte shootdowns would | ||
| 357 | increase the complexity quite a bit. | ||
| 358 | |||
| 359 | Interface: | ||
| 360 | int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *, | ||
| 361 | unsigned long); | ||
| 362 | |||
| 363 | If the importing subsystem simply provides a special-purpose mmap call to set | ||
| 364 | up a mapping in userspace, calling do_mmap with dma_buf->file will equally | ||
| 365 | achieve that for a dma-buf object. | ||
| 366 | |||
| 367 | 3. Implementation notes for exporters | ||
| 368 | |||
| 369 | Because dma-buf buffers have invariant size over their lifetime, the dma-buf | ||
| 370 | core checks whether a vma is too large and rejects such mappings. The | ||
| 371 | exporter hence does not need to duplicate this check. | ||
| 372 | |||
| 373 | Because existing importing subsystems might presume coherent mappings for | ||
| 374 | userspace, the exporter needs to set up a coherent mapping. If that's not | ||
| 375 | possible, it needs to fake coherency by manually shooting down ptes when | ||
| 376 | leaving the cpu domain and flushing caches at fault time. Note that all the | ||
| 377 | dma_buf files share the same anon inode, hence the exporter needs to replace | ||
| 378 | the dma_buf file stored in vma->vm_file with it's own if pte shootdown is | ||
| 379 | requred. This is because the kernel uses the underlying inode's address_space | ||
| 380 | for vma tracking (and hence pte tracking at shootdown time with | ||
| 381 | unmap_mapping_range). | ||
| 382 | |||
| 383 | If the above shootdown dance turns out to be too expensive in certain | ||
| 384 | scenarios, we can extend dma-buf with a more explicit cache tracking scheme | ||
| 385 | for userspace mappings. But the current assumption is that using mmap is | ||
| 386 | always a slower path, so some inefficiencies should be acceptable. | ||
| 387 | |||
| 388 | Exporters that shoot down mappings (for any reasons) shall not do any | ||
| 389 | synchronization at fault time with outstanding device operations. | ||
| 390 | Synchronization is an orthogonal issue to sharing the backing storage of a | ||
| 391 | buffer and hence should not be handled by dma-buf itself. This is explictly | ||
| 392 | mentioned here because many people seem to want something like this, but if | ||
| 393 | different exporters handle this differently, buffer sharing can fail in | ||
| 394 | interesting ways depending upong the exporter (if userspace starts depending | ||
| 395 | upon this implicit synchronization). | ||
| 396 | |||
| 316 | Miscellaneous notes | 397 | Miscellaneous notes |
| 317 | ------------------- | 398 | ------------------- |
| 318 | 399 | ||
| @@ -336,6 +417,20 @@ Miscellaneous notes | |||
| 336 | the exporting driver to create a dmabuf fd must provide a way to let | 417 | the exporting driver to create a dmabuf fd must provide a way to let |
| 337 | userspace control setting of O_CLOEXEC flag passed in to dma_buf_fd(). | 418 | userspace control setting of O_CLOEXEC flag passed in to dma_buf_fd(). |
| 338 | 419 | ||
| 420 | - If an exporter needs to manually flush caches and hence needs to fake | ||
| 421 | coherency for mmap support, it needs to be able to zap all the ptes pointing | ||
| 422 | at the backing storage. Now linux mm needs a struct address_space associated | ||
| 423 | with the struct file stored in vma->vm_file to do that with the function | ||
| 424 | unmap_mapping_range. But the dma_buf framework only backs every dma_buf fd | ||
| 425 | with the anon_file struct file, i.e. all dma_bufs share the same file. | ||
| 426 | |||
| 427 | Hence exporters need to setup their own file (and address_space) association | ||
| 428 | by setting vma->vm_file and adjusting vma->vm_pgoff in the dma_buf mmap | ||
| 429 | callback. In the specific case of a gem driver the exporter could use the | ||
| 430 | shmem file already provided by gem (and set vm_pgoff = 0). Exporters can then | ||
| 431 | zap ptes by unmapping the corresponding range of the struct address_space | ||
| 432 | associated with their own file. | ||
| 433 | |||
| 339 | References: | 434 | References: |
| 340 | [1] struct dma_buf_ops in include/linux/dma-buf.h | 435 | [1] struct dma_buf_ops in include/linux/dma-buf.h |
| 341 | [2] All interfaces mentioned above defined in include/linux/dma-buf.h | 436 | [2] All interfaces mentioned above defined in include/linux/dma-buf.h |
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 05c64c11bad2..24e88fe29ec1 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c | |||
| @@ -44,8 +44,26 @@ static int dma_buf_release(struct inode *inode, struct file *file) | |||
| 44 | return 0; | 44 | return 0; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma) | ||
| 48 | { | ||
| 49 | struct dma_buf *dmabuf; | ||
| 50 | |||
| 51 | if (!is_dma_buf_file(file)) | ||
| 52 | return -EINVAL; | ||
| 53 | |||
| 54 | dmabuf = file->private_data; | ||
| 55 | |||
| 56 | /* check for overflowing the buffer's size */ | ||
| 57 | if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > | ||
| 58 | dmabuf->size >> PAGE_SHIFT) | ||
| 59 | return -EINVAL; | ||
| 60 | |||
| 61 | return dmabuf->ops->mmap(dmabuf, vma); | ||
| 62 | } | ||
| 63 | |||
| 47 | static const struct file_operations dma_buf_fops = { | 64 | static const struct file_operations dma_buf_fops = { |
| 48 | .release = dma_buf_release, | 65 | .release = dma_buf_release, |
| 66 | .mmap = dma_buf_mmap_internal, | ||
| 49 | }; | 67 | }; |
| 50 | 68 | ||
| 51 | /* | 69 | /* |
| @@ -82,7 +100,8 @@ struct dma_buf *dma_buf_export(void *priv, const struct dma_buf_ops *ops, | |||
| 82 | || !ops->unmap_dma_buf | 100 | || !ops->unmap_dma_buf |
| 83 | || !ops->release | 101 | || !ops->release |
| 84 | || !ops->kmap_atomic | 102 | || !ops->kmap_atomic |
| 85 | || !ops->kmap)) { | 103 | || !ops->kmap |
| 104 | || !ops->mmap)) { | ||
| 86 | return ERR_PTR(-EINVAL); | 105 | return ERR_PTR(-EINVAL); |
| 87 | } | 106 | } |
| 88 | 107 | ||
| @@ -406,3 +425,81 @@ void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long page_num, | |||
| 406 | dmabuf->ops->kunmap(dmabuf, page_num, vaddr); | 425 | dmabuf->ops->kunmap(dmabuf, page_num, vaddr); |
| 407 | } | 426 | } |
| 408 | EXPORT_SYMBOL_GPL(dma_buf_kunmap); | 427 | EXPORT_SYMBOL_GPL(dma_buf_kunmap); |
| 428 | |||
| 429 | |||
| 430 | /** | ||
| 431 | * dma_buf_mmap - Setup up a userspace mmap with the given vma | ||
| 432 | * @dmabuf: [in] b | ||
