@Vengineerの戯言 : Twitter
SystemVerilogの世界へようこそ、すべては、SystemC v0.9公開から始まった
はじめに
Apple M1 で Linux 動くようになったのは、先週のブログにまとめました。
Linux では、Kernel (Imageなど)の他に、dts ファイルをコンパイル(バイナリ化)した dtb ファイルを読み込んでブートします。
この dts ファイルには、どのモジュールがどのアドレスにあって、どのくらいの空間(サイズ)を使っているのか?割り込みやその他の情報を設定するファイルであります。dts ファイルで設定された情報から Linux がブート中に各デバイスドライバを呼び出すのに使います。
ARM64用の dts ファイルは、arch/arm64/boot/dts ディレクトリにあります。各ベンダ毎にディレクトリに分かれています。Apple M1 Mac mini 用の dts ファイルは、apple ディレクトリの apple-m1-j274.dts です。j274 が Mac mini の型番か何かになっているんだと思います。
Apple M1 Mac mini のアドレスマップ
apple-m1-j274.dtsから各モジュールのアドレスとサイズを抽出し、どのようになっているかを見てみます。
まとめたのが、こんな感じになりました。
- memory 0x8 0x00000000 0x2 0x00000000
- fw_area 0x8 0x00000000 0x0 0x01000000
- fw_area 0x9 0xd0000000 0x0 0x30000000
- smpentry 0x8 0x03400000 0x0 0x4000
- I/O-1 0x2 0x00000000 0x2 0x00000000
- USB
- I/O-2 0x5 0x00000000 0x0 0x80000000
- USB
- I/O-3 0x6 0x80000000 0x0 0x20000000
- PCIe Port-0 0x6 0x81000000 0x0 0x20000
- PCIe Port-1 0x6 0x82000000 0x0 0x20000
- PCIe Port-2 0x6 0x83000000 0x0 0x20000
メモリは、0x8_0000_0000 からの 8GB です。この dts ファイルでは、8GBモデルになっています。16GBモデルになった場合、このエントリのサイズ部分の 0x2_0000_0000 が 0x4_0000_0000 になるのか、他のアドレス空間に 8GB のメモリがマッピングされるかはこのファイルではわかりません。
メモリの中に、fw_area が 2か所と smpentry が 1か所あります。この3つの領域は、Linuxが使用するメモリから除外されます。
I/O空間は、3つ。0x2_0000_0000 から 8GBの I/O-1、0x5_0000_0000 からの 2GBの I/O-2、0x6_8000_0000 からの 512MBのI/O-3 です。
I/O-1はUSB、I/O-2はUSB、I/O-3はPCIe の空間のようです。I/O-3のPCIe の空間では、3つのポートに対して、128KBを割り当てています。
ここまでは、CPUコアから見たアドレス空間です。下図は、先週のブログにも載せた図です。DMAを行う各モジュールには図のように I/O MMU が付いています。この I/O MMU を使って、論理アドレスから物理アドレス(上記の 0x8_0000_0000 からの8GB) に変換します。
dts ファイルでは、USBに関しては usb_dart、PCIeに関しては pcie_dart が I/O MMU になります。
下記は、I/O-1のUSB用のI/O MMU 部です。アドレス空間は2つで、0x3_82f0_0000 から 512KB と 0x3_2f80_0000 からの16KB です。page-bits というものが Page size を意味していて、14とありますので、14ビット、16KBが Page size になります。一般的なLinux (x86-64やarm32, arm64)では、4KB ですが、Apple の iOS/iPadOS/最新macOS では Page size が 16KB になっているので、同じになります。
usb_dart0: usb_dart0@382f00000 { compatible = "apple,dart-m1"; clocks = <&atc0_usb>; reg = <0x3 0x82f00000 0x0 0x80000 0x3 0x82f80000 0x0 0x4000>; interrupts = <0 781 4>; page-bits = <14>; sid-mask = <11>; sid-remap = <0 1>; #iommu-cells = <1>; };
下記は、PCIe の I/O MMU 部です。こちらのアドレス空間は、ひとつで、0x6_8100_8000 から 16KB です。page-bits が 14 なので、こちらも Page size は 16KB になります。
pcie_dart0: pcie_dart0@681008000 { compatible = "apple,dart-m1"; clocks = <&pcie_gp_clk>; reg = <0x6 0x81008000 0x0 0x4000>; interrupts = <0 696 4>; pcie-dart; page-bits = <14>; sid-mask = <65535>; #iommu-cells = <1>; };
PCIe の I/O MMU は、3つ、pcie_dart0、pcie_dart1、pcie_dart2、あります。この I/O MMU は、下記の pcie の ports と空いてあるところに接続しているんだと思っています。
pcie: pcie@690000000 { compatible = "apple,pcie-m1"; reg = <0x6 0x90000000 0x0 0x1000000 /* config */ 0x6 0x80000000 0x0 0x100000 0x6 0x8c000000 0x0 0x100000 /* core and AXI bridge */ 0x6 0x81000000 0x0 0x20000 0x6 0x82000000 0x0 0x20000 0x6 0x83000000 0x0 0x20000>; /* ports */ 途中、省略 iommu-map = <0x0000 &pcie_dart0 0x8000 0x0100>, /* fake, and should never be used as RC bridges don't DMA */ <0x0100 &pcie_dart0 0x0000 0x0100>, <0x0200 &pcie_dart1 0x0000 0x0100>, <0x0300 &pcie_dart2 0x0000 0x0100>; refclk-always-on-2; max-speed-2 = <1>; /* 2.5 GT/s */ };