Kernel-Code für GKI entwickeln

Das generische Kernel-Image (GKI) reduziert die Kernel-Fragmentierung, indem es eng ausgerichtet ist. mit dem vorgelagerten Linux-Kernel. Es gibt jedoch gute Gründe, einige Patches können Upstream nicht akzeptabel sein und es gibt Produktpläne, müssen erfüllt sein, sodass einige Patches im Android Common Kernel (ACK) verwaltet werden auf denen die GKI basiert.

Entwickler müssen Codeänderungen mithilfe von Linux Kernel Mailing im Upstream einreichen. Liste (LKML) als erste Wahl auf und sende Codeänderungen an die ACK. android-mainline-Zweig nur, wenn es einen triftigen Grund gibt, warum Upstream nicht umsetzbar sind. Im Folgenden finden Sie Beispiele für gültige Gründe und den Umgang damit.

  • Das Patch wurde an LKML gesendet, aber nicht rechtzeitig für ein Produkt akzeptiert Veröffentlichung. So verarbeiten Sie diesen Patch:

    • Weisen Sie nach, dass das Patch an LKML gesendet wurde, und fügen Sie Kommentare hinzu. für den Patch empfangen haben, oder eine geschätzte Zeit, in der der Patch vorgelagerte Emissionen.
    • Entscheide dich für eine Vorgehensweise, um den Patch in ACK zu erhalten und genehmigen zu lassen. und dann aus Bestätigung herausnehmen, wenn die endgültige Upstream-Version zu ACK zusammengeführt.
  • Der Patch definiert EXPORT_SYMBOLS_GPL() für ein Anbietermodul, konnte aber nicht vorgelagert werden, da es keine integrierten Module gibt, . Geben Sie zur Verarbeitung dieses Patches Details dazu an, warum Ihr Modul nicht vorgelagerte Elemente und die Alternativen, die Sie vor diesem Schritt in Betracht gezogen haben,

  • Der Patch ist nicht allgemein genug für Upstream-Inhalte und es ist keine Zeit, vor der Produktveröffentlichung refaktorieren. Um diesen Patch zu verarbeiten, musst du einen geschätzte Zeit, in der ein refaktorierter Patch vorgelagert wird (der Patch wird nur in ACK akzeptiert, wenn ein refaktoriertes Patch-Upstream zur Überprüfung).

  • Der Patch kann von Upstream nicht akzeptiert werden, weil... <Grund einfügen hier>. Wenden Sie sich zur Bewältigung dieses Patches an das Android-Kernel-Team und Gemeinsam mit uns Optionen zur Refaktorierung des Patch erarbeiten, damit er eingereicht werden kann zur Überprüfung und Genehmigung vor.

Es gibt noch viele weitere mögliche Gründe. Wenn Sie den Fehler melden oder Patch enthalten ist, eine gültige Begründung enthalten, und es ist mit Iteration und Erörterung zu rechnen. Wir erkennen, dass das ACK einige Patches enthält, insbesondere in den frühen Phasen von GKI, während alle lernen, wie sie vorgelagert sind, sich aber nicht entspannen können. Produktpläne verwendet werden. Die Anforderungen für das Upstreaming werden im Laufe der Zeit.

Patchanforderungen

Patches müssen den Codierungsstandards für den Linux-Kernel entsprechen, die in den Linux-Quellstruktur unabhängig davon, ob sie vorgelagert oder zur Bestätigung gesendet werden. Das scripts/checkpatch.pl Das Skript wird im Rahmen des Gerrit Presubmit-Tests ausgeführt. Führen Sie es daher im Voraus aus, ob er erfolgreich ist. Zum Ausführen des Checkpatch-Skripts mit der gleichen Konfiguration wie das Test vor dem Einreichen: //build/kernel/static_analysis:checkpatch_presubmit verwenden. Weitere Informationen finden Sie unter build/kernel/kleaf/docs/checkpatch.md.

ACK-Patches

An ACK gesendete Patches müssen den Programmierstandards für den Linux-Kernel entsprechen und die Richtlinien für Beiträge. Sie müssen einen Change-Id hinzufügen. -Tag in der Commit-Nachricht; wenn Sie das Patch an mehrere Zweige senden (für Beispiel android-mainline und android12-5.4), müssen Sie dieselben Change-Id für alle Instanzen des Patches.

Patches zur Überprüfung an LKML senden Wenn der Patch ist:

  • Wenn sie vorgelagert sind, wird sie automatisch mit „android-mainline“ zusammengeführt.
  • Werden nicht akzeptiert, senden Sie sie an android-mainline mit einer Ein Verweis auf die vorgelagerte Einreichung oder eine Erklärung, warum sie nicht an LKML gesendet.

Nachdem ein Patch entweder vorgelagert oder in android-mainline akzeptiert wurde, kann er an die entsprechende LTS-basierte Bestätigung zurückportiert werden (z. B. android12-5.4 und android11-5.4 für Patches, die Android-spezifischen Code korrigieren). Wird gesendet an android-mainline ermöglicht das Testen mit neuen vorgelagerten Releasekandidaten und garantiert, dass sich der Patch in der nächsten LTS-basierten Bestätigung befindet. Ausnahmen sind Fälle, Dabei wird ein Upstream-Patch zu android12-5.4 zurückportiert, da der Patch ist wahrscheinlich bereits in android-mainline).

Upstream-Patches

Wie im Beitrag Richtlinien, Upstream-Patches für ACK-Kernel fallen in die folgenden Gruppen (aufgeführt in der Reihenfolge der Wahrscheinlichkeit, dass sie angenommen werden.

  • UPSTREAM: – Patches aus „android-mainline“ werden wahrscheinlich akzeptiert, wenn es einen sinnvollen Anwendungsfall gibt.
  • BACKPORT: – Flecken aus der Upstream-Phase, die sich nicht sauber abtrennen lassen und die Sie benötigen. Änderungen sind wahrscheinlich auch dann zulässig, wenn eine angemessene Verwendung Fall.
  • FROMGIT: – Patches von einem Administrator eines Zweigs zur Vorbereitung gepflückt für die Einreichung an Linux Mainline kann angenommen werden, wenn es eine bevorstehende Frist. Dies muss sowohl im Hinblick auf den Inhalt als auch für den Zeitplan gerechtfertigt sein.
  • FROMLIST:: Patches, die an LKML gesendet, aber noch nicht gesendet wurden eine Aufnahme in einen Administrator-Zweig ist unwahrscheinlich, es sei denn, Die Begründung ist überzeugend genug, dass der Patch akzeptiert werden würde. ob es in Upstream Linux landet oder nicht. Wir gehen davon aus, dass dies nicht der Fall ist. Es muss ein Problem im Zusammenhang mit FROMLIST-Patches sein, um die Diskussion zu erleichtern. mit dem Android-Kernel-Team.

Android-spezifische Patches

Wenn Sie die erforderlichen Änderungen nicht in einer Upstream-Phase umsetzen können, haben Sie die Möglichkeit, Out-of-Tree-Patches direkt zu bestätigen. Das Einreichen von Patches erfordert dass Sie ein Problem in der IT anlegen, das den Patch und die Begründung dafür angibt, Der Patch kann nicht vorgelagert werden. Beispiele finden Sie in der vorherigen Liste. Es gibt jedoch einige Fälle, in denen der Code nicht vorgelagert werden kann. Diese Fälle werden im Folgenden behandelt und müssen nach dem Beitrag Richtlinien für Android-spezifische Patches und mit dem Präfix ANDROID: in der Person.

Änderungen an „gki_defconfig“

Alle „CONFIG“-Änderungen an „gki_defconfig“ müssen sowohl auf Verzweigung 64 als auch auf x86-Versionen, es sei denn, CONFIG ist architekturspezifisch. Änderung beantragen auf eine CONFIG-Einstellung setzen, erstellen Sie ein Problem in der IT-Abteilung, um die Änderung zu besprechen. Beliebig CONFIG-Änderung, die sich auf die Kernel Module Interface (KMI) auswirkt, nachdem sie „frozen“ wird abgelehnt. Wenn Partner einen Konflikt verursachen, Einstellungen für eine einzelne Konfiguration vornehmen, lösen wir Konflikte durch Diskussionen Fehler beheben.

Code, der vorgelagert nicht vorhanden ist

Änderungen an Code, der bereits Android-spezifisch ist, können nicht in Upstream gesendet werden. Beispiel: Obwohl der Bindertreiber vorgelagert wird, können Änderungen an priorisierte Vererbungsfunktionen des Binder-Treibers können nicht vorgeschaltet werden. weil sie Android-spezifisch sind. Geben Sie in Ihrem Fehler deutlich an, warum der Fehler kann Code nicht in Upstream gesendet werden. Teile die Patches nach Möglichkeit in einzelne Stücke, vorgelagerte Elemente und Android-spezifische Artikel, die nicht eingereicht werden können Upstream, um die Menge an Out-of-Tree-Code, der in ACK verwaltet wird, zu minimieren.

Weitere Änderungen in dieser Kategorie sind Aktualisierungen von KMI-Darstellungsdateien, KMI-Dateien Symbollisten, gki_defconfig, Build-Skripts, Konfiguration oder andere Skripts die es vorgelagert nicht gibt.

Veraltete Module

Upstream-Linux rät aktiv vom Support für das Erstellen von Out-of-Tree-Modulen ab. Dies ist eine angemessene Position, da Linux-Administratoren keine Garantien geben. zur In-Kernel- oder Binärkompatibilität und möchten keinen Code unterstützen. das nicht im Baum ist. Der Google KI-Dienst bietet jedoch ABI-Garantien für Anbietermodule, mit denen sichergestellt wird, dass die KMI-Schnittstellen für die unterstützten Lebensdauer eines Kernels. Daher gibt es eine Reihe von Änderungen, um Anbieter zu unterstützen, Module, die für ACK akzeptabel, aber für Upstream nicht akzeptabel sind.

Angenommen, Sie haben einen Patch, mit dem EXPORT_SYMBOL_GPL()-Makros hinzugefügt werden, Module, die den Export verwenden, befinden sich nicht in der Quellstruktur. Sie müssen es zwar versuchen, um EXPORT_SYMBOL_GPL() in Upstream anzufordern und ein Modul bereitzustellen, das die Methode neu exportiertes Symbol, wenn es eine gültige Begründung dafür gibt, warum das Modul nicht vorgelagert werden, können Sie den Patch stattdessen an ACK senden. Ich muss eine Begründung angegeben werden, warum das Modul nicht vorgelagert werden kann. Problem. Fordern Sie nicht die Nicht-GPL-Variante EXPORT_SYMBOL() an.

Ausgeblendete Konfigurationen

Einige integrierte Module wählen automatisch ausgeblendete Konfigurationen aus, die nicht angegeben werden können in „gki_defconfig“. Beispiel: CONFIG_SND_SOC_TOPOLOGY ist ausgewählt automatisch, wenn CONFIG_SND_SOC_SOF=y konfiguriert ist. Um Out-of-Tree-Modulerstellung bietet GKI einen Mechanismus, mit dem versteckte Konfigurationen aktiviert werden können.

Um eine ausgeblendete Konfiguration zu aktivieren, fügen Sie in init/Kconfig.gki eine select-Anweisung hinzu, basierend auf der Kernel-Konfiguration CONFIG_GKI_HACKS_TO_FIX automatisch ausgewählt, die in gki_defconfig aktiviert ist. Verwenden Sie diesen Mechanismus nur für versteckte Konfigurationen. Ist die Konfiguration nicht ausgeblendet, muss sie entweder in gki_defconfig angegeben werden oder als Abhängigkeit.

Gouverneure zum Laden

Für Kernel-Frameworks (z. B. cpufreq), die ladebare Governoren unterstützen, kann den Standard-Gouverneur überschreiben (z. B. den schedutil-Gouverneur von cpufreq. Für Konstruktionswerke (z. B. Wärmerahmen), die keine belastbaren Gouverneure unterstützen aber trotzdem eine anbieterspezifische Implementierung erfordern, in der IT und wenden Sie sich an das Android Kernel-Team.

Wir arbeiten mit Ihnen und den vorgelagerten Administratoren zusammen, um Ihnen den erforderlichen Support zu bieten.

Anbieter-Hooks

In früheren Releases konnten anbieterspezifische Änderungen direkt in das Feld Core Kernel. Dies ist mit GKI 2.0 nicht möglich, da produktspezifischer Code in Modulen implementiert sein und in den vorgelagerten Kern-Kerneln oder in ACK. Um wertschöpfende Funktionen zu ermöglichen, auf die sich Partner verlassen können, mit minimaler Auswirkung Bei Kern-Kernel-Code akzeptiert GKI Anbieter-Hooks, mit denen Module aufgerufen werden können aus dem Kern-Kernel-Code. Darüber hinaus können wichtige Datenstrukturen mit Anbieterdatenfelder, in denen anbieterspezifische Daten für die Implementierung gespeichert werden können diese Funktionen.

Es gibt zwei Varianten von Anbieter-Hooks (normal und eingeschränkt), die auf Tracepoints (keine Trace-Ereignisse), an die Anbietermodule angehängt werden können. Beispiel: anstatt eine neue sched_exit()-Funktion hinzuzufügen, um bei der Aufgabe eine Ressourcenerfassung vorzunehmen. Exit können Anbieter einen Hook in do_exit() hinzufügen, an den ein Anbietermodul angehängt werden kann. zu verarbeiten. Eine Beispielimplementierung umfasst die folgenden Anbieter-Hooks.

  • Normale Anbieter-Hooks verwenden DECLARE_HOOK(), um eine Tracepoint-Funktion zu erstellen mit dem Namen trace_name, wobei name ist die eindeutige Kennung für die Trace. Konventionsgemäß beginnen normale Namen von Anbieter-Hooks mit android_vh, sodass lautet der Name für den sched_exit()-Hook android_vh_sched_exit.
  • Eingeschränkte Anbieter-Hooks sind erforderlich, z. B. in Planer-Hooks, in denen Die angehängte Funktion muss aufgerufen werden, auch wenn die CPU offline ist oder nicht atomaren Kontext. Eingeschränkte Anbieter-Hooks können nicht getrennt werden, sodass Module die an einen eingeschränkten Hook angehängt sind, können sie nie entladen. Eingeschränkt Namen von Anbieter-Hooks beginnen mit android_rvh.

Um einen Anbieter-Hook hinzuzufügen, melden Sie ein Problem in der IT und reichen Sie Patches ein (wie bei allen Android-spezifische Patches, ein Problem muss vorhanden sein und Sie müssen Begründung). Anbieter-Hooks werden nur in ACK unterstützt, senden Sie diese also nicht. für Upstream-Linux-Patches.

Anbieterfelder zu Strukturen hinzufügen

Sie können Anbieterdaten wichtigen Datenstrukturen zuordnen, indem Sie android_vendor_data-Felder mit den ANDROID_VENDOR_DATA()-Makros. Für Um zusätzliche Funktionen zu unterstützen, hängen Sie beispielsweise Felder wie gezeigt an Strukturen an. im folgenden Codebeispiel.

Um potenzielle Konflikte zwischen Feldern zu vermeiden, die von Anbietern und Feldern benötigt werden die von OEMs benötigt werden, dürfen OEMs niemals Felder verwenden, die mit ANDROID_VENDOR_DATA()-Makros. Stattdessen müssen OEMs ANDROID_OEM_DATA() verwenden. um android_oem_data-Felder zu deklarieren.

#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 */
}

Anbieter-Hooks definieren

Fügen Sie dem Kernel-Code Anbieter-Hooks als Tracepoints hinzu, indem Sie sie mit DECLARE_HOOK() oder DECLARE_RESTRICTED_HOOK() und fügen Sie sie dann dem Code als ein Tracepoint. Um beispielsweise trace_android_vh_sched_exit() zum vorhandene do_exit()-Kernelfunktion:

#include <trace/hooks/exit.h>
void do_exit(long code)
{
    struct task_struct *tsk = current;
    ...
    trace_android_vh_sched_exit(tsk);
    ...
}

Die Funktion trace_android_vh_sched_exit() prüft anfangs nur, ob etwas ist angehängt. Registriert ein Anbietermodul einen Handler jedoch mithilfe von register_trace_android_vh_sched_exit() wird die registrierte Funktion aufgerufen. Die Der Handler muss den Kontext in Bezug auf Holds, den RCS-Status und anderen Faktoren. Der Hook muss in einer Headerdatei in der include/trace/hooks-Verzeichnis.

Der folgende Code stellt beispielsweise eine mögliche Deklaration für trace_android_vh_sched_exit() in der Datei 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>

Fügen Sie die Headerdatei hinzu, um die für den Anbieter-Hook erforderlichen Schnittstellen zu instanziieren mit der Hook-Deklaration in drivers/android/vendor_hooks.c und exportieren Sie die . Beispielsweise vervollständigt der folgende Code die Deklaration des android_vh_sched_exit()-Hook.

#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);

HINWEIS: Datenstrukturen, die innerhalb der Hook-Deklaration verwendet werden, müssen vollständig definiert, um die ABI-Stabilität zu gewährleisten. Andernfalls ist es nicht sicher, dereferenzieren die undurchsichtigen Zeiger oder verwenden die Struktur in einem größeren Kontext. Die Einbeziehung die die vollständige Definition dieser Datenstrukturen enthält, Abschnitt #ifndef __GENKSYMS__ von drivers/android/vendor_hooks.c. Der Header Dateien in include/trace/hooks sollten nicht die Kernel-Header-Datei mit dem geben Sie Definitionen ein, um CRC-Änderungen zu vermeiden, die die KMI beeinträchtigen. Stattdessen vorwärts die Typen deklariert werden.

An Anbieter-Hooks anhängen

Zur Verwendung von Anbieter-Hooks muss das Anbietermodul einen Handler für den Hook registrieren (normalerweise während der Modulinitialisierung). Der folgende Code zeigt den Handler des Moduls foo.ko für 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);
    ...
}

Anbieter-Hooks aus Headerdateien verwenden

Wenn Sie Anbieter-Hooks aus Headerdateien verwenden möchten, müssen Sie den Anbieter-Hook möglicherweise aktualisieren Headerdatei die Definition von TRACE_INCLUDE_PATH undefiniert, um Build-Fehler zu vermeiden, die auf Es wurde keine Trace-Punkt-Header-Datei gefunden. Beispiel:

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.

Wenden Sie die entsprechende Fehlerkorrektur auf den Anbieter-Hook an, um diesen Build-Fehler zu beheben. enthalten. Weitere Informationen finden Sie unter 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

Durch Festlegen von UNDEF_TRACE_INCLUDE_PATH wird include/trace/define_trace.h angewiesen, TRACE_INCLUDE_PATH nach dem Erstellen der Trace-Punkte nicht mehr definieren.

Kernfunktionen des Kernels

Wenn keine der vorherigen Techniken es Ihnen ermöglicht, eine Funktion aus einem Modul zu implementieren, müssen Sie die Funktion als Android-spezifische Modifikation Kernel. Erstellen Sie ein Problem im Issue Tracker (IT), um das Gespräch zu beginnen.

User Application Programming Interface (UAPI)

  • UAPI-Headerdateien: Änderungen an UAPI-Headerdateien muss vorgelagert sein, es sei denn, die Änderungen betreffen Android-spezifische Schnittstellen. Schnittstellen mit anbieterspezifischen Header-Dateien definieren zwischen den Anbietermodulen und dem Userspace-Code des Anbieters.
  • sysfs-Knoten. Fügen Sie dem GKI-Kernel keine neuen sysfs-Knoten hinzu, sind nur in Anbietermodulen gültig). sysfs-Knoten, die vom SoC- und geräteunabhängige Bibliotheken und Java-Code, die das Android-Framework bilden dürfen nur auf kompatible Weise geändert werden und müssen vorgelagert werden, wenn Es sind keine Android-spezifischen sysfs-Knoten. Sie können anbieterspezifische sysfs-Knoten, die vom Nutzerbereich des Anbieters verwendet werden. Standardmäßig Der Zugriff auf Sysfs-Knoten nach Userspace wird mit SELinux verweigert. Es liegt an der um die entsprechenden SELinux-Labels hinzuzufügen, Software von Anbietern.
  • DebugFS-Knoten: Anbietermodule können Knoten in debugfs für nur zur Fehlerbehebung (da debugfs während des normalen Betriebs des Gerät).