Golangではシステムコールのmmapを使用することができるので、/dev/mem かUIOで作成した/dev/uioX をmmapすれば物理メモリを読み書きすることができます。
ここではUIOを使った例を紹介します。
UIOのデバイスを登録する
UIOについてはこの記事を参照してください。
LinuxのUIO(User space I/O) その1
この記事に従って、/dev/uio0 が作成できたとして、次にそれをGolangで書かれたプログラムからアクセスする方法を示します。
Golangのサンプルプログラム
ソースコードはgistに置きました。ここ
func mmapRegs32(addr uint32, n int) []uint32 {
file := "/dev/uio0"
f, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
offset := int64(addr) &^ 0xfff
data, err := syscall.Mmap(int(f.Fd()), offset, (n+0xfff)&^0xfff, syscall.PROT_READ, syscall.MAP_SHARED)
if err != nil {
log.Fatalf("mmap %s: %v", f.Name(), err)
}
f.Close()
map_array := (*[math.MaxInt32 / 4]uint32)(unsafe.Pointer(&data[0]))
return map_array[(addr&0xfff)/4 : ((int(addr)&0xfff)+n)/4]
}
Cのプログラムと同様のパラメータでSyscall.Mmap()を使用します。このメソッドは戻り値が[]byte です。
バイト単位でアクセスしたい場合はこれをこのまま使用すればよいです。
今回は4バイト単位でアクセスしたいので、[]uintの型で欲しいところです。
そのためには、一度大きなサイズのuint32の配列のポインタに変換してから、それをベースにする[]int のスライスを作成すればよいです。