通用核心映像檔 (GKI) 會與上游 Linux 核心緊密配合,藉此減少核心分散現象。不過,有些修補程式無法接受上游更新,而且必須遵守產品時間表,因此有些修補程式會在 Android 通用核心 (ACK) 來源中維護,而 GKI 就是從中建構。
開發人員必須使用 Linux 核心郵件在上游提交程式碼變更
列出 (LKML) 做為第一個選項,然後將程式碼變更提交至 ACK
只有在有充分原因導致上游沒有使用時,才會出現 android-mainline
分支
以及有效原因和處理方式的範例如下所示。
修補程式已提交至 LKML,但未在產品發布時接受。如要處理這個修補程式:
- 提供證據證明修補程式已提交至 LKML 和註解 或修補程式預估時間 提交了上游。
- 決定採取實際行動,將修補程式送到 ACK 中,然後獲得核准 最後,當最終上游版本 合併成 ACK
此修補程式為供應商模組定義
EXPORT_SYMBOLS_GPL()
,但由於樹狀結構中沒有使用該符號的模組,因此無法提交至上游。如要處理這個修補程式,請詳細說明模組無法搭配使用的原因 以及您在提出異動前考慮的替代方案 請求。這個修補程式不夠通用,無法用於上游,而且在產品發布前也沒有時間進行重構。如要處理這個修補程式,請提供預估時間,說明何時會將重構的修補程式提交至上游 (如果沒有計畫將重構的修補程式提交至上游供審查,則 ACK 不會接受修補程式)。
修補程式無法接受上游,因為...<插入原因 >。如要處理這個修補程式,請與 Android 核心團隊聯絡,並 與我們合作處理重構修補程式的選項,以便順利提交修補程式 並獲得核准
還有許多其他可能的理由。提交錯誤或修補程式時,請附上有效的理由,並預期會進行一些重複作業和討論。我們瞭解 ACK 會提供一些修補程式,尤其是在 GKI 的初期階段,因為大家都在學習如何進行上游工作,但無法放寬產品時間表。請注意,上游要求會隨著時間而變得更嚴格。
修補程式需求
無論是提交至上游還是 ACK,修補程式都必須符合 Linux 來源樹狀結構中所述的 Linux kernel 程式碼標準。scripts/checkpatch.pl
指令碼包含在 Gerrit 的預先提交測試中,因此請事先執行
確保資料通過如要執行 checkpatch 指令碼,並使用與提交前測試相同的設定,請使用 //build/kernel/static_analysis:checkpatch_presubmit
。詳情請參閱
build/kernel/kleaf/docs/checkpatch.md。
ACK 修補程式
提交至 ACK 的修補程式必須符合 Linux 核心程式碼設計標準和貢獻指南。您必須在修訂版本訊息中加入 Change-Id
標記;如果您將修補程式提交至多個分支 (例如 android-mainline
和 android12-5.4
),則必須為所有修補程式例項使用相同的 Change-Id
。
請先將修補程式提交至 LKML,以便進行上游審查。如果修補程式:
- 已接受上游,會自動合併至
android-mainline
。 - 不接受上游,請以下列指示提交給「
android-mainline
」: 提及上游提交內容,或是無法說明原因 已提交至 LKML
在上游或 android-mainline
中接受修補程式後,即可
移植到適當的 LTS 型 ACK (例如 android12-5.4
和
android11-5.4
適用於修正 Android 專用程式碼的修補程式)。提交至 android-mainline
可使用新的上游候選版本進行測試,並保證修補程式會納入下一個以 LTS 為基礎的 ACK。例外狀況包括案件
其中,上游修補程式會向後移植至 android12-5.4
(因為修補程式
可能已在android-mainline
中)。
上游修補程式
如貢獻指南所述,專為 ACK 核心設計的上游修補程式可分為以下幾類 (依接受機率高低排序)。
UPSTREAM:
- 從「android-mainline」中挑選的修補程式可能是 在合理的用途下,將其識別為 ACK。BACKPORT:
- 來自上游的修補程式,這些修補程式並未乾淨且需要 若有合理的用途,也較有可能接受修改內容 確認是否屬於此情況FROMGIT:
- 如果有即將到來的截止日期,我們可能會接受從維護者分支中挑選出來的修補程式,以便提交至 Linux 主線。內容和時間表都必須符合規定。FROMLIST:
- 已提交至 LKML 但尚未的修補程式 通常獲準加入維護器分行,除非 理由足以證明使用者接受修補程式 是否可以在上游 Linux (我們假設並非如此)必須與FROMLIST
修補程式相關聯的問題,才能與 Android 核心團隊進行討論。
Android 專用修補程式
如果無法在上游完成必要的變更,您可以嘗試直接將樹外修補程提交至 ACK。如要提交樹狀結構外修補程式,您必須在 IT 中建立問題,並在其中引用修補程式,以及為何無法將修補程式提交至上游的理由 (請參閱前述清單中的範例)。不過,在某些情況下,程式碼無法提交至上游。這些情況如下所述,且必須遵循 Android 專屬修補程式的貢獻規範,並在主旨中加上 ANDROID:
前置字元。
gki_defconfig 的變更
除非 CONFIG
是特定架構,否則 gki_defconfig
的所有 CONFIG
變更都必須套用至 arm64 和 x86 版本。如要要求變更 CONFIG
設定,請在 IT 中建立問題,以便討論變更。任何在凍結後影響核心模組介面 (KMI) 的 CONFIG
變更都會遭到拒絕。如果合作夥伴針對單一設定要求互相衝突的設定,我們會討論相關錯誤,解決衝突問題。
程式碼不存在於上游
您無法將已針對 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_SOF=y
,系統會自動選取 CONFIG_SND_SOC_TOPOLOGY
。為了適應
GKI 內建樹狀結構式模組建構作業,其中含有啟用隱藏設定的機制。
如要啟用隱藏的設定,請在 init/Kconfig.gki
中新增 select
陳述式,讓系統根據 gki_defconfig
中啟用的 CONFIG_GKI_HACKS_TO_FIX
核心設定,自動選取該設定。請僅針對隱藏的設定使用此機制;如果設定未隱藏,則必須在 gki_defconfig
中明確指定,或設為依附元件。
可載入的調節器
對於支援可載入管理器的核心架構 (例如 cpufreq
),您必須
可覆寫預設主機 (例如 cpufreq
的 schedutil
主機)。適用對象
不支援可載入管理器的架構 (例如熱架構)
或驅動程式,但仍須導入特定供應商,請建立問題
,並洽詢 Android 核心團隊。
我們會與您和上游維護人員合作,新增必要的支援。
供應商掛鉤
在先前的版本中,您可以直接將供應商專屬修改內容新增至核心核心。但在 GKI 2.0 中無法實現這項功能,因為產品專屬程式碼必須在模組中實作,且無法在核心核心或 ACK 中接受。為在對核心核心程式碼影響降到最低的情況下,啟用合作夥伴所需的加值功能,GKI 會接受供應商鉤子,讓您可從核心核心程式碼叫用模組。此外,您還可以使用 供應商資料欄位,用來儲存要導入的供應商專屬資料 這些功能。
供應商掛鉤有兩種變化版本 (一般和受限),這些版本是根據供應商模組可附加的追蹤點 (而非追蹤事件) 而定。舉例來說,供應商可以選擇在 do_exit()
中新增鉤子,讓供應商模組可附加至該鉤子進行處理,而非新增新的 sched_exit()
函式來執行工作結束時的計算。實作範例包含以下廠商掛鉤。
- 一般供應商鉤子會使用
DECLARE_HOOK()
建立名稱為trace_name
的追蹤點函式,其中name
是追蹤的專屬 ID。按照慣例,一般供應商鉤子名稱會以android_vh
開頭,因此sched_exit()
鉤子的名稱會是android_vh_sched_exit
。 - 如果是排程器掛鉤等客服案件,
即使 CPU 離線或需要
非原子的內容受限制的供應商鉤子無法解除連結,因此連結至受限制鉤子的模組永遠無法卸載。受限制的供應商鉤子名稱開頭為
android_rvh
。
如要新增廠商掛鉤,請在 IT 人員中回報問題,然後提交修補程式 ( Android 專用修補程式、問題必須存在,並提供 理由)。只有 ACK 內才支援供應商掛鉤,因此請勿傳送 更新至上游 Linux
在結構中新增供應商欄位
您可以使用 ANDROID_VENDOR_DATA()
巨集新增 android_vendor_data
欄位,將供應商資料與主要資料結構建立關聯。舉例來說,如要支援附加價值功能,請在結構體中附加欄位,如以下程式碼範例所示。
為避免供應商所需的欄位與原始設備製造商 (OEM) 所需的欄位之間發生衝突,OEM 不得使用以 ANDROID_VENDOR_DATA()
巨集宣告的欄位。相反地,原始設備製造商必須使用 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 穩定性,您必須完整定義在掛鉤宣告中使用的資料結構。否則就不必擔心
解除參照不透明指標,或在大小環境中使用結構體。提供這類資料結構完整定義的 include 應放在 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 專屬的核心核心修改項目。在問題追蹤器 (IT) 中建立問題,即可開始對話。
使用者應用程式設計介面 (UAPI)
- UAPI 標頭檔案。除非變更為 Android 專屬介面,否則必須在上游變更 UAPI 標頭檔案。使用供應商專屬的標頭檔案定義介面 判斷供應商模組與供應商使用者空間程式碼之間的關聯
- sysfs 節點請勿在 GKI 核心中新增 sysfs 節點 (這類新增項目僅適用於供應商模組)。由 SoC 和裝置無關的程式庫使用的 sysfs 節點,以及組成 Android 架構的 Java 程式碼,只能以相容的方式變更,且如果不是 Android 專屬的 sysfs 節點,則必須在上游變更。您可以建立 供應商專屬的 sysfs 節點,供供應商使用者空間使用。根據預設,使用者空間會透過 SELinux 拒絕存取 sysfs 節點。供應商必須自行新增適當的 SELinux 標籤,以便授權供應商軟體存取。
- DebugFS 節點。供應商模組可定義
debugfs
中的節點: 僅供偵錯 (因為debugfs
並未在 裝置)。