1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

riscv-tests のメモリマップを調査した際のメモ

Posted at

最近 RISCV のエミュレータを書いているのだが、その時に riscv-tests (https://github.com/riscv/riscv-tests) メモリマップを調べたのでメモ。

手元で使っている riscv-tests は数か月以上前にチェックアウトしたものなので、今は変わっているかもしれない。

物理アドレス空間

アドレスは RV32 のもので、RV64 では符号拡張したアドレスが使われる。

アドレス サイズ 名称 備考
0x80000000 0x80000000 RAM
0x80001000 0x4 tohost riscv-tests の一部では、アドレスの下位 16 bit が 0x2000 / 0x3000 になる

カーネル論理アドレス空間

VM 有効のテストにおける、カーネルアドレス空間。

RV32

アドレス サイズ 内容 備考
0xffc00000 0x400000 RAM
0xffc01000 0x4 tohost 一部のテストでは、アドレスの下位 16 bit が 0x2000 / 0x3000 になる

RV64

アドレス サイズ 内容 備考
0xffffffff_ffe00000 0x200000 RAM
0xffffffff_ffe01000 0x4? tohost 一部のテストでは、アドレスの下位 16 bit が 0x2000 / 0x3000 になる

ユーザー論理アドレス空間

VM 有効のテストにおける、ユーザー論理アドレス空間。

RV32

アドレス サイズ 内容 備考
0x00000000 0x400000 RAM
0x00001000 0x4 tohost riscv-tests の一部では、アドレスの下位 16 bit が 0x2000 / 0x3000 になる

RV64

アドレス サイズ 内容 備考
0x00000000_00000000 0x200000 RAM
0x00000000_00001000 0x4? tohost riscv-tests の一部では、アドレスの下位 16 bit が 0x2000 / 0x3000 になる

ソースコード

アドレス変換は以下のマクロで行われる。uva2kva の引数が pa でややこしいけど、たぶん引数は uva が正しいのだと解釈。
ソースコードはいつぞやの https://github.com/riscv/riscv-tests からの引用だが、コメントは自分で入れている。

// vm.c
#define pa2kva(pa) ((void*)(pa) - DRAM_BASE - MEGAPAGE_SIZE)
#define uva2kva(pa) ((void*)(pa) - MEGAPAGE_SIZE) // i.e. uva = kva + MEGAPAGE_SIZE

DRAM_BASE, MEGAPAGE_SIZE の値を当てはめると以下のようになる。

// encoding.h

// RV32
#define pa2kva(pa) ((void*)(pa) - 0x80400000)
#define uva2kva(pa) ((void*)(pa) - 0x400000)

// RV64
#define pa2kva(pa) ((void*)(pa) - 0x80200000)
#define uva2kva(pa) ((void*)(pa) - 0x200000)

DRAM_BASE, MEGAPAGE_SIZE の定義は以下の通り。

// riscv_test.h
#define DRAM_BASE          0x80000000
// riscv_test.h
#if __riscv_xlen == 64
# define MSTATUS_SD MSTATUS64_SD
# define SSTATUS_SD SSTATUS64_SD
# define RISCV_PGLEVEL_BITS 9
# define SATP_MODE SATP64_MODE
#else
# define MSTATUS_SD MSTATUS32_SD
# define SSTATUS_SD SSTATUS32_SD
# define RISCV_PGLEVEL_BITS 10
# define SATP_MODE SATP32_MODE
#endif
// riscv_test.h
#define PGSHIFT 12
#define PGSIZE (1UL << PGSHIFT) // 0x1000
// riscv_test.h
#define PTES_PER_PT (1UL << RISCV_PGLEVEL_BITS) // RV32: 0x400, RV64:0x200
#define MEGAPAGE_SIZE (PTES_PER_PT * PGSIZE) // RV32: 0x400000 (4MB), RV64: 0x200000 (2MB)

ページテーブル

ページテーブルは以下のように定義されている。

#define l1pt pt[0]
#define user_l2pt pt[1]
#if __riscv_xlen == 64
# define NPT 4
#define kernel_l2pt pt[2]
# define user_l3pt pt[3]
#else
# define NPT 2
# define user_l3pt user_l2pt
#endif
pte_t pt[NPT][PTES_PER_PT] __attribute__((aligned(PGSIZE)));


// PTES_PER_PT is (RV32: 0x400, RV64:0x200)
// NPT is (RV32: 2, RV64:4)
// sizeof(pte_t) is (RV32: 4, RV64: 8)
// sizeof(pt[0]) is (RV32: 0x1000, RV64: 0x1000)
// sizeof(pt) is (RV32: 0x2000, RV64: 0x4000)

ページテーブルは2次元配列 pt であるが、これはアドレスがコードで指定されているわけではない(リンカスクリプトでも指定されていないようだ)。
リンカが決定するのだと思われる。

参考までに、先日 rv64ui-v-add を動かしたときは以下のようになっていた。

物理アドレス
pt 0x80004000
l1pt 0x80004000
user_l2pt 0x80005000
kernel_l2pt 0x80006000
user_l3pt 0x80007000
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?