Generic Kernel Image (GKI) mengurangi fragmentasi kernel dengan menyelaraskannya dengan kernel Linux upstream. Namun, ada alasan yang logis beberapa {i>patch<i} tidak dapat diterima di upstream, dan ada jadwal produk yang harus dipenuhi, sehingga beberapa patch dipertahankan dalam Android Common Kernel (ACK) sumber tempat GKI dibuat.
Developer harus mengirimkan perubahan kode ke upstream menggunakan Email Kernel Linux
Daftar (LKML) sebagai pilihan pertama, dan kirim perubahan kode ke ACK
Cabang android-mainline
hanya jika ada alasan kuat mengapa upstream tidak
layak. Contoh alasan yang valid dan cara menanganinya tercantum sebagai berikut.
Patch dikirim ke LKML, tetapi tidak diterima tepat waktu untuk produk data. Untuk menangani patch ini:
- Berikan bukti bahwa patch telah dikirim ke LKML dan komentar yang diterima untuk {i>patch<i}, atau perkiraan waktu {i>patch<i} itu dikirimkan ke hulu.
- Memutuskan tindakan untuk menempatkan patch di ACK, dan mendapatkan persetujuan upstream, dan kemudian mengeluarkannya dari ACK ketika versi upstream final adalah digabungkan ke dalam ACK.
Patch menentukan
EXPORT_SYMBOLS_GPL()
untuk modul vendor, tetapi tidak bisa dikirimkan ke hulu karena tidak ada modul dalam {i>in-tree<i} yang memakai simbol. Untuk menangani {i>patch<i} ini, berikan detail tentang mengapa modul Anda tidak dapat dikirimkan ke hulu dan alternatif yang Anda pertimbangkan sebelum membuat permintaan.{i>Patch<i} tidak cukup umum untuk upstream dan tidak ada waktu untuk memfaktorkan ulang sebelum produk dirilis. Untuk menangani patch ini, sediakan perkiraan waktu saat patch yang telah difaktorkan ulang dikirimkan ke upstream ( patch tidak akan diterima di ACK tanpa rencana untuk mengirimkan patch upstream untuk ditinjau).
Patch tidak dapat diterima oleh upstream karena... <masukkan alasan di sini>. Untuk menangani {i>patch<i} ini, hubungi tim {i>kernel<i} Android dan bekerja sama dengan kami untuk menentukan opsi untuk memfaktorkan ulang patch sehingga dapat dikirimkan untuk ditinjau dan diterima di upstream.
Masih ada banyak kemungkinan justifikasi. Saat mengirimkan bug atau patch, sertakan justifikasi yang valid dan tunggu beberapa iterasi dan diskusi. Kami menyadari bahwa ACK membawa beberapa {i>patch<i}, terutama pada tahap awal GKI di saat semua orang belajar bagaimana bekerja di hulu tetapi tidak dapat jadwal produk untuk melakukannya. Persyaratan upstreaming akan menjadi lebih ketat dari waktu ke waktu.
Persyaratan patch
Patch harus sesuai dengan standar pengkodean {i>kernel<i} Linux yang dijelaskan dalam
Hierarki sumber Linux,
apakah mereka dikirim ke upstream
atau ke ACK. scripts/checkpatch.pl
{i>script<i} dijalankan sebagai bagian dari pengujian
prapengiriman Gerrit, jadi jalankan terlebih dahulu untuk
lulus. Untuk menjalankan skrip checkpatch dengan konfigurasi yang sama dengan
pra-pengiriman pengujian, gunakan //build/kernel/static_analysis:checkpatch_presubmit
.
Untuk mengetahui detailnya, lihat
build/kernel/kleaf/docs/checkpatch.md.
Patch ACK
{i>Patch<i} yang dikirimkan ke ACK harus sesuai dengan
standar pengkodean {i>kernel<i} Linux dan
panduan kontribusi.
Anda harus menyertakan Change-Id
dalam pesan commit; jika Anda mengirimkan {i>patch<i} ke beberapa cabang (untuk
misalnya, android-mainline
dan android12-5.4
), Anda harus menggunakan
Change-Id
untuk semua instance patch.
Kirim patch ke LKML terlebih dahulu untuk peninjauan upstream. Jika patch:
- Diterima di upstream, kode ini digabungkan secara otomatis ke
android-mainline
. - Tidak diterima upstream, kirimkan ke
android-mainline
dengan merujuk ke kiriman upstream atau penjelasan mengapa hal itu tidak dikirimkan ke LKML.
Setelah diterima di upstream atau di android-mainline
, patch dapat berupa
di-backport ke ACK berbasis LTS yang sesuai (seperti android12-5.4
dan
android11-5.4
untuk patch yang memperbaiki kode khusus Android). Mengirimkan ke
android-mainline
memungkinkan pengujian dengan kandidat rilis upstream baru dan
menjamin bahwa patch berada di ACK berbasis LTS berikutnya. Pengecualian mencakup kasus
dengan patch upstream di-backport ke android12-5.4
(karena patch
mungkin sudah ada di android-mainline
).
Patch upstream
Seperti yang ditentukan dalam kontribusi pedoman, Patch upstream yang ditujukan untuk kernel ACK termasuk dalam grup berikut (tercantum sesuai urutan kemungkinan untuk diterima).
UPSTREAM:
- Patch yang dipilih dari 'android-mainline` kemungkinan besar diterima ke dalam ACK jika ada kasus penggunaan yang wajar.BACKPORT:
- Patch dari upstream yang tidak dipilih secara rapi dan memerlukan modifikasi juga mungkin diterima jika ada penggunaan yang wajar ini masalahnya atau bukan.FROMGIT:
- Patch yang diambil dari cabang pengelola sedang disiapkan untuk mengirimkan ke alur utama Linux mungkin diterima jika ada perintah pengiriman untuk memenuhi tenggat waktu itu. Hal ini harus dibenarkan, baik untuk konten maupun jadwal.FROMLIST:
- Patch yang telah dikirim ke LKML, tetapi belum dikirim diterima di cabang pemelihara namun mungkin tidak akan diterima, kecuali justifikasinya cukup menarik sehingga {i>patch<i} itu akan diterima apakah ia mendarat di hulu Linux atau tidak (kami berasumsi bahwa ia tidak akan melakukannya). Ada harus merupakan masalah yang terkait dengan patchFROMLIST
untuk memfasilitasi diskusi dengan tim kernel Android.
Patch khusus Android
Jika tidak dapat menempatkan perubahan yang diperlukan ke upstream, Anda dapat mencoba mengirimkannya
{i>patch<i} eksternal ke ACK secara langsung. Pengiriman patch di luar cakupan memerlukan
Anda menimbulkan masalah di bagian IT, yang mengutip patch dan alasannya
patch tidak dapat dikirim ke upstream (lihat daftar sebelumnya untuk mengetahui contohnya).
Namun, ada beberapa kasus saat kode tidak dapat dikirim ke upstream. Ini
kasus tercakup sebagai berikut dan harus mengikuti kontribusi
panduan
untuk patch khusus Android dan diberi tag dengan awalan ANDROID:
pada
subjek.
Perubahan pada gki_defconfig
Semua perubahan CONFIG
pada gki_defconfig
harus diterapkan ke arm64 dan
Versi x86 kecuali jika CONFIG
bersifat khusus arsitektur. Untuk meminta perubahan
ke setelan CONFIG
, ajukan masalah di bagian IT untuk membahas perubahan tersebut. Apa saja
Perubahan CONFIG
yang memengaruhi Kernel Module Interface (KMI) setelah
yang dibekukan akan ditolak. Jika partner meminta permintaan yang bertentangan
pengaturan untuk satu konfigurasi, kita menyelesaikan
konflik melalui diskusi tentang
{i>bugs<i} yang terkait.
Kode yang tidak ada upstream
Modifikasi pada kode yang sudah khusus Android tidak dapat dikirim ke upstream. Misalnya, meskipun driver binder dipertahankan di upstream, modifikasi ke fitur pewarisan prioritas dari driver binder tidak dapat dikirim ke upstream karena bersifat khusus Android. Jelaskan bug Anda dan tambahkan patch terkait penyebab kode tidak dapat dikirim ke upstream. Jika memungkinkan, bagi {i>patch<i} menjadi beberapa bagian yang dapat dikirimkan bagian upstream dan khusus Android yang tidak dapat dikirim upstream untuk meminimalkan jumlah kode {i>out-of-tree<i} yang dipertahankan dalam ACK.
Perubahan lain pada kategori ini adalah pembaruan pada file representasi KMI, KMI
daftar simbol, gki_defconfig
, skrip atau konfigurasi build, atau skrip lainnya
yang tidak ada di upstream.
Modul di luar hierarki
Linux upstream secara aktif tidak menyarankan dukungan untuk membangun modul di luar pohon. Ini adalah posisi yang wajar mengingat bahwa pemelihara Linux tidak memberikan jaminan tentang kompatibilitas sumber dalam {i>kernel<i} atau biner dan tidak ingin mendukung kode yang tidak ada di pohon. Namun, GKI memang memberikan jaminan ABI untuk vendor, memastikan bahwa antarmuka KMI stabil untuk masa aktif {i>kernel<i}. Oleh karena itu, ada kelas perubahan untuk mendukung vendor modul yang dapat diterima untuk ACK tetapi tidak dapat diterima untuk upstream.
Misalnya, perhatikan patch yang menambahkan makro EXPORT_SYMBOL_GPL()
dengan
modul yang menggunakan ekspor tidak ada di hierarki sumber. Sementara Anda harus mencoba
untuk meminta upstream EXPORT_SYMBOL_GPL()
dan menyediakan modul yang menggunakan
yang baru diekspor, jika ada
pembenaran yang valid mengapa modul
tidak dikirimkan ke upstream, Anda dapat mengirimkan {i>patch<i} ke ACK. Anda
perlu menyertakan justifikasi mengapa modul tidak dapat di-upstream di
masalah performa. (Jangan meminta varian non-GPL, EXPORT_SYMBOL()
.)
Konfigurasi tersembunyi
Beberapa modul dalam hierarki otomatis memilih konfigurasi tersembunyi yang tidak dapat ditentukan
di gki_defconfig
. Misalnya, CONFIG_SND_SOC_TOPOLOGY
dipilih
secara otomatis saat CONFIG_SND_SOC_SOF=y
dikonfigurasi. Untuk mengakomodasi
pembangunan modul {i>out-of-tree<i}, GKI menyertakan
mekanisme untuk mengaktifkan konfigurasi tersembunyi.
Untuk mengaktifkan konfigurasi tersembunyi, tambahkan pernyataan select
di init/Kconfig.gki
agar
dipilih secara otomatis berdasarkan
konfigurasi kernel CONFIG_GKI_HACKS_TO_FIX
,
yang diaktifkan di gki_defconfig
. Gunakan mekanisme ini hanya untuk konfigurasi tersembunyi;
jika konfigurasi tidak disembunyikan, konfigurasi juga harus ditentukan di gki_defconfig
secara eksplisit atau sebagai dependensi.
Gubernur yang dapat dimuat
Untuk framework kernel (seperti cpufreq
) yang mendukung gubernur yang dapat dimuat, Anda
dapat mengganti gubernur default (seperti gubernur schedutil
cpufreq
. Sebagai
framework (seperti framework termal) yang tidak mendukung gubernur yang dapat dimuat
atau {i>driver<i} tetapi masih memerlukan implementasi
khusus vendor, buat masalah
di bagian IT dan berkonsultasi dengan tim kernel Android.
Kami akan bekerja sama dengan Anda dan pengelola upstream untuk menambahkan dukungan yang diperlukan.
Hook vendor
Di rilis sebelumnya, Anda dapat menambahkan modifikasi khusus vendor langsung ke {i>kernel<i} inti. Ini tidak mungkin dilakukan dengan GKI 2.0 karena kode khusus produk harus diimplementasikan dalam modul dan tidak akan diterima di kernel inti upstream atau di ACK. Untuk mengaktifkan fitur bernilai tambah yang diandalkan partner dengan dampak minimal pada kode kernel inti, GKI menerima {i>hook<i} vendor yang memungkinkan modul untuk dipanggil dari kode kernel inti. Selain itu, struktur data utama dapat dilengkapi dengan kolom data vendor yang tersedia untuk menyimpan data khusus vendor yang akan diterapkan fitur-fitur ini.
Hook vendor tersedia dalam dua varian (normal dan dibatasi) yang didasarkan pada
titik pelacakan (bukan peristiwa pelacakan) yang dapat dipasang oleh modul vendor. Misalnya,
daripada menambahkan fungsi sched_exit()
baru untuk melakukan pencatatan pada tugas
keluar, vendor dapat menambahkan hook di do_exit()
yang dapat dipasang oleh modul vendor
untuk diproses. Contoh implementasi mencakup hook vendor berikut.
- Hook vendor normal menggunakan
DECLARE_HOOK()
untuk membuat fungsi tracepoint dengan namatrace_name
di mananame
adalah ID unik untuk rekaman aktivitas. Berdasarkan konvensi, nama hook vendor normal dimulai denganandroid_vh
, jadi nama untuk hooksched_exit()
adalahandroid_vh_sched_exit
. - Hook vendor yang dibatasi diperlukan untuk kasus seperti hook penjadwal di mana
fungsi yang terpasang harus dipanggil
meskipun CPU sedang {i>offline<i} atau membutuhkan
konteks nonatomik. Hook vendor yang dibatasi tidak dapat dilepas, sehingga modul
yang menempel pada hook terbatas
tidak pernah bisa melepas muatan. Dibatasi
nama hook vendor diawali dengan
android_rvh
.
Untuk menambahkan hook vendor, ajukan masalah di IT dan kirimkan patch (seperti pada umumnya Pada patch khusus Android, masalah harus ada dan Anda harus menyediakan justifikasi). Dukungan untuk {i>hook<i} vendor hanya ada di ACK, jadi jangan kirimkan {i>patch<i} ke Linux upstream.
Menambahkan kolom vendor ke struktur
Anda dapat mengaitkan data vendor dengan struktur data kunci dengan menambahkan
Kolom android_vendor_data
menggunakan makro ANDROID_VENDOR_DATA()
. Sebagai
misalnya, untuk mendukung fitur bernilai tambah, tambahkan kolom ke struktur seperti yang ditunjukkan
dalam contoh kode berikut.
Untuk menghindari potensi konflik antara kolom yang diperlukan oleh vendor dan kolom
diperlukan oleh OEM, OEM tidak boleh menggunakan kolom yang dideklarasikan menggunakan
Makro ANDROID_VENDOR_DATA()
. Sebagai gantinya, OEM harus menggunakan ANDROID_OEM_DATA()
untuk mendeklarasikan kolom 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 */
}
Menentukan hook vendor
Menambahkan {i>hook<i} vendor ke kode {i>kernel<i} sebagai {i>tracepoint<i} dengan mendeklarasikannya menggunakan
DECLARE_HOOK()
atau DECLARE_RESTRICTED_HOOK()
, lalu menambahkannya ke kode sebagai
sebuah {i>tracepoint<i}. Misalnya, untuk menambahkan trace_android_vh_sched_exit()
ke
fungsi kernel do_exit()
yang ada:
#include <trace/hooks/exit.h>
void do_exit(long code)
{
struct task_struct *tsk = current;
...
trace_android_vh_sched_exit(tsk);
...
}
Fungsi trace_android_vh_sched_exit()
awalnya hanya memeriksa apakah ada
terlampir. Namun, jika modul vendor mendaftarkan
pengendali menggunakan
register_trace_android_vh_sched_exit()
, fungsi yang terdaftar akan dipanggil. Tujuan
harus mengetahui konteks terkait kunci yang ditahan, status RCS, dan
faktor lain. Hook harus didefinisikan dalam file header di
Direktori include/trace/hooks
.
Misalnya, kode berikut memberikan kemungkinan deklarasi untuk
trace_android_vh_sched_exit()
dalam file 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>
Untuk membuat instance antarmuka yang diperlukan bagi hook vendor, tambahkan file header
dengan deklarasi hook ke drivers/android/vendor_hooks.c
dan ekspor
simbol. Misalnya, kode berikut melengkapi deklarasi
Hook 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);
CATATAN: Struktur data yang digunakan dalam deklarasi hook harus
sepenuhnya ditentukan untuk menjamin stabilitas ABI. Jika tidak, maka tidak aman untuk
menghapus referensi pointer buram atau menggunakan struct dalam konteks berukuran tertentu. Termasuk
yang memberikan definisi lengkap dari struktur data tersebut harus masuk ke dalam
Bagian #ifndef __GENKSYMS__
dari drivers/android/vendor_hooks.c
. {i>Header<i}
file dalam include/trace/hooks
tidak boleh menyertakan file header kernel dengan
definisi tipe untuk menghindari perubahan CRC yang merusak KMI. Maju
mendeklarasikan jenis.
Pasang ke hook vendor
Untuk menggunakan hook vendor, modul vendor harus mendaftarkan pengendali untuk hook tersebut
(biasanya dilakukan selama inisialisasi modul). Misalnya, kode berikut
menunjukkan pengendali foo.ko
modul untuk 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);
...
}
Menggunakan hook vendor dari file header
Untuk menggunakan hook vendor dari file header, Anda mungkin perlu memperbarui hook vendor
file header untuk membatalkan definisi TRACE_INCLUDE_PATH
guna menghindari error build yang menunjukkan
file header titik pelacakan tidak dapat ditemukan. Misalnya,
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.
Untuk memperbaiki jenis error build ini, terapkan perbaikan yang setara ke hook vendor {i>header <i}yang Anda sertakan. Untuk informasi tambahan, lihat 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
Mendefinisikan UNDEF_TRACE_INCLUDE_PATH
akan memberi tahu include/trace/define_trace.h
untuk
tidak menentukan TRACE_INCLUDE_PATH
setelah membuat titik rekaman aktivitas.
Fitur kernel inti
Jika tidak ada teknik sebelumnya yang memungkinkan Anda untuk mengimplementasikan fitur dari modul, maka Anda harus menambahkan fitur tersebut sebagai modifikasi khusus Android {i>kernel<i}. Sampaikan masalah di issue tracker (IT) untuk memulai percakapan.
User application programming interface (UAPI)
- File header UAPI. Perubahan pada File header UAPI harus terjadi upstream kecuali jika perubahan tersebut terjadi pada antarmuka khusus Android. Menggunakan file header khusus vendor untuk menentukan antarmuka antara modul vendor dan kode userspace vendor.
- node sysfs. Jangan tambahkan node sysfs baru ke {i>kernel<i} GKI (penambahan seperti hanya valid di modul vendor). {i>sysfs<i} yang digunakan oleh SoC- dan library agnostik perangkat dan kode Java yang menyusun framework Android hanya dapat diubah dengan cara yang kompatibel dan harus diubah upstream jika mereka bukan {i>node<i} sysfs khusus Android. Anda dapat membuat {i>node sysfs khusus vendor<i} yang akan digunakan oleh vendor userspace. Secara {i>default<i}, akses ke {i>node<i} sysfs oleh userspace ditolak menggunakan SELinux. Terserah untuk menambahkan label SELinux yang sesuai untuk mengizinkan akses oleh vendor perangkat lunak.
- Node DebugFS. Modul vendor dapat menentukan node di
debugfs
untuk khusus proses debug (karenadebugfs
tidak dipasang selama operasi normal perangkat).