From: Utkarsh Verma <[email protected]>
This series adds support for booting from a disk image under the
Virtual Open
Firmware (VOF) path for sPAPR/pseries machines in QEMU.
The most common use case for pseries VMs is booting from a distro qcow2
disk
image. These images carry a PReP boot partition containing GRUB2, which
in turn
loads the kernel and initrd via IEEE 1275 client interface calls.
VOF currently only supports direct -kernel/-initrd boot; there is no
firmware-mediated path to hand off to a bootloader on disk. This series
implements that missing path, making VOF capable of handling the
standard
distro qcow2 boot flow without requiring SLOF.
This series takes reference from an earlier implementation by Alexey
Kardashevskiy [1] which explored the same concept but was not carried
forward at
the time.
The existing load_elf function works on a file, whereas in the VOF the
PReP
partition (GRUB) is read from the disk image and loaded in the memory,
also
on loading the PReP partition in the guest memory the
/memory@0/available FDT
needs to be properly updated for each PT_LOAD segment of the core.elf
file
of the GRUB (PReP partition).
Implemented a new public elf loader API load_elf_ram_sym_buf() to
resolve both
these issues.
- load_elf_ram_sym_buf() accepts a caller-supplied memory buffer
instead of a
filename, using g_file_open_tmp() to obtain an anonymous file
descriptor for
the caller-supplied buffer. This means the ELF image has 2 copies,
the
caller's heap buffer and the temporary file. For typical PReP
partition sizes
(~4 MB) this is acceptable, but if a more memory-efficient approach
is
preferred we are open to alternatives. Feedback on the preferred
direction is
welcome.
- Also, added optional segment_fn_t callback in load_elf_ram_sym_buf()
through
the internal elf_ops.h.inc template; it is invoked once per PT_LOAD
segment
after the load address is resolved, allowing callers to perform
per-segment
work such as VOF memory claims.
When no -kernel is given, spapr_vof_reset() calls a newly implemented
function
spapr_vof_try_prep_boot() which iterates attached block backends, scans
partitions for a PReP boot partition, reads the partition contents into
a
host buffer, calls load_elf_ram_sym_buf() to load the GRUB in the guest
memory,
and on success stores the ELF entry point in spapr->kernel_addr.
spapr_vof_client_dt_finalize() then writes the entry point into
/chosen/qemu,boot-kernel so VOF then transfers control to GRUB.
- Partition scanner (spapr_vof_partition.c): scans MBR and GPT
partition tables
on a BlockBackend to locate the PReP boot partition.
- Core loader extension (hw/core/loader.c): new load_elf_ram_sym_buf()
API loads
a 32/64-bit ELF binary from a caller-supplied memory buffer, reusing
the
existing load_elf32/load_elf64 paths. A new segment_fn_t callback in
elf_ops.h.inc lets callers act on each PT_LOAD segment as it is
resolved.
- read, seek OF services: two previously unimplemented IEEE 1275 client
services, covering block device I/O needed by GRUB.
- vscsi-report-luns method: walks the SCSIBus and builds the LUN report
table
in guest memory in the format expected by GRUB's ofdisk driver,
matching
SLOF's dev-generate-srplun encoding.
- VTY write/read routing: routes console I/O through the VTY chardev
backend;
promotes vty_getchars to external linkage. Also opens a stdin ihandle
in
addition to stdout so GRUB can read from the console.
- FDT "disk" wildcard child node (spapr_vscsi.c): emits a single
generic "disk"
child FDT node under the vSCSI adapter (without a per-LUN suffix),
matching
the actual Open Firmware behaviour. The path_offset() wildcard
fallback
resolves any "disk@<srp-lun>" open request to this shared node; the
LUN is
extracted from the path string at runtime in vof_do_open().
We used AI to build prototype with manual changes incorporated as
identified
during debugging multiple issues faced while making it work, hence
using below
tag as being discussed in the ongoing AI policy patch:
[PATCH v4 0/4] docs/devel, AGENTS.md: a completely new policy on
AI-generated contributions
Link to the patch [2].
AI-used-for: Code
Testing:
The series has been tested end-to-end by booting a RHEL9.7 qcow2 image
on a
pseries machine with VOF enabled (no SLOF).
build$ ./qemu-system-ppc64 -M pseries,x-vof=on -cpu power9 -m 2G \
-hda ../../rhel-guest-image-9.7-20251021.0.ppc64le.qcow2 -nographic
qemu-system-ppc64: warning: TCG doesn't support requested feature,
cap-cfpc=workaround
qemu-system-ppc64: warning: TCG doesn't support requested feature,
cap-ibs=workaround
qemu-system-ppc64: warning: TCG doesn't support requested feature,
cap-ccf-assist=on
Welcome to GRUB!
<snip>
GRUB version 2.06
+----------------------------------------------------------------------------+
|*Red Hat Enterprise Linux (5.14.0-611.5.1.el9_7.ppc64le) 9.7 (Plow)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+----------------------------------------------------------------------------+
Use the ^ and v keys to select which entry is highlighted.
Press enter to boot the selected OS, `e' to edit the commands
before booting or `c' for a command-line.
<snip>
Red Hat Enterprise Linux 9.7 (Plow)
Kernel 5.14.0-611.5.1.el9_7.ppc64le on an ppc64le
Activate the web console with: systemctl enable --now cockpit.socket
localhost login: root
Password:
Last login: Fri Jul 10 01:45:44 on hvc0
[root@localhost ~]#
[root@localhost ~]# ls /
afs boot etc lib media opt root sbin sys usr
bin dev home lib64 mnt proc run srv tmp var
[root@localhost ~]#
[root@localhost ~]# echo "Hello, World!" > hello.txt
[root@localhost ~]# cat hello.txt
Hello, World!
[root@localhost ~]#
[1]
https://lore.kernel.org/qemu-devel/[email protected]/#t
[2]
https://lore.kernel.org/qemu-devel/[email protected]/
Utkarsh Verma (8):
ppc/spapr: add PReP boot partition detection
hw/loader: add load_elf_ram_sym_buf() for in-memory ELF loading
ppc/spapr: add baseline VOF disk boot support
ppc/spapr: add VTY backend support to OF read/write/open services
ppc/spapr: add block device backend to VOF open/read/write/seek
services
spapr_vscsi: add VOF disk nodes to the device tree
ppc/spapr: strip OF path argument suffix in path_offset
ppc/spapr: implement vscsi-report-luns call-method for PAPR vSCSI
hw/char/spapr_vty.c | 2 +-
hw/core/loader.c | 81 +++++-
hw/ppc/meson.build | 5 +-
hw/ppc/spapr_vof.c | 164 +++++++++++-
hw/ppc/spapr_vof_partition.c | 272 ++++++++++++++++++++
hw/ppc/trace-events | 4 +
hw/ppc/vof.c | 475 ++++++++++++++++++++++++++++++++++-
hw/scsi/spapr_vscsi.c | 23 ++
include/hw/core/loader.h | 30 +++
include/hw/elf_ops.h.inc | 12 +-
include/hw/ppc/spapr_vio.h | 1 +
include/hw/ppc/spapr_vof.h | 14 ++
include/hw/ppc/vof.h | 2 +
13 files changed, 1070 insertions(+), 15 deletions(-)
create mode 100644 hw/ppc/spapr_vof_partition.c
create mode 100644 include/hw/ppc/spapr_vof.h