2026/02/12

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カードインタフェース
  3. 2.11BSDのソースコードに適用するパッチ bsd211.patch

 概略手順

  1. SIMHをインストール
  2. SIMHに2.11BSDをインストール
  3. retro-fuseをインストール
  4. TangConsoleDCJ11MEMに2.11BSDをインストール
  5. インストールしたdiskイメージを書き換える

詳細手順

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

テープイメージの作成

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

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

dd if=disklabel of=211bsd.img conv=notrunc seek=65536
dd if=mkfs      of=211bsd.img conv=notrunc seek=131072
dd if=restor    of=211bsd.img conv=notrunc seek=196608
dd if=icheck    of=211bsd.img conv=notrunc seek=262144
dd if=root.dump of=211bsd.img conv=notrunc seek=327680
dd if=file6.tar of=211bsd.img conv=notrunc seek=393216
dd if=file7.tar of=211bsd.img conv=notrunc seek=458752
dd if=file8.tar of=211bsd.img conv=notrunc seek=524288

インストール

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

 @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
: 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します。 

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

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

  1. SIMHのディスクイメージをretro-fuseでマウント
  2. ソースコードにパッチを適用
  3. ディスクイメージをアンマウント
  4. SIMHを起動
  5. カーネルとブートブロックをビルド(SIMHで作業、手順は後述)
  6. SIMHを終了 
  7. SIMHのディスクイメージをretro-fuseでマウント
  8. ビルドしたカーネルとブートブロックをホストにコピー
  9. ディスクイメージをアンマウント
次に、カスタマイズされたカーネルとブートブロックをmicroSDカードイメージに書き込みます。 
  • 2.11BSDがインストールされたmicroSDカードイメージを取得
microSDカード全体のイメージを取得します(rk11.img)
  • カードイメージ上のRK11のディスクイメージをretro-fuseでマウント
 $ bsd211fs -o fsoffset=512 -o mapuid=1000:0 -o mapgid=1000:20  rk11.img /tmp/bsd
  • カーネルをコピー
  • ディスクイメージをアンマウント
  • ブートブロックをディスクイメージに書き込む
$ dd if=rkuboot of=rk11.img seek=1024 conv=notrunc

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

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

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

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

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

補足

2.11BSDを動かすためにはFPGAの実装の変更が必要です。オリジナルからforkした、こちらのリポジトリを参照してください。forkしたリポジトリ 

2026/02/09

2.11BSDを動かす試み その3

 シングルユーザモードの起動に成功

initがautoconfigを起動するあたりから進まなかったのはメモリ不足が原因のようです。

カーネルのコンフィグレーションを編集して不要なドライバを削除し、29KBほど メモリを増やしてブートしたところ、以下のようにシングルユーザモードのshが起動しました。

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

2.11 BSD UNIX #13: Mon Feb 9 14:22:07 PST 2026
    root@curly.2bsd.com:/usr/src/sys/SMALL


phys mem  = 253952
avail mem = 60096
user mem  = 307200
swap size = 311808

February  8 22:16:04 init: configure system

autoconfig: couldn't find symbols in /unix.
February  8 22:16:05 init: configuration setup error

erase, kill ^U, intr ^C
#

("swap size..."の表示はデバッグ用に足したものなので、オリジナルのカーネルでは表示されません。 )

autoconfigが動かないのでテープデバイスが使えませんが、気にしないことにします。メモリがかつかつでマルチユーザモードまでもっていっても実用性はあまりないような気がするので、「2.11BSDはこれで動いた」ことにします。

今後の予定

需要があるかどうかわかりませんが、2.11BSDをインストールするための手順やデバイスドライバの変更内容などについては文書化するつもりです。 

2026/02/08

2.11BSDを動かす試み その2

現状報告 

デバイスドライバに手を入れる必要があったので無改造ではありませんが、2.11BSDのカーネルが起動して、ある程度ユーザプロセスが動作するようになりました。現時点での起動時のメッセージは以下の通りです。

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

2.11 BSD UNIX #137: Sun Feb 8 12:04:58 PST 2026
    root@curly.2bsd.com:/usr/src/sys/GENERIC


phys mem  = 253952
avail mem = 29952
user mem  = 307200

February  6 23:40:57 init: configure system
 
initが動いて、autoconfigを起動したあたりで寝ているようです。もう一息といったところでしょうか。

2026/02/07

MC68020/68030プログラミングクイズの解答と解説

 Xで出題した問題の解答と解説です。Xのポスト

問題

 MC68020/68030のNOP命令には「何もしない」や「実行時間がかかる」以外の重要な機能がある。それは何か。

解答

 先行する命令が完了するまで整数パイプラインやバスオペレーションを同期する。

解説

 バスオペレーションの同期についてはメモリ保護をサポートしているOSカーネルの実装で必要になる場合があります。

例として、MC68020の外部MMUでアクセス違反をBERR信号で通知するシステムについて説明します。

カーネルではユーザ空間からカーネル空間にデータをコピーする場面がありますが、ユーザプロセスから渡されたアドレスが不正な場合はアクセス違反によるバスエラー例外が発生します。カーネルの実装ではこのバスエラーをトラップして、メモリコピーを中断する必要があります。

バスエラーを発生する可能性があるメモリアクセスで同期を実行しないと、以下のようなシナリオでカーネルが不正アドレスを参照してpanicします。

 前提として、ユーザ空間からカーネル空間へのコピーがmoves命令で実行され、バスエラー発生時はスタックフレーム上のコンディションコードやレジスタの値を調整してからmoves命令の次の命令に復帰する実装について考えます。実装のイメージとしては以下の通りです。

メモリコピーするループ

  1.  moves命令でユーザ空間とカーネル空間の間でメモリコピー(ループの本体)
  2. dbcc命令でループ実行。Cフラグがセットされていたらループ終了

バスエラーのトラップハンドラ 

バスエラーが発生した命令がmoves命令であった場合、スタックフレームを書き換えて、以下の処理を実行します。

  1. Cフラグをセット
  2. 戻り値を格納するレジスタの値を-1(エラーを示す)に変更
  3. 復帰アドレスをmoves命令の次の命令に変更

問題発生のシナリオ

  1. moves命令でバスエラーが発生
  2. 整数パイプラインが進んでおり、dbcc命令は「ループを実行する」と判定
  3. ループが終了しないため、カーネルアドレス空間でバスエラーが発生
  4. panic

解決方法

moves命令の後にnop命令を挿入しバスオペレーションを同期する。 

補足

以上はソニーのワークステーションNWS-700シリーズで実際に発生したバグとその対策を元にした説明です。30年以上前の記憶に頼って書いているので細部は不正確かもしれませんがイメージはつかめると思います。

2026/02/06

MC6809プログラミングクイズの解答と解説

Xで出題した問題の解答と解説です。 Xのポスト

問題

Xレジスタが0に初期化されている場合、以下の命令の実行結果を述べよ。

STX 0,X++

解答

0番地と1番地の2バイトのメモリに"2"が格納される。Xレジスタの値は"2"となる。

解説

 命令を素直に解釈すれば、「0番地と1番地の2バイトのメモリに"0"が格納される」のが期待動作ですが、実際の動作は異なります。これはCPUの設計に起因する内部処理の順序によるものです。

この挙動については、MC6809のデータシートに以下のように注意書きがあります。

 Care should be taken in performing operations on 16-bit pointer registers (X, Y, U, S) where the same register is used to calculate the effective address.
Consider the following instruction:

    STX 0,X++ (X initialized to 0)

The desired result is to store a zero in locations $0000 and $0001, then increment X to point to $0002. In reality, the following occurs:

0 -> temp    calculate the EA; temp is a holding register
X+2 -> X    perform auto increment
X  -> (temp)     do store operation

( 8-BIT MICROPROCESSOR & PERIPHERAL DATA, Motorola Inc., pp.3-250)

私の知る限り、6809のプログラミングの解説書である"MC68009-MC6809E : Microprocessor Programming Manual, Motorola Semiconductor Products Inc., c1981."でも説明されていないので、データシートを読んだ人でないと正解がわからないかもしれません。

この問題は、6809のプログラミングについてどれだけ詳しいかを判別するために使っていました。 

2026/02/05

separate I&Dのプログラムが起動しない問題 その2

現在の状況 

 テープデバイスのテープの位置の計算がなかなか思った通りにならなかったのですが、何とか2.11BSDのカーネルが起動してメッセージを表示するところまでたどり着きました。

まだシングルユーザモードまでは到達していないのですが、ようやくここまで来ました。

実際にやったことは以下の通りです。

  • 2.11BSDのアーカイブからテープイメージを生成
  • テープからmkfsを起動してルートファイルシステムを作成
  • restorを起動してルートファイルシステムの内容をリストア


まだHDDにブートコードをインストールできないのでテープからの起動ですが、カーネルが起動してメッセージが表示されました。 

 @100000g
100026
@0g
73Boot from tm(0,0,0) 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

これからカーネルのデバッグだと思ったのですが、ハードウェアの挙動が安定しないという問題が発生しており、心が折れそうです。 一縷の望みを託して代替のTang Console 138Kを注文したので、届くまでは調査は中断します。

2026/02/02

separate I&Dのプログラムが起動しない問題 その1

これまでの調査結果

 2.11BSDのインストール時に使用されるテープ上のプログラムの一つにrestorがあります。

このプログラムは命令領域のサイズが大きいため、 separate I&D(SID)としてリンクされています。一方、サイズの小さいmkfsなどのプログラムは命令とデータは単一のアドレス空間で動作します。

SIDプログラムも単一アドレス空間のプログラムもファイル上は.text, .dataの順番に配置されていることに違いはないのですが、2.11BSDのbootプログラムは、SIDプログラムに限っては、.data, .textの順番にメモリに読み込みます。したがって、テープデバイスに対しては以下のような動作を行います。

  1. .dataセクションの先頭まで順方向にシークする
  2. .dataを読み込む
  3. .textセクションの先頭まで 逆方向にシークする
  4. .textを読み込む
TangConsoleDCJ11MEMの現時点の実装ではテープデバイスのファイル単位のシークは実装されていますが、レコード単位でのシークは対応していません。したがって、上記の1.や2.の「ファイルの途中までシークする」という操作はファイル単位のシークとして実行されます。
 
以上から、SIDプログラムを起動するためにはレコード単位のシークも実装する必要があることがわかりました。 
 

テープデバイスのデータフォーマットの概略

 

前提知識としてテープデバイスのデータフォーマットについてごく簡単に書いておきます。
 
バイナリデータファイルは可変長のレコードに分割されて格納されます。一つのファイルは複数のレコードによって構成され、テープマークによってファイルの終わりが示されます。
 
テープデバイスはレコード単位やファイル単位で順方向/逆方向のシークが可能です。
 

 TM11コントローラの機能

 

 TM11のシーク関係のコマンドは、レコード単位の移動(Space forward, Space reverse)しかありません。よって、2BSDのドライバではファイル単位のシークを実現するためには以下のような工夫(?)をしています。
  1. ファイル単位のシークが要求されたらレコード単位のシークを実行する。この際、レコード数のパラメータとして極端に大きな値を設定する。
  2. TM11は指定された方向にシークを開始し、テープマークを検出することでシークを終了する。結果的にファイル単位でシークできる。
 「極端に大きな値」としては、0と-32760(8進数で100010)が使用されているので、TM11のエミュレーションではこのマジックナンバーで 見分けてファイル単位のシークとレコード単位のシークを区別すればよさそうです。
 

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

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