Porting Linux ke persyaratan platform lain [ditutup]

28

Saya tahu bahwa Linux tersedia dan telah porting untuk berbagai platform seperti untuk X86, ARM, PowerPC dll.

Namun, dalam hal porting, apa yang dibutuhkan sebenarnya?

Pemahaman saya adalah bahwa Linux adalah perangkat lunak yang ditulis dalam C. Oleh karena itu ketika porting Linux berasal dari X86 ke ARM atau yang lainnya misalnya, bukankah itu hanya masalah mengkompilasi ulang kode dengan kompiler untuk arsitektur target spesifik?

Mengesampingkan driver perangkat untuk periferal yang berbeda, apa lagi yang perlu dilakukan ketika porting Linux ke arsitektur baru. Apakah kompiler tidak mengurus semuanya untuk kita?

Insinyur999
sumber
11
Bisakah kami berasumsi bahwa Anda telah melihat sumber kernel khusus arsitektur? git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/…
Kusalananda

Jawaban:

57

Meskipun sebagian besar kode dalam kernel Linux ditulis dalam C, masih ada banyak bagian dari kode itu yang sangat spesifik untuk platform di mana ia berjalan dan perlu memperhitungkannya.

Salah satu contoh khusus dari ini adalah memori virtual, yang bekerja dengan cara yang serupa di sebagian besar arsitektur (hierarki tabel halaman) tetapi memiliki detail spesifik untuk setiap arsitektur (seperti jumlah level di setiap arsitektur, dan ini telah meningkat bahkan pada x86 dengan pengenalan chip baru yang lebih besar.) Kode kernel Linux memperkenalkan makro untuk menangani melintasi hierarki ini yang dapat dielakkan oleh kompiler pada arsitektur yang memiliki lebih sedikit tingkat tabel halaman (sehingga kode ditulis dalam C, tetapi mengambil rincian arsitektur ke dalam pertimbangan.)

Banyak area lain yang sangat spesifik untuk setiap arsitektur dan perlu ditangani dengan kode khusus lengkung. Sebagian besar dari ini melibatkan kode dalam bahasa assembly. Contohnya adalah:

  • Pengalihan Konteks : Pengalihan konteks melibatkan penghematan nilai semua register untuk proses yang dihilangkan dan mengembalikan register dari set proses tersimpan yang dijadwalkan ke dalam CPU. Bahkan jumlah dan set register sangat spesifik untuk setiap arsitektur. Kode ini biasanya diimplementasikan dalam perakitan, untuk memungkinkan akses penuh ke register dan juga untuk memastikan itu berjalan secepat mungkin, karena kinerja pengalihan konteks bisa sangat penting untuk sistem.

  • Panggilan Sistem : Mekanisme di mana kode userspace dapat memicu panggilan sistem biasanya khusus untuk arsitektur (dan kadang-kadang bahkan untuk model CPU tertentu, misalnya Intel dan AMD memperkenalkan instruksi yang berbeda untuk itu, CPU yang lebih tua mungkin kekurangan instruksi tersebut, jadi perinciannya). bagi mereka akan tetap unik.)

  • Interrupt Handler : Detail tentang cara menangani interupsi (interupsi perangkat keras) biasanya khusus untuk platform dan biasanya memerlukan lem tingkat rakitan untuk menangani konvensi pemanggilan khusus yang digunakan untuk platform. Juga, primitif untuk mengaktifkan / menonaktifkan interupsi biasanya platform-spesifik dan memerlukan kode perakitan juga.

  • Inisialisasi : Rincian tentang bagaimana inisialisasi harus terjadi juga biasanya mencakup detail yang khusus untuk platform dan sering memerlukan beberapa kode rakitan untuk menangani titik masuk ke kernel. Pada platform yang memiliki banyak CPU (SMP), perincian tentang cara menghadirkan CPU lain secara online biasanya juga berbasis platform.

  • Locking Primitives : Implementasi primitif penguncian (seperti spinlocks) biasanya melibatkan detail platform spesifik juga, karena beberapa arsitektur menyediakan (atau lebih suka) instruksi CPU yang berbeda untuk mengimplementasikannya secara efisien. Beberapa akan menerapkan operasi atom, beberapa akan memberikan cmpxchg yang dapat menguji / memperbarui (tetapi gagal jika penulis lain masuk terlebih dahulu), yang lain akan menyertakan pengubah "kunci" untuk instruksi CPU. Ini akan sering melibatkan penulisan kode assembly juga.

Mungkin ada area lain di mana kode platform-atau arsitektur-spesifik diperlukan di kernel (atau, khususnya, di kernel Linux.) Melihat pohon sumber kernel, ada sub pohon khusus arsitektur di bawah arch/dan di bawah di include/arch/mana Anda dapat menemukan lebih banyak contoh dari ini.

Beberapa sebenarnya mengejutkan, misalnya Anda akan melihat bahwa jumlah panggilan sistem yang tersedia pada setiap arsitektur berbeda dan beberapa panggilan sistem akan ada di beberapa arsitektur dan bukan yang lain. (Bahkan pada x86, daftar syscalls berbeda antara kernel 32-bit dan 64-bit.)

Singkatnya, ada banyak kasus yang perlu diperhatikan oleh kernel yang spesifik untuk suatu platform. Kernel Linux mencoba untuk mengabstraksi sebagian besar dari mereka, sehingga algoritma tingkat yang lebih tinggi (seperti bagaimana manajemen memori dan penjadwalan bekerja) dapat diimplementasikan dalam C dan bekerja sama (atau sebagian besar sama) pada semua arsitektur.

filbranden
sumber
7
Tulisan yang sangat bagus! Variasi dalam jumlah syscalls sebagian besar terkait dengan sejarah: port baru menyertakan syscalls yang valid pada saat port, mereka tidak repot dengan bagasi historis yang ada di port lama, jadi syscall yang sudah usang biasanya tidak ada di port lebih baru dari penghinaan. (Itu tidak mencakup semua skenario ...)
Stephen Kitt
10

Selain porting kernel Linux, Anda perlu mendefinisikan antarmuka biner aplikasi (ABI) untuk program "ruang pengguna" dan port lapisan paling bawah dari tumpukan perangkat lunak ruang pengguna. Linux biasanya digunakan dengan komponen ruang pengguna tingkat rendah dari proyek GNU, yang mana yang paling kritis adalah:

  • Kompiler C, assembler, dan tautan: GCC dan GNU Binutils . Untuk arsitektur CPU yang sepenuhnya baru, Anda perlu mem-porting perangkat lunak ini bahkan sebelum Anda mulai mem-porting kernel, karena kernel itu sendiri adalah program C dan harus dikompilasi. Jika sudah ada dukungan "back end" untuk CPU platform Anda, hanya saja tidak dengan Linux sebagai kernel OS, Anda memiliki lebih sedikit pekerjaan yang harus dilakukan dan Anda mungkin dapat pergi dengan menunda sebagian besar pekerjaan sampai kernel naik dan berlari.
  • Pustaka runtime C: " GNU libc ". Pustaka ini mencakup kode yang membuat panggilan sistem dan sebaliknya berinteraksi langsung dengan kernel.
  • Pustaka "antarmuka fungsi asing", libffi , yang merupakan komponen penting dari banyak penerjemah bahasa tingkat tinggi, dan melakukan salah satu dari sedikit tugas yang tersisa yang membutuhkan sejumlah kecil bahasa rakitan tulisan tangan.

Banyak perangkat lunak lain memiliki komponen opsional yang bergantung pada platform; misalnya, penjelajahan web akan jauh lebih cepat jika Anda menulis primitif kriptografi yang dioptimalkan untuk NSS dan OpenSSL untuk arsitektur CPU baru Anda, dan kompilasi back-end just-in-time untuk IonMonkey dan V8 . Tetapi ini tidak penting untuk memunculkan platform baru.

zwol
sumber
1

Anda harus memberi tahu kernel tentang perangkat keras yang Anda porting. Pekerjaan kernel adalah untuk langsung berinteraksi dengan perangkat keras, sehingga agar berfungsi dengan baik, kernel perlu tahu tentang CPU, osilator (jam), dan periferal apa pun, seperti berbagai jenis port serial (SPI, CAN, I2C, dll.).

Di masa lalu, Anda akan melakukan ini dengan menulis kode khusus platform yang kemudian akan digunakan driver untuk berfungsi. Hari-hari ini, ini dilakukan dengan menulis definisi Device Tree .

Bebek karet
sumber