GKI için Çekirdek Kodu Geliştirin

Genel Çekirdek Görüntüsü (GKI), yukarı akışlı Linux çekirdeğiyle yakından uyum sağlayarak çekirdek parçalanmasını azaltır. Bununla birlikte, bazı yamaların yukarı akışta kabul edilememesinin geçerli nedenleri vardır ve karşılanması gereken ürün programları vardır, bu nedenle bazı yamalar, GKI'nin oluşturulduğu Android Ortak Çekirdek (ACK) kaynaklarında tutulur.

Geliştiriciler, kod değişikliklerini ilk tercih olarak Linux Çekirdek Posta Listesini (LKML) kullanarak yukarı akışa göndermeli ve kod değişikliklerini yalnızca yukarı akışın geçerli olmamasının güçlü bir nedeni olduğunda ACK android-mainline şubesine göndermelidir. Geçerli nedenlerin örnekleri ve bunların nasıl ele alınacağı aşağıda listelenmiştir.

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

    • Yamanın LKML'ye gönderildiğine ve yama için alınan yorumlara veya yamanın yukarı akışa gönderileceği tahmini süreye dair kanıt sağlayın.
    • Yamayı ACK'ya yerleştirmek, yukarı yönde onaylatmak ve ardından son yukarı yönlü sürüm ACK ile birleştirildiğinde yamayı ACK'dan çıkarmak için bir eylem planına karar verin.
  • Yama, bir satıcı modülü için EXPORT_SYMBOLS_GPL() işlevini tanımlar, ancak bu sembolü kullanan hiçbir ağaç içi modül olmadığından yukarı yönde gönderilemedi. Bu yamayı ele almak için modülünüzün neden yukarı yönde gönderilemediğine ve bu isteği yapmadan önce değerlendirdiğiniz alternatiflere ilişkin ayrıntıları sağlayın.

  • Yama yukarı akış için yeterince genel değil ve ürünün piyasaya sürülmesinden önce onu yeniden düzenlemeye zaman yok. Bu yamayı ele almak için, yeniden düzenlenen yamanın yukarı akışa gönderileceği tahmini süreyi belirtin (yeniden düzenlenmiş bir yamayı incelenmek üzere yukarı akışa gönderme planı olmadan yama ACK'da kabul edilmeyecektir).

  • Yama yukarı akış tarafından kabul edilemiyor çünkü... <sebebi buraya ekleyin> . Bu yamayı ele almak için Android çekirdek ekibiyle iletişime geçin ve incelenmek üzere gönderilip yukarı akışta kabul edilebilmesi için yamayı yeniden düzenleme seçenekleri üzerinde bizimle birlikte çalışın.

Daha pek çok potansiyel gerekçe var. Hatanızı veya yamanızı gönderdiğinizde geçerli bir gerekçe ekleyin ve biraz yineleme ve tartışma bekleyin. Herkes yukarı yönde nasıl çalışacağını öğrenirken ancak ürün programlarını bunu yapmak için gevşetemezken, özellikle GKI'nin ilk aşamalarında ACK'nın bazı yamalar taşıyacağının farkındayız. Yukarı akış gereksinimlerinin zaman içinde daha sıkı hale gelmesini bekliyoruz.

Yama gereksinimleri

Yamalar, ister yukarı yönde ister ACK'ye gönderilsin, Linux kaynak ağacında açıklanan Linux çekirdek kodlama standartlarına uygun olmalıdır. scripts/checkpatch.pl betiği, Gerrit ön gönderim testinin bir parçası olarak çalıştırılır, bu nedenle geçtiğinden emin olmak için önceden çalıştırın. Checkpatch komut dosyasını gönderim öncesi 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 adresine bakın.

ACK yamaları

ACK'ya gönderilen yamalar, Linux çekirdek kodlama standartlarına ve katkı yönergelerine uygun olmalıdır. Taahhüt mesajına bir Change-Id etiketi eklemelisiniz; yamayı birden fazla şubeye gönderirseniz (örneğin, android-mainline ve android12-5.4 ), yamanın tüm örnekleri için aynı Change-Id kullanmanız gerekir.

Yukarı yönde inceleme için öncelikle yamaları LKML'ye gönderin. Yama şuysa:

  • Yukarı akışta kabul edilir, otomatik olarak android-mainline ile birleştirilir.
  • Yukarı akış kabul edilmedi, yukarı akış gönderimine referansla veya neden LKML'ye gönderilmediğine dair bir açıklamayla birlikte android-mainline gönderin.

Bir yama yukarı akışta veya android-mainline kabul edildikten sonra, uygun LTS tabanlı ACK'ye (Android'e özgü kodu düzelten yamalar için android12-5.4 ve android11-5.4 gibi) desteklenebilir. android-mainline gönderim, yeni yukarı akış sürüm adaylarıyla test yapılmasını sağlar ve yamanın bir sonraki LTS tabanlı ACK'da olmasını garanti eder. İstisnalar, bir yukarı akış yamasının android12-5.4 desteklendiği durumları içerir (çünkü yamanın zaten android-mainline olması muhtemeldir).

Yukarı akış yamaları

Katkı yönergelerinde belirtildiği gibi, ACK çekirdeklerine yönelik yukarı akış yamaları aşağıdaki gruplara ayrılır (kabul edilme olasılıklarına göre listelenmiştir).

  • UPSTREAM: - 'Android-mainline'dan seçilen yamaların, makul bir kullanım durumu olması durumunda büyük ihtimalle ACK'ye kabul edilmesi muhtemeldir.
  • BACKPORT: - Temiz bir şekilde seçilmeyen ve değişiklik yapılması gereken yukarı akış yamaları da makul bir kullanım durumu varsa muhtemelen kabul edilecektir.
  • FROMGIT: - Linux ana hattına gönderilmek üzere hazırlık aşamasında bir bakımcı şubesinden özenle seçilen yamalar, yaklaşan bir son tarih varsa kabul edilebilir. Bunlar hem içerik hem de program açısından gerekçelendirilmelidir.
  • FROMLIST: - LKML'ye gönderilen ancak henüz bir bakımcı şubesine kabul edilmeyen yamaların, yukarı akış Linux'a düşsün ya da gelmesin yamanın kabul edileceğine dair yeterince ikna edici bir gerekçe olmadığı sürece kabul edilmesi pek olası değildir (varsayalım) olmayacak). Android çekirdek ekibiyle tartışmayı kolaylaştırmak için FROMLIST yamalarıyla ilişkili bir sorun olması gerekir.

Android'e özgü yamalar

Gerekli değişiklikleri yukarı yönde gerçekleştiremezseniz, ağaç dışı yamaları doğrudan ACK'ye göndermeyi deneyebilirsiniz. Ağaç dışı yamaların gönderilmesi, BT'de yamayı belirten ve yamanın neden yukarı yönde gönderilemediğinin gerekçesini belirten bir sorun oluşturmanızı gerektirir (örnekler için önceki listeye bakın). Ancak kodun yukarı yönde gönderilemediği birkaç durum vardır. Bu durumlar aşağıdaki şekilde ele alınmaktadır ve Android'e özgü yamalara yönelik katkı yönergelerine uymalı ve konuda ANDROID: öneki ile etiketlenmelidir.

gki_defconfig'te yapılan değişiklikler

CONFIG mimariye özgü olmadığı sürece, gki_defconfig yapılan tüm CONFIG değişikliklerinin hem arm64 hem de x86 sürümlerine uygulanması gerekir. Bir CONFIG ayarında değişiklik talep etmek için BT'de değişikliği görüşmek üzere bir sorun oluşturun. Dondurulduktan sonra Çekirdek Modül Arayüzünü (KMI) etkileyen herhangi bir CONFIG değişikliği reddedilir. İş ortaklarının tek bir yapılandırma için çakışan ayarlar talep ettiği durumlarda, çakışmaları ilgili hatalar üzerinde tartışarak çözeriz.

Yukarı akışta bulunmayan kod

Zaten Android'e özel olan kodda yapılan değişiklikler yukarı akışa gönderilemez. Örneğin, ciltleyici sürücüsü yukarı yönde korunsa bile, ciltleyici sürücüsünün öncelikli devralma özelliklerinde yapılan değişiklikler Android'e özgü olduğundan yukarı yönde gönderilemez. Hatanızı açık bir şekilde belirtin ve kodun neden yukarı yönde gönderilemediğini düzeltin. Mümkünse, ACK'da tutulan ağaç dışı kod miktarını en aza indirmek için yamaları yukarı yönde gönderilebilecek parçalara ve yukarı yönde gönderilemeyen Android'e özgü parçalara bölün.

Bu kategorideki diğer değişiklikler; KMI gösterim dosyaları, KMI sembol listeleri, gki_defconfig , derleme komut dosyaları veya konfigürasyon veya yukarı akışta bulunmayan diğer komut dosyalarındaki güncellemelerdir.

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ımcılarının çekirdek içi kaynak veya ikili uyumluluk konusunda garanti vermedikleri ve ağaçta olmayan kodları desteklemek istemedikleri göz önüne alındığında, bu makul bir durumdur. Ancak GKI, satıcı modülleri için ABI garantileri vererek KMI arayüzlerinin bir çekirdeğin desteklenen ömrü boyunca kararlı olmasını sağlar . Bu nedenle, satıcı modüllerini desteklemek için ACK için kabul edilebilir ancak yukarı akış için kabul edilemeyen bir dizi değişiklik vardır.

Örneğin, dışa aktarmayı kullanan modüllerin kaynak ağaçta olmadığı EXPORT_SYMBOL_GPL() makrolarını ekleyen bir düzeltme eki düşünün. Yukarı yönde EXPORT_SYMBOL_GPL() isteğinde bulunmayı ve yeni dışa aktarılan sembolü kullanan bir modül sağlamayı denemeniz gerekse de, modülün neden yukarı yönde gönderilmediğine dair geçerli bir gerekçe varsa yamayı bunun yerine ACK'ye gönderebilirsiniz. Soruna modülün neden yukarı akışla aktarılamadığının gerekçesini eklemeniz gerekir. (GPL dışı değişken olan EXPORT_SYMBOL() u talep etmeyin.)

Gizli yapılandırmalar

Bazı ağaç içi modüller, gki_defconfig içinde belirtilmeyen gizli yapılandırmaları otomatik olarak seçer. Örneğin CONFIG_SND_SOC_TOPOLOGY , CONFIG_SND_SOC_SOF=y yapılandırıldığında otomatik olarak seçilir. Ağaç dışı modül oluşturmaya uyum sağlamak için GKI, gizli yapılandırmaları etkinleştiren bir mekanizma içerir.

Gizli bir yapılandırmayı etkinleştirmek için init/Kconfig.gki dosyasına bir select ifadesi ekleyin, böylece gki_defconfig içinde etkinleştirilen CONFIG_GKI_HACKS_TO_FIX çekirdek yapılandırmasına göre otomatik olarak seçilir. Bu mekanizmayı yalnızca gizli yapılandırmalar için kullanın; yapılandırma gizli değilse gki_defconfig açıkça veya bağımlılık olarak belirtilmelidir.

Yüklenebilir valiler

Yüklenebilir düzenleyicileri destekleyen çekirdek çerçeveleri ( cpufreq gibi) için, varsayılan düzenleyiciyi ( cpufreq schedutil düzenleyicisi gibi) geçersiz kılabilirsiniz. Yüklenebilir düzenleyicileri veya sürücüleri desteklemeyen ancak yine de bir denetleyici gerektiren çerçeveler için (termal çerçeve gibi) Satıcıya özel uygulama, BT'de bir sorun oluşturun ve Android çekirdek ekibine danışın.

Gerekli desteği eklemek için sizinle ve üretime yönelik bakım sağlayıcılarla birlikte çalışacağız.

Satıcı kancaları

Geçmiş sürümlerde satıcıya özel değişiklikleri doğrudan çekirdek çekirdeğe ekleyebiliyordunuz. Bu, GKI 2.0'da mümkün değildir çünkü ürüne özel kodun modüllerde uygulanması gerekir ve çekirdek çekirdeklerin yukarı akışında veya ACK'da kabul edilmez. İş ortaklarının güvendiği katma değerli özellikleri çekirdek çekirdek kodu üzerinde minimum etkiyle etkinleştirmek için GKI, modüllerin çekirdek çekirdek kodundan çağrılmasına izin veren satıcı kancalarını kabul eder. Ek olarak, anahtar veri yapıları, bu özelliklerin uygulanması için satıcıya özgü verileri depolamak üzere kullanılabilen satıcı veri alanlarıyla doldurulabilir.

Satıcı kancaları, satıcı modüllerinin eklenebileceği izleme noktalarına (izleme olaylarına değil) dayalı iki çeşitte (normal ve kısıtlı) gelir. Örneğin, görev çıkışında bir muhasebe yapmak için yeni bir sched_exit() işlevi eklemek yerine satıcılar do_exit() e satıcı modülünün işlem için ekleyebileceği bir kanca ekleyebilir. Örnek bir uygulama aşağıdaki satıcı kancalarını içerir.

  • Normal satıcı kancaları, trace_ name adıyla bir izleme noktası işlevi oluşturmak için DECLARE_HOOK() işlevini kullanır; burada name , izlemenin benzersiz tanımlayıcısıdır. Geleneksel olarak, normal satıcı kanca adları android_vh ile başlar, dolayısıyla sched_exit() kancasının adı android_vh_sched_exit olacaktır.
  • CPU çevrimdışı olsa veya atomik olmayan bir bağlam gerektirse bile eklenen işlevin çağrılmasının gerektiği zamanlayıcı kancaları gibi durumlar için sınırlı satıcı kancalarına ihtiyaç vardır. Kısıtlı satıcı kancaları ayrılamaz, dolayısıyla kısıtlı bir kancaya bağlanan modüller hiçbir zaman boşaltılamaz. Kısıtlı satıcı kancası adları android_rvh ile başlar.

Satıcı kancası eklemek için BT'ye bir sorun bildirin ve yamaları gönderin (Android'e özgü tüm yamalarda olduğu gibi, bir sorunun mevcut olması ve gerekçe sunmanız gerekir). Satıcı kancaları desteği yalnızca ACK'dedir, bu nedenle bu yamaları yukarı akışlı Linux'a göndermeyin.

Yapılara satıcı alanları ekleme

ANDROID_VENDOR_DATA() makrolarını kullanarak android_vendor_data alanlarını ekleyerek satıcı verilerini önemli veri yapılarıyla ilişkilendirebilirsiniz. Örneğin, katma değerli özellikleri desteklemek için aşağıdaki kod örneğinde gösterildiği gibi alanları yapılara ekleyin.

Satıcıların ihtiyaç duyduğu alanlarla OEM'lerin ihtiyaç duyduğu alanlar arasındaki olası çatışmaları önlemek için, OEM'ler hiçbir zaman ANDROID_VENDOR_DATA() makroları kullanılarak bildirilen alanları kullanmamalıdır. Bunun yerine, OEM'lerin android_oem_data alanlarını bildirmek için ANDROID_OEM_DATA() kullanması gerekir.

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

Satıcı kancalarını tanımlayın

Satıcı kancalarını DECLARE_HOOK() veya DECLARE_RESTRICTED_HOOK() kullanarak bildirip ardından bunları bir izleme noktası olarak koda ekleyerek çekirdek koduna izleme noktaları olarak ekleyin. Örneğin, trace_android_vh_sched_exit() i mevcut do_exit() çekirdek işlevine 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 bir şeyin eklenip eklenmediğini kontrol eder. Ancak bir satıcı modülü, register_trace_android_vh_sched_exit() işlevini kullanarak bir işleyiciyi kaydederse kayıtlı işlev çağrılır. İşleyici, tutulan kilitler, RCS durumu ve diğer faktörlerle ilgili bağlamdan haberdar olmalıdır. Kanca include/trace/hooks dizinindeki bir başlık dosyasında tanımlanmalıdır.

Örneğin, aşağıdaki kod include/trace/hooks/exit.h dosyasındaki trace_android_vh_sched_exit() için olası bir bildirimi verir.

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

Satıcı kancası için gereken arayüzleri başlatmak için, kanca bildirimini içeren başlık dosyasını drivers/android/vendor_hooks.c dosyasına ekleyin ve sembolleri dışa aktarın. Örneğin, aşağıdaki kod android_vh_sched_exit() kancasının bildirimini 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 : Kanca bildiriminde kullanılan veri yapılarının, ABI kararlılığını garanti etmek için tam olarak tanımlanması gerekir. Aksi takdirde, opak işaretçilerin referansını kaldırmak veya yapıyı boyutlu bağlamlarda kullanmak güvenli değildir. Bu tür veri yapılarının tam tanımını sağlayan içerme drivers/android/vendor_hooks.c dosyasının #ifndef __GENKSYMS__ bölümüne girmelidir. KMI'yi bozan CRC değişikliklerinden kaçınmak için include/trace/hooks içindeki başlık dosyaları tür tanımlarını içeren çekirdek başlık dosyasını içermemelidir. Bunun yerine türleri ileri doğru bildirin.

Satıcı kancalarına takın

Satıcı kancalarını kullanmak için satıcı modülünün kancaya yönelik 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);
    ...
}

Çekirdek çekirdek özellikleri

Önceki tekniklerden hiçbiri bir özelliği bir modülden uygulamanıza olanak vermiyorsa, o zaman özelliği çekirdek çekirdeğe Android'e özgü değişiklik olarak eklemelisiniz. Konuşmayı başlatmak için sorun izleyicide (BT) bir sorun oluşturun.

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

  • UAPI başlık dosyaları. Değişiklikler Android'e özgü arayüzlerde olmadığı sürece, UAPI başlık dosyalarındaki değişiklikler yukarı akışta gerçekleşmelidir. Satıcı modülleri ve satıcı kullanıcı alanı kodu arasındaki arayüzleri tanımlamak için satıcıya özel başlık dosyalarını kullanın.
  • sysf düğümleri. GKI çekirdeğine yeni sysfs düğümleri eklemeyin (bu tür eklemeler yalnızca satıcı modüllerde geçerlidir). SoC ve cihazdan bağımsız kitaplıklar tarafından kullanılan sysfs düğümleri ve Android çerçevesini oluşturan Java kodu yalnızca uyumlu yollarla değiştirilebilir ve Android'e özgü sysfs düğümleri değillerse yukarı yönde değiştirilmeleri gerekir. Satıcı kullanıcı alanı tarafından kullanılacak satıcıya özel sysfs düğümleri oluşturabilirsiniz . Varsayılan olarak, SELinux kullanılarak kullanıcı alanına göre sysfs düğümlerine erişim reddedilir. Yetkili satıcı yazılımının erişimine izin vermek için uygun SELinux etiketlerini eklemek satıcıya bağlıdır.
  • FS düğümlerinde hata ayıklama. Satıcı modülleri, yalnızca hata ayıklama için debugfs düğümleri tanımlayabilir (çünkü debugfs cihazın normal çalışması sırasında monte edilmemiştir).