LoginSignup
17
13

More than 3 years have passed since last update.

Go 1.8のMIPS32バイナリをルータ上で動かしてみた(成功編)

Last updated at Posted at 2017-01-20

(追記 2020/1/10)続編もご覧ください→ Go 1.10にMIPS32 softfloat対応が来たよー - Qiita

Go 1.8から32bit MIPS Linux環境がサポートされました(参考:https://tip.golang.org/doc/go1.8#ports )。32bit MIPSは組み込み系開発ボードなどに多く採用されているCPUで、身近なところでは家庭用ブロードバンドルータの半分以上1でMIPS32が採用されています。つまりブロードバンドルータ上でGoプログラムが動くというわけです。これはアツいですね!

本稿ではまず簡単なGoプログラムをMIPSベースのブロードバンドルータ上で動かします。次に、GoのMIPS32サポートの現状と今後について紹介します。

動かしてみた

では、さっそくGoでMIPS32バイナリを生成してみましょう。まずはGo 1.8RC1をインストールします。

$ go get golang.org/x/build/version/go1.8rc1
$ go1.8rc1 download

次に、下記のGoプログラムを用意します。

hello.go
package main

import "fmt"

func main() {
    fmt.Printf("Hello, world!\n")
}

次のようにコンパイルすれば32-bit MIPS用のhelloバイナリが得られます。

$ GOOS=linux GOARCH=mips go1.8rc1 build hello.go
$ file hello
hello: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, not stripped

さて、実際に動かしてみましょう。筆者はBuffalo社の有線ブロードバンドルータBHR-4GRV上にOpenWrtというLinuxディストリビューションをインストールしています。

このブロードバンドルータにscpでバイナリを送り込むと、バイナリが動作しました。

$ scp hello openwrt01:/tmp
$ ssh openwrt01


BusyBox v1.23.2 (2017-01-19 17:27:24 UTC) built-in shell (ash)

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 CHAOS CALMER (Chaos Calmer, unknown)
 -----------------------------------------------------
  * 1 1/2 oz Gin            Shake with a glassful
  * 1/4 oz Triple Sec       of broken ice and pour
  * 3/4 oz Lime Juice       unstrained into a goblet.
  * 1 1/2 oz Orange Juice
  * 1 tsp. Grenadine Syrup
 -----------------------------------------------------
# /tmp/hello
Hello, world!

こう書くと簡単に動くように見えますが、実はこのバイナリは多くの環境で動作しません。上記の環境ではこのバイナリを動かすため自前のカーネルに入れ替えています。

現時点のGoのMIPS32サポート状況

Go 1.8のリリースノートには、次のような記述があります。

Go now supports 32-bit MIPS on Linux for both big-endian (linux/mips) and little-endian machines (linux/mipsle) that implement the MIPS32r1 instruction set with FPU or kernel FPU emulation. Note that many common MIPS-based routers lack an FPU and have firmware that doesn't enable kernel FPU emulation; Go won't run on such machines.

Go 1.8の32-bit MIPSサポートはFPU(浮動小数点演算ユニット)またはカーネルによるFPUエミュレーションが必須だと書いてあります。これを満たす32-bit MIPS環境はごく少数であるため、かなり厳しい制約だと言えるでしょう。

実際、私の持っているブロードバンドルータにはFPUはありませんし、OpenWrtでもカーネルFPUエミュレーションはデフォルトで無効になっています。FPUエミュエーション有効にしてカーネルビルドしなおしたのが上の環境というわけです。

カーネルFPUエミュレーションとsoft-float

ところで、FPUが無い環境というのは組み込み系では珍しくありません。そうした環境でもC言語でfloatdoubleなどの型が使えるのはなぜでしょうか。

実は、整数演算命令のみで浮動小数点数演算を実現する機構が大半のCコンパイラで提供されています。これはsoftware floating pointとかsoft-floatなどと呼ばれます。この仕組みにより、FPUの無い環境でも浮動小数点数演算が実現できているわけです。逆に、Go 1.8でFPU必須という制約がついているのはsoft-floatが未実装であるという意味でもあります。

一方で、今回の実験で使ったようにカーネル側でFPU命令のエミュレーションを行うアプローチも考えられます。これはARM LinuxとMIPS Linuxで提供されている機構のようです(私が知らないだけで、他の環境でも珍しくないのかもしれません)。これを使えばコンパイラ側の実装コストは減りますが、FPU命令が発効されるたびにカーネル割り込みが走るため速度面ではかなり不利です。カーネルFPUエミュレーションとsoft-floatの好きな方が選べるのであれば、当然後者を選ぶべきです。

もちろんGoの中の人も同じ認識のようで、既にMIPS32のsoft-floatサポートについて議論されています(参考:「runtime: mips32 soft float point support · Issue #18162 · golang/go」)。ただ、Go 1.8のタイミングでは時間切れだったということのようです。Go 1.9以降に期待したいですね。

まとめ

  • Go 1.8でMIPS32バイナリが出力できるようになった
    • ただし、このバイナリが動く環境は少ないと思われる。大抵の環境ではカーネルリコンパイルが必要。
  • Go 1.9以降MIPS32のsoft-floatサポートが入るはず、そのタイミングが本命

  1. 組み込み系素人の感覚値です 

17
13
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
13