OSづくり。
前のエントリで「MINIX遅い」ってわかって、でもこれ直そうと思うと根本的に設計見直しだなあと思ってたんですが、意を決してOSを自分で作ってみることにしました。
もともと、どうせならARM32じゃなくてAARCH64でやりたいなあと思ってたのと、
https://github.com/bztsrc/raspi3-tutorial/
こちらのチュートリアルが決定的でした。
これみたらできそうだなぁと。基本的な仕組みはminix解析してわかってきてたし。
(そう言う意味でminix遊びはすごく勉強になりました)
いまはメモリ空間の分離や複数コンテキスト処理とかはもう動いていて、
ELF形式のユーザーアプリをRAMディスクからロードして起動するところに成功したところです。うふふ。すげえ楽しい。
ELF形式のロードとかメモリ分離とかコンテキスト切り替えとかちょっと前までちんぷんかんぷんだったもんなあ。。「これでいいんだなあ」ってわかるとすごく楽しい。
マルチコアのミニックスが遅い。
前回の記事でマルチコア化してみた、、と書いたミニックスなんだけど、…すごい、遅くて。
どうして遅いのか考えてたんですが、多分こう言うことなんじゃないかと。。(未検証)
- Linuxはモノリシックカーネルだから、システムコールはカーネル内で完結する。
カーネルはCPUに依存せずに処理できるからCPU間の移動は発生しない。 - Minixはマイクロカーネルだからシステムコールは一度サーバープロセスを経由する。
ただしシングルコアであればカーネルのコンテキストスイッチ程度のペナルティ。 - マルチコアであってもMinixはシステムコールはサーバープロセスを経由しなければならない。が、その肝心のサーバープロセスは別のCPUに配置される。したがってシステムコールを実行する際にいちいちCPU間通信が発生する。(しかもサーバーが処理している間ユーザープロセスは何もしてない!!…余計な処理が増えただけ!)
今の設計だと、マルチコアを活かせないどころか無駄にCPU間通信が発生する分遅いわけだ。。。
解決しようと思うとサーバーがユーザープロセスと同じCPU…現実的には全てのCPUにいてくれるのがベストで、それを実現するにはマルチスレッドが有効なはず。
でもMinixはマルチスレッドに対応していないので。。。。。。。。
QNXのリソースマネージャーがスレッドプールを利用している理由もこれでよくわかる。そう言う設計であれば各CPUにスレッドを配置できるもの。
勉強になりました。。
これなんかもう設計が古すぎるんやね。。マルチコアを生かそうと思ったらマルチスレッドが必須だなぁ。32bitだしもう再設計したいなって気になってきました(苦笑)
ARM版Minixのマルチコア対応
ARM版Minixをしこしこvirtボードに移植したり、ここ1年くらいはマルチコア化をのんびりやってたんだけどついに動いてしまった。
最初はなんでかCPU2が起きなくて、qemuをシングルコアで起動してたことに気づくとか
そんなお粗末な感じだったんですけど世の中そんなもんさ。。
とりあえず動かしたのはqemuのvirtボードなので実機ではないんだけど、骨組みはできたと言うことなので実機に持って行くのも難しくないと思う。
4コア。そのうちラズパイに持って行きたいと考えている。
ちょっと情報は整理できてないのでそのうち纏めますね。
まだvirtioでつまづくんですよね。実機にvirtioはないのでもう実機に移植した方が早いかもしれないですけど(苦笑)
追記2023.2.15
virtioは問題なくて単に割り込みの対応漏れでした。
それ直すと進み始めたけど、途中でクラッシュするので何かまだ隠れてそう。
同じコードをCPUだけ一個に制限すると動くのでほんとにマルチコアでしか動かない部分よな…
追記2023.2.20
ちゃんとうごいたヽ(´▽`)ノ 元々のARM実装が排他が不十分な雑な実装でしたああ。
マルチコア対応なんかしてないもんね。
これソースコード公開したらいいんやろか。勝手に公開して良いんかな。いやライセンス上は問題ないんですけどね。
どうせならVUAにフィードバックしたいよな。。(整形とかめんどう)
QEMUとかコンパイラとか
RaspberryPi上でMinixを動かす事を目標として…ただRaspberryPiは課題が多いので、
まずはQemu上の他のマシン上を目指してみる。
いろいろ試してみて分かった事をメモっておく。
Qemu
-kernel引数
-kernelに渡すElfバイナリのデータは、Elfバイナリに従ってメモリに展開される。
これはエントリポイントを含む。だからエントリポイントはElfにちゃんと書いていればどこでも良い。…ただ対象のボードのSDRAM上な。何もないとこに展開させたらその瞬間にクラッシュするので。
-M <machine>
qemuも全部のボードを網羅してない(できるわけがない)
代表的なボードとしてvexpressボードやversatilepbボードが割と有名なのでそれが使われがちだが
いや良いんだけど、、versatileボードってやっぱメモリマップとか古いので、、最大256MBしかないし…
qemuを見るとvirtボード使ってくれ!!って書かれてたので、ラズパイ4みたいな最近のリッチなボードをエミュレーションするならそれが良さそう
詳細はぐぐれ。
移植先もversatilepbよりvirtボードの方がいいかなあ。。
-initrd
これに指定したデータはメモリ256MB以上のメモリの先頭から128MBのとこ
…つまりbase + 0x08000000に展開される。
qemu/hw/boot.c参照
info->initrd_start = info->loader_start +
MIN(info->ram_size / 2, 128 * MiB);
Minixの場合各種サーバーはinitrdの方が美しい気がする
コンパイラ
脱線なんだけど
arm-none-eabi と arm-none-eabihf って何が違うんだろうって思ってたら
-mfloat-abiのデフォルト設定値の違いだけなんですね。
浮動小数点数の演算方法の違いだけどこれも詳細はググった方がいいかな。
べあめたる
このブログ書くの何年振りだろ、、って思ったけど結構最近かいてた。ふふ。
色々考えてたけど、やっぱminixをraspberry piで動かしてみたいのと、マルチコアで動かしてみたいよね、、と。
そのためのステップとしてまずqemu上で動かしてみたい。arm vexpressボードになるのかな。
以下に色々まとまってたので読んでる。頑張る。
MinixのMultipleDefinition
Minixのビルドエラー
MinixをUbuntu21…gcc10でビルドするとMultipleDefinitionエラーが出る。
明らかにソースコードがおかしいのだけど、古いgcc(8とか)だと問題ないようだ。
これ前もやった気がするので、もうしないようにパッチ登録しておきます。。
クイックハックなので動くかどうかは見てない
From 1e95e04e7ed7e1b01ff1e1c99433b8aeede22315 Mon Sep 17 00:00:00 2001 From: Yusuke SHIROYAMA <shiroyagiyuu@gmail.com> Date: Sun, 4 Jul 2021 09:16:22 +0900 Subject: [PATCH] fix multiple definition fix error on gcc10 --- bin/pax/extern.h | 1 - bin/pax/options.c | 1 + sbin/newfs_udf/newfs_udf.h | 4 ++-- sbin/newfs_udf/udf_create.c | 3 +++ usr.bin/make/main.c | 1 + usr.bin/make/make.h | 2 +- usr.sbin/installboot/machines.c | 8 ++++++-- 7 files changed, 14 insertions(+), 6 deletions(-) diff --git a/bin/pax/extern.h b/bin/pax/extern.h index 298600c2d..94ee13911 100644 --- a/bin/pax/extern.h +++ b/bin/pax/extern.h @@ -204,7 +204,6 @@ void options(int, char **); OPLIST * opt_next(void); int bad_opt(void); int mkpath(char *); -char *chdname; #if !HAVE_NBTOOL_CONFIG_H int do_chroot; #endif diff --git a/bin/pax/options.c b/bin/pax/options.c index 1af5fe4b7..ddb6a0e54 100644 --- a/bin/pax/options.c +++ b/bin/pax/options.c @@ -76,6 +76,7 @@ __RCSID("$NetBSD: options.c,v 1.116 2015/04/11 15:41:33 christos Exp $"); /* * Routines which handle command line options */ +char *chdname; static int nopids; /* tar mode: suppress "pids" for -p option */ static char flgch[] = FLGCH; /* list of all possible flags (pax) */ diff --git a/sbin/newfs_udf/newfs_udf.h b/sbin/newfs_udf/newfs_udf.h index 1c21a0b48..e9ff149a5 100644 --- a/sbin/newfs_udf/newfs_udf.h +++ b/sbin/newfs_udf/newfs_udf.h @@ -53,8 +53,8 @@ extern float meta_fract; /* shared structure between udf_create.c users */ -struct udf_create_context context; -struct udf_disclayout layout; +extern struct udf_create_context context; +extern struct udf_disclayout layout; /* prototypes */ int udf_write_sector(void *sector, uint64_t location); diff --git a/sbin/newfs_udf/udf_create.c b/sbin/newfs_udf/udf_create.c index ef92874af..856a6746b 100644 --- a/sbin/newfs_udf/udf_create.c +++ b/sbin/newfs_udf/udf_create.c @@ -45,6 +45,9 @@ __RCSID("$NetBSD: udf_create.c,v 1.25 2015/06/16 23:18:55 christos Exp $"); #include "unicode.h" #include "udf_create.h" +/* shared structure between udf_create.c users */ +struct udf_create_context context; +struct udf_disclayout layout; #if 0 # ifndef DEBUG diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c index 73f4aaa9c..66dd3e8d0 100644 --- a/usr.bin/make/main.c +++ b/usr.bin/make/main.c @@ -160,6 +160,7 @@ static Lst variables; /* list of variables to print */ int maxJobs; /* -j argument */ static int maxJobTokens; /* -j argument */ Boolean compatMake; /* -B argument */ +FILE *debug_file; /* Output written here - default stdout */ int debug; /* -d argument */ Boolean debugVflag; /* -dV */ Boolean noExecute; /* -n flag */ diff --git a/usr.bin/make/make.h b/usr.bin/make/make.h index f162ef670..968710d05 100644 --- a/usr.bin/make/make.h +++ b/usr.bin/make/make.h @@ -440,7 +440,7 @@ extern pid_t myPid; * There is one bit per module. It is up to the module what debug * information to print. */ -FILE *debug_file; /* Output written here - default stdout */ +extern FILE *debug_file; /* Output written here - default stdout */ extern int debug; #define DEBUG_ARCH 0x00001 #define DEBUG_COND 0x00002 diff --git a/usr.sbin/installboot/machines.c b/usr.sbin/installboot/machines.c index 357652b83..96dc99419 100644 --- a/usr.sbin/installboot/machines.c +++ b/usr.sbin/installboot/machines.c @@ -46,15 +46,19 @@ __RCSID("$NetBSD: machines.c,v 1.39 2014/02/24 07:23:44 skrll Exp $"); * isn't built with all the architectures defined. * A lot simpler that conditionally including the definitions themselves. */ +extern struct ib_mach + ib_mach_amd64, + ib_mach_i386; + struct ib_mach ib_mach_alpha, - ib_mach_amd64, +/* ib_mach_amd64, */ ib_mach_amiga, ib_mach_emips, ib_mach_ews4800mips, ib_mach_hp300, ib_mach_hppa, - ib_mach_i386, +/* ib_mach_i386, */ ib_mach_landisk, ib_mach_macppc, ib_mach_news68k, -- 2.30.2
qemu-linaroインストールログ
RaspberryPi 4用Ubuntu Desktop(21.04:64bit)にqemu-linaroを入れたインストールログ。
いや別に特別なことはしてないのでぱそこんのUbuntuでもこれで通ると思う。たぶん。
そもそもQemu-linaroって?
linaro向けにforkしたqemu。本線のqemuとの違いは、ARM関係のサポートボードを充実させていること。(本線ですでに削除されたボードが残っている)
以下でソースを入手。
https://releases.linaro.org/archive/14.01/components/toolchain/qemu-linaro/
BeagleBone(OMAP3xxx系)のエミュレーターが必要で、qemuで動くよ!って聞いたのに最新でボード見当たらなくて^^;これを見つけました。
何時から無いのか分からないけれど、qemu-linaroが1.7…なのでqemu2.0のときにはもうサポート対象外なんじゃないかなあ。。
Ubuntuだと17くらいからもう無いって見た気がします。
ビルド前にapt-installしたもの
sudo apt install python2 libglib2.0-dev libpixman-1-dev libfdt-dev
sudo apt install python-is-python2 (これは人による)
ひどいのは、./configureで以下みたいなエラーが出たとき、本当に足らないのはlibfdt-devだってとこ。(エラーメッセージが嘘。ていうかバグ。ぱっちもあった)
DTC not present. Your options:
(1) Preferred: Install the DTC devel package
(2) Fetch the DTC submodule, using:
git submodule update --init dtc
とりあえずこれだけインストールしておけばビルドは通る。
コンソールシリアルだけならこれで十分よー。
./configure --target-list=arm-softmmu
make
Aarch64で動くqemu-system-armがarm-softmmu以下にできます。(^o^)