https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=299088

            Bug ID: 299088
           Summary: riscv: kernel hangs early when the DTB is above its
                    1GB identity map (-kernel boot with >1GB RAM)
           Product: Base System
           Version: 15.1-RELEASE
          Hardware: riscv
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: [email protected]
          Reporter: [email protected]

Created attachment 275335
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=275335&action=edit
Map DTB when it is outside the kernel's 1G mapping

DESCRIPTION

When the riscv kernel is started directly by SBI firmware (no loader), it
gets the physical address of the DTB in a1.  locore.S only maps the 1GB
region that contains the kernel (the "1GB Identity Map" in pagetables:),
and initriscv() reads the DTB through that mapping.  If the firmware has
put the DTB in a different 1GB region, fake_preload_metadata() faults in
fdt_totalsize() (machdep.c:384).  This is before the console and before
the trap handler can deal with it, so the kernel hangs with no output.

Firmware that places the DTB near the top of RAM, as QEMU does, hits this
whenever there is more than about 1GB of RAM above the kernel.

Before bfb857546984 ("riscv: Construct an identity map in locore.S")
locore.S mapped the DTB separately, so this is a regression in 15.x.

The attached patch also maps the 1GB region that contains the DTB.  The
DTB can't straddle two regions in practice (it is 2MB aligned and much
smaller than 2MB), and if it is in the kernel's region the same entry is
written twice.


AFFECTED VERSIONS

main, stable/15 and releng/15.1.  stable/14 and releng/14.4 still have the
separate DTB mapping and are not affected.  Booting through loader.efi is
not affected either; the loader passes the DTB as a module instead.


HOW TO REPEAT

Easiest with QEMU, whose virt machine puts the DTB at the top of RAM:

  qemu-system-riscv64 -machine virt -smp 2 -m 2G -nographic \
      -bios default -kernel /boot/kernel/kernel \
      -drive file=root.img,format=raw,if=none,id=hd0 \
      -device virtio-blk-device,drive=hd0

using KERNCONF=QEMU (GENERIC plus ROOTDEVNAME).  RAM starts at 0x80000000
and the kernel loads at 0x80200000.  With -m 1G the DTB is at 0xbfe00000,
inside the kernel's 1GB region, and the kernel boots.  With -m 2G it is at
0xffe00000 and the kernel hangs after the OpenSBI banner.


TESTED

15.1-RELEASE-p3 world, KERNCONF=QEMU, booted as above:

  kernel             -m 1G   -m 2G   -m 4G   -m 8G
  15.1-RELEASE-p3    boots   hangs   hangs   hangs
  with patch         boots   boots   boots   boots

With the patch hw.physmem matches the configured RAM in each case.  Not
tested on riscv hardware (I don't have any).


ATTACHMENTS

0001-riscv-Map-the-DTB-when-it-is-outside-the-kernel-s-1G.patch
  against main ff2efe65a89a

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to