Linux Kernel に RDNA APU 「Cyan Skilfish」 をサポートするパッチが投稿される

Update: 2021/07/23 06:50 +0900

amd-gfxメーリングリストにて、Linux Kernel における AMD GPUドライバーに新たな RDNA APU Cyan Skilfish をサポートするパッチが公開された。一連のパッチの数は 29個で構成されている。

最初に書いておくと、一連のパッチの中でも SKILFISHSKILLFISH で表記が揺れており、とりあえず辞書を引いたところ、海水魚 アブラボウズの英名として SKILFISH が出てきたため、前者が正しいと考えここでは SKILFISH で統一する。

Index

"RDNA" APU

Cyan Skilfish は APU であり、パッチでは PCI (Device) ID に 0x13FE 1つが追加されている。
一応 The PCI ID Repository を確認したが、0x13FE はまだ登録されていなかった。

 +   /* CYAN_SKILLFISH */
 +   {0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
 +

Cyan Skilfish は Navi10 (Navi12) と同じキャッシュ構成を採っているとしている。 Navi10/Navi12/Cyan Skilfish のキャッシュ構成は、CU ごとの L1ベクタキャッシュは 16KiB、WGP 1基 (CU 2基) で共有する L1命令キャッシュは 32KiB、同様の L1データキャッシュは 16KiB、
ShaderArray ごとに持つ RDNA L1キャッシュ、オープンソースドライバー上では GL1データキャッシュとも呼ばれるものは 128KiB、そしてメモリサイドキャッシュである L2データキャッシュは 4096KiB (4MiB)、というものになる。
AMD GPU のキャッシュ構成情報 ―― Dimgrey Cavefish / Aldebaran / VanGogh | Coelacanth's Dream

     case CHIP_NAVI10:
     case CHIP_NAVI12:
 +   case CHIP_CYAN_SKILLFISH:
         pcache_info = navi10_cache_info;
         num_of_cache_types = ARRAY_SIZE(navi10_cache_info);
         break;
     static struct kfd_gpu_cache_info navi10_cache_info[] = {
     {
         /* TCP L1 Cache per CU */
         .cache_size = 16,
         .cache_level = 1,
         .flags = (CRAT_CACHE_FLAGS_ENABLED |
                 CRAT_CACHE_FLAGS_DATA_CACHE |
                 CRAT_CACHE_FLAGS_SIMD_CACHE),
         .num_cu_shared = 1,
     },
     {
         /* Scalar L1 Instruction Cache per SQC */
         .cache_size = 32,
         .cache_level = 1,
         .flags = (CRAT_CACHE_FLAGS_ENABLED |
                 CRAT_CACHE_FLAGS_INST_CACHE |
                 CRAT_CACHE_FLAGS_SIMD_CACHE),
         .num_cu_shared = 2,
     },
     {
         /* Scalar L1 Data Cache per SQC */
         .cache_size = 16,
         .cache_level = 1,
         .flags = (CRAT_CACHE_FLAGS_ENABLED |
                 CRAT_CACHE_FLAGS_DATA_CACHE |
                 CRAT_CACHE_FLAGS_SIMD_CACHE),
         .num_cu_shared = 2,
     },
     {
         /* GL1 Data Cache per SA */
         .cache_size = 128,
         .cache_level = 1,
         .flags = (CRAT_CACHE_FLAGS_ENABLED |
                 CRAT_CACHE_FLAGS_DATA_CACHE |
                 CRAT_CACHE_FLAGS_SIMD_CACHE),
         .num_cu_shared = 10,
     },
     {
         /* L2 Data Cache per GPU (Total Tex Cache) */
         .cache_size = 4096,
         .cache_level = 2,
         .flags = (CRAT_CACHE_FLAGS_ENABLED |
                 CRAT_CACHE_FLAGS_DATA_CACHE |
                 CRAT_CACHE_FLAGS_SIMD_CACHE),
         .num_cu_shared = 10,
     },
 };

ソースコード中では、RDNA 2/GFX10.3 GPU も一部は RDNA/GFX10.1 GPU と同じレジスタ設定等を用いていることもあり、RDNARDNA 2 かという判断が曖昧になる部分が出てくるが、
GFXコア部に関する部分では Navi10/Navi12/Navi14RDNA/GFX10.1 GPU と同じものを使用しているため、Cyan SkilfishRDNA/GFX10.1 を GPU部に採用した APU だと考えられる。

     [CHIP_DIMGREY_CAVEFISH] = &gfx_v10_3_kfd2kgd,
     [CHIP_BEIGE_GOBY] = &gfx_v10_3_kfd2kgd,
     [CHIP_YELLOW_CARP] = &gfx_v10_3_kfd2kgd,
 +   [CHIP_CYAN_SKILLFISH] = &gfx_v10_kfd2kgd,
  };
  @@ -4748,6 +4759,7 @@ static int gfx_v10_0_sw_init(void *handle)
     case CHIP_NAVI10:
     case CHIP_NAVI14:
     case CHIP_NAVI12:
 +   case CHIP_CYAN_SKILLFISH:
         adev->gfx.me.num_me = 1;
         adev->gfx.me.num_pipe_per_me = 1;
         adev->gfx.me.num_queue_per_pipe = 1;
 @@ -7712,6 +7724,7 @@ static int gfx_v10_0_early_init(void *handle)
     case CHIP_NAVI10:
     case CHIP_NAVI14:
     case CHIP_NAVI12:
 +   case CHIP_CYAN_SKILLFISH:
         adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_NV1X;
         break;

そして興味深いことに、 amd_asci_type 列挙体に Cyan Skilfish を追加する際、最近になって追加された Yellow Carp APU の後ではなく、Navi10Navi14 の間に入るように追加されている。

若干直感的ではあるが、以前 LLVM に追加された GPUID: gfx1013 が示す APU が Cyan Skilfish だと自分は考えている。何よりも gfx1013Cyan SkilfishRDNA APU という点が一致する。現在、他に RDNA APU は AMD GPU のオープンソースソフトウェアスタックにおいて存在しない。

Navi10Navi12/Navi14 は同じ RDNA/GFX10.1 世代であっても対応する機能や命令に違いが存在し、基本的に Navi12/Navi14 が多くの機能、命令をサポートしている。
Navi12/Navi14 が対応する、RB (Render Backend) 部における DCC (Delta Color Compression) 機能やドット積命令の一部は Navi10 ではサポートされていない。
RadeonSI、RADV が AMD Navy Flounder をサポート | Coelacanth's Dream gfx1013 は命令範囲について Navi10/gfx1010 をベースにしており、ドット積命令の一部に対応しない点も引き継いでいる。
RDNA/GFX10.1世代に新たな GPUID、gfx1013? | Coelacanth's Dream GPUID: gfx1013 は RDNA/Navi10ベースの APU で、レイトレーシング命令をサポートしている? | Coelacanth's Dream

GPU ASIC の開発時期を反映したか、関連して Navi10 をベースにしたとするならば、わざわざ Navi10Navi14 の間に Cyan Skilfish を置いたことがしっくりいく。

     CHIP_NAVI10,    /* 26 */
 -   CHIP_NAVI14,    /* 27 */
 -   CHIP_NAVI12,    /* 28 */
 -   CHIP_SIENNA_CICHLID,    /* 29 */
 -   CHIP_NAVY_FLOUNDER, /* 30 */
 -   CHIP_VANGOGH,   /* 31 */
 -   CHIP_DIMGREY_CAVEFISH,  /* 32 */
 -   CHIP_BEIGE_GOBY,    /* 33 */
 -   CHIP_YELLOW_CARP,   /* 34 */
 +   CHIP_CYAN_SKILLFISH,    /* 27 */
 +   CHIP_NAVI14,    /* 28 */
 +   CHIP_NAVI12,    /* 29 */
 +   CHIP_SIENNA_CICHLID,    /* 30 */
 +   CHIP_NAVY_FLOUNDER, /* 31 */
 +   CHIP_VANGOGH,   /* 32 */
 +   CHIP_DIMGREY_CAVEFISH,  /* 33 */
 +   CHIP_BEIGE_GOBY,    /* 34 */
 +   CHIP_YELLOW_CARP,   /* 35 */
     CHIP_LAST,
  };

ディスプレイ出力はサポートせず?

それと Cyan Skilfish は APU だが、今回のパッチではディスプレイコントローラー/エンジン部のサポートが追加されていない。
それだけでなくディスプレイコントローラー/エンジン部の IP に関しても仮想的なものを用いるように記述されており、ディスプレイ出力をサポートした Cyan Skilfish を想定していないか、あるいは本当に元から Cyan Skilfish にディスプレイ出力とコントローラー/エンジンが実装されていないか、だと思われる。

 +   case CHIP_CYAN_SKILLFISH:
 +       amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
 +                amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
 +                amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
 +                if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
 +                        amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
 +                amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
 +                amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
 +       break;

Cyan Skilfish と Cyan Skilfish2

Cyan Skilfish にはもう 1つ、Cyan Skilfish2 が存在することが示されており、読み込むファームウェアはその 2つで別に用意されることになっている。

 +   case CHIP_CYAN_SKILLFISH:
 +       if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)
 +           chip_name = "cyan_skillfish2";
 +       else
 +           chip_name = "cyan_skillfish";
 +       break;

ただ、ここで chip_name"cyan_skillfish2" と判定する部分に使われているフラグは PCI ID が 0x13FE の時にセットされるようになっている。上で触れたように Cyan Skilfish の ID として追加されたのはその 0x13FE のみである。
今回のパッチで想定しているのは Cyan Skilfish2 のみで、恐らくそうでない Cyan Skilfish は開発中に何かしらのバグがあった GPU ASIC ではないかと思われる。

 +   case CHIP_CYAN_SKILLFISH:
 +       if (adev->pdev->device == 0x13FE)
 +           adev->apu_flags |= AMD_APU_IS_CYAN_SKILLFISH2;
 +       break;

また、Cyan Skilfish/2 で処理が分けられているのは主に PSP (Platform Security Processor) に関する部分であり、開発中に問題が発生してしまったのも PSP部ではないかと考えられる。
Cyan Skilfish は PSP の IPバージョンが異なり、PSP v11.0.8 を採用している。
他の RDNA / RDNA 2 APU/GPU は PSP v11.0 を採用しているため、新規に開発したとすれば問題が起きやすいことが想像できる。

     case CHIP_CYAN_SKILLFISH:
 +       if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2 &&
 +           load_type > 1)
 +           return AMDGPU_FW_LOAD_PSP;
         return AMDGPU_FW_LOAD_DIRECT;

8-Core APU

Cyan Skilfish は SMU (System Management Unit) に関する記述から、CPU部 8-Core を持つ APU だと考えられる。
8-Core APU には Xbox Series S|X SoCPS5 SoC 、後はまあ AMD 4700S とか色々存在するが、0x13FEThe PCI ID Repository にもまだ追加されていなかった ID であり、そして AMD が公式的に提供している情報では Cyan Skilfish についてそれ以上の判断はできないため、とりあえず自分が触れるのもここまでにしておきたい。

 +#define NUMBER_OF_PSTATES      8
 +#define NUMBER_OF_CORES            8
 +typedef enum {
 +   CPU_CORE0 = 0,
 +   CPU_CORE1,
 +   CPU_CORE2,
 +   CPU_CORE3,
 +   CPU_CORE4,
 +   CPU_CORE5,
 +   CPU_CORE6,
 +   CPU_CORE7
 +} CORE_ID_e;
FeedbackChangelog