開發 GKI 的核心程式碼

一般核心映像檔 (GKI) 必須緊密對齊,藉此減少核心片段 與上游 Linux kernel 通訊然而,正當原因卻有 有些修補程式無法上游接受,但部分修補程式必須 以確保部分修補程式安裝在 Android Common 核心 (ACK) 中 GKI 的建構來源

開發人員必須使用 Linux 核心郵件在上游提交程式碼變更 列出 (LKML) 做為第一個選項,然後將程式碼變更提交至 ACK 只有在有充分原因導致上游沒有使用時,才會出現 android-mainline 分支 以及以下列出有效原因和處理方法。

  • 修補程式已提交至 LKML,但未及時接受產品修補程式 版本。如何處理這個修補程式:

    • 提供證據證明修補程式已提交至 LKML 和註解 或修補程式預估時間 提交了上游。
    • 決定採取實際行動,將修補程式送到 ACK 中,然後獲得核准 最後,當最終上游版本 合併成 ACK
  • 修補程式為供應商模組定義了 EXPORT_SYMBOLS_GPL(),但無法 因為沒有任何類神經模組會使用 符號。如要處理這個修補程式,請詳細說明模組無法搭配使用的原因 以及您在提出異動前考慮的替代方案 請求。

  • 修補程式對於上游而言不夠籠統,因此沒有時間 在產品推出前重構如要處理此修補程式,請提供 重構修補程式提交到上游的預估時間 沒有計畫提交重構的計畫,就無法在 ACK 中接受修補程式 修補程式的上游)。

  • 無法由上游接受這個修補程式,原因如下...<插入原因 >。如要處理這個修補程式,請與 Android 核心團隊聯絡,並 與我們合作處理重構修補程式的選項,以便順利提交修補程式 並獲得核准

不過,還有許多可能的理由。當您提交錯誤或 加入有效的理由,並預期部分疊代和討論 我們瞭解 ACK 含有某些修補程式,特別是在早期 而 GKI 階段,大家都在學習如何上游,但是無意放鬆 。預期上游需求會變得更加 變得越來越強

修補程式需求

修補程式必須符合 Linux 原始碼樹狀結構 無論要提交上游還是 ACKscripts/checkpatch.pl 指令碼包含在 Gerrit 預先提交測試中,因此請事先執行 確保資料通過如要執行 checkpatch 指令碼, 預先提交測試,請使用 //build/kernel/static_analysis:checkpatch_presubmit。 詳情請參閱 build/kernel/kleaf/docs/checkpatch.md

ACK 修補程式

提交至 ACK 的修補程式必須符合 Linux kernel 編碼標準, 捐款規範。 您必須加入 Change-Id 標記;如果您將修補程式提交至多個分支版本 例如 android-mainlineandroid12-5.4) 之間,您必須使用相同的 Change-Id 用於修補程式的所有執行個體。

先將修補程式提交至 LKML,以便進行上游審查。如果修補程式:

  • 已接受上游,已自動併入 android-mainline
  • 不接受上游,請以下列指示提交給「android-mainline」: 提及上游提交內容,或是無法說明原因 已提交至 LKML

在上游或 android-mainline 中接受修補程式後,即可 移植到適當的 LTS 型 ACK (例如 android12-5.4android11-5.4 適用於修正 Android 專用程式碼的修補程式)。提交至 android-mainline 可讓您對新的上游候選版本進行測試,以及 保證修補程式位於下一個以 LTS 為基礎的 ACK 中。例外狀況包括案件 其中,上游修補程式會向後移植至 android12-5.4 (因為修補程式 可能已在android-mainline中)。

上游修補程式

捐款中所述 規範 目的地為確認核心的上游修補程式屬於下列群組 (列於清單中) 。

  • UPSTREAM: - 從「android-mainline」中挑選的修補程式可能是 在合理的用途下,將其識別為 ACK。
  • BACKPORT: - 來自上游的修補程式,這些修補程式並未乾淨且需要 若有合理的用途,也較有可能接受修改內容 確認是否屬於此情況
  • FROMGIT: - 從維護器分支版本中取出的修補做準備 系統可能會接受提交至 Linux mainline 的 期限。無論是內容和時間表,都必須提供正當理由。
  • FROMLIST: - 已提交至 LKML 但尚未的修補程式 通常獲準加入維護器分行,除非 理由足以證明使用者接受修補程式 是否可以在上游 Linux (我們假設並非如此)有 必須為與「FROMLIST」修補程式相關的問題才能展開討論 我們與 Android 核心團隊做比較

Android 專用修補程式

如果無法將必要的變更傳送至上游,可以嘗試提交 樹狀結構中,直接 ACK。如要提交樹狀結構外修補程式, 您在 IT 部門建立了一個問題,引述了修補程式和原因 修補程式無法在上游提交 (請參閱先前的清單)。 不過在某些情況下,也無法在上游提交代碼。這些 案件列舉如下,且必須遵守 準則 ,並在ANDROID: 主旨。

gki_defconfig 的變更

gki_defconfig 的所有 CONFIG 變更都必須同時套用至 arm64 和 x86 版本,除非 CONFIG 僅限於特定架構。如何要求變更 至 CONFIG 設定,在 IT 人員建立問題討論變更。不限 CONFIG 變更會影響核心模組介面 (KMI) 發生後 凍結要求遭拒。合作夥伴要求產生相衝突的情況 為解決衝突,我們會透過 以便解決相關錯誤

程式碼不存在於上游

無法針對已用於 Android 的程式碼修改內容,因此無法在上游傳送。 舉例來說,即使繫結器驅動程式是由上游維護, 繫結器驅動程式的優先順序無法沿用到上游 因為它們是 Android 專屬的明確表現出錯誤,並修補 無法將代碼傳送到上游可以的話,請將修補程式分割成 無法提交上游和 Android 專屬作品 來盡量減少在 ACK 中維護的樹狀結構外程式碼數量。

這個類別的其他變更包括 KMI 表示法檔案 (KMI) 的更新 符號清單、gki_defconfig、建構指令碼或設定或其他指令碼 這裡並未存在於上游物件

樹狀結構外模組

上游 Linux 主動禁止建構外流模組。 由於 Linux 維護人員不保證 Linux 維護人員的安全性 關於核心來源或二進位檔相容性,而且不想支援程式碼 該項目並未出現在樹狀圖中不過,GKI「確實」會保證 ABI 的保證, 供應商模組,確保支援的 KMI 介面穩定 生命週期內的作業時間因此,為支援供應商做出重大調整 可接受 ACK 但不適用的上游模組。

舉例來說,假設有一個修補程式會新增 EXPORT_SYMBOL_GPL() 巨集, 但來源樹狀結構中沒有使用匯出的模組。雖然您必須設法 要求 EXPORT_SYMBOL_GPL() 上游,並提供使用 新匯出符號 (如果有合理原因)。 無法提交上游項目,請改為將修補程式提交至 ACK。個人中心 必須包含原因,說明模組無法向上串流的原因 問題。(請勿要求非 GPL 子類,EXPORT_SYMBOL())。

隱藏的設定

部分樹狀模組會自動選取無法指定的隱藏設定 在「gki_defconfig」中。舉例來說,已選取「CONFIG_SND_SOC_TOPOLOGY」 在 CONFIG_SND_SOC_SOF=y 設定後自動更新。為了適應 GKI 內建樹狀結構式模組建構作業,其中含有啟用隱藏設定的機制。

如要啟用隱藏設定,請在 init/Kconfig.gki 中新增 select 陳述式,以啟用該設定 會根據 CONFIG_GKI_HACKS_TO_FIX 核心設定自動選取 這項功能已在 gki_defconfig 啟用這項機制僅應用於隱藏設定; 如未隱藏設定,則必須在 gki_defconfig 中指定 明確或依附元件

可載入的管理者

對於支援可載入管理器的核心架構 (例如 cpufreq),您必須 可覆寫預設主機 (例如 cpufreqschedutil 主機)。適用對象 不支援可載入管理器的架構 (例如熱架構) 或驅動程式,但仍須導入特定供應商,請建立問題 ,並洽詢 Android 核心團隊

我們會與您和上游維護人員合作提供必要的支援服務。

廠商掛鉤

在過往版本中,您可以直接將特定供應商的修改內容加入 核心核心。GKI 2.0 不適用這項做法,因為產品專用的程式碼必須 實作於模組中,不會接受核心核心上游程式庫, 。希望在盡量減少影響下,提供合作夥伴仰賴的附加價值功能 核心程式碼上的 GKI 接受可叫用模組的廠商掛鉤 從核心程式碼擷取出來此外,您還可以使用 供應商資料欄位,用來儲存要導入的供應商專屬資料 這些功能。

供應商掛鉤分為兩種形式 (正常與受限),並依據 廠商模組可以附加的追蹤點 (非追蹤事件)。例如: 不必新增 sched_exit() 函式來在工作中處理會計 結束,廠商可在 do_exit() 中新增掛鉤,供供應商模組附加至 以便處理。實作範例包含以下廠商掛鉤。

  • 一般廠商掛鉤會使用 DECLARE_HOOK() 建立追蹤點函式 名為 trace_name,其中 name 是 追蹤記錄。按照慣例,一般供應商掛鉤名稱的開頭是 android_vh,因此 sched_exit() 掛鉤的名稱為 android_vh_sched_exit
  • 如果是排程器掛鉤等客服案件, 即使 CPU 離線或需要 非原子的內容受限制的供應商掛鉤無法卸離,因此模組 附加至受限制掛鉤永遠無法卸載。受限制 供應商掛鉤名稱開頭為 android_rvh

如要新增廠商掛鉤,請在 IT 人員中回報問題,然後提交修補程式 ( Android 專用修補程式、問題必須存在,並提供 理由)。只有 ACK 內才支援供應商掛鉤,因此請勿傳送 更新至上游 Linux

在結構中加入供應商欄位

您可以將供應商資料與金鑰資料結構建立關聯,方法是新增 android_vendor_data 欄位使用 ANDROID_VENDOR_DATA() 巨集。適用對象 舉例來說,如要支援加值功能,請將欄位附加至結構,如下所示 所能呼叫的函式

避免供應商和欄位所需的欄位之間發生衝突 原始設備製造商 (OEM) 所需的欄位,一律不得使用 ANDROID_VENDOR_DATA() 巨集。原始設備製造商 (OEM) 必須使用 ANDROID_OEM_DATA() 宣告 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 */
}

定義供應商掛鉤

使用以下程式碼宣告供應商掛鉤,將供應商掛鉤新增至核心程式碼做為追蹤點 DECLARE_HOOK()DECLARE_RESTRICTED_HOOK(),然後將其新增至程式碼,做為 追蹤記錄點舉例來說,如要將 trace_android_vh_sched_exit() 新增至 現有的 do_exit() 核心函式:

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

trace_android_vh_sched_exit() 函式一開始只會檢查 。但是,如果供應商模組使用 register_trace_android_vh_sched_exit(),系統會呼叫已註冊的函式。 處理常式必須掌握保留鎖定、RCS 狀態及 其他因素。您必須在 include/trace/hooks 目錄內。

舉例來說,下列程式碼可提供 include/trace/hooks/exit.h 檔案中的 trace_android_vh_sched_exit()

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

如要將供應商掛鉤所需的介面例項化,請新增標頭檔案 將 hook 宣告傳遞至 drivers/android/vendor_hooks.c,然後匯出 符號。舉例來說,下列程式碼會完成 android_vh_sched_exit()掛鉤。

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

注意:掛鉤宣告期間使用的資料結構必須 我們之所以完整定義,以確保 ABI 穩定性。否則就不必擔心 解除參照不透明指標,或在大小環境中使用結構體。加入 ,完整定義這類資料結構應位於 drivers/android/vendor_hooks.c#ifndef __GENKSYMS__部分。標題 include/trace/hooks 中的檔案不應含有 類型定義,以避免因 CRC 變更而破壞 KMI。改為轉寄 宣告類型

附加至廠商掛鉤

如要使用廠商掛鉤,供應商模組需要為掛鉤註冊處理常式 (通常在模組初始化期間執行)。例如,下列程式碼 會顯示 trace_android_vh_sched_exit() 的模組 foo.ko 處理常式。

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

從標頭檔案中使用廠商掛鉤

如要透過標頭檔案使用廠商掛鉤,你可能需要更新供應商掛鉤 來取消定義 TRACE_INCLUDE_PATH 的標頭檔案,以免發生以下建構錯誤: 找不到追蹤點標頭檔案。例如:

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.

如要修正這類建構錯誤,請將對等的修正套用至供應商掛鉤 加入要加入的標頭檔案詳情請參閱 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

定義 UNDEF_TRACE_INCLUDE_PATH 會指示 include/trace/define_trace.h 執行以下操作 建立追蹤點後,取消定義 TRACE_INCLUDE_PATH

核心功能

如果先前的技術都無法讓您從模組實作功能, 那麼,您必須將功能新增成 Android 專屬的修改核心 核心。在 Issue Tracker (IT) 中建立問題即可開始對話。

使用者應用程式設計介面 (UAPI)

  • UAPI 標頭檔案。變更內容 UAPI 標頭檔案 除非變更是套用至 Android 專用的介面,否則都必須向上游。 使用供應商專屬的標頭檔案定義介面 判斷供應商模組與供應商使用者空間程式碼之間的關聯
  • sysfs 節點不要在 GKI 核心中新增 sysfs 節點 (這類新增作業) 只在供應商模組中使用)。SoC- 和 構成 Android 架構的通用裝置通用程式庫和 Java 程式碼 只能透過相容的方式變更,且只有在 並非 Android 專屬的 sysfs 節點您可以建立 供應商專屬的 sysfs 節點,供供應商使用者空間使用。根據預設 透過 SELinux 存取 sysfs 節點時遭到拒絕。取決於 供應商新增適當的 SELinux 標籤,以允許經過授權的存取 供應商軟體
  • DebugFS 節點。供應商模組可定義 debugfs 中的節點: 僅供偵錯 (因為 debugfs 並未在 裝置)。