読者です 読者をやめる 読者になる 読者になる

Ryzen上でlinuxカーネルをテストしようとしたら問題が出た(未解決)

最近Ryzenを積んだデスクトップマシンを買いました。その上でカーネルビルド&テストをしようとしたんですが、2点問題が発生しました。先代のCore i5を積んだマシンでは起きなかった現象です。

NOTE: このエントリはメモがてら、随時更新していきます。落ち着いたらどこかにまとめるかも。

問題1: linux カーネルのビルドには成功するが、ビルドしたカーネルをguest上でブートしたら起動中に死ぬ(原因判明、修正待ち)

ブート時のカーネルのログはこんなかんじ。

...
[    0.227720] raid6: sse2x1   gen()  7985 MB/s
[    0.295709] raid6: sse2x1   xor()  8181 MB/s
[    0.363706] raid6: sse2x2   gen() 17531 MB/s
[    0.431699] raid6: sse2x2   xor() 11098 MB/s
[    0.499693] raid6: sse2x4   gen() 18509 MB/s
[    0.567688] raid6: sse2x4   xor() 10177 MB/s
[    0.571692] invalid opcode: 0000 [#1] SMP
[    0.572312] Modules linked in:
[    0.572822] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.11.0-rc8-ktest #1
[    0.573734] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
[    0.575040] task: ffff8f791e1c0000 task.stack: ffff9c72c00d0000
[    0.575865] RIP: 0010:raid6_avx21_gen_syndrome+0x3d/0x120
[    0.576634] RSP: 0018:ffff9c72c00d3d70 EFLAGS: 00010246
[    0.577376] RAX: 0000000000000000 RBX: ffff9c72c00d3dc0 RCX: 00000000fffedb97
[    0.578327] RDX: 0000000000000000 RSI: 0000000000001000 RDI: 0000000000000012
[    0.579283] RBP: ffff9c72c00d3da0 R08: 0000000000000000 R09: 00000000000000cd
[    0.580243] R10: 00000000fffedb86 R11: ffffffffa617008d R12: 0000000000001000
[    0.581211] R13: ffff8f791e39e000 R14: ffff8f791e39f000 R15: 0000000000000012
[    0.582163] FS:  0000000000000000(0000) GS:ffff8f791fc00000(0000) knlGS:0000000000000000
[    0.583324] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    0.584128] CR2: 0000000000000000 CR3: 000000001be09000 CR4: 00000000003006f0
[    0.585078] Call Trace:
[    0.594952]  raid6_select_algo+0x116/0x30b
[    0.595592]  ? libcrc32c_mod_init+0x2b/0x2b
[    0.596240]  do_one_initcall+0x53/0x1a0
[    0.596843]  ? parse_args+0x2cf/0x490
[    0.597421]  kernel_init_freeable+0x182/0x21c
[    0.598077]  ? rest_init+0x80/0x80
[    0.598626]  kernel_init+0xe/0x100
[    0.599175]  ret_from_fork+0x2c/0x40
[    0.599741] Code: 55 41 54 53 48 89 d3 48 8d 14 c5 00 00 00 00 41 89 ff 49 89 f4 48 83 ec 08 4c 8b 2c c3 4c 8b 74 13 08 48 89 55 d0 e8 53 ed a9 ff <c5> fd 6f 05 2b 2d 4e 00 c5 e5 ef db 4d 85 e4 48 8b 55 d0 0f 84
[    0.602215] RIP: raid6_avx21_gen_syndrome+0x3d/0x120 RSP: ffff9c72c00d3d70
[    0.603154] ---[ end trace 17ee01f86b8fc548 ]---
[    0.603850] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[    0.603850]
[    0.605276] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
...

AVX2命令の実行中に不正な命令を発行したとしてパニックしています。RyzenではAVX2命令が使えるはずだし、AMDのマニュアルを見ると仮想化環境では使えないとか書いてないように見えるし(隅から隅まで読んだわけではないので間違ってるかも)、なんかおかしい。次のようなダーティハックでとりあえずブートできるようにはなった。as-instrが何をするものなのかは知りません。

]diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 2d44933..b589097 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -162,7 +162,7 @@ asinstr := $(call as-instr,fxsaveq (%rax),-DCONFIG_AS_FXSAVEQ=1)
 asinstr += $(call as-instr,pshufb %xmm0$(comma)%xmm0,-DCONFIG_AS_SSSE3=1)
 asinstr += $(call as-instr,crc32l %eax$(comma)%eax,-DCONFIG_AS_CRC32=1)
 avx_instr := $(call as-instr,vxorps %ymm0$(comma)%ymm1$(comma)%ymm2,-DCONFIG_AS_AVX=1)
-avx2_instr :=$(call as-instr,vpbroadcastb %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)
+#avx2_instr :=$(call as-instr,vpbroadcastb %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)
 avx512_instr :=$(call as-instr,vpmovm2b %k1$(comma)%zmm5,-DCONFIG_AS_AVX512=1)
 sha1_ni_instr :=$(call as-instr,sha1msg1 %xmm0$(comma)%xmm1,-DCONFIG_AS_SHA1_NI=1)
 sha256_ni_instr :=$(call as-instr,sha256msg1 %xmm0$(comma)%xmm1,-DCONFIG_AS_SHA256_NI=1)

とりえあずは問題を整理してバグ報告しました。

LKML: Satoru Takeuchi: [BUG] x86: failed to boot a kernel on a Ryzen machine

幸いにもBorislav Petkovさん(linuxカーネルのいろんなコンポのメンテナ)からレスをいただき、彼のの環境で再現もできました。かつ、AMDRyzen Engineering Teamにも転送されたようです。

その後Masami Hiramatsuさん(kprobesのメンテナ)から、VMに見えているCPUのモデルと機能フラグの組み合わせの問題では、という指摘を受けました。

www.spinics.net

自分の環境ではlibvirtを使ってVMを管理しています。CPUのモデルはhostと同じもの(host-model)になるよう設定しているのですが、今のlibvirtではそれが実際には古いOpteron_G3に設定されます。これを、CPUのモデルをOpteron_G5にして、かつ、Ryzenがサポートしない機能(fma4, tbm, およびXOP)のフラグを落としたところ、無事上記カーネルで起動成功しました。

その後さらにPaolo Bonziniさん(KVMのメンテナかつqemu開発者)に、新しいCPUではこういうことがよくあること、およびmodeを"host-passthrough"にするように言われ、その通りにするとパニックしなくなりました。これでqemuのCPU modelにRyzen(あるいはZen)を追加してもらえれば完了なはずです。

問題2: linuxカーネルのビルド中に gcc が SEGV で死ぬ(原因不明、調査中)

/home/sat/src/elkdat/linux/block/partition-generic.c: In function 'part_alignment_offset_show':
/home/sat/src/elkdat/linux/block/partition-generic.c:103:1: internal compiler error: Segmentation fault
 }
 ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-5/README.Bugs> for instructions.
/home/sat/src/elkdat/linux/scripts/Makefile.build:294: recipe for target 'block/partition-generic.o' failed
make[2]: *** [block/partition-generic.o] Error 1

カーネルを10回連続でビルドしたら、7回成功して3回はsegmentation faultで死にました。死んだ場所はそれぞれ全然違うところです。このため、gccに関する問題というよりも、CPUやメモリなどのハードの問題に見えます。Gentoo Forumでも類似の報告がありました。

Gentoo Forums :: View topic - Segfaults during compilation on AMD Ryzen.

とりあえず自分の環境でも再現したことを同フォーラムに報告しましたが、Ubuntuの話をしたことが気にくわなかったらしい人に怒られて、投稿が削除されてしまいました。とりあえずGentoo Forumは今後ROMるだけにすると決めました。

最新カーネル(4.12-rc1)にアップデートした上で再現テストをすると、問題は依然残っていることがわかりました。この他に、こうすれば直った/回避できたという情報が錯綜していますが、私の環境ではどれも効果無しでした。

現在はAMDのサポートに問題を報告した上で、やりとり中です。当初はプライベートなサポートチケットを発行したのですが、応答が極端に鈍くてまともに調査してるか、そもそも問題として認識しているのかどうかもわからないような状況だったので困っていました。再度web上を調査したところ、問題認識当初は無かった、同じ問題についての報告する次のようなスレッドがサポートフォーラムにできていることがわかりました。

community.amd.com

ここで「AMDはこの問題をハンドルしてるのか、および、できれば進捗を教えてほしい。できれば公開で」と言うと、公式から「調査中である。進捗があったらここで報告する」という回答を得ました。どうやら問題そのものが無視/黙殺されている最悪のケースは回避できたようなので安心しました。