GNU/Linux >> Znalost Linux >  >> Linux

Pochopení podpory 52bitových virtuálních adres v jádře Arm64

Poté, co byl k dispozici 64bitový hardware, byla zřejmá potřeba zpracovávat větší adresní prostory (větší než 2 bajty). Někteří dodavatelé nyní nabízejí servery s pamětí 64TiB (nebo více), x86_64 a arm64 nyní umožňují adresování adresních prostorů větších než 2 bajty (k dispozici s výchozí podporou 48bitových adres).

x86_64 řešil tyto případy použití povolením podpory pětiúrovňových tabulek stránek v hardwaru i softwaru. To umožňuje adresování adresových prostorů o velikosti 2 bajtů (podrobnosti viz x86:Povolení 5úrovňového stránkování pro v4.12). Posouvá limity na 128 PiB virtuálního adresového prostoru a 4 PiB fyzického adresového prostoru.

arm64 dosáhl stejné věci zavedením dvou nových rozšíření architektury – ARMv8.2 LVA (Large Virtual Addressing) a ARMv8.2 LPA (Large Physical Addressing). Ty umožňují 4 PiB virtuálního adresního prostoru a 4 PiB fyzického adresního prostoru (tj. každý 2 bity).

Další zdroje pro Linux

  • Cheat pro příkazy Linuxu
  • Cheat sheet pro pokročilé příkazy systému Linux
  • Bezplatný online kurz:Technický přehled RHEL
  • Síťový cheat pro Linux
  • Cheat sheet SELinux
  • Cheat pro běžné příkazy pro Linux
  • Co jsou kontejnery systému Linux?
  • Naše nejnovější články o Linuxu

Díky rozšířením architektury ARMv8.2 dostupným v nových CPU arm64 jsou nyní tato dvě nová hardwarová rozšíření podporována v softwaru s otevřeným zdrojovým kódem.

Počínaje linuxovým jádrem verze 5.4 byla pro architekturu arm64 zavedena podpora 52bitové (velké) virtuální adresy (VA) a fyzické adresy (PA). Ačkoli dokumentace jádra popisuje tyto funkce a jak ovlivňují nová jádra běžící na starších CPU (které nepodporují 52bitové rozšíření VA v hardwaru) a novějších CPU (které podporují 52bitová rozšíření VA v hardwaru), může být složité pro průměrné uživatele, aby jim porozuměli a jak se mohou "přihlásit" k příjmu VA z 52bitového prostoru.

Proto v tomto článku představím tyto relativně nové pojmy:

  1. Jak se rozložení paměti jádra "převrátilo" pro Arm64 poté, co byla přidána podpora pro tyto funkce
  2. Dopad na aplikace v uživatelském prostoru, zejména ty, které poskytují podporu ladění (např. kexec-tools, makedumpfile a crash-utility)
  3. Jak se mohou aplikace v uživatelském prostoru "přihlásit" k přijímání VA z 52bitového prostoru zadáním parametru nápovědy mmap, který je větší než 48 bitů

Rozšíření LVA a LPA architektury ARMv8.2

Architektura ARMv8.2 poskytuje dvě důležitá rozšíření:Large Virtual Addressing (LVA) a Large Physical Addressing (LPA).

ARMv8.2-LVA podporuje větší prostor VA pro každý základní registr překladové tabulky až 52 bitů při použití granule překladu 64 kB.

ARMv8.2-LPA umožňuje:

  • Větší mezilehlá fyzická adresa (IPA) a PA prostor až 52 bitů při použití granule překladu 64 kB
  • Velikost bloku 1. úrovně, kde blok pokrývá rozsah adres 4 TB pro granule překladu 64 kB, pokud implementace podporuje 52 bitů PA

Upozorňujeme, že tyto funkce jsou podporovány pouze ve stavu AArch64.

V současné době podporují rozšíření ARMv8.2 následující procesory Arm64 Cortex-A:

  • Cortex-A55
  • Cortex-A75
  • Cortex-A76

Další podrobnosti naleznete v referenční příručce architektury Armv8.

Rozvržení paměti jádra na Arm64

S rozšířením ARMv8.2, které přidává podporu pro prostor LVA (který je k dispozici pouze při spuštění s velikostí stránky 64 kB), se počet deskriptorů rozšíří v první úrovni překladu.

Uživatelské adresy mají bity 63:48 nastavené na 0, zatímco adresy jádra mají stejné bity nastavené na 1. Výběr TTBRx je dán bitem 63 virtuální adresy. swapper_pg_dir obsahuje pouze mapování jádra (globální), zatímco uživatel pgd obsahuje pouze uživatelská (neglobální) mapování. swapper_pg_dir adresa se zapisuje do TTBR1 a nikdy se nezapisuje do TTBR0.

Rozvržení paměti AArch64 Linux se stránkami o velikosti 64 kB a třemi úrovněmi (52bitové s podporou hardwaru):

  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]

Vyhledávání v překladové tabulce se stránkami o velikosti 4 kB:

  +--------+--------+--------+--------+--------+--------+--------+--------+
  |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

Vyhledávání v překladové tabulce se stránkami o velikosti 64 kB:

  +--------+--------+--------+--------+--------+--------+--------+--------+
  |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

52bitová podpora VA v jádře

Vzhledem k tomu, že novější jádra s podporou LVA by měla dobře běžet na starších CPU (které nepodporují rozšíření LVA v hardwaru) a na novějších CPU (které podporují rozšíření LVA v hardwaru), zvoleným návrhovým přístupem je mít jediný binární soubor, který podporuje 52 bit (a pokud není přítomna hardwarová funkce, musí být schopen klesnout zpět na 48 bit při časném spouštění). To znamená, že VMEMMAP musí být dostatečně velký pro 52bitové VA a také musí být dostatečně velký, aby pojal pevný PAGE_OFFSET .

Tento přístup k návrhu vyžaduje, aby jádro podporovalo následující proměnné pro nový virtuální adresový prostor:

VA_BITS         constant        the *maximum* VA space size

vabits_actual   variable        the *actual* VA space size

Takže, zatímco VA_BITS označuje maximální velikost prostoru VA, skutečný podporovaný prostor VA (v závislosti na přepínači provedeném při spouštění) je označen vabits_actual .

Otočení rozložení paměti jádra

Návrhový přístup, který spočívá v udržování binárního kódu jednoho jádra, vyžaduje, aby kernel .text byl na vyšších adresách, takže jsou invariantní vůči 48/52bitovým VA. Vzhledem k tomu, že stín Kernel Address Sanitizer (KASAN) tvoří zlomek celého VA prostoru jádra, musí být konec stínu KASAN také ve vyšší polovině prostoru VA jádra pro 48 i 52 bity. (Při přepínání ze 48 bitů na 52 bitů je konec stínu KASAN neměnný a závislý na ~0UL , zatímco počáteční adresa bude "růst" směrem k nižším adresám).

Chcete-li optimalizovat phys_to_virt() a virt_to_phys() , PAGE_OFFSET je udržován konstantní na 0xFFF0000000000000 (odpovídající 52 bitům), tím odpadá nutnost čtení další proměnné. physvirt a vmemmap offsety jsou vypočítány při časném spouštění, aby byla tato logika povolena.

Zvažte následující převod fyzického vs. virtuálního adresního prostoru RAM:

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

Vliv na aplikace v uživatelském prostoru používané k ladění jádra

Několik aplikací v uživatelském prostoru se používá k ladění běžících/živých jader nebo analýze výpisu vmcore z havarujícího systému (např. k určení hlavní příčiny pádu jádra):kexec-tools, makedumpfile a crash-utility.

Když jsou tyto použity pro ladění jádra Arm64, je to také ovlivněno tím, že se „převrací“ paměťová mapa jádra Arm64. Tyto aplikace také potřebují provést procházku překladovou tabulkou pro určení fyzické adresy odpovídající virtuální adrese (podobně, jak se to dělá v jádře).

V souladu s tím musí být aplikace v uživatelském prostoru upraveny, protože jsou po zavedení „flipu“ do mapy paměti jádra přerušeny.

Navrhl jsem opravy ve třech dotčených aplikacích v uživatelském prostoru; zatímco některé byly přijaty proti proudu, jiné stále čekají:

  • Navrhovaná oprava upstream souboru makedumpfile
  • Navrhovaná oprava upstream nástrojů kexec-tools
  • Oprava přijata v utilitě při selhání

Pokud tyto změny neprovedete v aplikacích v uživatelském prostoru, zůstanou poškozené pro ladění běžících/živých jader nebo analýzu výpisu vmcore z havarujícího systému.

52bitové virtuální počítače v uživatelském prostoru

Aby byla zachována kompatibilita s aplikacemi v uživatelském prostoru, které se spoléhají na maximální velikost prostoru ARMv8.0 VA 48 bitů, jádro bude ve výchozím nastavení vracet virtuální adresy do uživatelského prostoru z rozsahu 48 bitů.

Aplikace v uživatelském prostoru se mohou "přihlásit" k přijímání VA z 52bitového prostoru zadáním parametru nápovědy mmap většího než 48 bitů.

Například:

.mmap_high_addr.c
----

   maybe_high_address = mmap(~0UL, size, prot, flags,...);

Je také možné sestavit ladicí jádro, které vrací adresy z 52bitového prostoru povolením následujících možností konfigurace jádra:

   CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y

Upozorňujeme, že tato možnost je určena pouze pro ladění aplikací a neměla by být použit ve výrobě.

Závěry

Abych to shrnul:

  1. Počínaje jádrem Linuxu verze 5.14 jsou nyní v jádře Linuxu dobře podporována nová hardwarová rozšíření Armv8.2 LVA a LPA.
  2. Aplikace v uživatelském prostoru jako kexec-tools a makedumpfile používané k ladění jádra jsou nefunkční právě a čeká na přijetí upstream oprav.
  3. Starší aplikace v uživatelském prostoru, které se spoléhají na jádro Arm64 a poskytují mu 48bitové VA, budou i nadále fungovat tak, jak jsou, zatímco novější aplikace v uživatelském prostoru se mohou „přihlásit“ k přijímání VA z 52bitového prostoru zadáním parametru nápovědy mmap která je větší než 48 bitů.

Tento článek čerpá z Memory Layout v AArch64 Linuxu a dokumentaci jádra Linuxu v5.9.12. Oba jsou licencovány pod licencí GPLv2.0.


Linux
  1. Linux – Co znamená rozložení paměti virtuálního jádra v Dmesg?

  2. Porozumění systému souborů /proc

  3. Pochopení efektivní verze jádra Ksplice

  1. Jak zkontrolovat HZ v terminálu?

  2. Proč je jádro mapováno do stejného adresního prostoru jako procesy?

  3. Jak je do linuxového jádra přidána nová hardwarová podpora?

  1. Analyzujte linuxové jádro pomocí ftrace

  2. Linux – Kernel:Podpora jmenných prostorů?

  3. K čemu je mít část jádra ve virtuálním paměťovém prostoru linuxových procesů?