ARMでメモリテスト Raspberry Pi2 でLinuxのearly_memtest

Linux Kernel 4.1からARMでもearly_memtest可能になった

メモリチェックソフトとしてはmemtest86が有名だけれど、このソフトのチェック処理はX86アセンブラで書かれており、ARM上では動作しない。

移植作業はホネが折れるがメモリテストはしておきたい。

と、そんな折、Linux Kernel 4.1からARMのmm初期化処理になにやらearly_memtestの文字が。

4.0まではx86限定?だったCONFIG_MEMTESTがARMでも使えるようになったっぽい。

ということでLinux Kernelのメモリテストを試してみる。

4.1のカーネルソースを取得

2015/07時点で、Raspberry Piの4.1カーネルは実験版のようだ。

Raspberry Pi2のカーネルソースは下記から取得して、4.1系のブランチをチェックアウトする。

raspberrypi/linux · GitHub

4.1系は、rpi-4.1.yというブランチで管理されていたので、下記コマンドでブランチを取得した。

$ git clone https://github.com/raspberrypi/linux.git
$ git checkout -b rpi-4.1.y origin/rpi-4.1.y

ツールチェインをチェックアウトしていない場合は、それもチェックアウトする。

$ git clone https://github.com/raspberrypi/tools.git

MEMTESTのconfigを有効にする

デフォルトのconfigをLoadしてからMEMTEST設定を有効化する。

$ make ARCH=arm bcm2709_defconfig
$ make ARCH=arm menuconfig

から、Kernel hackingを選択し、Memtestを選び、設定を有効化する。

f:id:nokute:20150724211410p:plain

カーネルのクロスコンパイル

Raspberry Pi 2 カーネル4.0.7のクロスコンパイルメモ - カッコ仮メモ置き

におおよそのことは書いてあるので、参考にしてコマンドをポチポチしていく。

下記でコンパイルして。

$ make ARCH=arm CROSS_COMPILE=../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- zImage modules dtbs
$ scripts/mkknlimg arch/arm/boot/zImage temp/kernel7.img

下記でtemp以下に必要なものを集める。

$ mkdir temp
$ mkdir temp/overlays
$ make ARCH=arm CROSS_COMPILE=../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- INSTALL_MOD_PATH=./temp  modules_install
$ cp arch/arm/boot/dts/*.dtb temp
$ cp arch/arm/boot/dts/overlays/*.dtb* temp/overlays
$ cp arch/arm/boot/dts/overlays/README temp/overlays
$ rm temp/lib/modules/4.1.2-v7+/source temp/lib/modules/4.1.2-v7+/build

インストール

上記のtempをscpなどでRaspberry Pi2に転送して、下記コマンドを実行する。

$ sudo cp temp/kernel7.img /boot/kernel7.img
$ sudo cp -r temp/lib /
$ sudo chown -R root /lib/modules
$ sudo chgrp -R root /lib/modules
$ sudo cp temp/*dtb /boot
$ sudo cp -r temp/overlays/ /boot

reboot後にunameでバージョンを確認する。

pi@raspberrypi ~ $ uname -a
Linux raspberrypi 4.1.2-v7+ #4 SMP PREEMPT Fri Jul 24 20:20:26 JST 2015 armv7l GNU/Linux

cmdline設定

menuconfigのhelpによると、cmdlineにてmemtest=という記述をして回数を指定する必要があるらしい。

/boot/cmdline.txtにmemtest=2を追記してみる。

pi@raspberrypi ~ $ sudo vi /boot/cmdline.txt
pi@raspberrypi ~ $ cat /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait memtest=2

memtestの動作確認結果

dmesgに下記のような出力がなされていれば動いているはず。

memtestを回すようにcmdline設定すると、起動後もシングルコアのままになる問題があったが、ひとまずスルーする。

pi@raspberrypi ~ $ dmesg
<中略>
[    0.000000] early_memtest: # of tests: 2
[    0.000000]   0000000000 - 0000000100 pattern ffffffffffffffff
[    0.000000]   0000008000 - 0000008240 pattern ffffffffffffffff
[    0.000000]   000091f74c - 003a7f2000 pattern ffffffffffffffff
[    0.000000]   003a7ff000 - 003a7ffe48 pattern ffffffffffffffff
[    0.000000]   0000000000 - 0000000100 pattern 0000000000000000
[    0.000000]   0000008000 - 0000008240 pattern 0000000000000000
[    0.000000]   000091f74c - 003a7f2000 pattern 0000000000000000
[    0.000000]   003a7ff000 - 003a7ffe48 pattern 0000000000000000
<中略>

どのようなテストか

実装はmm/memtest.cにある。

予め決まったパターンで8byteごとに値を書きこみ、その後の読み出しで化けていないかをチェックしているようだ。 パターンは4bit周期で0x0から0xfを繰り返した16パターンと、ASCIIでyeah ;-)となる数字列の17パターン。

ループ回数ごとに17パターンのうちのどれかを実施するようで、非常にシンプルなテスト。

memtest86+ほどの検知力は期待しない方が良いかも?

NGな領域があった場合は

ソースによると、下記のような文言が出力されるようだ。

static void __init reserve_bad_mem(u64 pattern, phys_addr_t start_bad, phys_addr_t end_bad)
{
    printk(KERN_INFO "  %016llx bad mem addr %010llx - %010llx reserved\n",
           (unsigned long long) pattern,
           (unsigned long long) start_bad,
           (unsigned long long) end_bad);
    memblock_reserve(start_bad, end_bad - start_bad);
}