RISC-V Bare Bones: Difference between revisions
[unchecked revision] | [unchecked revision] |
Content deleted Content added
m update source tags to syntaxhighlight |
|||
(9 intermediate revisions by 7 users not shown) | |||
Line 1:
{{ stub }}
RISC-V is a instruction set architecture, fully opensource. The ISA has a bunch of extensions, in this tutorial we will assume that imad are available.
Line 14 ⟶ 11:
The thing we will make here is a simple serial port output/reader.
<
#include <stdint.h>
#include <stddef.h>
Line 20 ⟶ 17:
unsigned char * uart = (unsigned char *)0x10000000;
void putchar(char c) {
*uart = c;
return;
Line 41 ⟶ 37:
return;
}
</syntaxhighlight>
This will print a simple "Hello world!" and a newline following, after that it will echo any input given to the serial port.
Line 48 ⟶ 44:
Be wary we are just setting up stack and jumping into kernel. It's the kernel's job to set up IRQs and other system stuff
<
.section .init
Line 75 ⟶ 71:
sd zero, (t5)
addi t5, t5, 8
la t0, kmain
Line 87 ⟶ 83:
.end
</syntaxhighlight>
Take in account that you need to implement a type of locking if you want to support SMP, and implement a trampoline or a jail for the CPUs. Be wary that we haven't enabled interrupts just yet and any return from kmain will result in invalid opcodes being executed.
Line 95 ⟶ 91:
We need to specify where our kernel will be loaded at. For this example we will use the start of the RAM as our load address.
<
ENTRY(start);
Line 122 ⟶ 118:
}
}
</syntaxhighlight>
== Final ==
The process is pretty straightforward:
<
riscv64-elf-gcc -Wall -Wextra -c -mcmodel=medany kernel.c -o kernel.o -ffreestanding
riscv64-elf-as -c entry.S -o entry.o
riscv64-elf-ld -T linker.ld -lgcc -nostdlib kernel.o entry.o -o kernel.elf
</syntaxhighlight>
Once this is done, the kernel can be run with the following:
<
qemu-system-riscv64 -machine virt -bios none -kernel kernel.elf -serial mon:stdio
</syntaxhighlight>
You will promptly see a terminal with the "Hello world!" and you can "write stuff" to it. A serial terminal is very "boring", but you still have a lot at your disposal, you have a PLIC, a CLIC and a bunch of opportunities to learn PCI internals.
Line 142 ⟶ 138:
== Going further ==
* Store input somewhere for later processing (i.e: "echo" command)
* Implement SMP support, for now our basic
* QEMU will give FDT in register a1. Use libfdt to parse the tree to avoid nightrames
* Implement a heap
Line 153 ⟶ 149:
* [[PCI Express]]
* [[HiFive-1 Bare Bones]]
* [[RISC-V_Meaty_Skeleton_with_QEMU_virt_board|RISC-V Meaty Skeleton with QEMU virt board]]
* [https://msyksphinz-self.github.io/riscv-isadoc/html/rvi.html RISC-V instruction set]
* [https://osblog.stephenmarz.com/ Small Bare Metal RISCV OS in asm and Rust]
* [https://marz.utk.edu/my-courses/cosc562/riscv/ Page of above with asm code setting up different kernel stack for each hart]
* [https://github.com/cksystemsteaching/selfie Selfie: a minimalist self hosting compiler, riscv64 os, and simulator]
* [https://github.com/cksystemsteaching/selfie/tree/main/theses Selfie page includes 2 well written bare-metal theses]
* [https://github.com/phoenix-rtos Complete open source Microkernel for riscv64 (also arm7, ia32) plus support code]
* [https://github.com/mit-pdos/xv6-riscv XV6: a reimplementation of original Unix for teaching riscv64 OS development]
* [https://github.com/michaelengel/xv6-vf2 Port of XV6 to execute on VisionFive 2 SoC]
* [https://github.com/lupyuen/nuttx-star64 Wonderfully clear and detailed base level port how2: NuttX RTOS to Star64 SoC]
[[Category:Bare bones tutorials|RISC-V bare bones]]
|