limine-bootloader / limine

Modern, advanced, portable, multiprotocol bootloader and boot manager.
https://limine-bootloader.org
BSD 2-Clause "Simplified" License
1.87k stars 141 forks source link

Invalid memory map with QEMU riscv64 #401

Closed bjorn3 closed 3 months ago

bjorn3 commented 3 months ago

The riscv64 virt machine of QEMU contains the following snippet in the device tree:

    reserved-memory {
        #address-cells = <0x2>
        #size-cells = <0x2>
        ranges = []

        mmode_resv0@80000000 {
            reg = <0x80000000 0x80000>
        };
    };

Any writes to this mmode_resv0 region will fault.

If I run U-Boot in supervisor mode as UEFI implementation, make it load limine 8.0.4 and then load my kernel using limine, the memory map produced by limine marks mmode_resv0 as usable memory:

(gdb) p/x *memory_map[0]
$19 = limine::memory_map::Entry {base: 0x80000000, length: 0x7efb000, entry_type: limine::memory_map::EntryType (0x0)}
(gdb) p/x *memory_map[1]
$20 = limine::memory_map::Entry {base: 0x87efb000, length: 0xa000, entry_type: limine::memory_map::EntryType (0x2)}
(gdb) p/x *memory_map[2]
$21 = limine::memory_map::Entry {base: 0x87f05000, length: 0x326ab000, entry_type: limine::memory_map::EntryType (0x0)}
(gdb) p/x *memory_map[3]
$22 = limine::memory_map::Entry {base: 0xba5b0000, length: 0x33000, entry_type: limine::memory_map::EntryType (0x5)}
(gdb) p/x *memory_map[4]
$23 = limine::memory_map::Entry {base: 0xba5e3000, length: 0x52000, entry_type: limine::memory_map::EntryType (0x6)}
(gdb) p/x *memory_map[5]
$24 = limine::memory_map::Entry {base: 0xba635000, length: 0xac000, entry_type: limine::memory_map::EntryType (0x5)}
(gdb) p/x *memory_map[6]
$25 = limine::memory_map::Entry {base: 0xba6e1000, length: 0x3ffd000, entry_type: limine::memory_map::EntryType (0x0)}
(gdb) p/x *memory_map[7]
$26 = limine::memory_map::Entry {base: 0xbe6de000, length: 0x3000, entry_type: limine::memory_map::EntryType (0x1)}
(gdb) p/x *memory_map[8]
$27 = limine::memory_map::Entry {base: 0xbe6e1000, length: 0xa000, entry_type: limine::memory_map::EntryType (0x1)}
(gdb) p/x *memory_map[9]
$28 = limine::memory_map::Entry {base: 0xbe6eb000, length: 0x31000, entry_type: limine::memory_map::EntryType (0x5)}
(gdb) p/x *memory_map[10]
$29 = limine::memory_map::Entry {base: 0xbe71c000, length: 0x8000, entry_type: limine::memory_map::EntryType (0x0)}
(gdb) p/x *memory_map[11]
$30 = limine::memory_map::Entry {base: 0xbe724000, length: 0x2000, entry_type: limine::memory_map::EntryType (0x1)}
(gdb) p/x *memory_map[12]
$31 = limine::memory_map::Entry {base: 0xbe726000, length: 0x1000, entry_type: limine::memory_map::EntryType (0x0)}
(gdb) p/x *memory_map[13]
$32 = limine::memory_map::Entry {base: 0xbe727000, length: 0x2000, entry_type: limine::memory_map::EntryType (0x1)}
(gdb) p/x *memory_map[14]
$33 = limine::memory_map::Entry {base: 0xbe729000, length: 0x1000, entry_type: limine::memory_map::EntryType (0x0)}
(gdb) p/x *memory_map[15]
$34 = limine::memory_map::Entry {base: 0xbe72a000, length: 0x4000, entry_type: limine::memory_map::EntryType (0x1)}
(gdb) p/x *memory_map[16]
$35 = limine::memory_map::Entry {base: 0xbe72e000, length: 0x1829000, entry_type: limine::memory_map::EntryType (0x0)}
(gdb) p/x *memory_map[17]
$36 = limine::memory_map::Entry {base: 0xbff57000, length: 0x1000, entry_type: limine::memory_map::EntryType (0x1)}
(gdb) p/x *memory_map[18]
$37 = limine::memory_map::Entry {base: 0xbff58000, length: 0xa8000, entry_type: limine::memory_map::EntryType (0x0)}
(gdb) p/x *memory_map[19]

As mmode_resv0 is marked as usable in the memory map, my kernel attempts to write to it, causing a crash.

qookei commented 3 months ago

At a glance this feels like a bug in U-Boot's UEFI implementation? Limine only ever uses the memory map obtained from UEFI.

bjorn3 commented 3 months ago

Could be.

qookei commented 3 months ago

I am unable to reproduce this with latest Limine, QEMU 8.2.3 and U-Boot 2024.10-rc2-00056-g7bd2559cb30a (Aug 11 2024 - 20:23:03 +0200).

I can confirm that the reserved memory does exist in the device tree (as seen by fdt print in the U-Boot console) and that writing there indeed does cause a crash, but the UEFI memory map properly reports it as reserved, and so does Limine.

Running the Limine test kernel (edited to stop after printing the memory map) reports the following memory map: image

bjorn3 commented 3 months ago

Based on what you all said I presume this is a bug in the U-Boot 2023.01+dfsg-2+deb12u1 shipped by Debian that has been fixed since.