QEMUでベアメタルプログラミング
以下はQEMUメモ。
QEMUの起動と終了
QEMUを起動してターミナルにQEMUのモニタを表示させる→ 「q」または「quit」でQEMUを終了させる
code:sh
$ qemu-system-riscv32 -M virt -monitor stdio
QEMU 6.2.0 monitor - type 'help' for more information
(qemu)q
レジスタの値を確認
QEMUモニタ上で「info registers」でレジスタの値を確認
code:qemu
(qemu) info registers
pc 00000000
mhartid 00000000
mstatus 80006180
mstatush 00000000
mip 00000000
mie 00000008
mideleg 00000222
medeleg 0000b109
mtvec 80000528
stvec 00000000
mepc 00000000
sepc 00000000
mcause 00000001
scause 00000001
mtval 00000000
stval 00000000
mscratch 80018000
sscratch 00000000
satp 00000000
x0/zero 00000000 x1/ra 80007778 x2/sp 80017f30 x3/gp 00000000
x4/tp 80018000 x5/t0 00000001 x6/t1 0000000b x7/t2 00001000
x8/s0 80017f50 x9/s1 00000001 x10/a0 00000000 x11/a1 87000000
x12/a2 00000007 x13/a3 00000019 x14/a4 00000001 x15/a5 00000001
x16/a6 00000008 x17/a7 00000002 x18/s2 80006800 x19/s3 00000000
x20/s4 87000000 x21/s5 00000000 x22/s6 00000000 x23/s7 80014080
x24/s8 0000007f x25/s9 80014310 x26/s10 00000000 x27/s11 00000000
x28/t3 00000000 x29/t4 616d6569 x30/t5 000000fc x31/t6 00000000
ROM一覧を確認
code:qemu
(qemu) info roms
addr=0000000000001000 size=0x000028 mem=rom name="mrom.reset"
addr=0000000000001028 size=0x000018 mem=rom name="mrom.finfo"
addr=0000000080000000 size=0x013358 mem=ram name="/usr/local/Cellar/qemu/6.2.0/bin/../share/qemu/opensbi-riscv32-generic-fw_dynamic.bin"
addr=0000000087000000 size=0x100000 mem=ram name="fdt"
メモリマップを確認
code:qemu
(qemu) info mtree
address-space: memory
0000000000000000-ffffffffffffffff (prio 0, i/o): system
0000000000001000-000000000000ffff (prio 0, rom): riscv_virt_board.mrom
0000000000100000-0000000000100fff (prio 0, i/o): riscv.sifive.test
0000000000101000-0000000000101023 (prio 0, i/o): goldfish_rtc
0000000002000000-0000000002003fff (prio 0, i/o): riscv.aclint.swi
0000000002004000-000000000200bfff (prio 0, i/o): riscv.aclint.mtimer
0000000003000000-000000000300ffff (prio 0, i/o): gpex_ioport_window
0000000003000000-000000000300ffff (prio 0, i/o): gpex_ioport
000000000c000000-000000000c20ffff (prio 0, i/o): riscv.sifive.plic
0000000010000000-0000000010000007 (prio 0, i/o): serial
0000000010001000-00000000100011ff (prio 0, i/o): virtio-mmio
0000000010002000-00000000100021ff (prio 0, i/o): virtio-mmio
0000000010003000-00000000100031ff (prio 0, i/o): virtio-mmio
0000000010004000-00000000100041ff (prio 0, i/o): virtio-mmio
0000000010005000-00000000100051ff (prio 0, i/o): virtio-mmio
0000000010006000-00000000100061ff (prio 0, i/o): virtio-mmio
0000000010007000-00000000100071ff (prio 0, i/o): virtio-mmio
0000000010008000-00000000100081ff (prio 0, i/o): virtio-mmio
0000000010100000-0000000010100007 (prio 0, i/o): fwcfg.data
0000000010100008-0000000010100009 (prio 0, i/o): fwcfg.ctl
0000000010100010-0000000010100017 (prio 0, i/o): fwcfg.dma
0000000020000000-0000000021ffffff (prio 0, romd): virt.flash0
0000000022000000-0000000023ffffff (prio 0, romd): virt.flash1
0000000030000000-000000003fffffff (prio 0, i/o): alias pcie-ecam @pcie-mmcfg-mmio 0000000000000000-000000000fffffff
0000000040000000-000000007fffffff (prio 0, i/o): alias pcie-mmio @gpex_mmio_window 0000000040000000-000000007fffffff
0000000080000000-0000000087ffffff (prio 0, ram): riscv_virt_board.ram
0000000300000000-00000003ffffffff (prio 0, i/o): alias pcie-mmio-high @gpex_mmio_window 0000000300000000-00000003ffffffff
address-space: I/O
0000000000000000-000000000000ffff (prio 0, i/o): io
(省略)
Virt MemMap
code:c
static const MemMapEntry virt_memmap[] = {
VIRT_PLIC = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) }, };
QEMUの詳細トレースの出しかたが便利そう。
-d in_asm:実行したアセンブリコードを出力する。
./qemu-riscv64 -D logfile.log -d in_asm -L riscv64-unknown-linux-gnu-gcc --print-sysroot ./a.out
-d cpu:CPUのレジスタ一覧を表示する。
./qemu-riscv64 -D logfile.log -d cpu -L riscv64-unknown-linux-gnu-gcc --print-sysroot ./a.out
-d guest_errors : ゲストOSのエラーを出力