Aarch64 adalah arsitektur 64-bit dari ARM (kadang-kadang disebut arm64). Pada artikel ini saya akan memberi tahu Anda perbedaannya dari ARM "reguler" (32-bit) dan betapa sulitnya untuk mem-port sistem Anda ke sana.
Artikel ini bukan panduan terperinci, melainkan gambaran umum modul-modul sistem yang harus diulang, dan seberapa besar arsitektur secara keseluruhan berbeda dari ARM 32-bit biasa; semua ini dari pengalaman pribadi saya porting Embox ke arsitektur ini. Untuk porting langsung dari sistem tertentu, dengan satu atau lain cara Anda harus berurusan dengan dokumentasi, di akhir artikel saya meninggalkan tautan ke beberapa dokumen yang mungkin berguna.
Bahkan, ada lebih banyak perbedaan daripada kesamaan, dan Aarch64 lebih merupakan arsitektur baru daripada ekstensi 64-bit dari ARM yang sudah dikenal. Pendahulu Aarch64 sebagian besar adalah Aarch32 (ini merupakan perpanjangan dari ARM 32-bit yang biasa), tetapi karena saya tidak memiliki pengalaman dengannya, saya tidak akan menulis tentang itu :)
Lebih lanjut dalam artikel ini, jika saya menulis tentang ARM "lama" atau "tua", maksud saya ARM 32-bit (dengan seperangkat perintah ARM).
Secara singkat saya akan membahas daftar perubahan dibandingkan dengan ARM 32-bit, dan kemudian saya akan menganalisisnya secara lebih rinci.
- Register untuk keperluan umum menjadi 2 kali lebih luas (sekarang masing-masing 64 bit), dan jumlahnya bertambah dua kali lipat (yaitu, sekarang tidak ada 16, tetapi 32).
- Penolakan konsep register coprocessor, sekarang mereka dapat diakses hanya dengan nama, misalnya
msr vbar_el1, x0
(terhadap mcr p15, 0, %0, c1, c1, 2
sebelumnya mcr p15, 0, %0, c1, c1, 2
) - Model MMU baru (tidak terhubung dengan yang lama dengan cara apa pun, Anda harus menulis lagi).
- Sebelumnya, ada dua level privilege: pengguna (sesuai dengan mode prosesor USR) dan sistem (terkait dengan SYS, IRQ, FIQ, ABT, ...) mode, sekarang semuanya lebih mudah dan lebih rumit pada saat yang sama - sekarang ada 4 mode.
- AdvSIMD menggantikan NEON, operasi floating-point dilakukan melaluinya.
Sekarang lebih lanjut tentang poin.
Register dan set instruksi
Register tujuan umum adalah r0-r30, sementara Anda dapat mengaksesnya sebagai 64-bit (x0-x30) atau 32-bit (w0-w30, akses ke 32 bit yang lebih rendah).
Set instruksi untuk Aarch64 disebut A64. Baca deskripsi instruksi di sini . Aritmatika dasar dan beberapa perintah lain dalam bahasa assembly tetap sama:
mov w0, w1 /* w1 w0 */ add x0, x1, 13 /* x0 x1 13 */ b label /* "" "label" bl label /* "" "label", x30 */ ldr x3, [x1, 0] /* x3 , x1 */ str x3, [x0, 0] /* x3 , x0 */
Sekarang sedikit tentang perbedaannya:
- Daftar "nol" khusus
rzr/xzr/wzr
, yaitu nol saat membaca (Anda dapat menggunakan tulis ke register, tetapi hasil perhitungan tidak akan ditulis di mana pun).
subs xzr, x1, x2 /* x1 x2 NZCV, */
- Anda tidak dapat menumpuk banyak register (
stmfd sp!, {r0-r3}
) ke dalam tumpukan sekaligus, Anda harus melakukan ini secara berpasangan:
stp x0, x1, [sp, 16]! stp x2, x3, [sp, 16]!
Register PC (Program counter, sebuah pointer ke instruksi pelaksanaan saat ini) sekarang bukan register umum (dulu R15), oleh karena itu, itu tidak dapat diakses dengan perintah biasa ( mov
, ldr
), hanya melalui ret
, bl
dan sebagainya.
Status program sekarang tidak menampilkan CPSR (register ini tidak ada), tetapi register DAIF (berisi IRQ, mask FIQ, dll., AIF - bit A yang sama, I, F dari CPSR), NZCV (bit negatif, nol, membawa , oVerflow - tiba-tiba, NZCV yang sama dari CPSR) dan System Control Register (SCTLR, untuk mengaktifkan caching, MMU, endianness, dan sebagainya).
Tampaknya perintah-perintah ini cukup untuk menulis bootloader sederhana yang dapat mentransfer kontrol ke kode platform-independen :)
Mode kinerja dan beralih di antara mereka
Mode kinerja ditulis dengan baik dalam Fundamentals of ARMv8-A , saya akan menceritakan secara singkat esensi dokumen ini di sini.
Aarch64 memiliki 4 level privilege (Level eksekusi, selanjutnya disingkat EL).
- EL3 - Secure Monitor (diasumsikan bahwa firmware berjalan pada level ini)
- EL2 - Hypervisor
- EL1 - OS
- EL0 - Aplikasi
Pada OS 64-bit, Anda dapat menjalankan aplikasi 32-bit dan 64-bit; pada OS 32-bit, hanya aplikasi 32-bit yang dapat dijalankan.

Transisi antar EL dilakukan dengan pengecualian (panggilan sistem, interupsi, kesalahan akses memori), atau dengan menggunakan perintah return from exception ( eret
).
Setiap EL memiliki register sendiri SPSR, ELR, SP (yaitu "register banked").
Banyak register sistem juga dibagi dengan EL - misalnya, register konteks MMU ttbr0
- ada ttbr0_el2
, ttbr0_el1
, dan Anda perlu mengakses register Anda pada EL yang sesuai. Hal yang sama berlaku untuk register status program - DAIF, NZCV, SCTLR, SPSR, ELR ...
MMU
Armv8-A mendukung MMU ARMv8.2 LPA, lebih lanjut tentang ini dapat ditemukan di bab D5 dari Manual Referensi Arsitektur ARM untuk Armv8, Armv8-A .
Singkatnya, MMU ini mendukung halaman 4KiB (4 level tabel memori virtual), 16KiB (4 level) dan 64KiB (3 level). Pada tingkat menengah mana pun, Anda dapat menentukan blok memori, dengan demikian tidak menunjukkan tingkat berikutnya dari tabel, tetapi keseluruhan memori dengan ukuran yang harus "ditutupi" oleh tabel tingkat berikutnya. Saya memiliki artikel lama tentang memori virtual, di mana Anda dapat membaca tentang tabel, level terjemahan, dan itu saja.
Dari perubahan kecil, mereka menolak domain, tetapi menambahkan bendera seperti sedikit kotor.
Secara umum, kecuali untuk "blok" alih-alih tabel terjemahan perantara, tidak ada perubahan konseptual khusus yang terlihat, MMU sebagai MMU.
SIMD lanjutan
Ada perbedaan AdvSIMD yang signifikan dalam NEON lama, baik ketika bekerja dengan floating point dan dengan operasi vektor (SIMD). Misalnya, jika sebelumnya D0 terdiri dari S0 dan S1, dan Q0 - dari D0 dan D1, maka sekarang tidak demikian: Q0 sesuai dengan D0 dan S0, untuk Q1 - D1 dan S0, dan seterusnya. Pada saat yang sama, dukungan untuk VFP / SIMD adalah wajib, dengan menelepon perjanjian sekarang tidak ada transfer parameter terprogram (apa yang dulu disebut "soft float ABI", di GCC - flag -mfloat-abi=softfp
), jadi Anda harus mengimplementasikan dukungan perangkat keras untuk floating point .
Ada 16 register 128 bit:

Ada 32 register masing-masing 128 bit:

Anda dapat membaca lebih lanjut tentang NEON di artikel ini , daftar perintah yang tersedia untuk Aarch64 dapat ditemukan di sini .
Operasi dasar dengan register floating point:
fadd s0, s1, s2 /* s0 = s1 + s2 */ fmul d0, d1, d2 /* d0 = d1 * d2 */
Operasi SIMD dasar:
/* , : NEON, */ /* q0 = q1 + q2, -- 4 */ vadd.s32 q0, q1, q2 /* : AdvSIMD, */ /* v0 = v1 + v2, -- 4 */ add v0.4s, v1.4s, v2.4s /* v1 ( 2 64- ) d1 */ addv d1, v1.ds /* 4 0 */ movi v1.4s, 0x0
QEMU
QEMU memiliki dukungan untuk Aarch64. Salah satu platformnya adalah virt
, sehingga dimulai dalam mode 64-bit, Anda juga harus melewati -cpu cortex-a53
, seperti ini:
qemu-system-aarch64 -M virt -cpu cortex-a53 -kernel ./embox -m 1024 -nographic # ./embox -- ELF-
Apa yang bagus, banyak periferal yang digunakan untuk platform ini, driver yang sudah ada di Embox - misalnya, PL011 untuk konsol, ARM Generic Interrupt Controller, dll. Tentu saja, perangkat ini memiliki alamat register pangkalan yang berbeda dan angka interupsi lainnya, tetapi yang utama adalah kode driver berfungsi tidak berubah pada arsitektur baru. Ketika sistem dimulai, kontrolnya ada di EL1.
i.MX8
Karena sepotong besi ini, porting ke Aarch64 - i.MX8MQ Nitrogen8M dimulai.

Tidak seperti QEMU, u-boot mentransfer kontrol ke gambar dalam EL2, dan, lebih lagi, untuk beberapa alasan itu termasuk MMU (semua memori dipetakan 1 ke 1), yang menciptakan beberapa masalah tambahan selama inisialisasi.
Embox sudah mendukung i.MX6, dan, yah, di i.MX8 bagian dari periferal adalah sama - misalnya, UART dan Ethernet, yang juga berfungsi (saya harus memperbaiki beberapa tempat di mana ada ikatan yang erat dengan alamat 32-bit). Di sisi lain, pengontrol interupsi berbeda di sana - ARM GICv3, yang sangat berbeda dari versi pertama.
Kesimpulan
Saat ini, dukungan untuk Aarch64 di Embox tidak lengkap, tetapi sudah ada fungsi minimal - interupsi, MMU, input-output melalui UART. Masih banyak yang harus diselesaikan, tetapi langkah-langkah pertama lebih mudah dibuat daripada yang tampak dari awal. Ada jauh lebih sedikit dokumentasi dan artikel daripada di ARM, tetapi ada lebih dari cukup informasi untuk menangani semuanya.
Secara umum, jika Anda memiliki pengalaman dengan ARM, porting ke Aarch64 adalah tugas yang layak. Meskipun, seperti biasa, Anda dapat menemukan beberapa hal kecil :)
Anda dapat mengunduh proyek untuk menyodoknya di QEMU dari repositori kami , jika Anda memiliki pertanyaan - tulis di komentar, atau di buletin , atau di obrolan di Telegram (ada juga saluran ).
Tautan yang bermanfaat
PS
24-25 Agustus, kami akan berbicara di TechTrain , mendengarkan penampilan kami sekitar dua atau tiga kali , datang ke stand - kami akan menjawab pertanyaan Anda :)