2026/03/25

2BSDの誤動作をバイナリパッチで捕まえる方法 その2

 実行中にODTでメモリを書き換える方法は

  1. 操作が煩雑
  2. 問題の再現性が低い(気がする)、あるいは挙動が変化する

ため、 カーネルにバイナリパッチを当てて自力でトリガをかけられるようにしました。

ソースコードの変更ではなくバイナリパッチなのは、

インストールされるカーネルバイナリと一致するソースコードが見つからない

ためです。 

後述するFPGAの変更と組み合わせることで、誤動作の発生を高確率で捕まえられるようになりました。

カーネルのバイナリパッチ

オリジナルのカーネル(rpunix)とパッチを当てたカーネルを比較すると以下のようになります。

    41 324 202
   42   3   4
   49 324 202
   50   3   4
 1187 346 300
 1188  35  25
 1189 170 172
 1190 373 377
 1191  46 310
 1192  20  25
 1193 346   1
 1194  35   0
 1195 234 300
 1196 133  25
 1197 146 200
 1198  20 376
 1199 246 310
 1200  20  25
 1201 346   1
 1202  20   0
 1203 203   0
 1204  35   0

先頭の4か所はトラップベクタの書き換えです。"Illegal instruction trap"と"IOT trap"の発生時に関数dzdmaにジャンプします。残りの部分は、使用されていないドライバの関数(002202 T dzdma)を上書きして、以下の命令列を書き込んでいます。アドレス依存性はないのでソースコードのアドレス指定は気にしなくても大丈夫です。

        1                                .asect
       2 000400                         .=400
       3 000400 012700  177572          mov #177572,r0
       4 000404 012710  000001          mov #1,(r0)
       5 000410 012700  177200          mov #177200,r0
       6 000414 012710  000001          mov #1,(r0)
       7 000420 000000                  halt

177572はMemory Management Register #0のアドレスです。"1"を書き込むことでアドレス変換を有効にしています。

177200はHALT信号をアサートするためのI/Oポートで、今回のデバッグのために追加しました。FPGAの変更については後述します。

FPGAの変更

I/Oポート(177200)に書き込みを行うとHALT信号をアサートするように改変しました。変更内容は以下のとおりです。

 diff --git a/hdl/20251017/TangConsoleDCJ11MEM_project/src/top.v b/hdl/20251017/TangConsoleDCJ11MEM_project/src/top.v
index 4133bd9..e4a4380 100644
--- a/hdl/20251017/TangConsoleDCJ11MEM_project/src/top.v
+++ b/hdl/20251017/TangConsoleDCJ11MEM_project/src/top.v
@@ -2219,6 +2219,13 @@ module top(
        default:;
       endcase

+  always @(posedge sys_clk or negedge INIT_n)
+    if( ~INIT_n )
+      dbg_trg <= 1'b0;
+    else if(negedge_SCTL_n & bus_write && address == 18'o777200)
+      dbg_trg <= 1'b1;
+
+/* -----\/----- EXCLUDED -----\/-----
   always @(posedge sys_clk or negedge RESET_n)
     if( ~RESET_n )
       {REG_DBG_CP, dbg_trg} <= 0;
@@ -2230,6 +2237,7 @@ module top(
       REG_DBG_CP <= 1'b1;
     else if( (address[15:0] == REG_DBG2) & aio_iread  & REG_DBG_CP)
       dbg_trg <= 1'b1;
+ -----/\----- EXCLUDED -----/\----- */
 //    else if( (address == 16'o001040) & aio_iread ) // trap at 'panic:'
 //      dbg_trg <= 1'b1;
 //  else if( (dpwa == (16'o25246 >> 1)) & (we0_lo | we0_hi |we1_lo | we1_hi))

オリジナルのデバッグ機能(ブレークポイント)と競合するので、該当部分をコメントアウトしています。

バッチの置き場所

パッチを当てたカーネルのバイナリと、FPGAのソースコードに対するパッチをここに置きました。ご利用ください。add-self-abort.patchとrpunix.patchedです。 

(3月27日追記) 2.11BSDでも同様の解析ができるように、カーネルパッチを置きました。2.11BSDのカーネルパッチ FPGAは2.11BSD用のアドレス拡張版が必要です。FPGAのパッチ

2026/03/23

2BSDの誤動作をバイナリパッチで捕まえる方法 その1

 カーネルに仕込みを入れなくても"Illegal instruction trap"を捕まえる方法を考案しました。成功率は高くないかもしれませんが、うまくいった場合はHALT信号をトリガにすることができます。手順を以下に説明します。

1) カーネルを起動してシングルユーザーモードのシェルのプロンプトが出た状態にする

2) HALTスイッチを押してODTを起動する

3)以下のようにメモリ書き換え/レジスタ設定を実行する 

@10/001724 400            // Illegal instruction trapベクタを400に変更
@20/001724 400            // IOT trapベクタを400に変更
@400/001724 0              // HALT命令に書き換え
@402/000356 0              // 念のためにもう一つHALT
@777100/177775 400     // breakpointを400に設定
@p                                 // シェルに復帰
 
4) シングルユーザモードのまま以下のコマンドを実行
 
# mount -a
# cd /usr/src/sys/GENERIC; make clean; make
 
うまくいけば"Illegal instruction trap"や"IOT trap"が発生した際にODTを起動し、breakpointによってHALT信号をアサートしてロジアナなどのトリガにすることができます。
 
成功して、ロジアナで取れたデータを解析したところ、やはり2.11BSDの場合と同様
 
正常な命令を読み込んだにもかかわらず"Illegal instruction trap"が発生した 
 
ように見えるという現象が観測できました。
 
なお、再現実験を繰り返しているとファイルシステムが破壊される可能性が高いので、SDカードのイメージのバックアップを取っておくことをお勧めします。 
 

補足説明

このような回りくどい方法を採用したのには理由があります。

DCJ11がトラップベクタの2 word(PC, SR)をアクセスする際は、「命令アクセス」ではなく、データとしてのメモリアクセスを行います。よって、命令アクセスを検出するブレークポイントでトラップベクタのアドレスを指定しても効果がありません。やむを得ず、トラップベクタのPCをアクセスされないはずのメモリ領域(アドレス400近傍)に書き換え、そこをブレークポイントで検出するようにしました。

2026/03/21

TangConsoleDCJ11MEMにおける2BSDの誤動作の調査 その1

2.9BSDの誤動作

オリジナルのFPGAで2.9BSDの誤動作が確認できました。確実に再現します。

再現方法と実行結果

 シングルユーザモードで起動後、以下のように実行します。

# mount -a
Mounted /usr on /dev/rp1h
# cd /usr/src/sys/GENERIC; make clean; make
rm -f *.o *.i
cc -V -S -O -DKERNEL -I. -I/usr/include ../sys/sys2.c
ed - < :splfix.movb sys2.s
as -V - -o sys2.o sys2.s
rm sys2.s

(snip)

cc -V -S -O -DKERNEL -I. -I/usr/include ../dev/ttynew.c
ed - < :splfix.movb ttynew.s
as -V - -o ttynew.o ttynew.s
rm ttynew.s
cc -V -S -O -DKERNEL -I. -I/usr/include ../dev/tty.c
ed - < :splfix.movb tty.s
Illegal instruction - core dumped
# strings core | head
@q6N
core
core
make
h
 h
  .

R0
MAKE.  VERSION 2.58     14 MARCH 1979
=|^();&<>*?[]:$`'"\
 :;&>|
No description argument after -f flag

# adb /bin/make core
$R
ps      0170011
pc      034110
sp      0171272
r5      0171306
r4      0171370
r3      0
r2      0
r1      06
r0      01560
034110:         mov     sp,r5
# make
cc -V -S -O -DKERNEL -I. -I/usr/include ../dev/tty.c
ed - < :splfix.movb tty.s
as -V - -o tty.o tty.s
rm tty.s

カーネルをビルドするとmakeが異常終了します。

コアダンプを調べても実行した命令は正常です。また、続けてmakeを実行すると正常に動作するので、ファイル上にもメモリ上にも不正な命令は存在しないものと考えられます。

2.11BSDの誤動作

 改造版のFPGAとPCBで2.11BSDの誤動作を確実に再現できる方法が見つかりました。

 再現方法と実行結果

 シングルユーザモードで起動後、以下のように実行します。

 @773010
73Boot from rk(0,0,0) at 0177404
:
: rk(0,0,0)unix
Boot: bootdev=03000 bootcsr=0177404

2.11 BSD UNIX #32: Fri Mar 13 00:15:09 PST 2026
    root@:/usr/src/sys/SMALL


phys mem  = 655360
avail mem = 414912
user mem  = 307200

March 15 18:32:17 init: configure system

hk ? csr 177440 vector 210 skipped:  No autoconfig routines.
ht ? csr 172440 vector 224 skipped:  No autoconfig routines.
ra ? csr 172150 vector 154 skipped:  No autoconfig routines.
rl ? csr 174400 vector 160 skipped:  No autoconfig routines.
tm 0 csr 172520 vector 224 attached
tms ? csr 174500 vector 260 skipped:  No autoconfig routines.
ts ? csr 172520 vector 224 skipped:  No autoconfig routines.
xp ? csr 176700 vector 254 skipped:  No autoconfig routines.
erase, kill ^U, intr ^C
# halt
IOT trap - core dumped
# ls *.core
halt.core
# adb /sbin/halt halt.core
adb: no memory for symbols
adb> $r
ps      0170000
pc      041174
sp      0174510
r5      0175214
r4      0175262
r3      040312
r2      045
r1      0
r0      0144
041174:         add     $010,r4
adb> #
#

haltコマンドがIOT命令(000004)を実行して異常終了します。

ODTでメモリダンプを調べてみましたが、異常終了したプロセスの該当するPCの命令はファイル上の命令と一致していました。 

48chのロジックアナライザを接続してすべての信号を観測できる環境を作り、カーネルとFPGAに仕込みを入れてロジアナにトリガをかけてみましたが、バス上で観測された命令はファイル上の命令と一致しており、IOT命令ではありませんでした。

バスのトランザクションとしては以下のような流れでした。

  1. PC(041174)近傍の4命令が読み出される
  2. IOT trapのベクタの2 word(PC, SR)が読み出される
  3. IOT trapベクタに設定されているロジアナトリガ用の命令列が読み出される
  4. トリガ用のI/Oアドレスに書き込みが実行されてトリガ信号がアサートされる 

念のためにIOT命令を実行するテストプログラムを作成してロジアナで解析しましたが、こちらはきちんとIOT命令を読み込んでいることが確認できたので、解析方法に誤りはないと思います。 

考察

 以上の観測結果から考えて、どちらの誤動作も

メモリから読み出したものとは異なる命令を実行した

のが現象のように見えます。この仮説が正しいとして、原因が何かを考えてみたのですが、現時点では何も思いつきません。

(4月6日追記) IOT Trap発生時にカーネルスタックに保存されるPCは、IOT命令のアドレスではなく、+2した値のようなので、上記の解釈は誤りでした。-2したアドレスにはIOT命令が存在することが確認できました。

なお、以上の現象は2セットの個体を用いて検証しているので、ハードウェアの個体差やCPUの故障などは考えにくいと思われます。

(追記) "/.profile"を編集してPATHに2文字追加しただけで再現しなくなったりします。再現条件はかなり限定されるようです。

2026/03/15

【改訂版】TangConsoleDCJ11MEMへの2.11BSDのインストール

 

 TangConsoleDCJ11MEMに2.11BSDをインストールする方法を簡単に説明します。要点だけ書きますので、きちんとした手順書にはなっていません。ご承知おきください。

前提条件

Windows 11とLinux(WSL上で動作するUbuntu) での操作を前提に説明します。読者はそれぞれの環境でのコマンド実行などについては特に説明を要しないものとします。

環境構築

LinuxでSIMHとretro-fuseをインストールします。retro-fuseはソースからビルドします。

参照する情報

  1. 2.11BSDの文書 211bsd-setup.pdf
  2. SIMHに2.11BSDをインストールする手順 Installation of 2.11BSD on SIMH 
  3. retro-fuseの使い方 retro-fuse/wiki 

用意するもの

  1. 2.11BSDの配布ファイル 2.11BSD
  2. Pmod0に接続するmicroSDカードインタフェース Pmod MicroSD
  3. 2.11BSDのソースコードに適用するパッチ 「全部入り」のパッチ
(4月17日追記:カーネルのバグ修正のための追加パッチがあります 追加パッチ

 概略手順

  1. ハードウェアの改造とFPGAの更新
  2. SIMHをインストール
  3. SIMHに2.11BSDをインストール
  4. retro-fuseをインストール
  5. TangConsoleDCJ11MEMに2.11BSDをインストール
  6. インストールしたdiskイメージを書き換える

詳細手順

上記概略手順の1.、5.と6.についてはもう少し詳しく説明します。

TangConsoleDCJ11MEMの改造とFPGAの更新

FPGAについてはこちらのリポジトリの内容で更新してください。 更新すると下記の改造を施さない限り起動しなくなります。

メモリサイズを256KBから640KBに拡張するため、アドレス線の追加配線が必要です。

アドレス腺(DALH[18], [19])の接続方法ですが、パターンカットを行ってバススイッチを経由してレベル変換するやり方を紹介します。

パターンカットの場所

CPUソケットの表面内側でBS0, 1からのパターンをカットします。 配線の間隔が広いので難しくはないと思います。

ジャンパ配線

CPUのDAL18, 19をそれぞれU5(SN74CB3T3245DWR)の6,7ピンに接続します。また、J5のBS0,1をそれぞれPmod1のW19とF19にそれぞれ接続してください。

U5の足は細いですが、そもそもこの基板を実装できる方なら問題ないでしょう。 

テープイメージの作成

2.11BSDの配布ファイルがある場所で以下のコマンドでテープイメージを作成します。

#!/bin/sh

# file 0
dd if=mtboot    of=211bsd.img conv=notrunc
dd if=mtboot    of=211bsd.img conv=notrunc seek=1
dd if=boot      of=211bsd.img conv=notrunc seek=2
# file 1
dd if=disklabel of=211bsd.img conv=notrunc seek=65536
# file 2
dd if=mkfs      of=211bsd.img conv=notrunc seek=131072
# file 3
dd if=restor    of=211bsd.img conv=notrunc seek=196608
# file 4
dd if=icheck    of=211bsd.img conv=notrunc seek=262144
# file 5
dd if=root.dump of=211bsd.img conv=notrunc seek=327680
# file 6
dd if=file6.tar of=211bsd.img conv=notrunc seek=393216
# file 7
# (this file is intentionally unused)
# file 8
dd if=file7.tar of=211bsd.img conv=notrunc seek=524288
# file 9
dd if=file8.tar of=211bsd.img conv=notrunc seek=589824
# file 10
# (this file is intentionally unused)

ルートファイルシステムのインストール

テープから起動してルートファイルシステムをmkfs, restor, icheckします。

@100000g
100026
@0g
73Boot from tm(0,0,0) at 0172522
: tm(0,2)
Boot: bootdev=0402 bootcsr=0172522
Mkfs
file system: rk(0,0)
rk(0,0,0) disklabel missing/corrupt
file sys size [0]: 3072
bytes per inode [4096]: 
interleaving factor (m; 2 default): 
interleaving modulus (n; 100 default): 
isize = 768
m/n = 2 100
Exit called

73Boot from tm(0,0,2) at 0172522
: tm(0,3)
Boot: bootdev=0403 bootcsr=0172522
Restor
Tape? tm(0,5)
Disk? rk(0,0)
Last chance before scribbling on disk. End of tape    ### RETを入力
73Boot from tm(0,0,3) at 0172522
: tm(0,4)
Boot: bootdev=0404 bootcsr=0172522
Icheck
File: rk(0,0)
rk(0,0):
files 609 (r=208,d=22,b=144,c=230,l=5,s=0)
used 2738 (i=106,ii=0,iii=0,d=2632)
free 284
missing 0

73Boot from tm(0,0,4) at 0172522
: rk(0,0)unix
Boot: bootdev=03000 bootcsr=0177404

2.11 BSD UNIX #115: Sat Apr 22 19:07:25 PDT 2000
    sms1@curly.2bsd.com:/usr/src/sys/GENERIC

panic: iinit
no fs on dev 6/0
syncing disks... done

006102
@

オリジナルのカーネルではルートファイルシステムがマウントできないのでブートするとpanicします。 

 置き換えるファイルの作成

カスタマイズされたカーネルとRK05用のブートブロックを作成します。

  1. SIMHのディスクイメージをretro-fuseでマウント
  2. ソースコードにパッチを適用
  3. ディスクイメージをアンマウント
  4. SIMHを起動
  5. カーネルとブートブロックをビルド(SIMHで作業、手順は後述)
  6. SIMHを終了 
  7. SIMHのディスクイメージをretro-fuseでマウント
  8. ビルドしたカーネルとブートブロックをホストにコピー
  9. ディスクイメージをアンマウント

カーネルとブートブロックのビルド手順

カーネルとブートブロックのビルド手順は以下の通りです。

# cd /usr/src/sys/conf
# ./config SMALL
# cd ../SMALL
# make all
# cd ../mdec
# make

最初のmakeでカーネル(unix)が、次のmakeでブートブロック(rkuboot)が生成されます。 

次に、カスタマイズされたカーネルとブートブロックをmicroSDカードイメージに書き込みます。 
  • 2.11BSDがインストールされたmicroSDカードイメージを取得
microSDカード全体のイメージを取得します(rk05.img)
  • カードイメージ上のRK11のディスクイメージをretro-fuseでマウント
 $ bsd211fs -o fsoffset=512 -o mapuid=1000:0 -o mapgid=1000:20  rk05.img /tmp/bsd
  • カーネルをコピー
  • ディスクイメージをアンマウント
  • ブートブロックをディスクイメージに書き込む
$ dd if=rkuboot of=rk05.img seek=1024 conv=notrunc

ディスクイメージをmicroSDカードに書き戻せば準備完了です。 

/usrとソースコードのインストール手順

以後の作業はシングルユーザモードで行います。デバイスファイルを作成するだけでも分のオーダーの時間がかかるので、気長に待ちましょう。

なお、引数"br[012]"でデバイスを作成していますが、生成されるデバイスファイル名は"rp*"となります。MAKEDEVはこういう実装になっていますので混乱しないようにしてください。 

@3773010g
73Boot from rk(0,0,0) at 0177404
: rk(0,0)unix
Boot: bootdev=03000 bootcsr=0177404

2.11 BSD UNIX #32: Fri Mar 13 00:15:09 PST 2026
    root@:/usr/src/sys/SMALL


phys mem  = 655360
avail mem = 414912
user mem  = 307200

March 13 00:17:03 init: configure system

hk ? csr 177440 vector 210 skipped:  No autoconfig routines.
ht ? csr 172440 vector 224 skipped:  No autoconfig routines.
ra ? csr 172150 vector 154 skipped:  No autoconfig routines.
rl ? csr 174400 vector 160 skipped:  No autoconfig routines.
tm 0 csr 172520 vector 224 attached
tms ? csr 174500 vector 260 skipped:  No autoconfig routines.
ts ? csr 172520 vector 224 skipped:  No autoconfig routines.
xp ? csr 176700 vector 254 skipped:  No autoconfig routines.
erase, kill ^U, intr ^C
# cd /dev
# rm -f *rk* *mt* *rp*
# ./MAKEDEV rk0 tm0 br0 br1 br2 br3
# stty erase \^h
# stty crt
# rm -f swap drum
# mknod swap b 6 1
# mknod drum b 6 1
# ls -l rk0* *mt0 rp* swap drum
brw-r-----  1 root       6,   1 Mar 13 00:19 drum
brw-rw-rw-  1 root       1,   0 Mar 13 00:18 mt0
brw-rw-rw-  1 root       1,   4 Mar 13 00:18 nmt0
crw-rw-rw-  1 root       7,   4 Mar 13 00:18 nrmt0
brw-r-----  1 root       6,   0 Mar 13 00:18 rk0h
crw-rw-rw-  1 root       7,   0 Mar 13 00:18 rmt0
brw-r-----  1 root      11,   0 Mar 13 00:18 rp0a
brw-r-----  1 root      11,   1 Mar 13 00:18 rp0b
brw-r-----  1 root      11,   2 Mar 13 00:18 rp0c
brw-r-----  1 root      11,   3 Mar 13 00:18 rp0d
brw-r-----  1 root      11,   4 Mar 13 00:18 rp0e
brw-r-----  1 root      11,   5 Mar 13 00:18 rp0f
brw-r-----  1 root      11,   6 Mar 13 00:18 rp0g
brw-r-----  1 root      11,   7 Mar 13 00:18 rp0h
brw-r-----  1 root      11,   8 Mar 13 00:18 rp1a
brw-r-----  1 root      11,   9 Mar 13 00:18 rp1b
brw-r-----  1 root      11,  10 Mar 13 00:18 rp1c
brw-r-----  1 root      11,  11 Mar 13 00:18 rp1d
brw-r-----  1 root      11,  12 Mar 13 00:18 rp1e
brw-r-----  1 root      11,  13 Mar 13 00:18 rp1f
brw-r-----  1 root      11,  14 Mar 13 00:18 rp1g
brw-r-----  1 root      11,  15 Mar 13 00:18 rp1h
brw-r-----  1 root      11,  16 Mar 13 00:18 rp2a
brw-r-----  1 root      11,  17 Mar 13 00:18 rp2b
brw-r-----  1 root      11,  18 Mar 13 00:18 rp2c
brw-r-----  1 root      11,  19 Mar 13 00:18 rp2d
brw-r-----  1 root      11,  20 Mar 13 00:18 rp2e
brw-r-----  1 root      11,  21 Mar 13 00:18 rp2f
brw-r-----  1 root      11,  22 Mar 13 00:18 rp2g
brw-r-----  1 root      11,  23 Mar 13 00:18 rp2h
brw-r-----  1 root      11,  24 Mar 13 00:18 rp3a
brw-r-----  1 root      11,  25 Mar 13 00:18 rp3b
brw-r-----  1 root      11,  26 Mar 13 00:18 rp3c
brw-r-----  1 root      11,  27 Mar 13 00:18 rp3d
brw-r-----  1 root      11,  28 Mar 13 00:18 rp3e
brw-r-----  1 root      11,  29 Mar 13 00:18 rp3f
brw-r-----  1 root      11,  30 Mar 13 00:18 rp3g
brw-r-----  1 root      11,  31 Mar 13 00:18 rp3h
brw-r-----  1 root       6,   1 Mar 13 00:19 swap
# cd /
# mkfs -s 80000 /dev/rp0h40000 /dev/rp0h
isize = 10000
m/n = 2 100
# mkfs -s 40000 /dev/rp0h1h
isize = 10000
m/n = 2 100
# mkfs -s 10400 /dev/rp2a5200 /dev/rp2a 
isize = 1296
m/n = 2 100
# mkfs -s 32200 /dev/rp2c
isize = 8048
m/n = 2 100
# mount /dev/rp0h /usr
# mkdir /usr/src
# mount /dev/rp1h /usr/src
# mkdir /usr/src/ucb
# mount /dev/rp2a /usr/src/ucb
# mkdir /usr/src/sys
# mount /dev/rp2c /usr/src/sys
# df
Filesystem  1K-blocks     Used    Avail Capacity  Mounted on
root             3022     2706      316    90%    /
/dev/rp0h       39373        3    39370     0%    /usr
/dev/rp1h       39373        4    39369     0%    /usr/src
/dev/rp2a        5117        2     5115     0%    /usr/src/ucb
/dev/rp2c       31695        2    31693     0%    /usr/src/sys
# TAPE=/dev/nrmt0; export TAPE
# mt rew
# mt fsf 6
# cd /usr
# tar time tar xvb 20
x adm/README, 107 bytes, 1 tape blocks
x adm/daily, 1609 bytes, 4 tape blocks
x adm/lpd-errs, 0 bytes, 0 tape blocks

(snip)

ucb/page linked to ucb/more
ucb/uptime linked to ucb/w
ucb/u linked to ucb/users
ucb/reset linked to ucb/tset
     1015.1 real        34.8 user       980.2 sys  
# mt rew
# mt fsf 8
# cd /usr/src
# time tar xvb 20
x sys/pdpuba/tmscp.c, 55882 bytes, 110 tape blocks
x sys/pdpuba/rl.c, 18839 bytes, 37 tape blocks
x sys/pdpuba/tags symbolic link to ../sys/tags

(snip)

x include/utmp.h, 1125 bytes, 3 tape blocks
x include/varargs.h, 219 bytes, 1 tape blocks
x include/vfont.h, 546 bytes, 2 tape blocks
x include/Makefile, 2959 bytes, 6 tape blocks
      178.2 real         7.7 user       170.5 sys  
# mt rew
# mt fsf 9
# time tar xvb 20
x Makefile, 3536 bytes, 7 tape blocks
x asm.sed, 53 bytes, 1 tape blocks
x asm.sed.pdp, 53 bytes, 1 tape blocks

(snip)

x usr.sbin/ntp/patchl, 5658 bytes, 12 tape blocks
x usr.sbin/ntp/read_local.c, 655 bytes, 2 tape blocks
x usr.sbin/Makefile, 777 bytes, 2 tape blocks
     1373.0 real        56.8 user      1316.1 sys  
# df
Filesystem  1K-blocks     Used    Avail Capacity  Mounted on
root             3022     2706      316    90%    /
/dev/rp0h       39373    33417     5956    85%    /usr
/dev/rp1h       39373    37281     2092    95%    /usr/src
/dev/rp2a        5117     4126      991    81%    /usr/src/ucb
/dev/rp2c       31695     5180    26515    16%    /usr/src/sys
# TERM=vt100
# stty rows 56 cols 80 9600 crt
# mount /dev/rp0h /usr
# vi /etc/fstab

fstabを編集する(下記参照)

# umount /usr
# mount -a
# df
Filesystem  1K-blocks     Used    Avail Capacity  Mounted on
/dev/rk0h        3022     2706      316    90%    /
/dev/rp0h       39373    33417     5956    85%    /usr
/dev/rp1h       39373    37281     2092    95%    /usr/src
/dev/rp2a        5117     4126      991    81%    /usr/src/ucb
/dev/rp2c       31695     5180    26515    16%    /usr/src/sys
# cat /etc/fstab
/dev/rk0h       /               ufs     rw      1       1
/dev/rk1h       none            swap    sw      0       0
/dev/rp0h       /usr            ufs     rw      2       1
/dev/rp1h       /usr/src        ufs     rw      3       1
/dev/rp2a       /usr/src/ucb    ufs     rw      4       1
/dev/rp2c       /usr/src/sys    ufs     rw      4       1
# umount -a
# time fsck -y
** /dev/rk0h
File System: /

** Last Mounted on /
** Root file system
** Phase 1 - Check Blocks and Sizes
** Phase 2 - Check Pathnames
** Phase 3 - Check Connectivity
** Phase 4 - Check Reference Counts
** Phase 5 - Check Free List
590 files, 2706 used, 316 free
** /dev/rrp0h
File System: /usr

** Last Mounted on /usr
** Phase 1 - Check Blocks and Sizes
** Phase 2 - Check Pathnames
** Phase 3 - Check Connectivity
** Phase 4 - Check Reference Counts
** Phase 5 - Check Free List
4145 files, 33417 used, 5956 free
** /dev/rrp1h
File System: /usr/src

** Last Mounted on /usr/src
** Phase 1 - Check Blocks and Sizes
** Phase 2 - Check Pathnames
** Phase 3 - Check Connectivity
** Phase 4 - Check Reference Counts
** Phase 5 - Check Free List
6787 files, 37281 used, 2092 free
** /dev/rrp2a
File System: /usr/src/uc

** Last Mounted on /usr/src/uc
** Phase 1 - Check Blocks and Sizes
** Phase 2 - Check Pathnames
** Phase 3 - Check Connectivity
** Phase 4 - Check Reference Counts
** Phase 5 - Check Free List
584 files, 4126 used, 991 free
** /dev/rrp2c
File System: /usr/src/sy

** Last Mounted on /usr/src/sy
** Phase 1 - Check Blocks and Sizes
** Phase 2 - Check Pathnames
** Phase 3 - Check Connectivity
** Phase 4 - Check Reference Counts
** Phase 5 - Check Free List
931 files, 5180 used, 26515 free
      156.2 real        53.1 user       103.0 sys  
# halt
syncing disks... done
halting

000014
@3773010g
73Boot from rk(0,0,0) at 0177404

: rk(0,0,0)unix    ### ここはRETでもOK
Boot: bootdev=03000 bootcsr=0177404

2.11 BSD UNIX #32: Fri Mar 13 00:15:09 PST 2026
    root@:/usr/src/sys/SMALL


phys mem  = 655360
avail mem = 414912
user mem  = 307200

March 13 01:46:38 init: configure system

hk ? csr 177440 vector 210 skipped:  No autoconfig routines.
ht ? csr 172440 vector 224 skipped:  No autoconfig routines.
ra ? csr 172150 vector 154 skipped:  No autoconfig routines.
rl ? csr 174400 vector 160 skipped:  No autoconfig routines.
tm 0 csr 172520 vector 224 attached
tms ? csr 174500 vector 260 skipped:  No autoconfig routines.
ts ? csr 172520 vector 224 skipped:  No autoconfig routines.
xp ? csr 176700 vector 254 skipped:  No autoconfig routines.
erase, kill ^U, intr ^C
# ^DFast boot ... skipping disk checks
checking quotas: done.
Assuming non-networking system ...
checking for core dump... 
preserving editor files
clearing /tmp
standard daemons: update cron accounting.
starting lpd
starting local daemons: sendmail.
Fri Mar 13 01:47:26 PST 2026


2.11 BSD UNIX (curly.2bsd.com) (console)

login: root
erase, kill ^U, intr ^C
# cd /usr/games
# ls
adventure    btlgammon    hack         number       snake        worm
arithmetic   canfield     hangman      phantasia    snscore      worms
backgammon   cfscores     hunt         ppt          teachgammon  wump
banner       chess        lib          primes       trek         zork
battlestar   cribbage     mille        quiz         ttt
bcd          factor       monop        rain         wargames
bj           fish         moo          robots       warp
boggle       fortune      morse        sail         words
# ./zork
>                       Saves game on file dsave.dat
<                       Restores game from file dsave.dat
!command                Execute shell command from Dungeon


Welcome to Dungeon.             This version created 10-SEP-78.
You are in an open field west of a big white house with a boarded
front door.
There is a small mailbox here.
>look
You are in an open field west of a big white house with a boarded
front door.
There is a small mailbox here.
>open mailbox
Opening the mailbox reveals:
  A leaflet.
>get leaflet
Taken.
>read it
                    Welcome to Dungeon!
 
   Dungeon is a game of adventure, danger, and low cunning.  In it
you will explore some of the most amazing territory ever seen by mortal
man.  Hardened adventurers have run screaming from the terrors contained
within.
 
   In Dungeon, the intrepid explorer delves into the forgotten secrets
of a lost labyrinth deep in the bowels of the earth, searching for
vast treasures long hidden from prying eyes, treasures guarded by
fearsome monsters and diabolical traps!
 
   No DECsystem should be without one!
 
   Dungeon was created at the Programming Technology Division of the MIT
Laboratory for Computer Science by Tim Anderson, Marc Blank, Bruce
Daniels, and Dave Lebling.  It was inspired by the Adventure game of
Crowther and Woods, and the Dungeons and Dragons game of Gygax
and Arneson.  The original version was written in MDL (alias MUDDLE).
The current version was translated from MDL into FORTRAN IV by
a somewhat paranoid DEC engineer who prefers to remain anonymous.
 
   On-line information may be obtained with the commands HELP and INFO.
>quit
Your score would be   0 [total of 560 points], in    7 moves.
This gives you the rank of beginner.
Do you wish to leave the game?
y

# halt
syncing disks... done
halting

000014
@

以上でフルインストールとマルチユーザモードの起動確認の完了です。

設定変更

/etc/rcや/etc/rc.local、/etc/netstartは動作しないデーモンなどをコメントアウトするとよいでしょう。現時点で判明しているのは、lpd, hostid, sendmailです。

諸注意

RAMの拡張に伴い、ディスクのブートローダのアドレスが0773xxxから3773xxxに変更されています。 

動作が不安定で再現性のない挙動をします。例えば、カーネルをビルドするためにmakeを実行すると、makeが"Memory fault - core dumped"になったり、/lib/cppが"Fatal error in /lib/cpp"になったりします。

こんな状態なので、これはあくまでも「実験」です。 

(4月17日追記) FPGAの実装の修正(CPUが駆動するABORT信号の対応)とカーネルのバグ修正(追加パッチ)により不安定な動作は解消されました。カーネルのビルドを10時間以上繰り返しても問題ない程度に安定して動作しています。

2026/03/08

【続】TangConsoleDCJ11MEMへの2.11BSDのインストール ~アドレス腺の拡張方法~

アドレス腺(DALH[18], [19])の接続方法ですが、パターンカットを行ってバススイッチを経由してレベル変換するやり方を紹介します。

パターンカットの場所

CPUソケットの表面内側でBS0, 1からのパターンをカットします。 配線の間隔が広いので難しくはないと思います。

ジャンパ配線

CPUのDAL18, 19をそれぞれU5(SN74CB3T3245DWR)の6,7ピンに接続します。また、J5のBS0,1をそれぞれPmod1のW19とF19にそれぞれ接続してください。

U5の足は細いですが、そもそもこの基板を実装できる方なら問題ないでしょう。

2026/03/07

【続】TangConsoleDCJ11MEMへの2.11BSDのインストール ~メモリの拡張実験~

実験的にRAMを124kw(248KB)から252kw(504KB)に拡張してみました。

必要な準備

アドレス腺を増やすため、ジャンパの配線が必要です。DCJ11のDALH[18]とDALH[19] をPmod1のW19とF19にそれぞれ接続してください。FPGAの更新も必要です。

なお、FPGAの入力耐圧については確認していませんので、ジャンパを直結すると故障する可能性があります。抵抗分圧回路を組んで接続したほうが良いと思います。なお、パターンカットを伴う方法についても検討中です。(追記:こちらを参照)

2.11BSDのカーネルについては追加のパッチが必要です。パッチはこちら パッチを適用したカーネルで置き換えてください。スワップデバイスに対してかなり大きなサイズのリクエストが来ていたので、PCで言うところのbounce bufferに相当するバッファのサイズを拡大しています。(3月9日更新: 誤ったパッチを登録していたため、パッチを更新しました。)

 設定変更

シングルユーザモードで起動後は、適宜/etc/fstabなどを変更してください。カーネルを置き換える際についでに編集するのがよいと思います(実機ではedしか使えないので)。

デバイスファイルに関しては、swapとdrumを作り直してください。デバイス番号は以下の通りです。(/dev/rk1hがスワップデバイスとして使用されます。)

 # ls -l /dev/swap /dev/drum
brw-r-----  1 root       6,   1 Mar  5 15:10 /dev/drum
brw-r-----  1 root       6,   1 Mar  5 15:10 /dev/swap

/etc/rcや/etc/rc.local、/etc/netstartは動作しないデーモンなどをコメントアウトするとよいでしょう。現時点で判明しているのは、lpd, hostid, sendmailです。

諸注意

RAMの拡張に伴い、ブートローダのアドレスが0773xxxから1773xxxに変更されています。 

動作が不安定で再現性のない挙動をします。例えば、カーネルをビルドするためにmakeを実行すると、makeが"Memory fault - core dumped"になったり、/lib/cppが"Fatal error in /lib/cpp"になったりします。viも正常動作はしません。

こんな状態なので、これはあくまでも「実験」です。 

なお、 メモリを640KB(RAM)+8KB(ROM)に拡張するとFPGAのBSRAMの使用率が100%になります。(3月9日追記: 実装方法を変更してメモリを640KB(RAM)+4KB(ROM)にしました。使用率は97%です。)

フルインストール方法の改良

インストールテープのイメージ作成ですが、以下の手順に変更すればmicroSDカードは1枚で済みます。"mt fsf"のパラメータは適宜変更してください。

 #!/bin/sh

# file 0
dd if=mtboot    of=211bsd.img conv=notrunc
dd if=mtboot    of=211bsd.img conv=notrunc seek=1
dd if=boot      of=211bsd.img conv=notrunc seek=2
# file 1
dd if=disklabel of=211bsd.img conv=notrunc seek=65536
# file 2
dd if=mkfs      of=211bsd.img conv=notrunc seek=131072
# file 3
dd if=restor    of=211bsd.img conv=notrunc seek=196608
# file 4
dd if=icheck    of=211bsd.img conv=notrunc seek=262144
# file 5
dd if=root.dump of=211bsd.img conv=notrunc seek=327680
# file 6
dd if=file6.tar of=211bsd.img conv=notrunc seek=393216
# file 7
# (this file is intentionally unused)
# file 8
dd if=file7.tar of=211bsd.img conv=notrunc seek=524288
# file 9
dd if=file8.tar of=211bsd.img conv=notrunc seek=589824
# file 10
# (this file is intentionally unused)

お試しあれ。

2026/03/01

【続】TangConsoleDCJ11MEMへの2.11BSDのインストール ~デバイスの追加~

警告  

 インストール手順に複数の誤りが見つかったため、新しい文書を準備中です。この文書の手順は実行しないでください。(3月11日追記)

改定版の文書を作成しました。こちらを参照してください。(3月15日追記)

前回はルートファイルシステムだけインストールしましたが、「デバイスを足せばフルインストールできるのでは」と思い立ち、磁気テープドライブ TM11 (TU10)と大容量ハードディスクドライブRP11 (RP03)を追加してみました。

2.11BSDのRP03ドライバ

配布されたソースツリーでは組み込めるようになっていませんが、RP03のドライバ(rp.c)は/usr/src/sys/OTHERS/rp03/の下にあります。ここにあるrp.cとrpreg.hを/usr/src/sys/pdpuba/に移動して後述のパッチを適用することで動作するようになります。

パッチを適用する前にファイルを移動するのを忘れないようにしてください。 

TM11のドライバの組み込み

こちらはドライバ自身は無改造で組み込めますが、カーネル起動時に初期化されないため、autoconfigを動かすか、静的に初期化関数を呼び出すかする必要があります。

メモリが足りない状態ではautoconfigを動かせる気がしなかったので、上記のRP03のドライバと合わせて静的に初期化関数を呼び出すことにしました。

デバイスを追加するためのパッチ

パッチはこちらです。 デバイスを追加するパッチ

変更量を少なくするために、デバイス番号などは既存のデバイスドライバ(br.c)が使用しているものを乗っ取っています(邪悪)。

なお、ドライバの初期化関数を静的に呼び出している部分を見ると魂が汚れるので、見ないふりをすることをお勧めします。 

用意するもの

前回と同様ですが、追加でfile6.tarのみを書き込んだmicroSDカードが必要です。これはテープデバイスのエミュレーションの1ファイル32MBの制限を回避するためのものです。 

インストール手順

まずは前回の手順に従ってシングルユーザモードで起動できるようにします。ただし、ソースコードのパッチは今回のものも追加で適用します。新しいカーネルで起動してください。

以後の作業はシングルユーザモードで行います。デバイスファイルを作成するだけでも分のオーダーの時間がかかるので、気長に待ちましょう。

なお、引数"br[012]"でデバイスを作成していますが、生成されるデバイスファイル名は"rp*"となります。MAKEDEVはこういう実装になっていますので混乱しないようにしてください。 

 @773010g
73Boot from rk(0,0,0) at 0177404
: rk(0,0)unix
Boot: bootdev=03000 bootcsr=0177404

2.11 BSD UNIX #46: Sat Feb 28 15:50:06 PST 2026
    root@curly.2bsd.com:/usr/src/sys/SMALL


phys mem  = 253952
avail mem = 64832
user mem  = 307200

February 28 03:27:10 init: configure system

autoconfig: couldn't find symbols in /unix.
February 28 03:27:11 init: configuration setup error

erase, kill ^U, intr ^C
# stty erase ^H crt
# cd /dev
# rm -f *rk* *mt* *rp*
# ./MAKEDEV rk0 tm0 br0 br1 br2
# ls -l rk0* *mt0 rp*
brw-rw-rw-  1 root       1,   0 Feb 28 03:28 mt0
brw-rw-rw-  1 root       1,   4 Feb 28 03:28 nmt0
crw-rw-rw-  1 root       7,   4 Feb 28 03:28 nrmt0
brw-r-----  1 root       6,   0 Feb 28 03:28 rk0h
crw-rw-rw-  1 root       7,   0 Feb 28 03:28 rmt0
brw-r-----  1 root      11,   0 Feb 28 03:29 rp0a
brw-r-----  1 root      11,   1 Feb 28 03:29 rp0b
brw-r-----  1 root      11,   2 Feb 28 03:29 rp0c
brw-r-----  1 root      11,   3 Feb 28 03:29 rp0d
brw-r-----  1 root      11,   4 Feb 28 03:29 rp0e
brw-r-----  1 root      11,   5 Feb 28 03:29 rp0f
brw-r-----  1 root      11,   6 Feb 28 03:29 rp0g
brw-r-----  1 root      11,   7 Feb 28 03:29 rp0h
brw-r-----  1 root      11,   8 Feb 28 03:29 rp1a
brw-r-----  1 root      11,   9 Feb 28 03:29 rp1b
brw-r-----  1 root      11,  10 Feb 28 03:29 rp1c
brw-r-----  1 root      11,  11 Feb 28 03:29 rp1d
brw-r-----  1 root      11,  12 Feb 28 03:29 rp1e
brw-r-----  1 root      11,  13 Feb 28 03:29 rp1f
brw-r-----  1 root      11,  14 Feb 28 03:29 rp1g
brw-r-----  1 root      11,  15 Feb 28 03:29 rp1h
brw-r-----  1 root      11,  16 Feb 28 03:30 rp2a
brw-r-----  1 root      11,  17 Feb 28 03:30 rp2b
brw-r-----  1 root      11,  18 Feb 28 03:30 rp2c
brw-r-----  1 root      11,  19 Feb 28 03:30 rp2d
brw-r-----  1 root      11,  20 Feb 28 03:30 rp2e
brw-r-----  1 root      11,  21 Feb 28 03:30 rp2f
brw-r-----  1 root      11,  22 Feb 28 03:30 rp2g
brw-r-----  1 root      11,  23 Feb 28 03:30 rp2h
# cd /
# mkfs -s 80000 /dev/rp0h
isize = 20000
m/n = 2 100
# mkfs -s 80000 /dev/rp1h
isize = 20000
m/n = 2 100
# mkfs -s 10400 /dev/rp2a
isize = 2592
m/n = 2 100
# mkfs -s 64400 /dev/rp2c
isize = 16096
m/n = 2 100
# mount /dev/rp0h /usr
# mkdir /usr/src
# mount /dev/rp1h /usr/src
# mkdir /usr/src/ucb
# mkdir /usr/src/sys
# mount /dev/rp2a /usr/src/ucb
# mount /dev/rp2c /usr/src/sys
# df
Filesystem  1K-blocks     Used    Avail Capacity  Mounted on
root             3022     2855      167    94%    /
/dev/rp0h       78748        5    78743     0%    /usr
/dev/rp1h       78748        4    78744     0%    /usr/src
/dev/rp2a       10236        2    10234     0%    /usr/src/ucb
/dev/rp2c       63392        2    63390     0%    /usr/src/sys

# TAPE=/dev/nrmt0; export TAPE
# mt rew
# mt fsf 7
# cd /usr/src
# tar xv
x sys/pdpuba/tmscp.c, 55882 bytes, 110 tape blocks
x sys/pdpuba/rl.c, 18839 bytes, 37 tape blocks
x sys/pdpuba/tags symbolic link to ../sys/tags

(snip)

x include/varargs.h, 219 bytes, 1 tape blocks
x include/vfont.h, 546 bytes, 2 tape blocks
x include/Makefile, 2959 bytes, 6 tape blocks
# mt rew
# mt fsf 8
# tar xv
x Makefile, 3536 bytes, 7 tape blocks
x asm.sed, 53 bytes, 1 tape blocks
x asm.sed.pdp, 53 bytes, 1 tape blocks

(snip)

x usr.sbin/ntp/patchl, 5658 bytes, 12 tape blocks
x usr.sbin/ntp/read_local.c, 655 bytes, 2 tape blocks
x usr.sbin/Makefile, 777 bytes, 2 tape blocks

ここでmicroSDカードをfile6.tarのみ書き込んだものに交換する

# mt rew

# cd /usr 

# tar xv

x adm/README, 107 bytes, 1 tape blocks
x adm/daily, 1609 bytes, 4 tape blocks
x adm/lpd-errs, 0 bytes, 0 tape blocks
 

(snip)

ucb/page linked to ucb/more
ucb/uptime linked to ucb/w
ucb/u linked to ucb/users
ucb/reset linked to ucb/tset
#
# df
Filesystem  1K-blocks     Used    Avail Capacity  Mounted on
root             3022     2705      317    90%    /
/dev/rp0h       78748    33417    45331    42%    /usr
/dev/rp1h       78748    37281    41467    47%    /usr/src
/dev/rp2a       10236     4126     6110    40%    /usr/src/ucb
/dev/rp2c       63392     5180    58212     8%    /usr/src/sys

以上でフルインストールの完了です。おそらくメモリ不足でログインプロンプトまでたどり着けないので、これ以上は先に進まないことをお勧めします。haltコマンドで終了しましょう。

次回予告(?) 

メモリ拡張について検討してみました。検討事項として思いついたのは以下の三つです。

  1. 追加のアドレス腺の接続方法
  2. DMA可能なアドレス範囲の制限
  3. FPGAの空き領域(?) 

BS信号(BS0, BS1)をPmodコネクタに接続する実験は行っていたので、1.については問題なさそうです(ジャンパ腺で対応可能)。

DMA可能なアドレス範囲ですが、ディスクもテープもDMAアドレスは18bitしかないので、サイズとしては256KBまでしかアクセスできません。このため、PDP-11ではUNIBUSのDMAアドレスを変換するUNIBUS mapという仕組みがあります。

このUNIBUS mapを新規実装するのは私のスキル的に難易度が高いのでためらっていたのですが、2.11BSDのドライバのソースを眺めていたら"SOFUB_MAP"というオプションに気が付きました。コンフィグファイルのコメントによると、

# Software UNIBUS/QBUS map.  Permits
# use of 18 bit controllers in a 22 bit
# Qbus system.  Normally NO except for
# the GENERIC kernel or if you actually
# have an 18 bit RX02 on a Qbus system. 

 とのことなので、これを有効にすればよさそうです。

FPGAの空き領域については余裕がありそうなので、これも大丈夫そうです。

ということで、メモリ拡張に挑戦してみようと思います。 

 

 

TangConsoleDCJ11MEMにおける2BSDの誤動作の調査 その3

誤動作の原因の二つ目が判明しました。 符号なし2進数と符号付2進数の比較 後述するSOFUB_MAPの実装に符号なし2進数と符号付2進数を比較しているコードがありました。直接の比較ではありませんでしたが、符号なし整数の値を符号付整数の変数に代入し、その変数と定数を比較していたため...