GNU/Linux >> Belajar Linux >  >> Linux

Memahami dukungan alamat virtual 52-bit di kernel Arm64

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:

  1. Bagaimana tata letak memori kernel "dibalik" untuk Arm64 setelah dukungan untuk fitur ini ditambahkan
  2. Dampak pada aplikasi userspace, terutama yang menyediakan dukungan debugging (misalnya, kexec-tools, makedumpfile, dan crash-utility)
  3. 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:

  1. Dimulai dengan kernel Linux versi 5.14, ekstensi perangkat keras Armv8.2 baru LVA dan LPA sekarang didukung dengan baik di kernel Linux.
  2. Aplikasi ruang pengguna seperti kexec-tools dan makedumpfile yang digunakan untuk men-debug kernel rusak sekarang dan menunggu penerimaan perbaikan upstream.
  3. 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.


Linux
  1. Kernel Linux:5 inovasi teratas

  2. Siklus hidup pengujian kernel Linux

  3. Linux – Kernel:Dukungan Namespaces?

  1. Memahami Sistem File /proc

  2. Mengapa kernel dipetakan ke ruang alamat yang sama dengan proses?

  3. Bagaimana dukungan perangkat keras baru ditambahkan ke kernel linux?

  1. Analisis kernel Linux dengan ftrace

  2. Temukan Komputer Di Jaringan Lan?

  3. Apa gunanya memiliki bagian kernel di ruang memori virtual proses Linux?