GKI için çekirdek kodu geliştirme

Genel Çekirdek Görüntüsü (GKI), yayın öncesi Linux çekirdeğiyle yakından uyum sağlayarak çekirdek parçalanmasını azaltır. Ancak bazı yamaların yayın öncesi kabul edilememesinin geçerli nedenleri vardır ve uyulması gereken ürün programları vardır. Bu nedenle, bazı yamalar GKI'nın derlendiği Android Ortak Çekirdeği (ACK) kaynaklarında korunur.

Geliştiriciler, kod değişikliklerini yukarı akışta Linux Kernel Postalama'yı kullanarak göndermelidir. LKML'yi ilk seçenek olarak listeleyin ve kod değişikliklerini ACK'ye gönderin android-mainline, yalnızca yukarı akışın iyi olmamasının güçlü bir nedeni olduğunda dal uygulanabilir. Geçerli nedenler ve bunların nasıl ele alınacağına dair örnekler aşağıda listelenmiştir.

  • Yama LKML'ye gönderildi ancak ürün sürümü için zamanında kabul edilmedi. Bu yamayı işlemek için:

    • Yama'nın LKML'ye gönderildiğine ve Yama için yorum alındığına dair kanıt veya Yama'nın yayın öncesi gönderilme zamanının tahmini bilgisini sağlayın.
    • Yamayı ACK'ye uygulamak ve onaylanmasını sağlamak için nasıl bir yol izleyeceğinize karar verin Sonra bu videoyu ACK'den çıkarırsınız. ACK ile birleştirilir.
  • Yama, tedarikçi modülü için EXPORT_SYMBOLS_GPL() öğesini tanımlıyor ancak çalıştırılamadı ağaç içi modüller içermediğinden yukarı akışla simgesini tıklayın. Bu yamayı işlemek için modülünüzün neden yayın öncesi gönderilemediğine ve bu isteği yapmadan önce değerlendirdiğiniz alternatiflere dair ayrıntılı bilgi verin.

  • Yama, yayın öncesi için yeterince genel değildir ve ürün yayınlanmadan önce yeniden yapılandırmaya zaman yoktur. Bu yamayı işlemek için, yeniden yapılandırılmış bir yamanın yayına gönderileceği tahmini zamanı belirtin (yeniden yapılandırılmış bir yamanın inceleme için yayına gönderilme planı olmadan ACK'de kabul edilmez).

  • Yama, yayın öncesi tarafından kabul edilemiyor çünkü... <insert reason here>. Bu yamayı işlemek için Android çekirdek ekibiyle iletişime geçin ve incelemeye gönderilip yayın öncesi kabul edilebilmesi için yamayı yeniden yapılandırmaya yönelik seçenekler konusunda bizimle birlikte çalışın.

Bunun gibi birçok olası gerekçe vardır. Hatanızı veya düzeltmenizi gönderirken geçerli bir gerekçe ekleyin ve bazı iterasyonlar ve tartışmalar bekleyin. ACK'nin, özellikle çocukların herkes yukarı akış üzerine çalışmayı öğrenirken bir yandan da gevşeyip ürün programlarını nasıl kullanacağınızı öğrenin. Lansman gereksinimlerinin gün geçtikçe artması bekleniyor zamanla sertleşir.

Yama şartları

Yamalar, Linux kaynak ağacı, gönderilip gönderilmediğine bakılır. scripts/checkpatch.pl komut dosyası, Gerrit ön gönderme testinin bir parçası olarak çalıştırıldığı için emin olun. checkpatch komut dosyasını, göndermeden önce testle aynı yapılandırmayla çalıştırmak için //build/kernel/static_analysis:checkpatch_presubmit kullanın. Ayrıntılar için build/kernel/kleaf/docs/checkpatch.md dosyasını inceleyin.

ACK yamaları

ACK'ya gönderilen yamalar Linux çekirdek kodlama standartlarına uygun olmalıdır. katkıda bulunma kurallarına uymalıdır. Change-Id eklemeniz gerekir etiket, yamayı birden fazla dala gönderirseniz ( örneğin, android-mainline ve android12-5.4) aynı değeri kullanmanız gerekir. Yamanın tüm örnekleri için Change-Id.

Öncelikle yukarı akış incelemesi için LKML'ye gönderin. Yama:

  • Yukarı akışta kabul edilen bu veri, android-mainline ile otomatik olarak birleştirilir.
  • Yukarı akış kabul edilmedi, android-mainline için bir bir yayın öncesi gönderime veya bunun neden olmadığına dair bir açıklamaya LKML'ye gönderildi.

Bir yama, yayın öncesi veya android-mainline'te kabul edildikten sonra, uygun LTS tabanlı ACK'ye (ör. Android'e özgü kodu düzelten yamalar için android12-5.4 ve android11-5.4) geri aktarılabilir. android-mainline'e gönderim, yeni yayın adayı üst akış sürümleriyle test yapmanızı sağlar ve yamanın bir sonraki LTS tabanlı ACK'de yer alacağını garanti eder. İstisnalar arasında, yayın öncesi bir yamanın android12-5.4'e geri bağlandığı durumlar (yama muhtemelen android-mainline'te zaten bulunduğu için) yer alır.

Yukarı akış yamaları

Katkıda belirtildiği gibi yönergeler ACK çekirdeklerine yönelik yukarı akış yamaları aşağıdaki gruplara ayrılır (listelenen öncelik sırasına göre ).

  • UPSTREAM: - "android-mainline"dan alınan yamalar büyük olasılıkla kabul edilir.
  • BACKPORT: - Yukarı akıştan gelen, düzgün şekilde çalışmayan ve değişikliklerinin kabul edilmesi için makul bir kullanım olması dava açın.
  • FROMGIT:: Linux ana hatlarına gönderilmek üzere hazırlanırken bir bakım dalından özenle seçilen yamalar, yaklaşan bir son tarih varsa kabul edilebilir. Bunların hem içerik hem de program açısından gerekçelendirilmesi gerekir.
  • FROMLIST: - LKML'ye gönderilmiş ancak henüz bir bakım dalına kabul edilmemiş yamalar, gerekçesi üst Linux'a eklenip eklenmeyeceğine bakılmaksızın yamanın kabul edileceği kadar ikna edici olmadığı sürece kabul edilmeyebilir (bu durumun gerçekleşmeyeceğini varsayıyoruz). Orada Tartışmayı kolaylaştırmak için FROMLIST yamalarıyla ilişkili bir sorun olmalıdır daha fazla bilgi edineceksiniz.

Android'e özel yamalar

Gerekli değişiklikleri ana akışa ekleyemiyorsanız ağaç dışı yamaları doğrudan ACK'ye göndermeyi deneyebilirsiniz. Ağaç dışı yama göndermek için şunlar gerekir: BT departmanında bunun neden olduğu sorunu ve gerekçesini yama yayın yolunda gönderilemez (örnekler için önceki listeye bakın). Ancak kodun yukarı akışla gönderilemediği birkaç durum vardır. Bu destek kayıtları aşağıdaki gibidir ve katkıya uygun olmalıdır: kuralları özel yamalar ve ANDROID: önekiyle konu.

gki_defconfig değişiklikleri

gki_defconfig için yapılan tüm CONFIG değişiklikleri hem kol64 hem de kol 64'e uygulanmalıdır CONFIG, mimariye özgü değilse x86 sürümleri. CONFIG ayarlarında değişiklik isteğinde bulunmak için BT bölümünde değişiklik hakkında görüşmek üzere bir sorun oluşturun. Herhangi biri Çekirdek Modülü Arabirimi'ni (KMI) etkileyen CONFIG değişikliği dondurulmuş reddedildi. İş ortaklarının, çakışan yapılandırmanın farklı yolları varsa, çakışmaları şurada tartışarak çözeriz: gözden geçirin.

Yukarı akışta bulunmayan kod

Android'e özgü olan kod değişiklikleri, yukarı akışla gönderilemez. Örneğin, bağlayıcı sürücüsü yukarı akışla korunuyor olsa da, bağlayıcı sürücünün öncelikli devralma özelliklerine Android'e özgüdür. Hatanızda açık olun ve kodu yukarı akış için gönderilemez. Mümkünse ACK'de tutulan ağa bağlı olmayan kod miktarını en aza indirmek için yamaları, yayına gönderilebilecek parçalara ve yayına gönderilemeyen Android'e özgü parçalara bölün.

Bu kategoride yer alan diğer değişiklikler, KMI temsil dosyalarında, KMI'da yapılan güncellemelerdir. simge listeleri, gki_defconfig, derleme komut dosyaları veya yapılandırma ya da diğer komut dosyaları dönüşüm hunisinin alt kısmında yer alır.

Ağaç dışı modüller

Upstream Linux, ağaç dışı modüllerin oluşturulmasına yönelik desteği aktif olarak caydırıyor. Linux bakım ekiplerinin çekirdek içi kaynak veya ikili uyumluluk hakkında garanti vermemesi ve ağaçta bulunmayan kodu desteklemek istememesi nedeniyle bu makul bir tutumdur. Ancak GKI, tedarikçi modülleri için ABI garantileri verir. Bu sayede KMI arayüzlerinin, bir çekirdeğin desteklenen ömrü boyunca kararlı olmasını sağlar. Bu nedenle, ACK için kabul edilebilir ancak yayın için kabul edilemez tedarikçi modüllerini desteklemek üzere bir değişiklik sınıfı vardır.

Örneğin, EXPORT_SYMBOL_GPL() dışa aktarma işlemini kullanan modüller kaynak ağacında değildir. EXPORT_SYMBOL_GPL()'ü yayın öncesi isteğinde bulunmaya ve yeni dışa aktarılan simgeyi kullanan bir modül sağlamaya çalışmanız gerekir. Ancak modülün yayın öncesi gönderilmemesinin geçerli bir nedeni varsa bunun yerine yamayı ACK'ye gönderebilirsiniz. Modülün neden yayına alınamadığını sorununuza eklemeniz gerekir. (GPL olmayan EXPORT_SYMBOL() varyantını istemeyin.)

Gizli yapılandırmalar

Bazı ağaç içi modüller, belirtilemeyen gizli yapılandırmaları otomatik olarak seçer gki_defconfig içinde. Örneğin, CONFIG_SND_SOC_TOPOLOGY seçildi. CONFIG_SND_SOC_SOF=y yapılandırıldığında otomatik olarak oluşturulur. Uymak için GKI, gizli yapılandırmaları etkinleştiren bir mekanizmaya sahiptir.

Gizli bir yapılandırmayı etkinleştirmek için init/Kconfig.gki bölümüne bir select ifadesi ekleyerek yapılandırmanın CONFIG_GKI_HACKS_TO_FIX çekirdek yapılandırmasına göre otomatik olarak seçilir. gki_defconfig ürününde etkindir. Bu mekanizmayı yalnızca gizli yapılandırmalar için kullanın. Yapılandırma gizli değilse gki_defconfig içinde açıkça veya bağımlılık olarak belirtilmelidir.

Yüklenebilir denetleyiciler

Yüklenebilir yöneticileri destekleyen çekirdek çerçeveleri (ör. cpufreq) için varsayılan yöneticiyi (cpufreq schedutil yöneticisi gibi) geçersiz kılabilir. Yüklenebilir denetleyicileri veya sürücüleri desteklemeyen ancak yine de tedarikçiye özel bir uygulama gerektiren çerçeveler (ör. termal çerçeve) için BT'de bir sorun oluşturun ve Android çekirdek ekibine danışın.

Gerekli desteği eklemek için sizinle ve üst yöndeki koruyucularla birlikte çalışacağız.

Tedarikçi firma kancaları

Önceki sürümlerde tedarikçiye özel değişiklikleri doğrudan çekirdeğine kadar uzanır. Ürüne özel kodun zorunlu olması gerektiğinden bu işlem GKI 2.0'da mümkün değildir. veya daha fazla satış yapılmasını sağlamak için değil, modüller halinde ACK olarak. GKI, iş ortaklarının temel çekirdek koduna en az düzeyde etki edecek şekilde yararlandığı katma değerli özellikleri etkinleştirmek için modüllerin temel çekirdek kodundan çağrılmasına olanak tanıyan tedarikçi bağlantı noktalarını kabul eder. Ayrıca, bu özellikleri uygulamak için tedarikçiye özgü verileri depolamak üzere kullanılabilen tedarikçi veri alanlarıyla temel veri yapıları doldurulabilir.

Tedarikçi firma kancaları şu ölçütlere göre iki varyantta (normal ve kısıtlı) sunulur: tedarikçi modüllerinin eklenebileceği izleme noktaları (izleme etkinlikleri değil) Örneğin, tedarikçi firmalar görev çıkışında muhasebe yapmak için yeni bir sched_exit() işlevi eklemek yerine do_exit()'a bir kanca ekleyerek tedarikçi firma modülünün işleme ekleyebilmesini sağlayabilir. Örnek uygulama aşağıdaki tedarikçi bağlantı noktalarını içerir.

  • Normal satıcı kancaları, izleme noktası işlevi oluşturmak için DECLARE_HOOK() kullanır şu adla: trace_name name, izler. Normal tedarikçi firma kanca adları android_vh ile başlar. Bu nedenle, sched_exit() kancasının adı android_vh_sched_exit olur.
  • Kısıtlanmış tedarikçi kancaları, ekli işlev, CPU çevrimdışı olsa veya çevrimdışı olsa bile çağrılmalıdır. atom olmayan bir bağlama sahip olmak. Kısıtlanmış tedarikçi kancaları ayrılamaz. Bu nedenle, kısıtlanmış bir kancaya bağlanan modüller hiçbir zaman kaldırılamaz. Kısıtlı satıcı kancası adları android_rvh ile başlar.

Tedarikçi firma kancası eklemek için BT departmanında bir sorun oluşturun ve yama gönderin (tüm Android'e özel yamalar; bir sorun olması ve gerekçe). Satıcı kancaları yalnızca ACK'de desteklenir. Bu nedenle, bu yamaları Linux'a göndermeyin.

Yapılara tedarikçi alanları ekleme

Tedarikçi firma verilerini anahtar veri yapılarıyla ilişkilendirebilirsiniz. Bunun için ANDROID_VENDOR_DATA() makrolarını kullanan android_vendor_data alanları. Örneğin, Örneğin, katma değerli özellikleri desteklemek için yapılara aşağıda gösterildiği gibi alanlar ekleyin aşağıda verilen kod örneğine bakalım.

Tedarikçi firmaların ihtiyaç duyduğu alanlar ile alanlar arasında olası çakışmaları önlemek için OEM'lerin, hiçbir zaman ANDROID_VENDOR_DATA() makro. Bunun yerine OEM'ler, android_oem_data alanlarını bildirmek için ANDROID_OEM_DATA() kullanmalıdır.

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

Tedarikçi firma kancalarını tanımlama

Tedarikçi firma kancalarını çekirdek koduna izleme noktaları olarak eklemek için bunları DECLARE_HOOK() veya DECLARE_RESTRICTED_HOOK() ve ardından bunları koda şu şekilde ekliyor: izin verir. Örneğin, mevcut do_exit() çekirdek işlevine trace_android_vh_sched_exit() eklemek için:

#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() işlevi, başlangıçta yalnızca kontrol ekli. Ancak bir tedarikçi modülü, register_trace_android_vh_sched_exit() ise kayıtlı işlev çağrılır. İlgili içeriği oluşturmak için kullanılan işleyici, tutulan kilitler, RCS durumu ve diğer faktörlerle ilgilidir. Kanca, include/trace/hooks dizini.

Örneğin, aşağıdaki kod, include/trace/hooks/exit.h dosyasındaki 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>

Tedarikçi kancası için gereken arayüzleri örneklemek üzere, kanca beyanını içeren başlık dosyasını drivers/android/vendor_hooks.c'e ekleyin ve simgeleri dışa aktarın. Örneğin, aşağıdaki kod android_vh_sched_exit() kancasının tanımını tamamlar.

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

NOT: ABI kararlılığını sağlamak için kanca beyanında kullanılan veri yapılarının tam olarak tanımlanması gerekir. Aksi takdirde opak işaretçileri kaldırın veya boyutlu bağlamlarda struct'ı kullanın. Dahil etme Bu örnek, veri yapılarının tam tanımını verir ve drivers/android/vendor_hooks.c dokümanının #ifndef __GENKSYMS__ bölümü. Üst bilgi include/trace/hooks içindeki dosyalar, KMI'yi bozan CRC değişikliklerini önlemek için tür tanımlarını kullanın. Bunun yerine yönlendir açıklayacağım.

Tedarikçi kancalarına ekleme

Tedarikçi firma kancalarını kullanmak istiyorsanız tedarikçi modülünün kanca için bir işleyici kaydetmesi gerekir (genellikle modül başlatma sırasında yapılır). Örneğin, aşağıdaki kod trace_android_vh_sched_exit() için foo.ko modül işleyicisini gösterir.

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

Üstbilgi dosyalarındaki tedarikçi bağlantılarını kullanma

Başlık dosyalarından tedarikçi kancaları kullanmak için, bir izleme noktası başlık dosyası bulunamadığını belirten derleme hatalarını önlemek amacıyla tedarikçi kanca başlık dosyasını TRACE_INCLUDE_PATH tanımını kaldıracak şekilde güncellemeniz gerekebilir. Örneğin,

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.

Bu tür bir yapı hatasını düzeltmek için tedarikçi kancasına eşdeğer düzeltmeyi uygulayın. başlık dosyasına göz atabilirsiniz. Daha fazla bilgi için https://r.android.com/3066703 adresine bakın.

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 tanımlandığında include/trace/define_trace.h şunları sağlar: İz noktalarını oluşturduktan sonra TRACE_INCLUDE_PATH tanımlamasını kaldırın.

Temel çekirdek özellikleri

Önceki tekniklerden hiçbiri bir modüldeki özelliği uygulamanıza olanak tanımıyorsa özelliği, çekirdek çekirdeğe Android'e özgü bir değişiklik olarak eklemeniz gerekir. Görüşmeyi başlatmak için Sorun İzleyici'de (BT) bir sorun oluşturun.

Kullanıcı uygulaması programlama arayüzü (UAPI)

  • UAPI üst dosyaları. Android'e özgü arayüzlerde değişiklik yapılmadığı sürece UAPI üstbilgi dosyalarında yapılan değişiklikler yayın öncesi aşamada yapılmalıdır. Tedarikçi modülleri ile tedarikçi kullanıcı alanı kodu arasındaki arayüzleri tanımlamak için tedarikçiye özgü üstbilgi dosyalarını kullanın.
  • sysfs düğümleri. GKI çekirdeğine yeni sysfs düğümü eklemeyin (bu tür eklemeler yalnızca tedarikçi modüllerinde geçerlidir). SoC ve cihaza özgü olmayan kitaplıklar ve Android çerçevesini oluşturan Java kodu tarafından kullanılan sysfs düğümleri yalnızca uyumlu yöntemlerle değiştirilebilir ve Android'e özgü sysfs düğümleri değilse yayın öncesi değiştirilmelidir. Şunları oluşturabilirsiniz: Tedarikçi firma kullanıcı alanı tarafından kullanılacak satıcıya özgü sysfs düğümleri. Varsayılan olarak SELinux kullanılırken sysfs düğümlerine kullanıcı alanı tarafından erişim reddedildi. Yetkili tedarikçi yazılımının erişmesine izin vermek için uygun SELinux etiketlerini eklemek tedarikçiye bağlıdır.
  • DebugFS düğümleri. Tedarikçi modülleri, yalnızca hata ayıklama için debugfs içinde düğümler tanımlayabilir (debugfs, cihazın normal çalışması sırasında monte edilmediğinden).