Devices shipping kernel 4.14 and higher are affected by a major refactoring of the ION kernel module, which many vendor graphics memory allocator (gralloc) hardware abstraction layer (HAL) implementations call to allocate shared memory buffers. This page provides guidance on migrating legacy vendor code over to the new version of ION and discusses possible future application binary interface (ABI) breaks.
About ION
ION is part of the upstream kernel's work-in-progress staging tree. While in staging, ION's userspace-to-kernel ABI may break between major kernel versions. While ION ABI breaks don't directly affect either ordinary apps or already launched devices, vendors migrating to new major kernel versions may encounter changes that affect vendor code calling into ION. Additionally, future ABI breaks may occur as the Android systems team works with upstream to move ION out of the staging tree.
Changes in android-4.14
Kernel 4.12 heavily refactored the ION kernel code, cleaning up and removing parts of ION that overlapped with other kernel frameworks. As a result, many legacy ION ioctls are no longer relevant and have been removed.
Removal of ION clients and handles
Before kernel 4.12, opening /dev/ion
allocated an
ION client. The ION_IOC_ALLOC
ioctl allocated
a new buffer and returned it to userspace as an ION handle
(an opaque integer meaningful only to the ION client that allocated it).
To map buffers into userspace or share them with other processes, ION
handles were re-exported as dma-buf fds using the ION_IOC_SHARE
ioctl.
In kernel 4.12, the ION_IOC_ALLOC
ioctl directly
outputs dma-buf fds. The intermediate ION handle state has been removed,
along with all ioctls that consume or produce ION handles. Because
dma-buf fds aren't tied to specific ION clients, the ION_IOC_SHARE
ioctl is no longer needed, and all ION client infrastructure has been removed.
Addition of cache-coherency ioctls
Before kernel 4.12, ION provided an ION_IOC_SYNC
ioctl to
synchronize the file descriptor with memory. This ioctl was poorly
documented and inflexible. As a result, many vendors implemented custom
ioctls to perform cache maintenance.
Kernel 4.12 replaced ION_IOC_SYNC
with the
DMA_BUF_IOCTL_SYNC ioctl
defined in
linux/dma-buf.h
.
Call DMA_BUF_IOCTL_SYNC
at the start and end of every CPU access, with flags
specifying whether these accesses are reads and/or writes. Although DMA_BUF_IOCTL_SYNC
is more verbose than ION_IOC_SYNC
, it gives userspace
more control over the underlying cache maintenance operations.
DMA_BUF_IOCTL_SYNC
is part of the kernel's stable ABI and is usable with
all dma-buf fds, whether or not they were allocated by ION.
Migrating vendor code to android-4.12+
For userspace clients, the Android systems team strongly encourages
using libion
rather than open-coding ioctl()
calls. As of Android 9, libion automatically
detects the ION ABI at runtime and attempts to mask any differences between kernels.
However, any libion functions that produced or consumed ion_user_handle_t
handles
no longer work after kernel 4.12. You can replace these functions with the following
equivalent operations on dma-buf fds, which work on all versions of the kernel to date.
Legacy ion_user_handle_t call | Equivalent dma-buf fd call |
---|---|
ion_alloc(ion_fd, …, &buf_handle) |
ion_alloc_fd(ion_fd, ..., &buf_fd) |
ion_share(ion_fd, buf_handle, &buf_fd) |
N/A (this call isn't needed with dma-buf fds) |
ion_map(ion_fd, buf_handle, ...) |
mmap(buf_fd, ...) |
ion_free(ion_fd, buf_handle) |
close(buf_fd) |
ion_import(ion_fd, buf_fd, &buf_handle) |
N/A (this call isn't needed with dma-buf fds) |
ion_sync_fd(ion_fd, buf_fd) |
If (ion_is_legacy(ion_fd)) ion_sync_fd(ion_fd, buf_fd); else ioctl(buf_fd, DMA_BUF_IOCTL_SYNC, ...); |
For in-kernel clients, because ION no longer exports
any kernel-facing APIs, drivers that previously used the in-kernel
ION kernel API with ion_import_dma_buf_fd()
must be converted to
use the in-kernel dma-buf API
with dma_buf_get()
.
Future ION ABI breaks
Before ION can be moved out of the staging tree, future kernel releases may need to break the ION ABI again. The Android systems team doesn't expect these changes to affect devices launching with the next Android version, but such changes may affect devices launching with subsequent Android versions.
For example, the upstream community has proposed splitting the single
/dev/ion
node into multiple, per-heap nodes (for example, /dev/ion/heap0
)
to enable devices to apply different SELinux policies to each heap. If this
change is implemented in a future kernel release, it would break ION ABI.