Opened 2 years ago

Last modified 5 months ago

#14095 new bug

ARM RPI2: Device mapping commented out

Reported by: robg2 Owned by: nobody
Priority: normal Milestone: Unscheduled
Component: System/Boot Loader/uboot Version: R1/Development
Keywords: ARM RPI2 Cc:
Blocked By: Blocking:
Platform: arm


I've been looking into the issue with the 'MMU hang' when running Haiku on an emulated Raspberry Pi2 via QEMU.

I believe the problem is that the device memory mapping has been commented out at

The MMU is enabled as the last act of init_page_directory(), and control returns to mmu_init(), line 743. At line 748, a TRACE message is attempted, which will write to the UART. Without the device memory at 0x3f000000 mapped, this will fail.

This quick hack to uncomment the code and #define some DEVICE_* parameters let me get farther:

diff --git a/src/system/boot/arch/arm/arch_mmu.cpp b/src/system/boot/arch/arm/arch_mmu.cpp
index d4c5450ed21..e4f77c3a5fb 100644
--- a/src/system/boot/arch/arm/arch_mmu.cpp
+++ b/src/system/boot/arch/arm/arch_mmu.cpp
@@ -87,15 +87,17 @@ struct memblock {

 #warning TODO: Plot pref. base from fdt!
+#define DEVICE_BASE 0x3f000000
+#define DEVICE_SIZE 0x01000000
 static struct memblock LOADER_MEMORYMAP[] = {
                DEVICE_BASE + DEVICE_SIZE - 1,
                "RAM_kernel", // 8MB space for kernel, drivers etc

With this hack I can get a screen on the serial port that looks like this:

                                Welcome to the
                               Haiku Boot Loader

                        Copyright 2004-2014 Haiku, Inc.

          Select boot volume (Current: None)
          Select safe mode options
          Select debug options

          Continue booting

The qemu command line I am using is

qemu-system-arm -M raspi2 -kernel haiku_loader.ub -initrd haiku-floppyboot.tgz.ub -dtb rpi2.dtb -serial stdio  -m 2G

I suppose the proper fix is to read device mapping info from the device tree. It looks like the code may be in the middle of a transition from pre-device-tree to device-tree. I'm not sure.

Attachments (2)

7.png (187.0 KB ) - added by kallisti5 2 years ago.
step preparing to putc to serial port
8.png (96.0 KB ) - added by kallisti5 2 years ago.
arm exception and hang

Download all attachments as: .zip

Change History (9)

comment:1 by pulkomandy, 2 years ago

Yes, the migration to device tree is in progress. And you are right, instead of hardcoding things in the sourcecode, the whole memory map should be built from the device tree.

comment:2 by mmlr, 2 years ago

Might the work in be relevant? Either regarding the issue directly (though it looks like that work is all about aarch64) or regarding the device tree?

comment:3 by kallisti5, 2 years ago

I ran over (slowly) what happens.

The first attempt to print to the serial port after init_page_directory() in mmu_allocate() results in the exception handler getting triggered.

Attaching a gdb trace.

fdt_get_range_offset: range offset: 0x0
fdt_get_device_reg_byname: /axi/mbox found @ 0x3f00b880
Found boot tgz from FDT @ 0x08000000, 1601071 bytes
argc = 0
os: 2
gd @ 0x00000000
FDT @ 0x08187000:
fdt_totalsize: 36654
fdt_off_dt_struct: 56
fdt_off_dt_strings: 7780
fdt_off_mem_rsvmap: 40
fdt_version: 17
fdt_last_comp_version: 16
fdt_boot_cpuid_phys: 3840
fdt_size_dt_strings: 615
fdt_size_dt_struct: 7724
fdtSize: 0x8f2e
checking for memory...
0: base = 0,size = 2080374784
total physical memory = 1984MB
mmu_map_identity: [ 1000000 - 1053000]
get_next_page_table, sNextPageTableAddress 0x1104000, sPageTableRegionEnd 0x1300000, type 0x1
mmu_map_identity: [ 1100000 - 1300000]
get_next_page_table, sNextPageTableAddress 0x1104400, sPageTableRegionEnd 0x1300000, type 0x1
get_next_page_table, sNextPageTableAddress 0x1104800, sPageTableRegionEnd 0x1300000, type 0x1
BLOCK: RAM_kernel START: 80000000 END 807fffff
mmu_map_identity: [ 80000000 - 80800000]
get_next_page_table, sNextPageTableAddress 0x1104c00, sPageTableRegionEnd 0x1300000, type 0x1
get_next_page_table, sNextPageTableAddress 0x1105000, sPageTableRegionEnd 0x1300000, type 0x1
get_next_page_table, sNextPageTableAddress 0x1105400, sPageTableRegionEnd 0x1300000, type 0x1
get_next_page_table, sNextPageTableAddress 0x1105800, sPageTableRegionEnd 0x1300000, type 0x1
get_next_page_table, sNextPageTableAddress 0x1105c00, sPageTableRegionEnd 0x1300000, type 0x1
get_next_page_table, sNextPageTableAddress 0x1106000, sPageTableRegionEnd 0x1300000, type 0x1
get_next_page_table, sNextPageTableAddress 0x1106400, sPageTableRegionEnd 0x1300000, type 0x1
get_next_page_table, sNextPageTableAddress 0x1106800, sPageTableRegionEnd 0x1300000, type 0x1

I never see the reported mmu_allocate: requested vaddr: 0x00000000, next free vaddr: 0x80800000, size: 16384.

by kallisti5, 2 years ago

Attachment: 7.png added

step preparing to putc to serial port

by kallisti5, 2 years ago

Attachment: 8.png added

arm exception and hang

comment:4 by kallisti5, 2 years ago

Obviously, I spent a while figuring out what you already did @robg2 :-)

So, we need to parse the DTB to determine the base of the hardware devices.

On broadcom (rpi) and TI (beaglebone) devices it is "simple-bus".

  • The broadcom dts specifies where simple-bus is.
  • The TI dts specifies simple-bus, but doesn't give a base.

We might need setup memory areas for each physical device in the dtb vs assuming they will all be present in a preserved range :-|

comment:5 by pulkomandy, 2 years ago

Yes, mapping each device separately makes sense and saves on address space.

We will need an FDT bus (similar to the PCI one) providing access to device information (base address, size, etc). Then it is up to each device driver to map this into memory (as is the case with PCI already - we don't map the whole PCI space to memory as a big block). Note that this also provides some protection between drivers - you write to your device page, and normally you don't accidentally access registers from neighbor devices.

For the debug serial port case, it is ok to have a setting in the kernel settings file as we need this setup much earlier than everything else. In fact there is already a setting for x86 (it sets an IO port and not a memory address, but the idea is the same). This is needed anyways because there can be multiple serial ports, and the kernel wouldn't know which one to use (and they may not all be reachable by the user, for example connected internally to a GPS receiver or IR port or whatnot).


  • For the serial port, just use the existing serial_debug_port setting (accept an address here) and look for a typical 16c550 serial controller at that address.
  • For all other devices, before accessing them, we need to find where they are in the FDT.
  • We may need the FDT for other purposes early in the kernel, for example to find where the RAM is (I'm sure we'll need this at some point before the bus manager can be set up). But we can live with some hardcoded things as a first step here.

comment:6 by kallisti5, 2 years ago

A first iteration of FDT-based mapping of peripherals was pushed in hrev52175.

hrev52175 is limited to functioning under the following situations:

  • /axi is where the peripherals are
  • /axi contains the register offsets for "all the peripherals"
  • The peripheral space is 0x01000000 long

This "fixes" Haiku under qemu emulating the raspberry pi, and should fix Haiku booting on the raspberry pi.

I need to write a lot of FDT support code to improve this and make it more generic:

  • We need a function to "find" compatible devices in the FDT tree.
  • We need fdt_get_device_size to get the size of the FDT device register space.

After the above is complete, we need to "find" simple-bus and map *each* peripheral (vs the overall "peripheral space" since all of the peripherals existing in the same space isn't guaranteed) under it.

I'd avoid making any changes to FDT support code however until we decide if is going in the right direction. I need feedback from mmu_man on that one.

comment:7 by pulkomandy, 5 months ago

Component: System/Boot LoaderSystem/Boot Loader/uboot
Note: See TracTickets for help on using tickets.