Supervisión de ABI de kernel de Android

Puedes usar las herramientas de supervisión de la interfaz binaria de aplicación (ABI), disponibles en Android 11 y versiones posteriores, para estabilizar la ABI de kernel de los kernels de Android. Las herramientas recopilan y comparan las representaciones de ABI de los objetos binarios de kernel existentes (vmlinux + módulos de GKI). Estas representaciones de ABI son los archivos .stg y las listas de símbolos. La interfaz en la que la representación muestra una vista se denomina interfaz de módulo de kernel (KMI). Puedes usar las herramientas para hacer un seguimiento de los cambios en el KMI y mitigarlos.

Las herramientas de supervisión de ABI se desarrollan en AOSP y usan STG (o libabigail en Android 13 y versiones anteriores) para generar y comparar representaciones.

En esta página, se describen las herramientas, el proceso de recopilación y análisis de las representaciones de ABI, y el uso de esas representaciones para proporcionar estabilidad a la ABI en el kernel. En esta página, también se proporciona información para contribuir con cambios en los kernels de Android.

Proceso

Analizar la ABI del kernel requiere varios pasos, la mayoría de los cuales pueden automatizarse:

  1. Compila el kernel y su representación de ABI.
  2. Analiza las diferencias de ABI entre la compilación y una referencia.
  3. Actualiza la representación de ABI (si es necesario).
  4. Trabaja con listas de símbolos.

Las siguientes instrucciones funcionan para cualquier kernel que puedas compilar con una cadena de herramientas compatible (como la cadena de herramientas de Clang precompilada). repo manifests están disponibles para todas las ramas de kernel comunes de Android y para varios kernels específicos del dispositivo. Garantizan que se use la cadena de herramientas correcta cuando compilas una distribución de kernel para el análisis.

Listas de símbolos

El KMI no incluye todos los símbolos del kernel ni siquiera los más de 30,000 símbolos exportados. En su lugar, los símbolos que pueden usar los módulos de proveedores se enumeran de forma explícita en un conjunto de archivos de lista de símbolos que se mantienen de forma pública en la raíz del árbol del kernel. La unión de todos los símbolos de todos los archivos de lista de símbolos define el conjunto de símbolos de KMI que se mantienen estables. Un ejemplo de archivo de lista de símbolos es abi_gki_aarch64_db845c, que declara los símbolos necesarios para la DragonBoard 845c.

Solo los símbolos que se enumeran en una lista de símbolos y sus estructuras y definiciones relacionadas se consideran parte del KMI. Puedes publicar cambios en tus listas de símbolos si no están presentes los símbolos que necesitas. Una vez que las interfaces nuevas se encuentran en una lista de símbolos y forman parte de la descripción de KMI, se mantienen estables y no se deben quitar de la lista de símbolos ni modificarse después de que se congele la rama.

Cada rama del kernel de KMI del kernel común de Android (ACK) tiene su propio conjunto de listas de símbolos. No se intenta proporcionar estabilidad de ABI entre diferentes ramas del kernel de KMI. Por ejemplo, el KMI de android12-5.10 es completamente independiente del KMI de android13-5.10.

Las herramientas de ABI usan listas de símbolos de KMI para limitar qué interfaces se deben supervisar para verificar su estabilidad. La lista de símbolos principales contiene los símbolos que requieren los módulos del kernel de GKI. Se espera que los proveedores envíen y actualicen listas de símbolos adicionales para garantizar que las interfaces de las que dependen mantengan la compatibilidad con ABI. Por ejemplo, para ver una lista de listas de símbolos para android13-5.15, consulta https://android.googlesource.com/kernel/common/+/refs/heads/android13-5.15/android.

Una lista de símbolos contiene los símbolos que se informan como necesarios para el proveedor o dispositivo en particular. La lista completa que usan las herramientas es la unión de todos los archivos de la lista de símbolos de KMI. Las herramientas de ABI determinan los detalles de cada símbolo, incluida la firma de la función y las estructuras de datos anidadas.

Cuando el KMI está inmovilizado, no se permiten cambios en las interfaces de KMI existentes, ya que son estables. Sin embargo, los proveedores tienen la libertad de agregar símbolos al KMI en cualquier momento, siempre y cuando los cambios no afecten la estabilidad de la ABI existente. Los símbolos agregados recientemente se mantienen estables en cuanto los cita una lista de símbolos de KMI. Los símbolos no se deben quitar de la lista de un kernel, a menos que se pueda confirmar que ningún dispositivo se envió con una dependencia en ese símbolo.

Puedes generar una lista de símbolos de KMI para un dispositivo con las instrucciones de Cómo trabajar con listas de símbolos. Muchos socios envían una lista de símbolos por ACK, pero esto no es un requisito estricto. Si te ayuda con el mantenimiento, puedes enviar varias listas de símbolos.

Extiende el KMI

Si bien los símbolos de KMI y las estructuras relacionadas se mantienen estables (lo que significa que no se aceptan los cambios que rompen las interfaces estables en un kernel con un KMI inmovilizado), el kernel de GKI permanece abierto a las extensiones para que los dispositivos que se envíen más adelante en el año no necesiten definir todas sus dependencias antes de que se congele el KMI. Para extender el KMI, puedes agregar símbolos nuevos a este para funciones de kernel exportadas nuevas o existentes, incluso si el KMI está inmovilizado. También se pueden aceptar parches de kernel nuevos si no dañan el KMI.

Acerca de las rupturas de KMI

Un kernel tiene fuentes y los objetos binarios se compilan a partir de ellas. Las ramas de kernel supervisadas por ABI incluyen una representación de la ABI de la ABI de GKI actual (en forma de un archivo .stg). Después de compilar los objetos binarios (vmlinux, Image y cualquier módulo de GKI), se puede extraer una representación de ABI de los objetos binarios. Cualquier cambio que se realice en el archivo de origen del kernel puede afectar los objetos binarios y, a su vez, el .stg extraído. El analizador AbiAnalyzer compara el archivo .stg confirmado con el que se extrae de los artefactos de compilación y establece una etiqueta de lint-1 en el cambio en Gerrit si encuentra una diferencia semántica.

Controla las rupturas de ABI

A modo de ejemplo, el siguiente parche introduce una ruptura de ABI muy obvia:

diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 42786e6364ef..e15f1d0f137b 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -657,6 +657,7 @@ struct mm_struct {
                ANDROID_KABI_RESERVE(1);
        } __randomize_layout;

+       int tickle_count;
        /*
         * The mm_cpumask needs to be at the end of mm_struct, because it
         * is dynamically sized based on nr_cpu_ids.

Cuando ejecutas la ABI de compilación con este parche aplicado, las herramientas se cierran con un código de error distinto de cero y, además, informan una diferencia de ABI similar a la siguiente:

function symbol 'struct block_device* I_BDEV(struct inode*)' changed
  CRC changed from 0x8d400dbd to 0xabfc92ad

function symbol 'void* PDE_DATA(const struct inode*)' changed
  CRC changed from 0xc3c38b5c to 0x7ad96c0d

function symbol 'void __ClearPageMovable(struct page*)' changed
  CRC changed from 0xf489e5e8 to 0x92bd005e

... 4492 omitted; 4495 symbols have only CRC changes

type 'struct mm_struct' changed
  byte size changed from 992 to 1000
  member 'int tickle_count' was added
  member 'unsigned long cpu_bitmap[0]' changed
    offset changed by 64

Se detectaron diferencias de ABI durante la compilación

La causa más común de los errores es cuando un controlador usa un símbolo nuevo del kernel que no está en ninguna de las listas de símbolos.

Si el símbolo no se incluye en la lista de símbolos (android/abi_gki_aarch64), primero debes verificar que se exporte con EXPORT_SYMBOL_GPL(symbol_name) y, luego, actualizar la representación XML de ABI y la lista de símbolos. Por ejemplo, los siguientes cambios agregan la nueva función de FS incremental a la rama android-12-5.10, que incluye la actualización de la lista de símbolos y la representación XML de ABI.

  • El ejemplo de cambio de funciones está en aosp/1345659.
  • El ejemplo de la lista de símbolos se encuentra en aosp/1346742.
  • El ejemplo de cambio de XML de ABI se encuentra en aosp/1349377.

Si el símbolo se exporta (ya sea que lo hayas hecho tú o se haya exportado anteriormente), pero ningún otro controlador lo usa, es posible que obtengas un error de compilación similar al siguiente.

Comparing the KMI and the symbol lists:
+ build/abi/compare_to_symbol_list out/$BRANCH/common/Module.symvers out/$BRANCH/common/abi_symbollist.raw
ERROR: Differences between ksymtab and symbol list detected!
Symbols missing from ksymtab:
Symbols missing from symbol list:
 - simple_strtoull

Para resolverlo, actualiza la lista de símbolos de KMI en tu kernel y en el ACK (consulta Cómo actualizar la representación de ABI). Para ver un ejemplo de actualización de la lista XML de ABI y de símbolos en el ACK, consulta aosp/1367601.

Cómo resolver las rupturas de ABI del kernel

Para controlar las rupturas de ABI del kernel, puedes refactorizar el código para que no cambie la ABI o actualizar la representación de la ABI. Usa el siguiente diagrama para determinar el mejor enfoque para tu situación.

Diagrama de flujo de la ruptura de ABI

Figura 1: Resolución de rupturas de ABI

Refactoriza el código para evitar cambios en la ABI

Haz todo lo posible para evitar modificar la ABI existente. En muchos casos, puedes refactorizar tu código para quitar los cambios que afectan la ABI.

  • Refactoriza los cambios en los campos de struct. Si un cambio modifica la ABI para una función de depuración, agrega un #ifdef alrededor de los campos (en las estructuras y las referencias de origen) y asegúrate de que el CONFIG que se usa para el #ifdef esté inhabilitado para la defconfig de producción y gki_defconfig. Para ver un ejemplo de cómo se puede agregar una configuración de depuración a una estructura sin romper la ABI, consulta este conjunto de parches.

  • Refactorización de funciones para no cambiar el kernel principal Si se deben agregar funciones nuevas a ACK para admitir los módulos de socios, intenta refactorizar la parte de ABI del cambio para evitar modificar la ABI del kernel. Para ver un ejemplo del uso de la ABI del kernel existente para agregar capacidades adicionales sin cambiar la ABI del kernel, consulta aosp/1312213.

Cómo corregir una ABI dañada en Android Gerrit

Si no rompiste intencionalmente la ABI de kernel, debes investigar siguiendo la orientación proporcionada por las herramientas de supervisión de ABI. Las causas más comunes de las fallas son los cambios en las estructuras de datos y los cambios en el CRC de símbolos asociados, o bien debido a cambios en las opciones de configuración que generan cualquiera de las situaciones mencionadas anteriormente. Primero, aborda los problemas que encontró la herramienta.

Para reproducir los resultados de la ABI de forma local, consulta Cómo compilar el kernel y su representación de ABI.

Información acerca de las etiquetas de lint-1

Si subes cambios a una rama que contiene un KMI congelado o finalizado, los cambios deben pasar el AbiAnalyzer para garantizar que no afecten la ABI estable de una manera incompatible. Durante este proceso, AbiAnalyzer busca el informe de ABI que se creó durante la compilación (una compilación extendida que realiza la compilación normal y, luego, algunos pasos de extracción y comparación de ABI).

Si AbiAnalyzer encuentra un informe no vacío, establece la etiqueta Lint-1 y se bloquea el envío del cambio hasta que se resuelva, hasta que el conjunto de parches reciba una etiqueta Lint+1.

Actualiza la ABI del kernel

Si la modificación de la ABI es inevitable, debes aplicar los cambios de código, la representación de la ABI y la lista de símbolos al ACK. Para que lint quite el -1 y no rompa la compatibilidad con GKI, sigue estos pasos:

  1. Sube los cambios de código al ACK.

  2. Espera a recibir una revisión de código de +2 para el conjunto de parches.

  3. Actualiza la representación de ABI de referencia.

  4. Combina los cambios de código y el cambio de actualización de ABI.

Sube los cambios de código de ABI al ACK

La actualización de la ABI de ACK depende del tipo de cambio que se realice.

  • Si un cambio de ABI está relacionado con una función que afecta las pruebas de CTS o VTS, por lo general, el cambio se puede elegir para confirmarlo tal como está. Por ejemplo:

  • Si un cambio de ABI es para una función que se puede compartir con el ACK, ese cambio se puede elegir para ACK tal como está. Por ejemplo, los siguientes cambios no son necesarios para la prueba de CTS o VTS, pero se pueden compartir con ACK:

  • Si un cambio de ABI introduce una función nueva que no es necesario incluir en el ACK, puedes introducir los símbolos en el ACK con un stub, como se describe en la siguiente sección.

Usa stubs para ACK

Los stub solo deben ser necesarios para los cambios en el kernel principal que no benefician al ACK, como los cambios de rendimiento y energía. En la siguiente lista, se detallan ejemplos de stubs y selecciones parciales en ACK para GKI.

  • stub de la función de aislamiento de núcleo (aosp/1284493). Las capacidades en ACK no son necesarias, pero los símbolos deben estar presentes en ACK para que tus módulos los usen.

  • Símbolo de marcador de posición para el módulo de proveedores (aosp/1288860).

  • Selección exclusiva de ABI de la función de seguimiento de eventos de mm por proceso (aosp/1288454). El parche original se seleccionó para ACK y, luego, se recortó para incluir solo los cambios necesarios para resolver la diferencia de ABI para task_struct y mm_event_count. Este parche también actualiza la enum mm_event_type para que contenga los miembros finales.

  • Selección parcial de cambios de ABI de la estructura térmica que requerían más que solo agregar los nuevos campos de ABI.

    • El parche aosp/1255544 resolvió las diferencias de ABI entre el kernel del socio y ACK.

    • El parche aosp/1291018 solucionó los problemas funcionales que se encontraron durante la prueba de GKI del parche anterior. La corrección incluyó la inicialización de la estructura del parámetro del sensor para registrar varias zonas térmicas en un solo sensor.

  • Cambios en la ABI de CONFIG_NL80211_TESTMODE (aosp/1344321). Este parche agregó los cambios de estructura necesarios para la ABI y se aseguró de que los campos adicionales no causaran diferencias funcionales, lo que permitió a los socios incluir CONFIG_NL80211_TESTMODE en sus kernels de producción y, al mismo tiempo, mantener el cumplimiento de GKI.

Aplica el KMI durante el tiempo de ejecución

Los kernels de GKI usan las opciones de configuración TRIM_UNUSED_KSYMS=y y UNUSED_KSYMS_WHITELIST=<union of all symbol lists>, que limitan los símbolos exportados (como los símbolos exportados con EXPORT_SYMBOL_GPL()) a los que aparecen en una lista de símbolos. Todos los demás símbolos no se exportan y se rechaza la carga de un módulo que requiera un símbolo no exportado. Esta restricción se aplica en el tiempo de compilación y se marcan las entradas faltantes.

Para fines de desarrollo, puedes usar una compilación del kernel de GKI que no incluya el recorte de símbolos (es decir, se pueden usar todos los símbolos que se exportan de forma habitual). Para ubicar estas compilaciones, busca las compilaciones de kernel_debug_aarch64 en ci.android.com.

Cómo aplicar la KMI con el control de versiones de módulos

Los kernels de la imagen genérica de kernel (GKI) usan el control de versiones de módulos (CONFIG_MODVERSIONS) como una medida adicional para aplicar el cumplimiento de la KMI durante el tiempo de ejecución. El control de versiones de módulos puede causar errores de desajuste en la verificación de redundancia cíclica (CRC) en el tiempo de carga del módulo si el KMI esperado de un módulo no coincide con el KMI vmlinux. Por ejemplo, la siguiente es una falla típica que ocurre durante el tiempo de carga del módulo debido a una discrepancia de CRC para el símbolo module_layout():

init: Loading module /lib/modules/kernel/.../XXX.ko with args ""
XXX: disagrees about version of symbol module_layout
init: Failed to insmod '/lib/modules/kernel/.../XXX.ko' with args ''

Usos del control de versiones de módulos

El control de versiones de módulos es útil por los siguientes motivos:

  • El control de versiones de módulos detecta cambios en la visibilidad de la estructura de datos. Si los módulos cambian las estructuras de datos opacas, es decir, las estructuras de datos que no forman parte de la KMI, se rompen después de futuros cambios en la estructura.

    A modo de ejemplo, considera el campo fwnode en struct device. Este campo DEBE ser opaco para los módulos, de modo que no puedan realizar cambios en los campos de device->fw_node ni hacer suposiciones sobre su tamaño.

    Sin embargo, si un módulo incluye <linux/fwnode.h> (directa o indirectamente), el campo fwnode en struct device ya no es opaco para él. Luego, el módulo puede realizar cambios en device->fwnode->dev o device->fwnode->ops. Esta situación es problemática por varios motivos, que se indican a continuación:

    • Puede romper las suposiciones que hace el código del kernel principal sobre sus estructuras de datos internas.

    • Si una actualización futura del kernel cambia el struct fwnode_handle (el tipo de datos de fwnode), el módulo ya no funcionará con el kernel nuevo. Además, stgdiff no mostrará ninguna diferencia, ya que el módulo rompe el KMI manipulando directamente las estructuras internas de datos de maneras que no se pueden capturar solo inspeccionando la representación binaria.

  • Un módulo actual se considera incompatible con KMI cuando se carga más adelante con un kernel nuevo que no es compatible. El control de versiones de módulos agrega una verificación de tiempo de ejecución para evitar cargar accidentalmente un módulo que no sea compatible con el KMI del kernel. Esta verificación evita problemas de tiempo de ejecución difíciles de depurar y fallas del kernel que podrían ser resultado de una incompatibilidad no detectada en el KMI.

Si habilitas el control de versiones de módulos, se evitan todos estos problemas.

Cómo verificar si hay discrepancias de CRC sin iniciar el dispositivo

stgdiff compara e informa las discrepancias de CRC entre los kernels junto con otras diferencias de ABI.

Además, una compilación de kernel completa con CONFIG_MODVERSIONS habilitado genera un archivo Module.symvers como parte del proceso de compilación normal. Este archivo tiene una línea para cada símbolo que exporta el kernel (vmlinux) y los módulos. Cada línea consta del valor de CRC, el nombre del símbolo, el espacio de nombres del símbolo, el vmlinux o nombre del módulo que exporta el símbolo y el tipo de exportación (por ejemplo, EXPORT_SYMBOL frente a EXPORT_SYMBOL_GPL).

Puedes comparar los archivos Module.symvers entre la compilación de GKI y la tuya para verificar si hay diferencias de CRC en los símbolos que exporta vmlinux. Si hay una diferencia en el valor de CRC en cualquier símbolo exportado por vmlinux y ese símbolo es usado por uno de los módulos que cargas en tu dispositivo, el módulo no se carga.

Si no tienes todos los artefactos de compilación, pero tienes los archivos vmlinux del kernel de GKI y el tuyo, puedes comparar los valores de CRC de un símbolo específico. Para ello, ejecuta el siguiente comando en ambos kernels y compara el resultado:

nm <path to vmlinux>/vmlinux | grep __crc_<symbol name>

Por ejemplo, el siguiente comando verifica el valor de CRC para el símbolo module_layout:

nm vmlinux | grep __crc_module_layout
0000000008663742 A __crc_module_layout

Cómo resolver discrepancias de CRC

Sigue estos pasos para resolver una discrepancia de CRC cuando se carga un módulo:

  1. Compila el kernel de GKI y el kernel de tu dispositivo con la opción --kbuild_symtypes, como se muestra en el siguiente comando:

    tools/bazel run --kbuild_symtypes //common:kernel_aarch64_dist
    

    Este comando genera un archivo .symtypes para cada archivo .o. Consulta KBUILD_SYMTYPES en Kleaf para obtener más detalles.

    Para Android 13 y versiones anteriores, compila el kernel de GKI y el kernel de tu dispositivo. Para ello, agrega KBUILD_SYMTYPES=1 al principio del comando que usas para compilar el kernel, como se muestra en el siguiente comando:

    KBUILD_SYMTYPES=1 BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
    

    Cuando usas build_abi.sh,, la marca KBUILD_SYMTYPES=1 ya se configuró de forma implícita.

  2. Busca el archivo .c en el que se exporta el símbolo con discrepancia de CRC con el siguiente comando:

    cd common && git grep EXPORT_SYMBOL.*module_layout
    kernel/module.c:EXPORT_SYMBOL(module_layout);
    
  3. El archivo .c tiene un archivo .symtypes correspondiente en el GKI y los artefactos de compilación del kernel del dispositivo. Para ubicar el archivo .c, usa los siguientes comandos:

    cd out/$BRANCH/common && ls -1 kernel/module.*
    kernel/module.o
    kernel/module.o.symversions
    kernel/module.symtypes
    

    Las siguientes son las características del archivo .c:

    • El formato del archivo .c es una línea (potencialmente muy larga) por símbolo.

    • [s|u|e|etc]# al comienzo de la línea significa que el símbolo es del tipo de datos [struct|union|enum|etc]. Por ejemplo:

      t#bool typedef _Bool bool
      
    • Si falta el prefijo # al comienzo de la línea, significa que el símbolo es una función. Por ejemplo:

      find_module s#module * find_module ( const char * )
      
  4. Compara los dos archivos y corrige todas las diferencias.

Caso 1: Diferencias debido a la visibilidad del tipo de datos

Si un kernel mantiene un símbolo o un tipo de datos opaco para los módulos y el otro kernel no lo hace, esa diferencia aparece entre los archivos .symtypes de los dos kernels. El archivo .symtypes de uno de los kernels tiene UNKNOWN para un símbolo, y el archivo .symtypes del otro kernel tiene una vista expandida del símbolo o tipo de datos.

Por ejemplo, agregar la siguiente línea al archivo include/linux/device.h en el kernel causa discrepancias de CRC, una de las cuales es para module_layout():

 #include <linux/fwnode.h>

Cuando se compara el module.symtypes de ese símbolo, se exponen las siguientes diferencias:

 $ diff -u <GKI>/kernel/module.symtypes <your kernel>/kernel/module.symtypes
  --- <GKI>/kernel/module.symtypes
  +++ <your kernel>/kernel/module.symtypes
  @@ -334,12 +334,15 @@
  ...
  -s#fwnode_handle struct fwnode_handle { UNKNOWN }
  +s#fwnode_reference_args struct fwnode_reference_args { s#fwnode_handle * fwnode ; unsigned int nargs ; t#u64 args [ 8 ] ; }
  ...

Si tu kernel tiene un valor de UNKNOWN y el kernel de GKI tiene la vista expandida del símbolo (muy improbable), combina el kernel común de Android más reciente en tu kernel para que uses la base de kernel de GKI más reciente.

En la mayoría de los casos, el kernel de GKI tiene un valor de UNKNOWN, pero tu kernel tiene los detalles internos del símbolo debido a los cambios que se realizaron en él. Esto se debe a que uno de los archivos de tu kernel agregó un #include que no está presente en el kernel de GKI.

A menudo, la corrección solo oculta el nuevo #include de genksyms.

#ifndef __GENKSYMS__
#include <linux/fwnode.h>
#endif

De lo contrario, para identificar el #include que causa la diferencia, sigue estos pasos:

  1. Abre el archivo de encabezado que define el símbolo o el tipo de datos que tiene esta diferencia. Por ejemplo, edita include/linux/fwnode.h para el struct fwnode_handle.

  2. Agrega el siguiente código en la parte superior del archivo de encabezado:

    #ifdef CRC_CATCH
    #error "Included from here"
    #endif
    
  3. En el archivo .c del módulo que tiene una discrepancia de CRC, agrega lo siguiente como primera línea antes de cualquiera de las líneas #include.

    #define CRC_CATCH 1
    
  4. Compila tu módulo. El error de tiempo de compilación resultante muestra la cadena de archivos de encabezado #include que generó esta discrepancia de CRC. Por ejemplo:

    In file included from .../drivers/clk/XXX.c:16:`
    In file included from .../include/linux/of_device.h:5:
    In file included from .../include/linux/cpu.h:17:
    In file included from .../include/linux/node.h:18:
    .../include/linux/device.h:16:2: error: "Included from here"
    #error "Included from here"
    

    Uno de los vínculos de esta cadena de #include se debe a un cambio realizado en el kernel que falta en el kernel de GKI.

  5. Identifica el cambio, reviertelo en tu kernel o súbelo a ACK y haz que se combine.

Caso 2: Diferencias debido a cambios en el tipo de datos

Si la discrepancia de la CRC para un símbolo o un tipo de datos no se debe a una diferencia en la visibilidad, se debe a cambios reales (adiciones, eliminaciones o cambios) en el tipo de datos en sí.

Por ejemplo, realizar el siguiente cambio en tu kernel provoca varias discrepancias de CRC, ya que muchos símbolos se ven afectados indirectamente por este tipo de cambio:

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
  --- a/include/linux/iommu.h
  +++ b/include/linux/iommu.h
  @@ -259,7 +259,7 @@ struct iommu_ops {
     void (*iotlb_sync)(struct iommu_domain *domain);
     phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova);
     phys_addr_t (*iova_to_phys_hard)(struct iommu_domain *domain,
  -        dma_addr_t iova);
  +        dma_addr_t iova, unsigned long trans_flag);
     int (*add_device)(struct device *dev);
     void (*remove_device)(struct device *dev);
     struct iommu_group *(*device_group)(struct device *dev);

Una discrepancia de CRC es para devm_of_platform_populate().

Si comparas los archivos .symtypes de ese símbolo, es posible que se vean de la siguiente manera:

 $ diff -u <GKI>/drivers/of/platform.symtypes <your kernel>/drivers/of/platform.symtypes
  --- <GKI>/drivers/of/platform.symtypes
  +++ <your kernel>/drivers/of/platform.symtypes
  @@ -399,7 +399,7 @@
  ...
  -s#iommu_ops struct iommu_ops { ... ; t#phy
  s_addr_t ( * iova_to_phys_hard ) ( s#iommu_domain * , t#dma_addr_t ) ; int
    ( * add_device ) ( s#device * ) ; ...
  +s#iommu_ops struct iommu_ops { ... ; t#phy
  s_addr_t ( * iova_to_phys_hard ) ( s#iommu_domain * , t#dma_addr_t , unsigned long ) ; int ( * add_device ) ( s#device * ) ; ...

Para identificar el tipo modificado, sigue estos pasos:

  1. Busca la definición del símbolo en el código fuente (por lo general, en archivos .h).

    • Para ver las diferencias de símbolos entre tu kernel y el kernel de GKI, ejecuta el siguiente comando para encontrar la confirmación:
    git blame
    
    • En el caso de los símbolos borrados (cuando se borra un símbolo en un árbol y también deseas borrarlo en el otro), debes encontrar el cambio que borra la línea. Usa el siguiente comando en el árbol donde se borró la línea:
    git log -S "copy paste of deleted line/word" -- <file where it was deleted>
    
  2. Revisa la lista de confirmaciones que se muestra para encontrar el cambio o la eliminación. Es probable que el primer commit sea el que buscas. Si no es así, revisa la lista hasta que encuentres la confirmación.

  3. Después de identificar el cambio, revierte el cambio en el kernel o sube el cambio a ACK y haz que se combine.