My Haiku ARM (UEFI) port progress


You can use my FDT bus and VirtIO MMIO driver to get boot disk mounted.


FDT dump from the bootloader: fdt dump from bootloader -
dm_tree: dm_tree -


     (3) @0x8139b6e8 "bus_managers/fdt/driver_v1" (ref 2, init 1, module 0x82279434, data 0x8101b0e0)
           "device/bus" : string : "fdt"
           "device/pretty name" : string : "virtio_mmio@a000200"
           "fdt/node" : uint32 : 648 (0x288)
           "fdt/name" : string : "virtio_mmio@a000200"
           "fdt/compatible" : string : "virtio,mmio"
           "device/driver" : string : "bus_managers/fdt/driver_v1"
     (3) @0x8139b9b8 "bus_managers/fdt/driver_v1" (ref 2, init 1, module 0x82279434, data 0x8101b160)
           "device/bus" : string : "fdt"
           "device/pretty name" : string : "virtio_mmio@a000000"
           "fdt/node" : uint32 : 532 (0x214)
           "fdt/name" : string : "virtio_mmio@a000000"
           "fdt/compatible" : string : "virtio,mmio"
           "device/driver" : string : "bus_managers/fdt/driver_v1"

so the devices from the fdt are already there in device manager, with compatble = “virtio,mmio” but no virtio driver is attached.

1 Like

This is a problem with device manager, it have hardcoded table for detecting devices. See


Also note that VirtIO version 2 is required (QEMU option -global virtio-mmio.force-legacy=false).


thanks for the suggestion! that’s definitely a step in the right direction:

     (3) @0x8139b9b8 "bus_managers/fdt/driver_v1" (ref 4, init 2, module 0x82279434, data 0x8101b160)
           "device/bus" : string : "fdt"
           "device/pretty name" : string : "virtio_mmio@a000000"
           "fdt/node" : uint32 : 532 (0x214)
           "fdt/name" : string : "virtio_mmio@a000000"
           "fdt/compatible" : string : "virtio,mmio"
           "device/driver" : string : "bus_managers/fdt/driver_v1"
        (4) @0x8139b6e8 "busses/virtio/virtio_mmio/driver_v1" (ref 2, init 1, module 0x823c41c0, data 0x8125c998)
              "device/pretty name" : string : "Virtio MMIO"
              "device/bus" : string : "virtio"
              "virtio/version" : uint32 : 2 (0x2)
              "virtio/device_id" : uint32 : 0 (0x0)
              "virtio/type" : uint16 : 0 (0x0)
              "virtio/vendor_id" : uint32 : 1431127377 (0x554d4551)
              "device/driver" : string : "busses/virtio/virtio_mmio/driver_v1"

VirtIO block device should be connected. See My Haiku RISC-V port progress - #43 by X512.


the virtio/type does not look good.
it’s all set to zeroes while it should be 2 for the block devices.

there are 32 virtio-mmio nodes in the tree, all of them has virtio/type = 0

Have you tried -global virtio-mmio.force-legacy=false? Also it can be some broken structure layout on 32 bits. Code was originally written for 64 bits.

1 Like

Yes, I get the same with virtio-mmio.force-legacy=false. I can see the difference in virtio/version=1 vs 2 but not much else.

1 Like

My bad, I was using the wrong qemu command line with options -hda esp.image -hdb haiku-minimum.image

Should rather be using the following:

	-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 \
	-device virtio-blk-device,drive=x1,bus=virtio-mmio-bus.1 \
	-drive file="esp.image",if=none,format=raw,id=x0 \
	-drive file="haiku-minimum.image",if=none,format=raw,id=x1 \

This way the virtio-block driver gets attached.
Then it locks up in virtio_block_read when trying to probe the partition table:

  trying: partitioning_systems/efi_gpt/v1
virtio_block: CALLED status_t virtio_block_open(void*, const char*, int, void**)
virtio_block: CALLED status_t virtio_block_read(void*, off_t, void*, size_t*)

Also note that with the -global virtio-mmio.force-legacy=false EDK is not able to start the haiku_loader and we’re stuck at a PXE boot screen.

So my qemu command line now looks like this:

qemu-system-arm -bios /usr/share/edk2/arm/QEMU_EFI-pflash.raw \
	-M virt -cpu cortex-a15 -m 512 \
	-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 \
	-device virtio-blk-device,drive=x1,bus=virtio-mmio-bus.1 \
	-drive file="esp.image",if=none,format=raw,id=x0 \
	-drive file="haiku-minimum.image",if=none,format=raw,id=x1 \
	-device ramfb -usb -device qemu-xhci,id=xhci -device usb-mouse -device usb-kbd -serial stdio

Next - perhaps tomorrow - find out why virtio_block_read get stuck. E.g. is there any interrupt handling implemented on ARM at all.


I was able to make some progress with the virtio driver, now we get to the rocket icon on the splash screen.
Loading of the add-on modules fails with ‘bad data’
Then we get to an infinite loop of Data Abort in launch_daemon.

Screenshot from 2021-10-24 09-52-43

Meanwhile, my patches for MMU initialization in the EFI bootloader were accepted, so this is a big thank you to the Haiku maintainers for the code review.

Next: clean up the patches for getting virtio-mmio working (timer is still missing, I’m using a kludge in cpu_idle for now)
Then probably some troubleshooting for the ELF loader.


Running userland is near!

I manged to run even desktop without timer interrupt in my early RISC-V port.

Note that you may need some information from FDT to make hardware and timer interrupts working, but FDT bus driver is not yet working at that stage. You can gather all required information in haiku_loader and pass it in kernel args.


That’s already an issue for the interrupt controller. For now I just did a quick and dirty initialization routine for GICv2 with hard coded addresses. Some major cleanup will be needed before I can submit that…


You can submit early work marked with -1 vote so others can reproduce results and help.


It might be time to look at linker scripts. I think the kernel one is mostly copied from risc-v at the moment. The runtime one is very old, probably has never seen any usage yet.
Here is the scripts:

Edit: Also ARM64 and RISC-V are setup to use .iniarray while ARM probably still .ctor .dtor based. I think going .iniarray should be default for new archs.


Short update on the ARM port… some memory management issues. After applying some workarounds, we stop at entering userspace as it’s not implemented.

PANIC: arch_thread_enter_uspace(): not yet implemented

Welcome to Kernel Debugging Land...
Thread 788 "launch_daemon" running on CPU 0
frame            caller     <image>:function + offset
 0 5c208558 (+   0) 00000021   

Can you upload all patches somewhere so result can be reproduced? It is hard to give advises when nothing is working.

sure, I pushed to github:


I haven’t looked into enter_userspace yet as I was trying to consolidate my patches for the previous phases first.


  • currently bootstrapping fails for ARM because of the float-abi issue and outdated package version
  • I was able to get a successful gcc_bootstrap by adding -nostartfiles to the compiler options for libgcc-boot.a etc. If I also update the package versions then we get a successful ARM bootstrap. (even though the bootloader is still built with hard-float)
    So the question… do you guys think it’s a good approach to use nostartfiles to avoid linking libgcc-boot to the glue or should we rather try to build a glue-boot with softfloat instead?


  • it’s still built with hardfloat, probably the compile flags will need to be adjusted in ArchitectureRules
  • MMU setup seems to be good enough for the kernel to start, even though maybe a bit too many things are still identity-mapped
  • we need a fixup in the ELF relocation routine - the kernel is located in high addresses above 0x80000000 in virtual address space but currently the bootloader uses the physical addresses for relocation

Kernel - virtio initialization - reviews are open, I got a few comments so I’ll try to rework my patches

Page table initialization: I found a few issues in this area, this probably needs to be cleaned up before we can switch to user space

  • page table allocation and alignment needs to be adjusted
  • switch TTBR on thread context switch - this is not implemented yet, the remaining identity-mapped regions have to be removed to get it working.

You can see my RISC-V code as reference: haiku_loader.riscv, haiku_loader.efi. But on 32 bits mapping of whole RAM memory may be not possible.