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出版の本を買えよってのは無しの方向です。 終い仕度の一環として、これ以上保存用の本は買わないという方向です。

組み込み用ARM9

Xv6-rpi 掘削

仮想メモリ・・・その準備

MMU有効化

割り込み

Linux Support for ARM LPAE

オペレーティングシステム(2014年度) ARMじゃないけど、xv6のソース観光が出来る。

仮想記憶 なんてのがウィキに上がってた。

Operating System Engineering

MMU(メモリマネージメントユニット)

卒業論文でARM

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出来る。後は、いろいろみなさんが やっておられるので、おいおい見てけばいいだろう。

UNIX v7

2238クラブ

七誌さんの開発日記(旧)

アクティブページレジスタ(Active Page Register)について

UNIX 6thのソースコードの読書メモ(はじめてのOSコードリーディング本の著者)

PDP-11のブートストラップ

ファイルシステムの読み込み

はじめてのOSコードリーディング

unix/v6 物理メモリーの管理

slideshare

とよしま語録

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クロ現

まさに、メディア人の仕事。目先の事より、後からじわーと効いてくるね。