OpenBSD/sgi on octane2 - SMP化についての考察
未だ未だまともに動いてくれてはいないのだが、一応ユーザランドが起動していてドライバさえ直ればマルチユーザモードで起動してきそうな雰囲気なので、OpenBSD/sgiのSMP化に取り掛かろうと思う。
OpenBSD/sgiをSMP化するにあたってやらなければいけない事を考えてみる。
。
mips64/include/cpu.h, mips64/mips64/cpu.c
struct cpu_info
CPUの情報を記録する構造体。
SMP対応するには、ci_next、ci_cpuidなどいくつかのメンバを追加する必要がある。
curcpu()
現在のCPUのstruct cpu_info*を取得する。
OpenBSD/sgiではCPU1個決め打ちな実装になっている:
#define curcpu() (&cpu_info_primary)
これをstruct cpu_infoの配列へ参照しにいくコードに変更しなければならない。
cpu_number()
現在のCPUのCPU IDを取得する。
OpenBSD/sgiではCPU1個決め打ちな実装になっている:
#define cpu_number() 0
MIPS32/64ならrdhwr命令でCPU IDを取得出来るのだが、R10000にはこれがないらしい。
代わりに、Octane2にはHEARTというハードウェア機構にPR_IDというレジスタがあり、ここからCPU IDを取得出来るらしい。
cpu_unidle()
隣のCPUをidleループから復帰させる。
OpenBSD/sgiではCPU1個決め打ちなので実装されていない。
隣のCPUをidleから起こすのに、IPIを送るコードを実装する必要がある。
cpuattach()
2個目以降のプロセッサを適切に認識させ、初期化する必要がある。
cpu_boot_secondary_processors(), cpu_boot_secondary()
セカンダリプロセッサのブートを行う。
マルチプロセッサを管理する為のハードウェア機構にアクセスし、セカンダリプロセッサのエントリポイントを指定してプロセッサの有効化を行わなければならない。
Octane2にはこのハードウェア機構としてMPCONFというものが用意されているらしい。
cpu_spinup_trampoline(), cpu_hatch()
cpu_boot_secondary()からセカンダリプロセッサのエントリポイントとしてcpu_spinup_trampoline()を指定し、このアセンブリコードから起動してセカンダリCPUを初期化し、Cで書かれたcpu_hatch()を呼び出す。
cpu_hatch()ではCPUの初期化の続きを行い、UVMとスケジューラにCPUを登録してからアイドルループを実行する。
astpending, want_resched
astpending, want_reschedはグローバル変数として定義されているが、これはCPU毎に管理されなければならない。
sgi/include/intr.h, mips64/mips64/interrupt.c
mips64/mips64/pmap.c
TLBのinvalidate, updateする所でアドレスがCPU間で共有されている時はIPIを送って関係するCPUのTLBも更新する作業(Mach TLB Shootdown)を行うように改造する必要がある。
FreeBSD-current/mipsにある程度実装されているので、これが参考になる。
また、ASIDをCPU毎に管理する必要がある。
mips64/mips64/clock.c
クロックの管理もグローバル変数で行われているので、CPU毎に管理する必要がある。
mips64/mips64/cache_r10k.S
CPUのドキュメントをきちんと読み込んでいないので未だ良く分からないが、キャッシュの構造によってはCPU間でキャッシュの同期を行う必要がある。
IPIドライバ
ハードウェア機構を呼び出してIPIを行うドライバを実装する必要がある。