You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
11 KiB
Markdown
219 lines
11 KiB
Markdown
5 months ago
|
# Baremetal RISC-V
|
||
|
|
||
|
Ok this chuck guy knows his stuff it seems https://www.youtube.com/watch?v=qLzD33xVcRE
|
||
|
|
||
|
`barmetal.ld` contains the linker scripts.
|
||
|
|
||
|
The `SECTIONS` keyword indicates the beginning of the linker script sections where he specifies the memory layout, and the sections of the program.
|
||
|
|
||
|
```
|
||
|
{
|
||
|
. = 0x800000000;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
This sets the location counter to the 0x800000000 memory address. This means that the following sections of the linker script will be placed as if starting from this address in memory. This is important because we need to know where in memory to load our application, so that the cpu boots we know what address will be loaded into the program counter to start executing instructions.
|
||
|
|
||
|
ADD MORE DETAILS
|
||
|
|
||
|
## QEMU
|
||
|
|
||
|
Run this command
|
||
|
|
||
|
```
|
||
|
qemu-system-riscv32 -nographic -serial mon:stdio -machine virt
|
||
|
```
|
||
|
|
||
|
If you encounter
|
||
|
```
|
||
|
qemu-system-riscv32: Unable to load the RISC-V firmware "opensbi-riscv32-generic-fw_dynamic.bin"
|
||
|
```
|
||
|
|
||
|
Well it's going to suck a little. Running `sudo apt install opensbi` only appears to include qemu-system-riscv64 builds. I tried building from source and hit a ton of issues, so instead I untarred a binary release in my home directory
|
||
|
|
||
|
```
|
||
|
wget https://github.com/riscv-software-src/opensbi/releases/download/v1.5.1/opensbi-1.5.1-rv-bin.tar.xz
|
||
|
tar -xf opensbi-1.5.1-rv-bin.tar.xz -C ~/
|
||
|
ls ~/opensbi-1.5.1-rv-bin
|
||
|
```
|
||
|
|
||
|
```
|
||
|
qemu-system-riscv32 -nographic -serial mon:stdio -machine virt -bios ~/opensbi-1.5.1-rv-bin/share/opensbi/ilp32/generic/firmware/fw_dynamic.bin
|
||
|
```
|
||
|
|
||
|
Now we can continue...
|
||
|
|
||
|
We start qemu in `-nographic` mode. We redirect the console input/output to our terminal `-serial mon:stdio`, and we start the `virt` machine type that we will do the simulation under.
|
||
|
|
||
|
|
||
|
```
|
||
|
OpenSBI v1.5.1
|
||
|
____ _____ ____ _____
|
||
|
/ __ \ / ____| _ \_ _|
|
||
|
| | | |_ __ ___ _ __ | (___ | |_) || |
|
||
|
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
|
||
|
| |__| | |_) | __/ | | |____) | |_) || |_
|
||
|
\____/| .__/ \___|_| |_|_____/|____/_____|
|
||
|
| |
|
||
|
|_|
|
||
|
|
||
|
Platform Name : riscv-virtio,qemu
|
||
|
Platform Features : medeleg
|
||
|
Platform HART Count : 1
|
||
|
Platform IPI Device : aclint-mswi
|
||
|
Platform Timer Device : aclint-mtimer @ 10000000Hz
|
||
|
Platform Console Device : semihosting
|
||
|
Platform HSM Device : ---
|
||
|
Platform PMU Device : ---
|
||
|
Platform Reboot Device : syscon-reboot
|
||
|
Platform Shutdown Device : syscon-poweroff
|
||
|
Platform Suspend Device : ---
|
||
|
Platform CPPC Device : ---
|
||
|
Firmware Base : 0x80000000
|
||
|
Firmware Size : 319 KB
|
||
|
Firmware RW Offset : 0x40000
|
||
|
Firmware RW Size : 63 KB
|
||
|
Firmware Heap Offset : 0x47000
|
||
|
Firmware Heap Size : 35 KB (total), 2 KB (reserved), 9 KB (used), 23 KB (free)
|
||
|
Firmware Scratch Size : 4096 B (total), 240 B (used), 3856 B (free)
|
||
|
Runtime SBI Version : 2.0
|
||
|
|
||
|
Domain0 Name : root
|
||
|
Domain0 Boot HART : 0
|
||
|
Domain0 HARTs : 0*
|
||
|
Domain0 Region00 : 0x00100000-0x00100fff M: (I,R,W) S/U: (R,W)
|
||
|
Domain0 Region01 : 0x02000000-0x0200ffff M: (I,R,W) S/U: ()
|
||
|
Domain0 Region02 : 0x0c200000-0x0c20ffff M: (I,R,W) S/U: (R,W)
|
||
|
Domain0 Region03 : 0x80040000-0x8004ffff M: (R,W) S/U: ()
|
||
|
Domain0 Region04 : 0x80000000-0x8003ffff M: (R,X) S/U: ()
|
||
|
Domain0 Region05 : 0x0c000000-0x0c1fffff M: (I,R,W) S/U: (R,W)
|
||
|
Domain0 Region06 : 0x00000000-0xffffffff M: () S/U: (R,W,X)
|
||
|
Domain0 Next Address : 0x00000000
|
||
|
Domain0 Next Arg1 : 0x87000000
|
||
|
Domain0 Next Mode : S-mode
|
||
|
Domain0 SysReset : yes
|
||
|
Domain0 SysSuspend : yes
|
||
|
|
||
|
Boot HART ID : 0
|
||
|
Boot HART Domain : root
|
||
|
Boot HART Priv Version : v1.10
|
||
|
Boot HART Base ISA : rv32imafdc
|
||
|
Boot HART ISA Extensions : zicntr
|
||
|
Boot HART PMP Count : 16
|
||
|
Boot HART PMP Granularity : 2 bits
|
||
|
Boot HART PMP Address Bits: 32
|
||
|
Boot HART MHPM Info : 0 (0x00000000)
|
||
|
Boot HART Debug Triggers : 0 triggers
|
||
|
Boot HART MIDELEG : 0x00000222
|
||
|
Boot HART MEDELEG : 0x0000b109
|
||
|
```
|
||
|
|
||
|
We see that our `Firmware Base : 0x80000000` is address where the firmware should be loaded from. You can also see that `Domain0 Region04 : 0x80000000-0x8003ffff M: (R,X) S/U: ()` this region is marked as X for executable.
|
||
|
|
||
|
How do we know that the serial UART is at 0x10000000? This UART is defined as a NS16550 Uart in https://www.qemu.org/docs/master/system/riscv/virt.html
|
||
|
Looking at the [UART16550 Core technical manual](https://uart16550.readthedocs.io/en/latest/uart16550doc.html#registers) we see that `Transmitter Holding Register (THR)` is at Address 0. Lastly, we want to enter the qemu console, so `Ctrl-A C` will take us to the qemu console. We want to inspect the `info mtree` output we can see that the `0000000010000000-0000000010000007 (prio 0, i/o): serial` serial device memory location starts at 0x10000000. So since the register the THR is at 0, we know we can use that as our UART target.
|
||
|
|
||
|
|
||
|
```
|
||
|
(qemu) info mtree
|
||
|
(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
|
||
|
|
||
|
address-space: cpu-memory-0
|
||
|
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: gpex-root
|
||
|
0000000000000000-ffffffffffffffff (prio 0, i/o): bus master container
|
||
|
|
||
|
memory-region: pcie-mmcfg-mmio
|
||
|
0000000000000000-000000001fffffff (prio 0, i/o): pcie-mmcfg-mmio
|
||
|
|
||
|
memory-region: gpex_mmio_window
|
||
|
0000000000000000-ffffffffffffffff (prio 0, i/o): gpex_mmio_window
|
||
|
0000000000000000-ffffffffffffffff (prio 0, i/o): gpex_mmio
|
||
|
|
||
|
memory-region: system
|
||
|
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
|
||
|
```
|