RalinkがMediatekに買収されてからのMIPS SOCはMT7620(24K), MT7621(1004K), MT7628(24K)があります。
もともとMediatekはARMのSOCを作っていて、近い型番の製品もあります。
MT7621はなんとマルチThreadでL2キャッシュまで付いてます。
昔SONYが販売していたワークステーションのNewsでこのスペックだと1000万円くらいしたものが、Hardoffで110円で手に入ります。
FreeBSD/mipsのMediatekを実装はMT7620,MT7621,MT7628すべてサポートがあります。MT7620,MT7621は新しい作り込みが入っていますが、MT7628はRalink時代のRT5350に近いようです。
ただMT7621のマルチThread(SMP)のコードはなかったので、作ってみました。MIPSではThreadの事をVirtual Processing Elements (VPE)とよんでいます。
SMPの対応にはIPIの送信とクリアとVPE自身のIDの取得とVPEの起動の処理が必要です。
ブートのVPEは0でOS起動時はそれ以外の1,2,3のVPEは止まっています。
まずVPEの起動は、0x80000000からの32バイトx4がVPE制御用になっていて、ここに関数のメモリアドレスを起動時のプログラムカウンター(PC)として設定して、フラグを設定するとVPEが起動します。LinuxのコードはSP,GPなどのレジスタも設定していましたが、FreeBSDではPCだけで後は勝手に設定してくれます。
0x80000000は物理メモリのキャッシュありのKSEG0とかぶっていますが、この機能が優先されるようです。
IPIの処理はGICで行っていて、GICの60-63で各VEPに割り込み2を送れます。割り込み2を受け取ったVPEはそのGIC割り込みをクリアします。正式には受け取るのもGICで受け取るのがいいのかもしれませんが、既存コードがそういう作りになってなかったので、MIPS 4Kの割り込みを直接拾っています。
GICは1004Kの仕様ですが、中身はベンダー毎に違いそうです。
VPEのIDはmaltaのコードをそのままで動いているようです。
とここまででVPEは動くのですが、FreeBSDではこのほかにVPE毎にタイマーの処理が必要です。このSOCではMIPS4Kのタイマー割り込みがVPE0でしか受け取れません。仕方がないので、各VPEに割り込み1として送れるGIC 57-59でダミー割り込みをIPIと同じように送るようにしました。 MIPS 4Kの共通コードのtick.cのTimecounterが正しく動作しないのが原因だったので、SOCのTimerを使ってTimecounterを追加しました。それぞれのVPEがCP0のTimerを持っていて、それぞれ別の値になるため、Timecounterを問い合わせたVPE毎に違った値が返るのでおかしな動作になっていたと思われます、
psコマンドでidelを見ると起動時間より長く表示されて、各VPEの合計値になるようです。
これでSMPは動いたのですが、今回のターゲットのFlashはNANDでドライバーがありません。
NANDのドライバーを書くのは面倒なので、NetBSDのインストールイメージのようなメモリディスク(md)を使う方法にしました。幸いNANDもDRAMも128Mと大きいので余裕です。
rayにきいたらMFSBSDが参考になるかもよって事だったので、ソースツリーのsys/confでMFSをgrepしたところMFS_IMAGEなるmake optionがあることがわかりました。
このオプションにZRouterでビルドしたrootfsを設定してカーネルをビルドするとmdが見えるのでrootfsのマウントポイントをそこにします。
NetBSDのmdイメージはサイズの設定が必要でしたが、MFS_IMAGEはイメージのファイルを設定するだけでよきに計らってくれます。
カーネルビルド時にMFS_IMAGEの設定があると、そのファイルが存在しないとエラーになります。rootfsにはkernelモジュールが入るためにkernelのビルドも行っています。このため一度普通にビルドして、もう一度mfskernelのターゲットをビルドするとmd入りカーネルが出来上がります。
SMPの効果はないですが、mruby3.3のfib(32)は10秒でした。
ソースはここにあります。
freebsd-mipsのMLにメールを投げたのですが、まったくレスありません。FreeBSDは屍のようです。
まだちょっとおかしいので、ぼちぼちみていきます。
Ethernetドライバのrtが不安定でいろいろいじってみたのですが、SMPだとときどき落ちてしまいます。Gigaでリンクしてiperf3で負荷をかけると落ちます。100Mだととりあえず落ちないようなので、switchのポートを100baseTXにして帯域規制をかけるようにしました。ただこれでは発生頻度が下がるだけで、根本的な問題の解決にはなってません。不思議なのはNON SMPでもmbufのリークが確認できるのですが、問題にならないことです。(2025/03)
[zone: mbuf_jumbo_page] kern.ipc.nmbjumbop limit reached
そもそもrtは割り込み処理をfilterではなくithreadで行ってるにも関わらず、そこからtaskqueueに処理を乗せています。おそらく古い実装なのではないでしょうか。