I run
qemu-system-aarch64 -s -S \
-machine virt,gic_version=2,virtualization=on,secure=off \
-cpu cortex-a72 \
-m 2G \
-kernel mykernel.elf \
\
-chardev stdio,mux=on,id=char0 \
-mon chardev=char0,mode=readline \
-serial chardev:char0 \
\
-device virtio-net-pci,mac=ca:fe:00:ba:be:01,netdev=net0 \
-netdev bridge,br=br0,id=net0 \
\
-nographic \
-device virtio-gpu-pci \
\
-device virtio-rng-pci
I connect to the initially stopped guest with gdb-multiarch
and target remote :1234
. Using info reg
I see that register X0 is zero. I have been debugging with gdb this way, stepping through the kernel, etc. for weeks with great success. I'm certain it's showing the real register values.
Why doesn't qemu pass an FDT pointer to the guest? How can I get the FDT?
The documentation at https://www.qemu.org/docs/master/system/arm/virt.html#hardware-configuration-information-for-bare-metal-programming says:
QEMU supports two types of guest image boot for virt, and the way for the guest code to locate the dtb binary differs:
For guests using the Linux kernel boot protocol (this means any non-ELF file passed to the QEMU -kernel option) the address of the DTB is passed in a register (r2 for 32-bit guests, or x0 for 64-bit guests)
For guests booting as “bare-metal” (any other kind of boot), the DTB is at the start of RAM (0x4000_0000)
You are passing an ELF file, and so you are the second of these two categories. You will find the DTB at 0x4000_0000 (assuming your ELF file is linked so that it does not overlap with that memory range). The address is not passed in a register: it's just at a known location.