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

cpl, ipending, astpending

cpl, ipending, astpendingはグローバル変数として定義されているが、これはCPU毎に管理されなければならない。

sgi/sgi/machdep.c, mips64/mips64/*.S

curprocpaddr

curprocpaddrはグローバル変数として定義されているが、これはCPU毎に管理されなければならない。
そこら中のアセンブリコードからアクセスされているので結構面倒。

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を行うドライバを実装する必要がある。

sgi/sgi/mutex.c

開いてみて仰天したんだが、single processor systemにはMutexは要らないよ〜って書いてあって、殆どスタブのようなコードが置いてあるだけ。
OpenBSDでのmtx_enter()/mtx_leave()はSMP環境下でのspin lockを提供するAPIらしく、その前提に於いてはこれはスタブでいいんだろう。
が、SMP化するには当然実装しなければならない。

__mp_lock

なにをするのか良く調べてないが、__mp_lockというAPIがあるらしい。
これはsgiにはまったく実装されてないので、実装する必要がある。
とりあえずはpowerpcのmplock.hをそのままコピーするだけで良さそうに見える。