L'image du noyau générique (GKI) réduit la fragmentation du noyau en alignant étroitement avec le noyau Linux en amont. Cependant, il existe des raisons valables certains correctifs ne peuvent pas être acceptés en amont, et des calendriers de produit doit être respectée. Par conséquent, certains correctifs sont conservés dans le noyau commun (ACK) d'Android. sources à partir desquelles le GKI est créé.
Les développeurs doivent soumettre les modifications de code en amont à l'aide du publipostage du noyau Linux.
List (LKML) comme premier choix et envoyez les modifications de code à l'ACK
Branche android-mainline
uniquement lorsqu'il existe une bonne raison pour laquelle les flux en amont ne sont pas
viable. Vous trouverez ci-dessous des exemples de motifs valides et la façon de les gérer.
Le correctif a été envoyé à LKML, mais n'a pas été accepté à temps pour un produit de sortie. Pour gérer ce correctif:
- Fournissez la preuve que le correctif a été envoyé au LKML et envoyez vos commentaires le correctif reçu, ou la durée estimée du correctif envoyé en amont.
- Décidez du plan d'action pour envoyer le correctif dans ACK, faites-le approuver en amont, puis de le retirer de l'ACK lorsque la version finale en amont est fusionné en ACK.
Le correctif définit
EXPORT_SYMBOLS_GPL()
pour un module de fournisseur, mais n'a pas pu être envoyé en amont, car aucun module "in-tree" ne l'utilise . Pour gérer ce correctif, indiquez pourquoi votre module ne peut pas être soumis en amont ainsi que les alternatives envisagées requête.Le correctif n'est pas assez générique pour l'amont et il n'y a pas le temps de le refactoriser avant le lancement d’un produit. Pour gérer ce correctif, fournissez un l'heure estimée à laquelle un correctif refactorisé est envoyé en amont (le patch ne sera pas accepté dans ACK sans plan de soumission d’une refactorisation en amont pour examen).
Impossible d'accepter le correctif en amont pour les raisons suivantes : <insérer le motif ici>. Pour gérer ce correctif, contactez l'équipe chargée du noyau Android et travailler avec nous sur les options permettant de refactoriser le correctif afin qu'il puisse être envoyé. pour examen et acceptation en amont.
Il existe bien d'autres justifications potentielles. Lorsque vous signalez un bug ou un correctif, incluez une justification valide et attendez-vous à des itérations et à des discussions. Nous reconnaissons que l’ACK comporte des correctifs, en particulier au début les phases de GKI pendant que tout le monde apprend à travailler en amont, mais ne peut pas se détendre le calendrier du produit. Attendez-vous à ce que les exigences liées à l'augmentation rigoureux au fil du temps.
Exigences concernant les correctifs
Les correctifs doivent respecter les normes de codage du noyau Linux décrites dans les
Arborescence source Linux,
qu'ils soient envoyés en amont ou envoyés à l'accusé de réception (ACK). scripts/checkpatch.pl
est exécuté dans le cadre des tests de pré-envoi Gerrit. Vous devez donc l'exécuter à l'avance pour
pour garantir sa réussite. Pour exécuter le script checkpatch avec la même configuration que
les tests avant envoi, utilisez //build/kernel/static_analysis:checkpatch_presubmit
.
Pour en savoir plus, consultez
build/kernel/kleaf/docs/checkpatch.md.
Correctifs ACK
Les correctifs envoyés à l'ACK doivent respecter les normes de codage du noyau Linux et
les consignes relatives aux contributions.
Vous devez inclure un élément Change-Id
dans le message de commit. si vous envoyez le correctif à plusieurs branches
exemple, android-mainline
et android12-5.4
), vous devez utiliser la même
Change-Id
pour toutes les instances du correctif.
Envoyez d'abord les correctifs au LKML pour examen en amont. Si le correctif est:
- Accepté en amont, il a été fusionné automatiquement dans
android-mainline
. - Refusé en amont, envoyez-le à
android-mainline
avec un une référence à l'envoi en amont ou une explication pour expliquer pourquoi envoyés au LKML.
Une fois qu'un correctif est accepté en amont ou dans android-mainline
, il peut être
rétroporté vers l'ACK basé sur LTS approprié (comme android12-5.4
et
android11-5.4
pour les correctifs qui corrigent le code spécifique à Android). Envoi à
android-mainline
permet d'effectuer des tests avec de nouvelles versions candidates en amont et
garantit que le correctif se trouve dans
le prochain ACK basé sur LTS. à l'exception des cas
où un correctif en amont est rétroporté vers android12-5.4
(car le correctif est
figure probablement déjà dans android-mainline
).
Correctifs en amont
Comme indiqué dans la contribution consignes, les correctifs en amont destinés aux noyaux ACK appartiennent aux groupes suivants (répertoriés par ordre de probabilité d'être acceptés).
UPSTREAM:
: les correctifs sélectionnés dans "android-mainline" sont susceptibles d'être accepté en ACK dans le cas d’un cas d’utilisation raisonnable.BACKPORT:
: correctifs en amont qui ne sont pas soigneusement sélectionnés modification sont également susceptibles d'être acceptées s'il existe une utilisation raisonnable .FROMGIT:
: correctifs sélectionnés par une branche chargée de la maintenance en préparation pour l'envoi au réseau principal Linux peuvent être acceptés s'il y a les délais. Ces raisons doivent être justifiées aussi bien pour le contenu que pour le calendrier.FROMLIST:
: correctifs qui ont été envoyés à LKML, mais qui n'ont pas été acceptées dans une branche de gestion mais sont peu susceptibles d'être acceptées, à moins la justification est suffisamment convaincante pour que le correctif soit accepté s'il atterrit ou non sous Linux en amont (nous supposons que ce n'est pas le cas). Il y doit être un problème associé aux correctifsFROMLIST
pour faciliter la discussion avec l'équipe du noyau Android.
Correctifs spécifiques à Android
Si vous n'arrivez pas à apporter les modifications requises en amont, vous pouvez essayer d'envoyer
des correctifs hors de l’arborescence
à ACK directement. L'envoi de correctifs
hors arbre nécessite
que vous créez un problème dans le service informatique qui cite le correctif et explique pourquoi
le correctif ne peut pas être envoyé en amont (voir la liste précédente pour des exemples).
Toutefois, dans certains cas, le code ne peut pas être envoyé en amont. Ces
les cas d'utilisation sont traités comme suit et doivent respecter la contribution
consignes
pour les correctifs spécifiques à Android et être taguée avec le préfixe ANDROID:
dans
l'objet.
Modifications apportées à gki_defconfig
Toutes les modifications de CONFIG
apportées à gki_defconfig
doivent être appliquées à la fois au groupe arm64 et
Versions x86, sauf si CONFIG
est spécifique à l'architecture. Pour demander une modification
sur un paramètre CONFIG
, demandez à l'équipe informatique de discuter du changement. N'importe quelle valeur
Modification de CONFIG
qui affecte l'interface de module du noyau (KMI) après son
figée est refusée. Dans les cas où les partenaires demandent
d'une seule configuration, nous résolvons les conflits en discutant
les bugs associés.
Code qui n'existe pas en amont
Les modifications du code déjà spécifique à Android ne peuvent pas être envoyées en amont. Par exemple, même si le pilote de liaison est géré en amont, les modifications aux caractéristiques d'héritage prioritaires du pilote de liaison ne peuvent pas être envoyées en amont car ils sont spécifiques à Android. Soyez explicite dans le bug et corrigez la cause du problème. ne peut pas être envoyé en amont. Si possible, divisez les correctifs en morceaux qui peuvent être envoyés en amont et des éléments spécifiques à Android qui ne peuvent pas être envoyés ; en amont afin de minimiser la quantité de code hors-arbre conservé dans ACK.
D'autres modifications de cette catégorie sont les mises à jour des fichiers de représentation KMI, KMI
listes de symboles, gki_defconfig
, scripts de compilation, configuration ou autres scripts
qui n'existent pas en amont.
Modules hors arborescence
Linux en amont déconseille activement la création de modules hors arborescence. C'est une position raisonnable étant donné que les responsables de Linux n'offrent aucune garantie à propos de la compatibilité binaire ou source dans le noyau et ne voulez pas prendre en charge le code qui ne figure pas dans l'arborescence. Cependant, le GKI émet des garanties d'ABI pour modules fournisseurs, ce qui garantit la stabilité des interfaces KMI pour les durée de vie d’un noyau. Il existe donc une série de modifications pour le fournisseur d'assistance modules qui sont acceptables pour l'ACK, mais pas pour l'amont.
Prenons l'exemple d'un correctif qui ajoute des macros EXPORT_SYMBOL_GPL()
aux endroits
modules qui utilisent l'exportation ne figurent pas dans l'arborescence source. Bien que vous deviez essayer
pour demander EXPORT_SYMBOL_GPL()
en amont et fournir un module qui utilise le
récemment exporté, si la raison pour laquelle le module
n'est pas envoyé en amont, vous pouvez envoyer le correctif à ACK à la place. Toi
vous devez justifier la raison pour laquelle le module ne peut pas être mis en place
problème. (Ne demandez pas la variante non-GPL, EXPORT_SYMBOL()
.)
Configurations masquées
Certains modules "in-tree" sélectionnent automatiquement les configurations masquées qui ne peuvent pas être spécifiées
dans gki_defconfig
. Par exemple, CONFIG_SND_SOC_TOPOLOGY
est sélectionné
automatiquement lorsque CONFIG_SND_SOC_SOF=y
est configuré. Pour accueillir
création de modules hors arborescence, GKI inclut un mécanisme permettant d'activer les configurations masquées.
Pour activer une configuration masquée, ajoutez une instruction select
dans init/Kconfig.gki
afin qu'elle
est automatiquement sélectionné en fonction de la configuration du noyau CONFIG_GKI_HACKS_TO_FIX
,
qui est activé dans gki_defconfig
. N'utilisez ce mécanisme que pour les configurations masquées.
Si la configuration n'est pas masquée, elle doit être spécifiée dans gki_defconfig
explicitement ou en tant que dépendance.
Gouverneurs chargeables
Pour les frameworks de noyau (tels que cpufreq
) compatibles avec les gouverneurs chargeables, vous
peut remplacer le gouverneur par défaut (tel que le gouverneur schedutil
de cpufreq
). Pour
(par exemple, l'infrastructure thermique) qui ne sont pas compatibles avec les gouverneurs chargeables
ou pilotes, mais nécessitant une mise en œuvre spécifique au fournisseur, créez un problème
au service informatique et consultez l'équipe du noyau Android.
Nous collaborerons avec vous et les responsables de la maintenance en amont pour ajouter la prise en charge nécessaire.
Hooks des fournisseurs
Dans les versions précédentes, vous pouviez ajouter des modifications spécifiques au fournisseur directement dans la noyau. Cela n'est pas possible avec GKI 2.0, car le code spécifique au produit doit être implémentée dans des modules et ne sera pas acceptée dans les noyaux en amont ou dans ACK. Pour proposer des fonctionnalités à valeur ajoutée dont dépendent les partenaires, avec un impact minimal sur le code central du noyau, GKI accepte les hooks de fournisseur qui permettent d'appeler des modules du code du noyau. De plus, les structures de données clés peuvent être remplies champs de données de fournisseur disponibles pour stocker des données spécifiques aux fournisseurs à implémenter ces fonctionnalités.
Il existe deux variantes des accroches de fournisseurs (normales et limitées), basées sur
Points de trace (et non les événements de trace) auxquels les modules du fournisseur peuvent s'associer. Par exemple :
au lieu d'ajouter une nouvelle fonction sched_exit()
pour effectuer une traçabilité au niveau de la tâche
les fournisseurs peuvent ajouter un hook dans do_exit()
qu'un module de fournisseur peut associer
pour traitement. Un exemple d'implémentation inclut les hooks de fournisseur suivants.
- Les hooks de fournisseur normaux utilisent
DECLARE_HOOK()
pour créer une fonction tracepoint nomméetrace_name
, oùname
est l'identifiant unique de traceur. Par convention, les noms de hook de fournisseur normaux commencent parandroid_vh
. le nom du hooksched_exit()
seraitandroid_vh_sched_exit
. - Des hooks de fournisseur restreints sont nécessaires dans les cas, par exemple, pour les hooks de planificateur.
la fonction associée doit être appelée même si le processeur est hors connexion ou nécessite
dans un contexte non atomique. Les hooks de fournisseur restreints ne peuvent pas être dissociés, donc les modules
qui s'attachent à un crochet limité ne peuvent jamais être déchargés. Limité
Les noms des hook de fournisseur commencent par
android_rvh
.
Pour ajouter une accroche de fournisseur, signalez un problème au service informatique et envoyez des correctifs (comme Correctifs spécifiques à Android, un problème doit exister et vous devez fournir justification). La prise en charge des hooks de fournisseur ne se fait qu'en ACK. N'envoyez donc pas ces des correctifs à Linux en amont.
Ajouter des champs de fournisseur aux structures
Vous pouvez associer des données de fournisseurs à des structures de données clés en ajoutant
Champs android_vendor_data
à l'aide des macros ANDROID_VENDOR_DATA()
. Pour
Par exemple, pour accepter des caractéristiques à valeur ajoutée, ajoutez des champs aux structures comme indiqué.
dans l'exemple de code suivant.
Pour éviter les conflits potentiels entre les champs nécessaires aux fournisseurs et les champs
requis par les OEM, ils ne doivent jamais utiliser de champs déclarés via
ANDROID_VENDOR_DATA()
. Les OEM doivent utiliser ANDROID_OEM_DATA()
à la place.
pour déclarer les champs android_oem_data
.
#include <linux/android_vendor.h>
...
struct important_kernel_data {
[all the standard fields];
/* Create vendor data for use by hook implementations. The
* size of vendor data is based on vendor input. Vendor data
* can be defined as single u64 fields like the following that
* declares a single u64 field named "android_vendor_data1" :
*/
ANDROID_VENDOR_DATA(1);
/*
* ...or an array can be declared. The following is equivalent to
* u64 android_vendor_data2[20]:
*/
ANDROID_VENDOR_DATA_ARRAY(2, 20);
/*
* SoC vendors must not use fields declared for OEMs and
* OEMs must not use fields declared for SoC vendors.
*/
ANDROID_OEM_DATA(1);
/* no further fields */
}
Définir les hooks de fournisseur
Ajoutez des hooks de fournisseur au code du noyau en tant que tracepoints en les déclarant à l'aide de
DECLARE_HOOK()
ou DECLARE_RESTRICTED_HOOK()
, puis en les ajoutant au code en tant que
un point de trace. Par exemple, pour ajouter trace_android_vh_sched_exit()
au
fonction de noyau do_exit()
existante:
#include <trace/hooks/exit.h>
void do_exit(long code)
{
struct task_struct *tsk = current;
...
trace_android_vh_sched_exit(tsk);
...
}
Au départ, la fonction trace_android_vh_sched_exit()
ne vérifie que si quelque chose
est jointe. Toutefois, si un module "provider" enregistre un gestionnaire à l'aide de
register_trace_android_vh_sched_exit()
, la fonction enregistrée est appelée. La
le gestionnaire doit connaître le contexte concernant les verrouillages de ce type, l'état RCS et
d'autres facteurs. Le hook doit être défini dans un fichier d'en-tête dans la
Répertoire include/trace/hooks
.
Par exemple, le code suivant donne une déclaration possible pour
trace_android_vh_sched_exit()
dans le fichier include/trace/hooks/exit.h
.
/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM sched
#define TRACE_INCLUDE_PATH trace/hooks
#if !defined(_TRACE_HOOK_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_HOOK_SCHED_H
#include <trace/hooks/vendor_hooks.h>
/*
* Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality
*/
struct task_struct;
DECLARE_HOOK(android_vh_sched_exit,
TP_PROTO(struct task_struct *p),
TP_ARGS(p));
#endif /* _TRACE_HOOK_SCHED_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
Pour instancier les interfaces requises pour le hook de fournisseur, ajoutez le fichier d'en-tête
avec la déclaration de hook vers drivers/android/vendor_hooks.c
et exporter
symboles. Par exemple, le code suivant complète la déclaration du
android_vh_sched_exit()
crochet.
#ifndef __GENKSYMS__
/* struct task_struct */
#include <linux/sched.h>
#endif
#define CREATE_TRACE_POINTS
#include <trace/hooks/vendor_hooks.h>
#include <trace/hooks/exit.h>
/*
* Export tracepoints that act as a bare tracehook (i.e. have no trace
* event associated with them) to allow external modules to probe
* them.
*/
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sched_exit);
REMARQUE: Les structures de données utilisées dans la déclaration de hook doivent être
entièrement définie pour garantir la stabilité de l'ABI. Sinon, il est dangereux de
déréférencer les pointeurs opaques ou utiliser le struct dans des contextes dimensionnés. L'inclusion
qui fournit la définition complète de ces structures de données, doit se trouver
Section #ifndef __GENKSYMS__
sur drivers/android/vendor_hooks.c
. L'en-tête
les fichiers dans include/trace/hooks
ne doivent pas inclure le fichier d'en-tête du noyau avec le
les définitions de type pour éviter les modifications
du CRC qui rompent le KMI. Transférer plutôt
déclarer les types.
Associer aux hooks de fournisseur
Pour utiliser des hooks de fournisseur, le module du fournisseur doit enregistrer un gestionnaire pour le hook.
(généralement effectuée lors de l'initialisation du module). Par exemple, le code suivant
affiche le gestionnaire du module foo.ko
pour trace_android_vh_sched_exit()
.
#include <trace/hooks/sched.h>
...
static void foo_sched_exit_handler(void *data, struct task_struct *p)
{
foo_do_exit_accounting(p);
}
...
static int foo_probe(..)
{
...
rc = register_trace_android_vh_sched_exit(foo_sched_exit_handler, NULL);
...
}
Utiliser des hooks de fournisseur à partir des fichiers d'en-tête
Pour utiliser des hooks de fournisseur à partir des fichiers d'en-tête, vous devrez peut-être le mettre à jour
d'en-tête pour annuler la définition de TRACE_INCLUDE_PATH
afin d'éviter les erreurs de compilation indiquant
un fichier d'en-tête de point de trace est introuvable. Par exemple :
In file included from .../common/init/main.c:111:
In file included from .../common/include/trace/events/initcall.h:74:
.../common/include/trace/define_trace.h:95:10: fatal error: 'trace/hooks/initcall.h' file not found
95 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.../common/include/trace/define_trace.h:90:32: note: expanded from macro 'TRACE_INCLUDE'
90 | # define TRACE_INCLUDE(system) __TRACE_INCLUDE(system)
| ^~~~~~~~~~~~~~~~~~~~~~~
.../common/include/trace/define_trace.h:87:34: note: expanded from macro '__TRACE_INCLUDE'
87 | # define __TRACE_INCLUDE(system) __stringify(TRACE_INCLUDE_PATH/system.h)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.../common/include/linux/stringify.h:10:27: note: expanded from macro '__stringify'
10 | #define __stringify(x...) __stringify_1(x)
| ^~~~~~~~~~~~~~~~
.../common/include/linux/stringify.h:9:29: note: expanded from macro '__stringify_1'
9 | #define __stringify_1(x...) #x
| ^~
<scratch space>:14:1: note: expanded from here
14 | "trace/hooks/initcall.h"
| ^~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Pour corriger ce type d'erreur de compilation, appliquez le correctif équivalent au hook de fournisseur. que vous incluez. Pour en savoir plus, consultez https://r.android.com/3066703
diff --git a/include/trace/hooks/mm.h b/include/trace/hooks/mm.h
index bc6de7e53d66..039926f7701d 100644
--- a/include/trace/hooks/mm.h
+++ b/include/trace/hooks/mm.h
@@ -2,7 +2,10 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mm
+#ifdef CREATE_TRACE_POINTS
#define TRACE_INCLUDE_PATH trace/hooks
+#define UNDEF_TRACE_INCLUDE_PATH
+#endif
Définir UNDEF_TRACE_INCLUDE_PATH
indique à include/trace/define_trace.h
de
annulez la définition de TRACE_INCLUDE_PATH
après avoir créé les points de trace.
Principales fonctionnalités du noyau
Si aucune des techniques précédentes ne vous permet d'implémenter une fonctionnalité à partir d'un module, vous devez ajouter la fonctionnalité en tant que modification spécifique à Android dans noyau. Créez un problème dans l'outil de suivi des problèmes (en informatique) pour engager la conversation.
Interface de programmation d'application utilisateur (UAPI)
- Fichiers d'en-tête UAPI. Modifications apportées à Fichiers d'en-tête UAPI doivent avoir lieu en amont, sauf si les modifications concernent des interfaces spécifiques à Android. Utiliser des fichiers d'en-tête spécifiques au fournisseur pour définir les interfaces entre les modules du fournisseur et le code de l'espace utilisateur du fournisseur.
- nœuds sysfs. N'ajoutez pas de nouveaux nœuds sysfs au noyau GKI (de tels ajouts ne sont valides que dans les modules de fournisseurs). nœuds sysfs utilisés par le SoC et des bibliothèques indépendantes de l'appareil et du code Java qui comprend le framework Android. ne peuvent être modifiés que d'une manière compatible et doivent être modifiés en amont si ce ne sont pas des nœuds sysfs spécifiques à Android. Vous pouvez créer des nœuds sysfs spécifiques au fournisseur à utiliser par l’espace utilisateur du fournisseur. Par défaut, l'accès aux nœuds sysfs par l'espace utilisateur est refusé en utilisant SELinux. C'est à vous pour ajouter les étiquettes SELinux appropriées afin d'autoriser l'accès le logiciel du fournisseur.
- Nœuds DebugFS Les modules des fournisseurs peuvent définir des nœuds dans
debugfs
pour débogage uniquement (cardebugfs
n'est pas installé en fonctionnement normal de la appareil).