Raspberry Pi: CMA area cannot be created on GPU memory without a help of firmware


概要

Raspberry Piにおいては,GPU側メモリをCMA領域として使用することができない. これは,ファームウェアの助けがないことと,カーネル内の初期化の順序によるものである. ファームウェアが起動時にGPU側メモリに大きな領域を確保し,そのアドレスとサイズを cmdline経由でカーネルに指定するようになれば,GPU側メモリをCMA領域として使えるようになるだろう.

環境

Raspberry Pi 3 Model B を用いた.Linuxカーネルは Idein:linux -b rpi-4.9.y を,これをコンパイルするためには cross-rpi-kernel のDockerコンテナとスクリプトを用いた.

GPU側メモリの確保

GPU側メモリの確保にはファームウェアとのインターフェイスであるMailboxを用いる. メモリ確保に関するMailboxコールには以下がある.

ALLOCATE_MEM
確保したいメモリサイズをファームウェアに登録する. ユニークなハンドルが返される.
LOCK_MEM
メモリを実際に確保し,バスアドレスが返される.
UNLOCK_MEM
メモリのロックを解除する.内容は保持される.
RELEASE_MEM
メモリを解放する.

Mailboxインターフェイスを使うには, rpi_firmware_propertyコールを用いる. rpi_firmware_propertyには,Device Treeに記述された ファームウェアからの情報を渡す必要がある. 具体的には以下のようにする.

      #include <soc/bcm2835/raspberrypi-firmware.h>

      ......

      struct device_node *np;
      struct rpi_firmware *fw;

      np = of_find_compatible_node(NULL, NULL, "raspberrypi,bcm2835-firmware");
      fw = rpi_firmware_get(np);
      if (!fw) {
          /* Error! */
      }

      ......

      int ret;
      struct {
          union {
              struct {
                  u32 handle;
              } in;
              struct {
                  u32 bus_addr;
              } out;
          };
      } ioparam = {
          .in = {
              .handle = ......;
          },
      };

      ret = rpi_firmware_property(fw, RPI_FIRMWARE_LOCK_MEMORY, &ioparam, sizeof(ioparam));
      if (ret) {
          /* Error! */
      }
    

なお,バスアドレスは~0xC000_0000との論理積をとると物理アドレスになる.

CMA領域の確保および登録

Linuxカーネルにおける初期化順序

Linuxカーネルには初期化関数を登録する機能があり,カーネルの起動時に 特定の関数を実行できる.初期化関数の順序は以下である.

      early, pure, core, postcore, arch, subsys, fs, rootfs, device, late
    
例えば,関数funcpure時に実行したい場合は, 関数宣言と登録は以下のようになる.
      static int __init func(void)
      {
          ......
      }
      pure_initcall(func);
    

Setting memory area as CMA

To read/write from/to registers of CP15, MRC and MCR instructions are used, respectively. The registers are selected by CRn, CRm, opc1 and opc2 arguments of the instructions. Table 1 shows a part of the registers related to caches. To be more precise, MRC p15, opc1, Rt, CRn, CRm, opc2 reads from a CP15 register and writes the content of it to an ARM register Rt, and MCR p15, opc1, Rt, CRn, CRm, opc2 writes the content of an ARM register Rt to a CP15 register.

Table 1. A part of CP15 registers related to caches
Name CRn CRm opc1 opc2 Description
CCSIDR c0 c0 1 0 Cache size ID register
CLIDR c0 c0 1 1 Cache level ID register
CSSELR c0 c0 2 0 Cache size selection register


Environment

Our experiments in this article are carried out on these boards:

They all have ARM CPUs and thus have CP15 coprocessor.

Accessing CP15 registers needs PL1 privilege, which is normally the one at which operating system runs. So we wrote a Linux driver which accesses CP15 registers on loading.


Obtaining cache information

First, we obtain the number of caches the ARM CPUs implement. The CLIDR register bits [$3(n-1)+2$:$3(n-1)$] indicates whether level-$n$ cache exists and the type of that if it does.

It is shown that Raspberry Pi 2 and 3 have level-1 and level-2 caches: the former is separated to instruction and data ones and the latter is unified.

In the next, we obtain the characteristics of the caches. The CCSIDR register shows policies and sizes of the caches selected in the CSSELR register. Bit $0$ of the CSSELR register indicates which type of the cache is selected ($0$ means data or unified cache and $1$ means instruction cache). And bits [$3$:$1$] indicates the level of the cache $-1$ selected (e.g., $0\mathrm{b}000$ indicates level-1 cache).

The results are shown on Table 2, Table 3 and Table 4.

Table 3. Raspberry Pi 2
L1C data L1C insn. L2C
Write-through not supported not supported not supported
Write-back supported not supported supported
Read-alloc supported supported supported
Write-alloc supported not supported supported
Num. of sets 128 512 1024
Associativity 4 2 8
Line size 16 8 16

Table 4. Raspberry Pi 3
L1C data L1C insn. L2C
Write-through not supported not supported not supported
Write-back supported not supported supported
Read-alloc supported supported supported
Write-alloc supported not supported supported
Num. of sets 128 256 512
Associativity 4 2 16
Line size 16 16 16


Reference


Copyright notice

© 2017 Yukimasa Sugizaki. All rights reserved.

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.