Files

5.2 KiB

QEMU testing

QEMU tests UniXNU, the injection paths, DarwinBoot and the kernel entry without a device.

Procedure

  1. Install the requirements, including AArch64 firmware. Choose the behavior to exercise: common UEFI, a staged ESP or XNU entry.
  2. For the maintained common UEFI scenarios, run the smoke test. For custom EFI inputs, first stage an ESP, then use Run with expected log markers.
  3. For kernel-entry work, prepare the XNU entry fixture and follow its runner options. Record the kernel and ADT used.
  4. Inspect the selected scenario's logs and screenshot. Record the exact expected marker reached and the timeout or failure when it was not reached. Continue with device bring-up for board resources.

Requirements

Tool Purpose
qemu-system-aarch64 AArch64 virtual machine
AAVMF or EDK2 AArch64 firmware UEFI environment
dtc Device tree compilation
mtools or pyfatfs FAT image for the block slice test

The QEMU runner looks for the firmware in the common Homebrew and distribution paths, or takes --firmware.

Stage an ESP

python3 package/Scripts/stage-esp.py -o out/esp \
  package/UniXNUPkg/Test/Qemu/esp \
  --put out/<device>/<os_profile>/<config>/package/Build/Out/AARCH64-DEBUG/UniXNU.efi=EFI/BOOT/BOOTAA64.EFI \
  --put out/<device>/<os_profile>/<config>/package/Build/Out/AARCH64-DEBUG/HelloPayload.efi=EFI/UniXNU/Payloads/HelloPayload.efi \
  --put out/<device>/<os_profile>/<config>/package/Build/Out/AARCH64-DEBUG/SampleDriver.efi=EFI/UniXNU/Kits/SampleDriver.kit/SampleDriver.efi

stage-esp.py copies the tree, compiles .dts to .dtb and .dtso to .dtbo, and places each --put file at its destination.

Run

python3 package/Scripts/qemu-run.py out/esp \
  --log out/qemu.log --screenshot out/menu.png \
  --expect 'UNIXNU: menu: shown' \
  --expect 'UNIXNU-HELLO: RESULT PASS'
Option Meaning
--firmware FILE AAVMF code image
--log FILE Serial log
--screenshot FILE PNG captured when the menu appears
--keys LIST QEMU key codes sent after the menu
--expect REGEX Pattern that must match the serial log
--reject REGEX Pattern that must not match
--no-gop No display device, text console only
--display-size WxH Virtio GPU display of this size instead of ramfb, for example 1080x2400 for a portrait panel. The firmware needs at least 640 pixels of width
--disk FILE Extra read-only raw disk
--timeout SECONDS Run timeout
--cpus N Virtual CPU count
--finish-on-expect Stop two seconds after all expectations match
--menu-marker TEXT Log marker that triggers the screenshot and keys

The runner exposes the ESP read-only through QEMU vvfat, captures the serial log, and talks to QEMU over QMP for screenshots and keys.

Smoke test

JOBS=8 bash package/Scripts/smoke.sh

The script builds the package and runs six scenarios:

Scenario Checks
Default entry Device tree patches, overlay, kit driver, initrd media, entry variable
Keyboard Down and Enter select the second entry
Degraded No GOP and no configuration, built-in entries, text console
Block slice Configuration on a FAT partition head, tail published as a block device
Kext staging Revision 2 handoff, revision 1 refusal, invalid bundles, duplicates
Layout A 1080x2400 display uses portrait, an 800x1000 display stays landscape

Logs and screenshots go to package/Build/Smoke/.

XNU entry fixture

The QEMU entry generator builds an Apple-format device tree for the kernel:

python3 scripts/qemu-entry/make-dt.py \
  --armvirt --armcpu --smp 2 \
  --owned-memory-size 0x20000000 \
  --output build/qemu-test.adt
Option Meaning
--armvirt Describe QEMU virt devices
--armcpu Add the GICv3 distributor and redistributor
--smp N CPU count and PSCI
--owned-memory-size Contiguous DarwinBoot window
--data-ramdisk Scratch Data placeholder
--trust-cache Trust cache placeholder
--nvram-proxy Volatile CHRP NVRAM proxy
--root-match-volume-uuid Root volume match
--osenvironment main, recoveryos or ramdisk
--qemu-vmm-present Report the VMM in /defaults
--crypto-hash-method Image4 hash method

The generator describes QEMU and uses QEMU values only.

HVF

On Apple Silicon macOS, QEMU can use HVF:

python3 scripts/qemu-entry/make-dt.py --armvirt --armcpu --qemu-vmm-present \
  --qemu-accel hvf --output build/qemu-hvf.adt

The generator reads the host counter frequency for the CPU timebase. The bound fixture is used to observe the actual TCR_EL1, SCTLR_EL1 and TTBR registers at the kernel stop point.

Stop point

python3 scripts/qemu-entry/gdb-stop.py --help

The helper stops QEMU at a symbol and records registers, memory and the last checkpoint. The output is a JSON report.

Next steps