Modifiche dell'ABI degli ioni

I dispositivi che distribuiscono il kernel 4.14 e versioni successive sono interessati da un importante refactoring del modulo del kernel Ion , che molte implementazioni HAL (Hardware Abstraction Layer) di allocatori di memoria grafica (gralloc) dei fornitori chiamano per allocare buffer di memoria condivisa. Questo articolo fornisce indicazioni sulla migrazione del codice del fornitore legacy alla nuova versione di Ion e discute le possibili future interruzioni dell'interfaccia binaria dell'applicazione (ABI).

A proposito di Ione

Ion fa parte dell'albero di staging in fase di elaborazione del kernel upstream. Durante la fase di staging, l'ABI dallo spazio utente al kernel di Ion potrebbe interrompersi tra le principali versioni del kernel. Sebbene le interruzioni dell'ABI di Ion non influiscano direttamente né sulle applicazioni ordinarie né sui dispositivi già lanciati , i fornitori che migrano verso nuove versioni principali del kernel potrebbero riscontrare modifiche che influiscono sul codice del fornitore che chiama Ion. Inoltre, potrebbero verificarsi future interruzioni dell'ABI poiché il team dei sistemi Android collabora con l'upstream per spostare Ion fuori dall'albero di staging.

Modifiche in Android-4.14

Il kernel 4.12 ha effettuato un pesante refactoring del codice del kernel di Ion, ripulendo e rimuovendo parti di Ion che si sovrapponevano ad altri framework del kernel. Di conseguenza, molti ioctl Ion legacy non sono più rilevanti e sono stati rimossi.

Rimozione di client e handle Ion

Prima del kernel 4.12, l'apertura /dev/ion allocava un client Ion . L'ioctl ION_IOC_ALLOC ha allocato un nuovo buffer e lo ha restituito allo spazio utente come handle Ion (un numero intero opaco significativo solo per il client Ion che lo ha allocato). Per mappare i buffer nello spazio utente o condividerli con altri processi, gli handle di Ion sono stati riesportati come dma-buf fds utilizzando l'ioctl ION_IOC_SHARE .

Nel kernel 4.12, l'ioctl ION_IOC_ALLOC restituisce direttamente dma-buf fds. Lo stato intermedio dell'handle di ioni è stato rimosso, insieme a tutti gli ioctl che consumano o producono handle di ioni. Poiché i fd dma-buf non sono legati a client Ion specifici, l'ioctl ION_IOC_SHARE non è più necessario e tutta l'infrastruttura client Ion è stata rimossa.

Aggiunta di ioctl con coerenza della cache

Prima del kernel 4.12, Ion forniva un ioctl ION_IOC_SYNC per sincronizzare il descrittore di file con la memoria. Questo ioctl era scarsamente documentato e inflessibile. Di conseguenza, molti fornitori hanno implementato ioctl personalizzati per eseguire la manutenzione della cache.

Il kernel 4.12 ha sostituito ION_IOC_SYNC con l' DMA_BUF_IOCTL_SYNC ioctl definito in linux/dma-buf.h . Chiama DMA_BUF_IOCTL_SYNC all'inizio e alla fine di ogni accesso alla CPU, con flag che specificano se questi accessi sono letture e/o scritture. Sebbene DMA_BUF_IOCTL_SYNC sia più dettagliato di ION_IOC_SYNC , offre allo spazio utente un maggiore controllo sulle operazioni di manutenzione della cache sottostanti.

DMA_BUF_IOCTL_SYNC fa parte dell'ABI stabile del kernel ed è utilizzabile con tutti i fd dma-buf, indipendentemente dal fatto che siano stati allocati o meno da Ion.

Migrazione del codice fornitore ad Android-4.12+

Per i client in spazio utente , il team dei sistemi Android incoraggia fortemente l'uso di libion ​​anziché delle chiamate ioctl() a codifica aperta. A partire da Android 9, libion ​​rileva automaticamente Ion ABI in fase di esecuzione e tenta di mascherare eventuali differenze tra i kernel. Tuttavia, qualsiasi funzione libion ​​che produceva o consumava gli handle ion_user_handle_t non funzionerà più dopo il kernel 4.12. È possibile sostituire queste funzioni con le seguenti operazioni equivalenti su dma-buf fds, che funzionano su tutte le versioni del kernel fino ad oggi.

Chiamata legacy ion_user_handle_t Chiamata equivalente dma-buff fd
ion_alloc(ion_fd, …, &buf_handle) ion_alloc_fd(ion_fd, ..., &buf_fd)
ion_share(ion_fd, buf_handle, &buf_fd) N/A (questa chiamata non è necessaria con dma-buff 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 (questa chiamata non è necessaria con dma-buff 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, ...);

Per i client in-kernel , poiché Ion non esporta più alcuna API rivolta al kernel, i driver che in precedenza utilizzavano l'API del kernel Ion in-kernel con ion_import_dma_buf_fd() devono essere convertiti per utilizzare l'API dma-buf in-kernel con dma_buf_get() .

Il futuro Ion ABI si rompe

Prima che Ion possa essere spostato fuori dall'albero di staging, le future versioni del kernel potrebbero dover interrompere nuovamente l'ABI di Ion. Il team dei sistemi Android non prevede che queste modifiche influenzino il lancio dei dispositivi con la prossima versione di Android, ma tali modifiche potrebbero influire sul lancio dei dispositivi con le versioni Android successive.

Ad esempio, la comunità upstream ha proposto di dividere il singolo nodo /dev/ion in più nodi per heap (ad esempio, /dev/ion/heap0 ) per consentire ai dispositivi di applicare diverse policy SELinux a ciascun heap. Se questa modifica venisse implementata in una futura versione del kernel, interromperebbe Ion ABI.