Setelah perangkat keras 64-bit tersedia, kebutuhan untuk menangani ruang alamat yang lebih besar (lebih dari 2 byte) menjadi jelas. Dengan beberapa vendor yang kini menawarkan server dengan memori 64TiB (atau lebih), x86_64 dan arm64 sekarang memungkinkan pengalamatan ruang alamat yang lebih besar dari 2 byte (tersedia dengan dukungan alamat 48-bit default).
x86_64 menangani kasus penggunaan ini dengan mengaktifkan dukungan untuk tabel halaman lima tingkat di perangkat keras dan perangkat lunak. Ini memungkinkan pengalamatan ruang alamat yang sama dengan 2 byte (lihat x86:Paging 5 tingkat yang diaktifkan untuk v4.12 untuk detailnya). Ini melampaui batas 128PiB ruang alamat virtual dan 4PiB ruang alamat fisik.
arm64 mencapai hal yang sama dengan memperkenalkan dua ekstensi arsitektur baru—ARMv8.2 LVA (Large Virtual Addressing) dan ARMv8.2 LPA (Large Physical Addressing). Ini memungkinkan 4PiB ruang alamat virtual dan 4 PiB ruang alamat fisik (yaitu, masing-masing 2 bit).
Lebih banyak sumber daya Linux
- Lembar contekan perintah Linux
- Lembar contekan perintah Linux tingkat lanjut
- Kursus online gratis:Ikhtisar Teknis RHEL
- Lembar contekan jaringan Linux
- Lembar contekan SELinux
- Lembar contekan perintah umum Linux
- Apa itu container Linux?
- Artikel Linux terbaru kami
Dengan ekstensi arsitektur ARMv8.2 tersedia di CPU arm64 baru, dua ekstensi hardware baru kini didukung di software open source.
Dimulai dengan kernel Linux versi 5.4, dukungan Alamat Virtual (VA) dan Alamat Fisik (PA) 52-bit (Besar) diperkenalkan untuk arsitektur arm64. Meskipun dokumentasi kernel menjelaskan fitur-fitur ini dan bagaimana pengaruhnya terhadap kernel baru yang berjalan pada CPU yang lebih lama (yang tidak mendukung ekstensi VA 52-bit di perangkat keras) dan CPU yang lebih baru (yang mendukung ekstensi VA 52-bit di perangkat keras), itu bisa saja rumit bagi rata-rata pengguna untuk memahaminya dan bagaimana mereka dapat "memilih" untuk menerima VA dari ruang 52-bit.
Oleh karena itu, saya akan memperkenalkan konsep yang relatif baru ini dalam artikel ini:
- Bagaimana tata letak memori kernel "dibalik" untuk Arm64 setelah dukungan untuk fitur ini ditambahkan
- Dampak pada aplikasi userspace, terutama yang menyediakan dukungan debugging (misalnya, kexec-tools, makedumpfile, dan crash-utility)
- Bagaimana aplikasi userspace dapat "memilih" untuk menerima VA dari ruang 52-bit dengan menentukan parameter petunjuk mmap yang lebih besar dari 48 bit
Arsitektur ARMv8.2 ekstensi LVA dan LPA
Arsitektur ARMv8.2 menyediakan dua ekstensi penting:Large Virtual Addressing (LVA) dan Large Physical Addressing (LPA).
ARMv8.2-LVA mendukung ruang VA yang lebih besar untuk setiap register dasar tabel terjemahan hingga 52 bit saat menggunakan granula terjemahan 64KB.
ARMv8.2-LPA memungkinkan:
- Alamat fisik perantara (IPA) dan ruang PA yang lebih besar hingga 52 bit saat menggunakan granula terjemahan 64KB
- Ukuran blok level 1 di mana blok mencakup rentang alamat 4TB untuk granula terjemahan 64KB jika implementasinya mendukung 52 bit PA
Perhatikan bahwa fitur ini hanya didukung dalam status AArch64.
Saat ini, prosesor Arm64 Cortex-A berikut mendukung ekstensi ARMv8.2:
- Korteks-A55
- Korteks-A75
- Korteks-A76
Untuk detail selengkapnya, lihat Manual Referensi Arsitektur Armv8.
Tata letak memori kernel di Arm64
Dengan ekstensi ARMv8.2 yang menambahkan dukungan untuk ruang LVA (yang hanya tersedia saat dijalankan dengan ukuran halaman 64 KB), jumlah deskriptor akan diperluas di tingkat terjemahan pertama.
Alamat pengguna memiliki bit 63:48 yang disetel ke 0, sedangkan alamat kernel memiliki bit yang sama yang disetel ke 1. Pemilihan TTBRx diberikan oleh bit 63 dari alamat virtual. swapper_pg_dir
hanya berisi pemetaan kernel (global), sedangkan pengguna pgd
hanya berisi pemetaan pengguna (non-global). swapper_pg_dir
alamat ditulis ke TTBR1 dan tidak pernah ditulis ke TTBR0.
Tata letak memori AArch64 Linux dengan halaman 64KB ditambah tiga tingkat (52-bit dengan dukungan perangkat keras):
Start End Size Use
-----------------------------------------------------------------------
0000000000000000 000fffffffffffff 4PB user
fff0000000000000 fff7ffffffffffff 2PB kernel logical memory map
fff8000000000000 fffd9fffffffffff 1440TB [gap]
fffda00000000000 ffff9fffffffffff 512TB kasan shadow region
ffffa00000000000 ffffa00007ffffff 128MB bpf jit region
ffffa00008000000 ffffa0000fffffff 128MB modules
ffffa00010000000 fffff81ffffeffff ~88TB vmalloc
fffff81fffff0000 fffffc1ffe58ffff ~3TB [guard region]
fffffc1ffe590000 fffffc1ffe9fffff 4544KB fixed mappings
fffffc1ffea00000 fffffc1ffebfffff 2MB [guard region]
fffffc1ffec00000 fffffc1fffbfffff 16MB PCI I/O space
fffffc1fffc00000 fffffc1fffdfffff 2MB [guard region]
fffffc1fffe00000 ffffffffffdfffff 3968GB vmemmap
ffffffffffe00000 ffffffffffffffff 2MB [guard region]
Pencarian tabel terjemahan dengan halaman 4KB:
+--------+--------+--------+--------+--------+--------+--------+--------+
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0|
+--------+--------+--------+--------+--------+--------+--------+--------+
| | | | | |
| | | | | v
| | | | | [11:0] in-page offset
| | | | +-> [20:12] L3 index
| | | +-----------> [29:21] L2 index
| | +---------------------> [38:30] L1 index
| +-------------------------------> [47:39] L0 index
+-------------------------------------------------> [63] TTBR0/1
Pencarian tabel terjemahan dengan halaman 64KB:
+--------+--------+--------+--------+--------+--------+--------+--------+
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0|
+--------+--------+--------+--------+--------+--------+--------+--------+
| | | | |
| | | | v
| | | | [15:0] in-page offset
| | | +----------> [28:16] L3 index
| | +--------------------------> [41:29] L2 index
| +-------------------------------> [47:42] L1 index (48-bit)
| [51:42] L1 index (52-bit)
+-------------------------------------------------> [63] TTBR0/1
dukungan VA 52-bit di kernel
Karena kernel yang lebih baru dengan dukungan LVA harus berjalan dengan baik pada CPU yang lebih lama (yang tidak mendukung ekstensi LVA di perangkat keras) dan CPU yang lebih baru (yang mendukung ekstensi LVA di perangkat keras), pendekatan desain yang dipilih adalah memiliki biner tunggal yang mendukung 52 bit (dan harus dapat kembali ke 48 bit pada waktu boot awal jika fitur perangkat keras tidak ada). Artinya, VMEMMAP harus berukuran cukup besar untuk VA 52-bit dan juga harus berukuran cukup besar untuk mengakomodasi PAGE_OFFSET
tetap .
Pendekatan desain ini membutuhkan kernel untuk mendukung variabel berikut untuk ruang alamat virtual baru:
VA_BITS constant the *maximum* VA space size
vabits_actual variable the *actual* VA space size
Jadi, sementara VA_BITS
menunjukkan ukuran ruang VA maksimum, ruang VA aktual yang didukung (bergantung pada sakelar yang dibuat saat boot) ditunjukkan oleh vabits_actual
.
Membalik tata letak memori kernel
Pendekatan desain untuk menjaga biner kernel tunggal membutuhkan kernel .text berada di alamat yang lebih tinggi, sehingga mereka invarian untuk VA 48/52-bit. Karena bayangan Kernel Address Sanitizer (KASAN) menjadi sebagian kecil dari seluruh ruang VA kernel, ujung bayangan KASAN juga harus berada di bagian yang lebih tinggi dari ruang VA kernel untuk 48 dan 52 bit. (Beralih dari 48 bit ke 52 bit, ujung bayangan KASAN tidak berubah dan bergantung pada ~0UL
, sedangkan alamat awal akan "tumbuh" menuju alamat yang lebih rendah).
Untuk mengoptimalkan phys_to_virt()
dan virt_to_phys()
, PAGE_OFFSET
dijaga konstan pada 0xFFF0000000000000
(sesuai dengan 52 bit), ini meniadakan kebutuhan untuk membaca variabel tambahan. physvirt
dan vmemmap
offset dihitung pada boot awal untuk mengaktifkan logika ini.
Pertimbangkan konversi ruang alamat RAM fisik vs virtual berikut:
/*
* The linear kernel range starts at the bottom of the virtual address
* space. Testing the top bit for the start of the region is a
* sufficient check and avoids having to worry about the tag.
*/
#define virt_to_phys(addr) ({ \
if (!(((u64)addr) & BIT(vabits_actual - 1))) \
(((addr) & ~PAGE_OFFSET) + PHYS_OFFSET)
})
#define phys_to_virt(addr) ((unsigned long)((addr) - PHYS_OFFSET) | PAGE_OFFSET)
where:
PAGE_OFFSET - the virtual address of the start of the linear map, at the
start of the TTBR1 address space,
PHYS_OFFSET - the physical address of the start of memory, and
vabits_actual - the *actual* VA space size
Dampak pada aplikasi userspace yang digunakan untuk men-debug kernel
Beberapa aplikasi ruang pengguna digunakan untuk men-debug kernel yang berjalan/langsung atau menganalisis dump vmcore dari sistem yang mogok (misalnya, untuk menentukan akar penyebab kerusakan kernel):kexec-tools, makedumpfile, dan crash-utility.
Ketika ini digunakan untuk men-debug kernel Arm64, ada juga dampak pada mereka karena peta memori kernel Arm64 menjadi "terbalik". Aplikasi ini juga perlu menjalankan tabel terjemahan untuk menentukan alamat fisik yang sesuai dengan alamat virtual (mirip dengan cara yang dilakukan di kernel).
Oleh karena itu, aplikasi ruang pengguna harus dimodifikasi karena rusak di bagian hulu setelah "flip" diperkenalkan di peta memori kernel.
Saya telah mengusulkan perbaikan di tiga aplikasi ruang pengguna yang terpengaruh; sementara beberapa telah diterima di hulu, yang lain masih tertunda:
- Perbaikan upstream makedumpfile yang diusulkan
- Perbaikan hulu kexec-tools yang diusulkan
- Perbaikan diterima di crash-utility
Kecuali jika perubahan ini dibuat di aplikasi ruang pengguna, perubahan tersebut akan tetap rusak untuk men-debug kernel yang berjalan/langsung atau menganalisis dump vmcore dari sistem yang mogok.
VA ruang pengguna 52-bit
Untuk menjaga kompatibilitas dengan aplikasi ruang pengguna yang mengandalkan ruang ARMv8.0 VA ukuran maksimum 48 bit, kernel akan, secara default, mengembalikan alamat virtual ke ruang pengguna dari kisaran 48 bit.
Aplikasi ruang pengguna dapat "memilih" untuk menerima VA dari ruang 52-bit dengan menetapkan parameter petunjuk mmap yang lebih besar dari 48 bit.
Misalnya:
.mmap_high_addr.c
----
maybe_high_address = mmap(~0UL, size, prot, flags,...);
Dimungkinkan juga untuk membangun kernel debug yang mengembalikan alamat dari ruang 52-bit dengan mengaktifkan opsi konfigurasi kernel berikut:
CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y
Perhatikan bahwa opsi ini hanya ditujukan untuk men-debug aplikasi dan seharusnya tidak digunakan dalam produksi.
Kesimpulan
Untuk meringkas:
- Dimulai dengan kernel Linux versi 5.14, ekstensi perangkat keras Armv8.2 baru LVA dan LPA sekarang didukung dengan baik di kernel Linux.
- Aplikasi ruang pengguna seperti kexec-tools dan makedumpfile yang digunakan untuk men-debug kernel rusak sekarang dan menunggu penerimaan perbaikan upstream.
- Aplikasi ruang pengguna lama yang mengandalkan kernel Arm64 yang menyediakan VA 48-bit akan terus bekerja apa adanya, sedangkan aplikasi ruang pengguna yang lebih baru dapat "memilih" untuk menerima VA dari ruang 52-bit dengan menetapkan parameter petunjuk mmap yang lebih besar dari 48 bit.
Artikel ini mengacu pada Tata Letak Memori pada AArch64 Linux dan dokumentasi kernel Linux v5.9.12. Keduanya dilisensikan di bawah GPLv2.0.