xv6-armv7 (2)
某Pythonなんてのをコンパイルしてます。何時終わるとも分からないコンパイルに付き合って、 裏でPython のソースを読んでみる なんてのを見てるんですが、ふと机の片隅に眼が行きました。
MACをかたどった文鎮があるじゃないですか。久しぶりに手に取って眺めてみると、裏に MMM 900922なんて刻印が入ってましたよ。
はい、20世紀は1990年9月22日に、岩手県安比スキー場で行われた、仙台地区のMAC同好会の 記念品でした。あの頃は、オイラーはマカーだったんす。広瀬通りと一番町の角にある、 東北放送だかのコマーシャル映像を手がけているデザイナーな人と知り合いになり、、、
その人が主催するMACグループ会に入れて貰ったのさ。そして安比。夫婦同伴可ってんで、 安比くんだりのタワーホテルまで出かけたのだった。あの頃は生き生きしてましたねぇ。 どこでもホイホイと顔を出す、そして飲んで語って。。あの時は徹夜でMAC談義をしたっけ。
もう25年も前か。あの頃MACは高かった。確かMAC/SEが60万円ぐらいしてたな。取り扱いは キャノンさんで、さぞかしボロ儲けしたでしょう。MAC信者がお布施を盛んにしてましたから。
懐かしくなってMACのシルエットを追ってみた。 「Apple I」から「iPhone 4」までApple製品の進化の歴史をまとめた画像45枚
会社でもMACブームが起こって(発祥はオイラーだった)、色々な人がMACを使ってたな。 特に人気だったのがカード型のデータベースソフト(名前は失念)。これで名刺管理をするのがナウい 仕事術だった。技術屋さんはドローが定番だったかな。ああ、定番と言えば、メールソフトの ユードラもそうだった。
オイラーの特技は、ResEditを使って、ゲームのプロテクション解除。debuggerSWを付けて、 パスワードとかが求められた時に、マシン語まで潜り、あたりを見回してからResEditで ごにょごにょしてた。(ただ破るのが楽しかっただけで、それを公開とかはしてないので、 通報はしないでね。)
アメリカに長期出張で帰りに、MACを持ち帰る人もいたな。行く度に買ってくるものだから、 その人の机はMACで足の踏み場もなくなっていた。当然、床の上には、据え置き型のサーバー が置いてあったり。。独身貴族は違うと思ったものだ。
いろいろなMACが発売されてきたけど、 初代Macintoshを現代風にアレンジしたら? こういうMACが有ったら、是非使ってみたいぞ。
armv7用の資料とか
を探してみた。特にMMUについてだ。そんなのCQ出版の本を買えよってのは無しの方向です。 終い仕度の一環として、これ以上保存用の本は買わないという方向です。
オペレーティングシステム(2014年度) ARMじゃないけど、xv6のソース観光が出来る。
仮想記憶 なんてのがウィキに上がってた。
ARM_VMM: Cortex-A7でMMUを有効化する方法メモ
オイラーが疑問なのはMMUはいいんだけど、そこに割り当てる物理メモリーをどうやって 管理してるか。kmallocなんだろうけど、その為の資源管理をどうしてるか? ソース嫁はごもっともなんだけど。いまいち読みきれていない。
uv6 on pdp11
上記を検索中に、 uv6 なんてのを見つけてしまったので、ウブに入れてみた。
sudo apt-get install simh wget http://simh.trailing-edge.com/kits/uv6swre.zip
zipを展開するとdiskが4本出てくる。そいつらをpdp11に割り当てて、起動する ちょっとした設定ファイルを用意する。次にそれを使って起動
[ob: pdp11]$ cat boot #!/usr/local/bin/simh-pdp11 set cpu 11/40 set cpu u18 att rk0 unix0_v6_rk.dsk att rk1 unix1_v6_rk.dsk att rk2 unix2_v6_rk.dsk att rk3 unix3_v6_rk.dsk set cpu history=1000 boot rk0
[ob: pdp11]$ ./boot PDP-11 simulator V3.9-0 ./boot> #!/usr/local/bin/simh-pdp11 Unknown command Disabling XQ @unix login: root # ;;;CTRL+E to sim Simulation stopped, PC: 021630 (MOV (SP)+,177776) sim> sh cpu history=10 PC PSW src dst IR 034334 030000|034334 005262 CMPB #3,(R2) 034340 030000| BNE 34372 034372 030000|000001 034372 SOB R4,34316 034374 030000| 034374 TST 41576 034400 030004| BNE 34414 034402 030004|005262 034402 MOV R2,41576 034406 030000|034406 034406 JSR PC,21620 021620 030000|021620 141712 MOV 177776,-(SP) 021624 030000| 140004 SPL 0 021626 030000| WAIT sim> c ;;;continue target #
シュミレータとuv6の間を行ったりきたりは、CTRL+e と cだ。細かい事は、/usr/share/doc/simhに 行ってみればいいのかな。
pdp11のレジスタ全部を見るには、e stateする。絞り込む場合は
sim> e pc-sp PC: 021630 R0: 140004 R1: 034272 R2: 005262 R3: 000200 R4: 000000 R5: 141724 SP: 141710 sim> e KDPAR0-KDPDR7 KDPAR0: 000000 KDPDR0: 077506 KDPAR1: 000200 KDPDR1: 077506 KDPAR2: 000400 KDPDR2: 077506 KDPAR3: 000600 KDPDR3: 077406 KDPAR4: 001000 KDPDR4: 077406 KDPAR5: 001200 KDPDR5: 077406 KDPAR6: 001171 KDPDR6: 077506 KDPAR7: 007600 KDPDR7: 077506 sim> e UDPAR0-UDPDR7 UDPAR0: 001341 UDPDR0: 046402 UDPAR1: 001517 UDPDR1: 021506 UDPAR2: 001341 UDPDR2: 000000 UDPAR3: 001341 UDPDR3: 000000 UDPAR4: 001341 UDPDR4: 000000 UDPAR5: 001341 UDPDR5: 000000 UDPAR6: 001341 UDPDR6: 000000 UDPAR7: 001407 UDPDR7: 066116
物理メモリーの管理。KDPARn とかUDPARnとかに割り当てるブロックの管理をどうしてる。 コードを書いた人の頭の中に入ってる?実行中にダイナミックに変更される事も有る だろうに。
# chdir / # nm unix | grep savu 021636T _savu # Simulation stopped, PC: 021630 (MOV (SP)+,177776) sim> break 021636 ;;; 頭の0は8進数のマークなんで省略するなよ sim> c Breakpoint, PC: 021636 (SPL 6) sim>
アセンブラなんだけど、各ルーチンのロード先を調べてbreak出来る。後は、いろいろみなさんが やっておられるので、おいおい見てけばいいだろう。
アクティブページレジスタ(Active Page Register)について
UNIX 6thのソースコードの読書メモ(はじめてのOSコードリーディング本の著者)
syscall
上記のuv6って、昔(2010年)にやってた。深入りしても進歩がなさそうなので、xv6-armv7に 戻ります。で、いきなりsyscallってどう書くの? サンプルが有った。 initcode.S
# Initial process execs /init. #include "syscall.h" .globl start # exec(init, argv) start: LDR r1, =init LDR r2, =argv MOV r0, #SYS_exec SWI 0x00 exit: MOV r0, #SYS_exit SWI 0x00 B exit # char init[] = "/init\0"; init: .string "/init\0" # char *argv[] = { init, 0 }; .p2align 2 argv: .word init .word 0
いきなりアセンブラーが出てきたけど、#includeって、アセンブラーのコメントでは無いよね。 後ろの方になる、# char init... は、コメントだろうけど。ええい、どういう風に 翻訳されたか見ればいいんか。initcode.asm
build/initcode.o: file format elf32-littlearm Disassembly of section .text: 00000000 <start>: 0: e59f1024 ldr r1, [pc, #36] ; 2c <argv+0x8> 4: e59f2024 ldr r2, [pc, #36] ; 30 <argv+0xc> 8: e3a00007 mov r0, #7 c: ef000000 svc 0x00000000 00000010 <exit>: 10: e3a00002 mov r0, #2 14: ef000000 svc 0x00000000 18: eafffffc b 10 <exit> 0000001c <init>: 1c: 696e692f .word 0x696e692f ;;; ini/ 20: 0074 .short 0x0074 ;;; t ... 00000024 <argv>: 24: 0000001c andeq r0, r0, ip, lsl r0 28: 00000000 andeq r0, r0, r0 2c: 0000001c .word 0x0000001c 30: 00000024 .word 0x00000024
ソース上の文字列 /initが、objdumpを通すと、ユーザーを惑わす結果が表示される。 本当のコード部分以外(文字列とかデータ宣言)は、objdumpの都合によって表示されるよ。 注意、注意! それから、データをテキスト領域に埋め込み、それにアクセスする為の ARM特有なアセンブラーの技法が使われている。
このコードの実際のメモリーイメージは、
sakae@uB:~/xv6-armv7/src/build$ bmore initcode 00000000 24 10 9F E5 24 20 9F E5 07 00 A0 E3 00 00 00 EF $...$ .......... 00000010 02 00 A0 E3 00 00 00 EF FC FF FF EA 2F 69 6E 69 ............/ini 00000020 74 00 00 00 1C 00 00 00 00 00 00 00 1C 00 00 00 t............... 00000030 24 00 00 00 $...
initcodeって言うなれば、/init(ユーザーランドで一番最初に走るアプリ)をloadするための ローダーなんだな。実体はexecを呼んでるだけだけど、なんでこれだけアセンブラで書いてあるの?
usr/sh.cの中で使ってるexec(ecmd->argv[0], ecmd->argv);みたいな使い方じゃ駄目なの? ああ、これどう展開されるか見ておくと、usr/usys.Sにあるマクロで展開されて
00000120 <exec>: 120: e52d4004 push {r4} ; (str r4, [sp, #-4]!) 124: e1a04003 mov r4, r3 128: e1a03002 mov r3, r2 12c: e1a02001 mov r2, r1 130: e1a01000 mov r1, r0 134: e3a00007 mov r0, #7 138: ef000000 svc 0x00000000 13c: e49d4004 pop {r4} ; (ldr r4, [sp], #4) 140: e12fff1e bx lr
汎用化されてるのと、実行終了した時に、呼び出し元に戻るようになってる。それに対して initcodeの方は、贅肉を落とし、戻ってくる事を期待しないコードになってる。何たって、initは、 ユーザーランドで唯一永久に動き続けるプロセスだから。
もし誤動作して戻ってきても、exitのトラップに掴まって、そこから抜け出す事は無い(はず、まあそれには、カーネルが壊れていないと仮定してだけど)
sh
xv6には当たり前だけどshが搭載されてて、そいつがユーザーランドのアプリとして起動 してくる。当たり前っちゃあたり前なんだけど、ソースが陽にさらされているんで、読んどく (そして理解)しておくのがいいだろう。
みんなカーネルばかりに注目してるけど、こういう裏方さんも大事にしないとね。arm7版では ソースがusr/sh.cにおいてある500行ぐらいのコードだ。どんな機能を搭載してる?
shはどこで起動するかと言うと、usr/init.cから、fork exec されてる。このinitの 役目は、生まれたshの挙動を監視しててshが死んだら、また新しいshを生む事。こうして shにユーザーランドのアプリのランチャーの役目を委譲してる。
起動直後は、initのpidは1、shは2になってる。
$ kill 2 $ init: starting sh $ 1 sleep init ;;; CTRL-Pでpsの真似 4 sleep sh
initを殺すとどうなるか? パニクッって、stackdumpしたよ。
: init: starting sh init: starting sh init: fork failed cpu0: panic: init exiting 15: 0x0 14: 0x0 13: 0x0 12: 0x0 11: 0x0 10: 0x0 9: 0x0 8: 0x0 7: 0x0 6: 0xc002750c 5: 0xc0027688 4: 0xc00261b4 3: 0xc00272d0 2: 0xc0025578 1: 0xc0021b14 qemu: terminating on signal 15 from pid 1160
armが暴走してたんで、別端末からqemuを殺した(term)っていう穏やかな方法で。 あれ? xv6のkillでどんな信号が送られるのだろう? ソース嫁ですかね。
etc
最近のNHKは民放化してて酷いな。もう終わっちゃったけど、一路の番宣はなんだ。鼻につく 鼻につく、そんなの死んでも見るか。とっくに原本をよんどるわい。
朝がきたとかの主演さんもいろんな所に出て顔ならぬ番組を売ってた。新人歌手のレコード 店回りじゃあるまいし(たとえが古すぎ)。
これもそれも、視聴率と言う絶対基準があって、それで会長が評価するから、現場がやむに やまれぬ所業に出たんでしょうな。
そんなNHKだけど、クローズアップ現代こと、クロ現が、アーカイブを残してくれている。 NHKクロ現
まさに、メディア人の仕事。目先の事より、後からじわーと効いてくるね。