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:
- Jak se rozložení paměti jádra "převrátilo" pro Arm64 poté, co byla přidána podpora pro tyto funkce
- Dopad na aplikace v uživatelském prostoru, zejména ty, které poskytují podporu ladění (např. kexec-tools, makedumpfile a crash-utility)
- 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:
- 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.
- 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.
- 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.