26
1 Tricky implementation Of Go ARM soft float Tetsuyuki Kobayashi 2015.2.14 Kernel/VM 2015.2.22 YAPF

Tricky implementation of Go ARM soft float

Embed Size (px)

Citation preview

1

Tricky implementationOf Go ARM soft float

Tetsuyuki Kobayashi

2015.2.14 Kernel/VM 探検隊2015.2.22 YAPF

2

The latest version of this slide will be available from here

http://www.slideshare.net/tetsu.koba/presentations

3

Who am I?

20+ years involved in embedded systems 10 years in real time OS, such as iTRON 10 years in embedded Java Virtual Machine Now GCC, Linux, QEMU, Android, …

Blogs http://d.hatena.ne.jp/embedded/ http://kobablog.wordpress.com/(English)

Twitter @tetsu_koba

4

Golang for ARM Linux

ツールチェインのビルド ソースコードを入手して

$ cd go/src$ GOOS=linux GOARCH=arm GOARM=5 ./make.bash

実行型のビルド Go コマンドに PATHを通して

$ GOOS=linux GOARCH=arm GOARM=5 go build hello.go

5

GOARM

GOARM=5 For armv5, no FPU, soft float

GOARM=6 (Default) For armv6, VFPv1

GOARM=7 For armv7, VFPv3

6

以上。

7

間違えなければどうということはない。

8

しかし、

9

間違いから理解が深まることもある。

10

ツールチェインのビルドミス

$ GOOS=linux GOARCH=arm GOARM=5 ./make.bash

GOARMを指定しないときはGOARM=6

これを忘れた!

11

ARM$ ./helloIllegal Instruction

できた実行ファイルを実機 (armv5, no FPU)に持って行って実行すると

$ GOOS=linux GOARCH=arm GOARM=5 go build hello.go

12

FPU命令が混じってた

vldr d2, [r3]

gdbで illegal instructionを起こした命令を調べると

ランタイムライブラリがGOARM=6でビルドされているからか!

13

やり直し

$ GOOS=linux GOARCH=arm GOARM=5 ./make.bash

$ GOOS=linux GOARCH=arm GOARM=5 go build hello.go

14

念のために逆アセンブル

$ arm-linux-gnueabi-objdump -d hello

... bl <_sfloat> vldr d2, [r3] fcpyd d4, d2 ...

  FPU命令がまだある?!

15

Go1.4は armv5サポート無くなった?

gitで go1.3, go1.2, go1.1 のそれぞれのタグをチェックアウトして調べた 全て同じだった

16

Soft float emulation

ARMの Linux kernelには soft float emulationがあった

kernelを再ビルドCONFIG_OABI_COMAT=yCONFIG_FPE_NWFPE=y

これで動いた!ARM$ ./helloHello, Go

17

しかし

Go ARM がカーネルコンフィグに依存するとはどこにも書いてない?

しかも ARMの soft float emulationは

Deprecated 最近のカーネルではすでに削除されている

18

実は

soft float emulation を有効にしていないカーネルでも hello は動いた カーネルのコンフィグは無関係

(本当はツールチェインのビルドを間違っただけ )

19

謎の関数 _sfloat

... bl <_sfloat> vldr d2, [r3] fcpyd d4, d2 ...

フロート演算のコードに共通するパターンを発見。

... bl <_sfloat> vldr d2, [r0] fcmped d3, d2 fmstat bvs 117fc ...

  FPU命令の前に必ず_sfloatを呼び出す

20

_sfloatのソースコードを追跡

_sfloat in go/src/runtime/vlop_arm.s → runtime・ _sfloat2

_sfloat2 in go/src/runtime/softfloat_arm.c → sfloat2

21

static void sfloat2(void){ … while (skip = stepflt(pc, (uint32*)&regs->r0)){ : : pc += skip } g->m->ptarg[0] = pc;}

Soft float emulation inside golang

Comment is source code:stepflt returns number of words that the fp instruction is occupying, 0 if next instruction isn't float

FPU命令のインタープリタ

22

// returns number of words that the fp instruction// is occupying, 0 if next instruction isn't float.static uint32stepflt(uint32 *pc, uint32 *regs){ ...

switch(i & 0xffff0ff0) {default:

goto done;

case 0xeeb00a40: // F[regd] = F[regm] (MOVF)m->freglo[regd] = m->freglo[regm];

if(trace)runtime·printf("*** F[%d] = F[%d] %x\n",

regd, regm, m->freglo[regd]);break;

case 0xeeb00b40: // D[regd] = D[regm] (MOVD)

stepflt は FPU命令のインタープリタ

23

FPU命令は CPUで実行されていない

FPU命令が混じっていてもillegal instruction にならない

... bl <_sfloat> vldr d2, [r0] fcmped d3, d2 fmstat bvs 117fc ...

_sfloatから戻ってきた後にこの命令から実行再開

24

GOARM=5と 6の生成コードの違い

どちらも FPU 命令を生成する GOARM=5の場合は FPU命令の塊の前に

_sfloatへの呼び出しが挿入される。(リンカーがこれを行っている )

生成された FPU命令は同じ。 コンパイラは soft floatのための命令を生成しないので実装がラク。

25

結論

Golang は自前で soft float emulation する仕組みを持っている。 カーネルの soft float emulationは不要。

正しくビルドすれば普通に動く。 ついでにわかったこと

ARM Linuxの soft float emulationはdeprecated

26

Q & A

@tetsu_koba

Thank you for listening!