My Haiku RISC-V port progress

Here I will write about my progress in 64 bit RISC-V port. Previous disscussion is starting at UEFI Haiku boot loader for ARM.

Port is currently targeting TinyEMU because it is simple and its source code can be used as reference, later adding QEmu support is planned. haiku_loader is directly used as firmware, no u-boot or UEFI biit loaders are used.

All development and testing is performed on Haiku.

28 Likes

After fightning with compiler and linker flags and and also linker scripts I managed to execute haiku_loader to main(&args) call. Color rectangles means checkpoints: red: checkpoint, blue: constructor call in call_ctors() (first I got constructor table misalignment crash so .ctors section alignment in linker script was changed to 8 byte), green: main(&args) reached.

Currently only framebuffer is working.

screenshot27

10 Likes

great job, @X512.

The frame buffer is amazing :wink:

Also I get terminal output, but it require TinyEMU patching because by default framebuffer and terminal are mutually exclusive, enabling framebuffer will disable terminal.

I managed to get initial console support for framebuffer. I use my own font rendering with embedded 8 bit raster font with anti-aliasing (DejaVu Sans Mono).

screenshot29

11 Likes

Colors implemented.

screenshot30

18 Likes

I managed to get virtio working, but something wrong with heap is happening:

> run.sh
This is a test
dprintf test
boot(): enter
malloc(512) -> 0x000000008005a008
boot(): heap initialized...
virtio_init()
virtio_input[0]: virtio_keyboard
malloc(64) -> 0x000000008005a210
+VirtioDevice
features: 00000000
queueNumMax: 16
malloc(4360) -> 0x000000008005a258
malloc(4144) -> 0x000000008005b368
malloc(4240) -> 0x000000008005c3a0
malloc(24) -> 0x000000008005d438
malloc(128) -> 0x000000008005d458
fDescs: 0x000000008005b000
fAvail: 0x000000008005c000
fUsed: 0x000000008005d000
name: virtio_keyboard
virtio_input[1]: virtio_tablet
virtio_input count: 2
malloc(32) -> 0x000000008005d4e0
malloc(24) -> 0x000000008005d508
malloc(32) -> 0x000000008005d528
malloc(24) -> 0x000000008005d550
malloc(32) -> 0x000000008005d570
malloc(24) -> 0x000000008005d598
malloc(32) -> 0x000000008005d5b8
malloc(24) -> 0x000000008005d5e0
VirtioInputPacket(1, 10, 1)
free(0x000000008005d4e0)
free(0x000000008005d508)
malloc(32) -> 0x000000008005d4e0
malloc(24) -> 0x000000008005d508
VirtioInputPacket(0, 0, 0)
free(0x000000008005d528)
free(0x000000008005d550)
malloc(32) -> 0x000000008005d528
malloc(24) -> 0x000000008005d550
VirtioInputPacket(1, 10, 0)
free(0x000000008005d570)
free(0x000000008005d598)
malloc(32) -> 0x000000008005d570
malloc(24) -> 0x000000008005d598
VirtioInputPacket(0, 0, 0)
free(0x000000008005d5b8)
free(0x000000008005d5e0)
malloc(32) -> 0x000000008005d5b8
malloc(24) -> 0x000000008005d5e0
VirtioInputPacket(1, 11, 1)
free(0x000000008005d4e0)
free(0x000000008005d508)
malloc(32) -> 0x000000008005d4e0
malloc(24) -> 0x000000008005d508
VirtioInputPacket(0, 0, 0)
free(0x000000008005d528)
free(0x000000008005d550)
malloc(32) -> 0x000000008005d528
malloc(24) -> 0x000000008005d550
VirtioInputPacket(1, 11, 0)
free(0x000000008005d570)
free(0x000000008005d598)
malloc(32) -> 0x000000008005d570
malloc(24) -> 0x000000008005d598
VirtioInputPacket(0, 0, 0)
free(0x000000008005d5b8)
free(0x000000008005d5e0)
malloc(32) -> 0x000000008005d5b8
malloc(24) -> 0x000000008005d5e0
VirtioInputPacket(1, 12, 1)
free(0x000000008005d4e0)
free(0x000000008005d508)
malloc(32) -> 0x000000008005d4e0
malloc(24) -> 0x000000008005d508
VirtioInputPacket(0, 0, 0)
free(0x000000008005d528)
free(0x000000008005d550)
malloc(32) -> 0x000000008005d528
malloc(24) -> 0x000000008005d550
VirtioInputPacket(1, 12, 0)
free(0x000000008005d570)
free(0x000000008005d598)
malloc(32) -> 0x000000008005d570
malloc(24) -> 0x000000008005d598
VirtioInputPacket(0, 0, 0)
free(0x000000008005d5b8)
free(0x000000008005d5e0)
malloc(32) -> 0x000000008005d5b8
malloc(24) -> 0x000000008005d5e0
VirtioInputPacket(1, 13, 1)
free(0x000000008005d4e0)
free(0x000000008005d508)
malloc(32) -> 0x000000008005d4e0
malloc(24) -> 0x000000008005d508
VirtioInputPacket(0, 0, 0)
free(0x000000008005d528)
free(0x000000008005d550)
malloc(32) -> 0x000000008005d528
malloc(24) -> 0x000000008005d550
VirtioInputPacket(1, 13, 0)
free(0x000000008005d570)
free(0x000000008005d598)
malloc(32) -> 0x000000008005d570
malloc(24) -> 0x000000008005d598
VirtioInputPacket(0, 0, 0)
free(0x000000008005d5b8)
free(0x000000008005d5e0)
malloc(32) -> 0x000000008005d5b8
malloc(24) -> 0x000000008005d5e0
VirtioInputPacket(1, 14, 1)
free(0x000000008005d4e0)
*** PANIC ***
freed chunk 0x000000008005d4d8 clobbered (0x8005d500)!

Virtio keyboard is working.

screenshot31

15 Likes

Virtio block device is working and haiku_loader now can read boot disk and file system:

screenshot32
screenshot33

9 Likes

Boot splash is working:

screenshot34

43 Likes

Great progress. Keep going! Молодэц!

1 Like

I managed to get debug output working in kernel. It required implementing setting current thread register and enabling/disabling interrupts, otherewize mutex_lock used by dprintf() will fail (spinlock with interrupts disabled or something like that). Currently kernel stops at vm_allocate_early: could not allocate virtual address .

This is a test
dprintf test
boot(): enter
boot(): heap initialized...
virtio_init()
virtio_input[0]: virtio_keyboard
+VirtioDevice
features: 00000000
virtio_input[1]: virtio_tablet
target_read_slow: invalid physical address 0x0000000040015000, PC: 0000000080001942
virtio_input count: 2
Welcome to the Haiku boot loader!
+VirtioDevice
features: 00000000
target_read_slow: invalid physical address 0x0000000040015000, PC: 0000000080001428
add_partitions_for(0x000000008006b918, mountFS = yes)
add_partitions_for(fd = 0, mountFS = yes)
0x000000008006b970 Partition::Partition
0x000000008006b970 Partition::Scan()
check for partitioning_system: Intel Partition Map
check for partitioning_system: Intel Extended Partition
0x000000008006b970 Partition::_Mount check for file_system: BFS Filesystem
PackageVolumeInfo::SetTo()
PackageVolumeInfo::_InitState(): failed to parse activated-packages: No such file or directory
PackageVolumeInfo::SetTo()
PackageVolumeInfo::_InitState(): failed to parse activated-packages: No such file or directory
PackageVolumeInfo::LoadOldStates(): failed to open administrative directory: No such file or directory
PackageVolumeInfo::SetTo()
PackageVolumeInfo::_InitState(): failed to parse activated-packages: No such file or directory
load kernel kernel_riscv64...
maximum boot loader heap usage: 455112, currently used: 444568
kernel entry at 8033d434
Kernel stack at 0x8310a000
Kernel entry point
(1)
(2)
(2:2)
(3)
(3)
(4)
(5)
(6)
(7)
(8)
Welcome to kernel debugger output!
(9)
Haiku revision: hrev54982+42+dirty, debug level: 2
INIT: init CPU
INIT: init interrupts
INIT: init VM
vm_translation_map_init: entry
physical memory ranges:
allocated physical ranges:
allocated virtual ranges:
vm_allocate_early: could not allocate virtual address
8 Likes

Now it go until early virtual memory mapping. Virtual memory is currently not implemented at all. Next step will be swithing to supervisor mode (currently everything is running in machime mode that don’t support MMU) and implementing MMU page table. Some experiments with my mini OS are needed first.

haiku_loader entry point
boot(): enter
boot(): heap initialized...
virtio_init()
virtio_input[0]: virtio_keyboard
+VirtioDevice
features: 00000000
virtio_input[1]: virtio_tablet
target_read_slow: invalid physical address 0x0000000040015000, PC: 0000000080001a2c
virtio_input count: 2
Welcome to the Haiku boot loader!
+VirtioDevice
features: 00000000
virtio_block[0]
target_read_slow: invalid physical address 0x0000000040015000, PC: 0000000080001512
add_partitions_for(0x000000008014b918, mountFS = no)
add_partitions_for(fd = 0, mountFS = no)
0x000000008014b970 Partition::Partition
0x000000008014b970 Partition::Scan()
check for partitioning_system: Intel Partition Map
check for partitioning_system: Intel Extended Partition
0x000000008014b970 Partition::Scan()
check for partitioning_system: Intel Partition Map
check for partitioning_system: Intel Extended Partition
0x000000008014b970 Partition::_Mount check for file_system: BFS Filesystem
PackageVolumeInfo::SetTo()
PackageVolumeInfo::SetTo(): failed to open packages directory: No such file or directory
PackageVolumeInfo::SetTo()
PackageVolumeInfo::SetTo(): failed to open packages directory: No such file or directory
PackageVolumeInfo::SetTo()
PackageVolumeInfo::SetTo(): failed to open packages directory: No such file or directory
load kernel kernel_riscv64...
maximum boot loader heap usage: 48176, currently used: 32104
Kernel stack at 0x80bab000
kernel entry at 802b1444
Kernel entry point
Welcome to kernel debugger output!
Haiku revision: , debug level: 2
INIT: init CPU
INIT: init interrupts
INIT: init VM
vm_translation_map_init: entry
physical memory ranges:
  80000000 - 88000000
allocated physical ranges:
  80000000 - 80bb0000
allocated virtual ranges:
  80000000 - 80bb0000
early_tmap: entry pa 0x80bb0000 va 0x81000000
early_tmap: entry pa 0x80bb1000 va 0x81001000
early_tmap: entry pa 0x80bb2000 va 0x81002000
early_tmap: entry pa 0x80bb3000 va 0x81003000
early_tmap: entry pa 0x80bb4000 va 0x81004000
early_tmap: entry pa 0x80bb5000 va 0x81005000
early_tmap: entry pa 0x80bb6000 va 0x81006000
early_tmap: entry pa 0x80bb7000 va 0x81007000
early_tmap: entry pa 0x80bb8000 va 0x81008000
early_tmap: entry pa 0x80bb9000 va 0x81009000
early_tmap: entry pa 0x80bba000 va 0x8100a000
early_tmap: entry pa 0x80bbb000 va 0x8100b000
early_tmap: entry pa 0x80bbc000 va 0x8100c000
early_tmap: entry pa 0x80bbd000 va 0x8100d000
early_tmap: entry pa 0x80bbe000 va 0x8100e000
early_tmap: entry pa 0x80bbf000 va 0x8100f000
early_tmap: entry pa 0x80bc0000 va 0x81010000
early_tmap: entry pa 0x80bc1000 va 0x81011000
early_tmap: entry pa 0x80bc2000 va 0x81012000
early_tmap: entry pa 0x80bc3000 va 0x81013000
early_tmap: entry pa 0x80bc4000 va 0x81014000
early_tmap: entry pa 0x80bc5000 va 0x81015000
early_tmap: entry pa 0x80bc6000 va 0x81016000
early_tmap: entry pa 0x80bc7000 va 0x81017000
early_tmap: entry pa 0x80bc8000 va 0x81018000
early_tmap: entry pa 0x80bc9000 va 0x81019000
early_tmap: entry pa 0x80bca000 va 0x8101a000
early_tmap: entry pa 0x80bcb000 va 0x8101b000
early_tmap: entry pa 0x80bcc000 va 0x8101c000
early_tmap: entry pa 0x80bcd000 va 0x8101d000
early_tmap: entry pa 0x80bce000 va 0x8101e000
early_tmap: entry pa 0x80bcf000 va 0x8101f000
early_tmap: entry pa 0x80bd0000 va 0x81020000
early_tmap: entry pa 0x80bd1000 va 0x81021000
early_tmap: entry pa 0x80bd2000 va 0x81022000
early_tmap: entry pa 0x80bd3000 va 0x81023000
early_tmap: entry pa 0x80bd4000 va 0x81024000
early_tmap: entry pa 0x80bd5000 va 0x81025000
early_tmap: entry pa 0x80bd6000 va 0x81026000
early_tmap: entry pa 0x80bd7000 va 0x81027000
early_tmap: entry pa 0x80bd8000 va 0x81028000
early_tmap: entry pa 0x80bd9000 va 0x81029000
early_tmap: entry pa 0x80bda000 va 0x8102a000
early_tmap: entry pa 0x80bdb000 va 0x8102b000
early_tmap: entry pa 0x80bdc000 va 0x8102c000
early_tmap: entry pa 0x80bdd000 va 0x8102d000
early_tmap: entry pa 0x80bde000 va 0x8102e000
early_tmap: entry pa 0x80bdf000 va 0x8102f000
early_tmap: entry pa 0x80be0000 va 0x81030000
early_tmap: entry pa 0x80be1000 va 0x81031000
early_tmap: entry pa 0x80be2000 va 0x81032000
early_tmap: entry pa 0x80be3000 va 0x81033000
early_tmap: entry pa 0x80be4000 va 0x81034000
early_tmap: entry pa 0x80be5000 va 0x81035000
early_tmap: entry pa 0x80be6000 va 0x81036000
early_tmap: entry pa 0x80be7000 va 0x81037000
early_tmap: entry pa 0x80be8000 va 0x81038000
early_tmap: entry pa 0x80be9000 va 0x81039000
early_tmap: entry pa 0x80bea000 va 0x8103a000
early_tmap: entry pa 0x80beb000 va 0x8103b000
early_tmap: entry pa 0x80bec000 va 0x8103c000
early_tmap: entry pa 0x80bed000 va 0x8103d000
early_tmap: entry pa 0x80bee000 va 0x8103e000
early_tmap: entry pa 0x80bef000 va 0x8103f000
early_tmap: entry pa 0x80bf0000 va 0x81040000
early_tmap: entry pa 0x80bf1000 va 0x81041000
early_tmap: entry pa 0x80bf2000 va 0x81042000
early_tmap: entry pa 0x80bf3000 va 0x81043000
early_tmap: entry pa 0x80bf4000 va 0x81044000
early_tmap: entry pa 0x80bf5000 va 0x81045000
early_tmap: entry pa 0x80bf6000 va 0x81046000
early_tmap: entry pa 0x80bf7000 va 0x81047000
early_tmap: entry pa 0x80bf8000 va 0x81048000
early_tmap: entry pa 0x80bf9000 va 0x81049000
early_tmap: entry pa 0x80bfa000 va 0x8104a000
...
12 Likes

Some good reference for page table: https://xiayingp.gitbook.io/build_a_os/virtual-memory/xv6-virtual-memory.

This is SO cool. I can’t wait to get my hands on a RISC-V SoC

1 Like

haiku_loader is directly used as firmware, no u-boot or UEFI biit loaders are used.

Interesting… my work has been targeting UEFI on RISC-V since that gives us easy bios services to wire into. You’re adding framebuffer drivers into our bootloader at fixed addresses? How are you loading our bootloader?

I feel like you posted a similar thread for ARM a while ago, but we never saw any patches or code… EDIT: nevermind. you did here :slight_smile: https://review.haiku-os.org/c/haiku/+/2413

This might be helpful… I started forming the page tables in the bootloader to hand-off to the kernel:
https://review.haiku-os.org/c/haiku/+/3733

I’m in way over my head with the deep page table stuff… feel free to see if it’s useful :slight_smile:

For now, yes. But emulator pass FDT pointer to firmware entry point so framebuffer address and parameters can be obtained from there. Also I implemented software text mode by using embedded 8 bit font.

By using “bios” option in emulator, it load RAW image at 0x80000000 and execute at beginning.

That was a copy of Haiku sources with my own build system and Clang compiler, so providing full patches is difficult. Current port is in tree and making patches is much easier. It add new “riscv” boot loader platform and compiled by jam -q haiku_loader.riscv.

I published my current work, but it is incomplete and need clean up:

https://review.haiku-os.org/c/haiku/+/3882\
https://review.haiku-os.org/c/haiku/+/3883

11 Likes

It seems that there’s a way to potentially get a free RISC-V machine from RISC-V International, according to this article: https://www.hackster.io/news/risc-v-international-offers-academics-individuals-free-development-boards-with-up-to-16gb-of-ram-e46c7b15b4ac. You have to join RISC-V International, but for individuals, academic organizations, and non-profits, it’s free. It might be a way to get some real hardware in your hands to help make this happen! I’m very excited to see this develop, thank you for the awesome work! :slight_smile:

9 Likes