Hatena::ブログ(Diary)

七誌の開発日記(旧) このページをアンテナに追加 RSSフィード

新ブログ Twitter OneDrive Wiki

2010-03-08

[]カーネルビルド計測

id:syuu1228さんがOpenBSD/sgiカーネルビルドを計測されています(セルフ/amd64上のクロス)。私の手元のマシンでも計測してみました。Interixはid:n7shi:20100113で移植したクロス環境を使用しています。

f:id:n7shi:20100308152427p:image

VMオーバーヘッド

Athlon 64 X2 3800+ではVMware Player 3.0.1でAMD-Vが有効にできないため、バイナリ変換となっています。そのため実機でネイティブに実行するよりかなり遅くなっていますが、Interixよりは高速です。

makei386(VM)/i386Interix/i386(VM)Interix/i386
-j11.531.352.08
-j21.821.212.21

極端に遅いケース

色々な組み合わせでテストしていて、以下の環境が特に遅いことが分かりました。

Virtual PCAMD-Vが有効にも関わらず使い物にならないくらい遅いです。VMware PlayerではAMD-Vが無効なため、バイナリ変換のオーバーヘッドだと思われます。なぜか-j1のままでもMPカーネルにするだけで高速化します。バイナリ変換がパラレル化されるためでしょうか。

f:id:n7shi:20100308163111p:image

MPカーネルは2プロセッサなのにジョブ数に比例して高速化するという不思議な挙動を示します。バイナリ変換のキャッシュの関係ではないかと推測します。

f:id:n7shi:20100308163127p:image

まとめ

Windows上の仮想環境でOpenBSDを使用するには、VMware Playerでi386のMPカーネルが良いようです。

今回計測した生データをExcelでまとめて置いておきます。

2010-03-04

[]クロス開発の環境変数

id:n7shi:20100113でも取り上げましたが、OpenBSD上で他のアーキテクチャカーネルをクロスビルドする手順はid:syuu1228:20090805にまとめられています。カーネルビルドするときの環境変数が多いので、簡略化するための俺々スクリプトを作りました。

cross-env.mk

以下を/usr/src/cross-env.mkに保存します。

.if !defined(TARGET)
error:
	@echo "Please set TARGET."
	@exit 1
.else
all: cross-${TARGET}
install: cross-${TARGET}
	cp cross-${TARGET} /usr/local/bin
cross-${TARGET}:
	echo "#!/bin/sh" > $@
	echo "TARGET=${TARGET} MACHINE=${TARGET} MACHINE_ARCH=${TARGET_ARCH} MACHINE_ENDIAN=${TARGET_ENDIAN} ${CROSSENV} \$$@" >> $@
	chmod 755 $@
.include "Makefile"
.endif

使用方法

クロスgccまで従来通りに作ります。

cd /usr/src
TARGET=loongson make cross-gcc

今回のMakefileを使用して、環境変数をセットするスクリプトを生成します。

TARGET=loongson make -f cross-env.mk install

スクリプトが/usr/local/bin/cross-loongsonにインストールされます。名前はTARGETで指定したものが反映されます。カーネルビルド時にこのスクリプトを前置して呼び出します。

cd /usr/src/sys/arch/loongson/conf
config GENERIC
cd ../compile/GENERIC
cross-loongson make depend all

これでカーネルが出来上がります。

2010-03-02

[][][]GOTエラー

OpenBSDportsビルドしていて、CUPSでエラーになりました。

Linking texttops...
(snip)
/usr/bin/ld: not enough GOT space for local GOT entries

GOTというのはGlobal Object Tableのことで、どうやらグローバル変数が収まりきらないというエラーのようです。初めて見るエラーなので、対処方法のメモを残しておきます。

パッチ

texttops.cには巨大なグローバル配列が定義されていますが、これらは他のソースからは参照されていないので、staticにしただけでビルドが通りました。

--- filter/texttops.c.orig
+++ filter/texttops.c
@@ -33,16 +33,16 @@
 
 
 /*
- * Globals...
+ * Locals...
  */
 
-char		*Glyphs[65536];	/* PostScript glyphs for Unicode */
-int		NumFonts;	/* Number of fonts to use */
-char		*Fonts[256][4];	/* Fonts to use */
-unsigned short	Chars[65536];	/* 0xffcc (ff = font, cc = char) */
-unsigned short	Codes[65536];	/* Unicode glyph mapping to fonts */
-int		Widths[256];	/* Widths of each font */
-int		Directions[256];/* Text directions for each font */
+static char		*Glyphs[65536];	/* PostScript glyphs for Unicode */
+static int		NumFonts;	/* Number of fonts to use */
+static char		*Fonts[256][4];	/* Fonts to use */
+static unsigned short	Chars[65536];	/* 0xffcc (ff = font, cc = char) */
+static unsigned short	Codes[65536];	/* Unicode glyph mapping to fonts */
+static int		Widths[256];	/* Widths of each font */
+static int		Directions[256];/* Text directions for each font */
 
 
 /*

他の方法

もし他からも参照されていたらstaticにするだけでは対処できません。マクロでアクセス関数変数に見立てるようにするしかなさそうです。

static char *Glyphs[65536];
char **_Glyphs() { return Glyphs; }

これをヘッダで以下のように公開します。

extern char **_Glyphs();
#define Glyphs (_Glyphs())

理由は異なると思いますが、errnoが似たような方法で公開されています。

int *__errno(void);
#define errno (*__errno())

2010-03-01

[][][]パッケージ

私が手も足も出ないでまごまごしているうちに、GdiumにOpenBSDが移植されました!

さっそくportsを色々とビルドしています。ものすごく時間が掛かるため消えると痛いので、自分用のバックアップを兼ねてSkyDriveに置いておきます。

SkyDriveダウンロードにワンクッションあるため1つずつダウンロードするのは苦痛ですが、「その他→ZIP形式でダウンロードする」とすれば無圧縮ZIPで丸ごと落ちてきます。

2010-01-13

[][][][][]クロス開発環境構築

GdiumでOpenBSDの動作確認を行うため、カーネルをクロスビルドしました。最初は無難にOpenBSD上で行い、同じ動作を他のOSで再現するという手順を採りました。

  1. OpenBSD(i386)上でOpenBSD(mips64el)カーネルとユーザーランドをクロスビルド
  2. Interix上でOpenBSD(mips64el)カーネルをクロスビルド
  3. Hurd上でOpenBSD(mips64el)カーネルをクロスビルド

ビルドしたカーネルはGdiumで起動中にパニックします。それを修正するため、日常的に使っている環境でクロス開発できるようにしました。Interix上でOpenBSDの開発というのは一見無茶な組み合わせですが、実はそうでもありません。なぜかというとInterixのlibcの一部はOpenBSD由来で、他のUNIXに比べて親和性があるためです。

OpenBSD(i386)

OpenBSD上で他のアーキテクチャカーネルをクロスビルドする手順は驟雨さんがまとめています。

Gdiumはloongsonアーキテクチャですが、loongsonサポートはつい最近CVSにコミットされたばかりで、CVSからcurrentを取得する必要があります。sgiもloongsonもmips64ですがエンディアンが異なるため、ビルド時にエンディアンを区別する必要がありますが、そのための修正はCVSにはコミットされていません。後述のビルドツールに同梱しているので参照してください。

エンディアンに関する修正を施せば、カーネルはすんなりビルドできました。

Interix

OpenBSD上でのビルドの動きを見ていると、ビルドに必要なコマンドを用意すれば他のOSでもビルドできそうです。

真っ先に必要になるのはmakeです。OpenBSD特有のマクロを使用するため、GNU makeでは代用できません。OpenBSDのソースから抜き出してビルドできるように改変しました。GNU makeなどと区別するためobmakeという名前で/usr/local/binに入れてビルドプロセスを試しました。

TARGET=loongson obmake cross-gcc

プロセスが進むうちにコマンドがなかったり非互換だったりでエラーが出ます。その度にコマンドを持って来ることを繰り返して、最終的には以下のコマンドを用意すればカーネルビルドまで完了しました。

  • make, mkdep, config, mtree, readlink, rpcgen, compile_et

binutilsやgccは本来のビルドプロセスに含まれているため、別途用意しなくても問題ありません。

ビルド中に構築される仮想ルートで所有権の設定を試みますが、Interixにはrootやwheelなどが存在しないためエラーになります。そのため所有権を無視したコマンドも用意しました。

  • chown, install

こうして用意したコマンドだけを、OpenBSDのソースツリーから抜き出してビルドできるようにまとめました。

Debian/Interix環境で以下のパッケージがインストールされていることが前提です。Debian/Interixについてはid:n7shi:20091214id:n7shi:20091215を参照してください。

  • binutils, bison, flex, gcc, groff, install-info, libreadline5-dev, texinfo

環境が整えばクロスツールのインストールは簡単です。

make install

OpenBSDのソースを/usr/srcに展開します。前述のエンディアンやInterix特有の問題などを修正したパッチがpatch/cross.diffにあるため適用します。CVSの時期によってははじかれる可能性があるため、はじかれた場合は手動で対処が必要です。

パッチを適用後、ソースツリーに移動してビルドします。カーネルビルドには大量の環境変数を設定する必要があるため、cross-wrapperとして環境変数をシェルスクリプトにダンプできるように改変しています。

cd /usr/src
TARGET=loongson obmake cross-gcc
TARGET=loongson obmake cross-wrapper ← 独自拡張
mv cross-wrapper /usr/local/bin/loongson
cd sys/arch/loongson/conf
obconfig GENERIC
cd ../compile/GENERIC
loongson obmake depend
loongson obmake

この手順は複雑なため一発でできるようにも改変しましたが、今回はカーネルを修正しながら何度もビルドするのが目的のため、あまり意味はありません。

cd /usr/src
TARGET=loongson obmake cross-kernel ← 独自拡張

RAMDISKカーネルにはディスクイメージを入れる必要がありますが、前述の所有権やディスクイメージのマウントなど問題が山積しているため、OpenBSDビルドしたイメージを持って来るのが現実的です。

それ以前の問題として、現段階ではルートのマウントの前にカーネルパニックしてしまうため、RAMDISKカーネルを用意しても意味がありません。パニックせずにルートのマウントまで進むようにカーネルをハックするのが先です。RAMDISKについてはその後で考えることにします。

Hurd

Interixで成功したので、Hurdでも試みました。基本的なやり方はInterixと同じですが、前述のようにInterixはOpenBSDに近いため比較的簡単で、Hurdではそれよりもかなり手間が掛かりました。一部の関数OpenBSDから持って来るのが困難だったため、NetBSDのpkgsrcの互換レイヤ(libnbcompat)から持って来ました。

Hurdで動くようにしたものを置いておきます。readlineは注意が必要で、libreadline6-devではなくlibreadline5-devをインストールしてください。基本的にInterix版にHurd対応コードを付け足したものなので、config.mkを書き換えればInterixでも使えます。

Hurd対応というより実質的にglibc対応です。そのためglibcを使用する他のOS(Debian GNU/kFreeBSDなど)でも少しの修正で使用できると思われます。

ちなみにこれをkではないオリジナルのFreeBSDに持って行くと大量のエラーが出ます。OpenBSDとFreeBSDとで同じ定義が重複するためです。それらはもともと存在して互換レイヤとして必要ないものですから、削ればうまくいくと思われます。