GNU/Linux >> Linux の 問題 >  >> Linux

Arm64カーネルでの52ビット仮想アドレスのサポートを理解する

64ビットハードウェアが利用可能になった後、より大きなアドレス空間(2バイトを超える)を処理する必要性が明らかになりました。一部のベンダーは現在、64TiB(またはそれ以上)のメモリを備えたサーバーを提供していますが、x86_64およびarm64では、2バイトを超えるアドレススペースのアドレス指定が可能になりました(デフォルトの48ビットアドレスサポートで利用可能)。

x86_64は、ハードウェアとソフトウェアの両方で5レベルのページテーブルのサポートを有効にすることで、これらのユースケースに対処しました。これにより、2バイトに等しいアドレス空間のアドレス指定が可能になります(詳細については、x86:v4.12で有効になっている5レベルのページングを参照してください)。制限を128PiBの仮想アドレス空間と4PiBの物理アドレス空間に引き上げます。

arm64は、ARMv8.2 LVA(大規模仮想アドレス指定)とARMv8.2 LPA(大規模物理アドレス指定)という2つの新しいアーキテクチャ拡張機能を導入することで同じことを実現しました。これらにより、4PiBの仮想アドレス空間と4 PiBの物理アドレス空間(つまり、それぞれ2ビット)が可能になります。

その他のLinuxリソース

  • Linuxコマンドのチートシート
  • 高度なLinuxコマンドのチートシート
  • 無料のオンラインコース:RHELの技術概要
  • Linuxネットワーキングのチートシート
  • SELinuxチートシート
  • Linuxの一般的なコマンドのチートシート
  • Linuxコンテナとは何ですか?
  • 最新のLinux記事

新しいarm64CPUで利用可能なARMv8.2アーキテクチャ拡張機能により、2つの新しいハードウェア拡張機能がオープンソースソフトウェアでサポートされるようになりました。

Linuxカーネルバージョン5.4以降、arm64アーキテクチャに52ビット(大)仮想アドレス(VA)と物理アドレス(PA)のサポートが導入されました。カーネルのドキュメントでは、これらの機能と、古いCPU(ハードウェアで52ビットVA拡張をサポートしない)および新しいCPU(ハードウェアで52ビットVA拡張をサポートする)で実行される新しいカーネルにどのように影響するかについて説明していますが、平均的なユーザーがそれらを理解し、52ビットスペースからのVAの受信に「オプトイン」する方法を理解するには複雑です。

したがって、この記事ではこれらの比較的新しい概念を紹介します。

  1. これらの機能のサポートが追加された後、Arm64のカーネルメモリレイアウトがどのように「反転」したか
  2. ユーザースペースアプリケーション、特にデバッグサポートを提供するアプリケーション(kexec-tools、makedumpfile、crash-utilityなど)への影響
  3. ユーザースペースアプリケーションが、48ビットより大きいmmapヒントパラメータを指定することにより、52ビットスペースからのVAの受信に「オプトイン」する方法

ARMv8.2アーキテクチャLVAおよびLPA拡張機能

ARMv8.2アーキテクチャは、ラージ仮想アドレス指定(LVA)とラージ物理アドレス指定(LPA)の2つの重要な拡張機能を提供します。

ARMv8.2-LVAは、64KB変換グラニュールを使用する場合、最大52ビットの変換テーブルベースレジスタごとに、より大きなVAスペースをサポートします。

ARMv8.2-LPAでは次のことが可能です:

  • 64KBの変換グラニュルを使用する場合、最大52ビットのより大きな中間物理アドレス(IPA)とPAスペース
  • 実装が52ビットのPAをサポートしている場合、ブロックが64KB変換グラニュルの4TBアドレス範囲をカバーするレベル1ブロックサイズ

これらの機能はAArch64状態でのみサポートされていることに注意してください。

現在、次のArm64Cortex-AプロセッサがARMv8.2拡張機能をサポートしています。

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

詳細については、Armv8アーキテクチャリファレンスマニュアルを参照してください。

Arm64のカーネルメモリレイアウト

ARMv8.2拡張機能がLVAスペース(64KBのページサイズで実行している場合にのみ使用可能)のサポートを追加すると、記述子の数が第1レベルの変換で拡張されます。

ユーザーアドレスのビット63:48は0に設定されていますが、カーネルアドレスの同じビットは1に設定されています。TTBRxの選択は、仮想アドレスのビット63によって行われます。 swapper_pg_dir ユーザーがpgdであるのに対し、カーネル(グローバル)マッピングのみが含まれます ユーザー(非グローバル)マッピングのみが含まれます。 swapper_pg_dir アドレスはTTBR1に書き込まれ、TTBR0には書き込まれません。

64KBページと3つのレベル(ハードウェアサポート付きの52ビット)を備えたAArch64 Linuxメモリレイアウト:

  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]

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

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

カーネルでの52ビットVAのサポート

LVAをサポートする新しいカーネルは古いCPU(ハードウェアでLVA拡張をサポートしない)と新しいCPU(ハードウェアでLVA拡張をサポートする)でうまく動作するはずなので、選択した設計アプローチは、サポートする単一のバイナリを使用することです。 52ビット(ハードウェア機能が存在しない場合は、起動時に48ビットにフォールバックできる必要があります)。つまり、VMEMMAPは、52ビットVAに十分なサイズである必要があり、固定のPAGE_OFFSETに対応するのに十分なサイズである必要があります。 。

この設計アプローチでは、カーネルが新しい仮想アドレス空間に対して次の変数をサポートする必要があります。

VA_BITS         constant        the *maximum* VA space size

vabits_actual   variable        the *actual* VA space size

つまり、VA_BITS 最大VAスペースサイズを示します。サポートされる実際のVAスペース(起動時に行われたスイッチによって異なります)は、vabits_actualで示されます。 。

カーネルメモリレイアウトの反転

単一のカーネルバイナリを保持する設計アプローチでは、カーネル.textが48/52ビットVAに対して不変であるように、より高いアドレスにある必要があります。カーネルアドレスサニタイザー(KASAN)シャドウはカーネルVAスペース全体の一部であるため、KASANシャドウの終わりも48ビットと52ビットの両方でカーネルVAスペースの上位半分にある必要があります。 (48ビットから52ビットに切り替えると、KASANシャドウの終わりは不変であり、~0ULに依存します。 、開始アドレスは下位アドレスに向かって「成長」します。

phys_to_virt()を最適化するには およびvirt_to_phys()PAGE_OFFSET 0xFFF0000000000000で一定に保たれます (52ビットに対応)、これにより、余分な変数の読み取りが不要になります。 physvirt およびvmemmap このロジックを有効にするために、初期起動時にオフセットが計算されます。

次の物理RAMと仮想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
カーネルのデバッグに使用されるユーザースペースアプリケーションへの影響

実行中/ライブカーネルをデバッグしたり、クラッシュしたシステムからのvmcoreダンプを分析したりするために(たとえば、カーネルクラッシュの根本原因を特定するために)、kexec-tools、makedumpfile、crash-utilityなどのいくつかのユーザースペースアプリケーションが使用されます。

これらをArm64カーネルのデバッグに使用すると、Arm64カーネルのメモリマップが「反転」するため、これらにも影響があります。これらのアプリケーションは、仮想アドレスに対応する物理アドレスを決定するために変換テーブルウォークを実行する必要もあります(カーネルで行われる方法と同様です)。

したがって、ユーザースペースアプリケーションは、カーネルメモリマップに「フリップ」が導入された後にアップストリームで中断されるため、変更する必要があります。

影響を受ける3つのユーザースペースアプリケーションの修正を提案しました。上流で受け入れられたものもあれば、まだ保留中のものもあります:

  • 提案されたmakedumpfileアップストリーム修正
  • 提案されたkexec-toolsアップストリーム修正
  • crash-utilityで受け入れられた修正

これらの変更がユーザースペースアプリケーションで行われない限り、実行中/ライブカーネルのデバッグや、クラッシュしているシステムからのvmcoreダンプの分析のために壊れたままになります。

52ビットのユーザースペースVA

ARMv8.0 VAスペースの最大サイズ48ビットに依存するユーザースペースアプリケーションとの互換性を維持するために、カーネルはデフォルトで仮想アドレスを48ビット範囲からユーザースペースに返します。

ユーザースペースアプリケーションは、48ビットより大きいmmapヒントパラメータを指定することにより、52ビットスペースからのVAの受信に「オプトイン」できます。

例:

.mmap_high_addr.c
----

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

次のカーネル構成オプションを有効にすることで、52ビットスペースからアドレスを返すデバッグカーネルを構築することもできます。

   CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y

このオプションはアプリケーションのデバッグのみを目的としており、使用しないことに注意してください。 本番環境で使用できます。

結論

要約すると:

  1. Linuxカーネルバージョン5.14以降、新しいArmv8.2ハードウェア拡張機能LVAおよびLPAがLinuxカーネルで十分にサポートされるようになりました。
  2. カーネルのデバッグに使用されるkexec-toolsやmakedumpfileなどのユーザースペースアプリケーションが壊れています現在 上流の修正が受け入れられるのを待っています。
  3. 48ビットVAを提供するArm64カーネルに依存するレガシーユーザースペースアプリケーションはそのまま動作し続けますが、新しいユーザースペースアプリケーションは、mmapヒントパラメーターを指定することで52ビットスペースからのVAの受信に「オプトイン」できます。これは48ビットより大きいです。

この記事は、AArch64LinuxおよびLinuxカーネルのドキュメントv5.9.12のメモリレイアウトを利用しています。どちらもGPLv2.0でライセンスされています。


Linux
  1. Linux –カーネル:名前空間のサポート?

  2. LANネットワーク上でコンピューターを見つけますか?

  3. XfceでのHidpiサポートのステータスは?

  1. Linux – Dmesgの仮想カーネルメモリレイアウトは何を意味しますか?

  2. ターミナルでHZを確認するには?

  3. 新しいハードウェア サポートはどのように Linux カーネルに追加されますか?

  1. Linuxカーネル:イノベーショントップ5

  2. Linuxカーネルテストのライフサイクル

  3. RaspberryPi4でUbuntu20.04Ltsを使用してカーネル(arm64)をカスタマイズしますか?