Vengineerの戯言

人生は短いけど、長いです。人生を楽しみましょう!

Zynq MPSoCで、コンピュータを学ぼう (その3)

はじめに

「Zynq MPSoCで、コンピュータを学ぼう」のその2です。

  • その1 : Xilinx社のZynqUltrascale+ MPSoC について
  • その2 : Zynq Ultrascale+ MPSoC がどのように立ち上がっていくのか
  • その3 : Linux の dts を見て、どのようなハードウェアを使っているのか?
  • その4 : Linuxデバイスドライバについて
  • その5 : Programmable Logic
  • その6 : QEMU (Zynq Ultrascale+ MPSoC の実物が無くても、Linuxが立ち上がる)

Linux の dts を見て、どのようなハードウェアを使っているのか?

Linuxソースコードを調べるポイントとしては、次の2つです。

  • dts ファイルの中を見て、どのようなハードウェアを使っているのか?
  • dts ファイルの中で使っているハードウェアのデバイスドライバは何をやっているのか?

今回は、この2つの内、最初の dts ファイルの中を見ていきます。

dts って何?

dts とは、device tree source の略です。Qiita に説明があります。

qiita.com

dts を DTC (Device Tree Compiler) というソフトウェアでコンパイルしたのが、DTB (Device Tree Blob) です。この DTB ファイルを Linux で使います。

Linuxで使っている DTB ファイルは、DTC にて逆アセンブルしてくれます。

Xilinx社に関係する dts の場所は、

github.com

にあります。

  • Ultra96 v1用 : avnet-ultra96-rev1.dts
  • Kria KV260用 : zynqmp-sm-k26-revA.dts / zynqmp-smk-k26-revA.dts

の dts があります。

Ultra96 v1用の avnet-ultra96-rev1.dts を見てみます。zynqmp-zcu100-revC.dts という dts ファイルを include しています。

/dts-v1/;

#include "zynqmp-zcu100-revC.dts"

/ {
    model = "Avnet Ultra96 Rev1";
    compatible = "avnet,ultra96-rev1", "avnet,ultra96",
             "xlnx,zynqmp-zcu100-revC", "xlnx,zynqmp-zcu100",
             "xlnx,zynqmp";
};

zynqmp-zcu100-revC.dts の最初で、zynqmp.dtsi ファイルを include しています。

/dts-v1/;

#include "zynqmp.dtsi"
#include "zynqmp-clk-ccf.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
#include <dt-bindings/phy/phy.h>

zynqmp-sm-k26-revA.dts でも同様に zynqmp.dtsi ファイルを include しています。

zynqmp.dtsi の中を覗いてみますと、下記の cpus に、ARM Cortex-A53x4 のエントリーがあります。

#include <dt-bindings/dma/xlnx-zynqmp-dpdma.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/power/xlnx-zynqmp-power.h>
#include <dt-bindings/reset/xlnx-zynqmp-resets.h>

/ {
    compatible = "xlnx,zynqmp";
    #address-cells = <2>;
    #size-cells = <2>;

    cpus {
        #address-cells = <1>;
        #size-cells = <0>;

        cpu0: cpu@0 {
            compatible = "arm,cortex-a53";
            device_type = "cpu";
            enable-method = "psci";
            operating-points-v2 = <&cpu_opp_table>;
            reg = <0x0>;
            cpu-idle-states = <&CPU_SLEEP_0>;
        };

        cpu1: cpu@1 {
            compatible = "arm,cortex-a53";
            device_type = "cpu";
            enable-method = "psci";
            reg = <0x1>;
            operating-points-v2 = <&cpu_opp_table>;
            cpu-idle-states = <&CPU_SLEEP_0>;
        };

        cpu2: cpu@2 {
            compatible = "arm,cortex-a53";
            device_type = "cpu";
            enable-method = "psci";
            reg = <0x2>;
            operating-points-v2 = <&cpu_opp_table>;
            cpu-idle-states = <&CPU_SLEEP_0>;
        };

        cpu3: cpu@3 {
            compatible = "arm,cortex-a53";
            device_type = "cpu";
            enable-method = "psci";
            reg = <0x3>;
            operating-points-v2 = <&cpu_opp_table>;
            cpu-idle-states = <&CPU_SLEEP_0>;
        };

        idle-states {
            entry-method = "psci";

            CPU_SLEEP_0: cpu-sleep-0 {
                compatible = "arm,idle-state";
                arm,psci-suspend-param = <0x40000000>;
                local-timer-stop;
                entry-latency-us = <300>;
                exit-latency-us = <600>;
                min-residency-us = <10000>;
            };
        };
    };

cpus の cpu0 を詳しく見てみます。cpuX: cpu@X の X は、コアの番号です。compatible の部分がどんなコアかを示すもので、"arm,cortex-a53"、つまり、ARM Cortex-A53 だということを示しています。

      cpu0: cpu@0 {
            compatible = "arm,cortex-a53";
            device_type = "cpu";
            enable-method = "psci";
            operating-points-v2 = <&cpu_opp_table>;
            reg = <0x0>;
            cpu-idle-states = <&CPU_SLEEP_0>;
        };

この中のポイントは、enable-method です。これは、省エネの時にどのような方法を行って制御するのかを示すもので、ここでは、"psci" となっています。psci とは、Power State Coordination Interface の略で、サスペンド、シャットダウン、リブートなど、Arm プロセッサのシステ ム電源ステータスを制御するための標準インターフェイスです。psci のエントリーは、下記のようになっています。"arm,psic-0.2", method が "smc" です。

  psci {
        compatible = "arm,psci-0.2";
        method = "smc";
    };

PSCIについては、下記のスライドにまとめていますので、参考にしてくださいね。

www.slideshare.net

PSCIは、ARM v8 64ビットの標準的な省エネ機能を実現するソフトウェアです。ただし、サーバーやAppleのM1シリーズ/M2 に関しては、"psci" にはなっていません。M1 (t8103) の dts ファイル (t8103.dts) の cpu0 のエントリーを見てみます。enable-method は、"spin-table" になっています。

      cpu0: cpu@0 {
            compatible = "apple,icestorm";
            device_type = "cpu";
            reg = <0x0 0x0>;
            enable-method = "spin-table";
            cpu-release-addr = <0 0>; /* To be filled by loader */
        };

"spin-table" の時の処理は、下記の smp_spin_table.c がそのようです。

github.com

おわりに

2016年2月20日(金)のZynq Ultrasclae+ MPSoC 勉強会で使った資料です。

この時には、Zynq Ultrascale+ MPSoC の実物はまだリリースされていませんでした。

こちらには、前半はブートの説明、後半はLinuxの説明をしています。

参考までに