From: Jared Rossi <[email protected]> Call Logical Processor (CLP) Architecture is used for managing PCI functions on s390x. Define and include the structures and routines needed to interact with PCI devices during IPL.
Headers in ~/qemu/include/hw are not normally visible and must be included using a relative path. Due to this, the QEMU_PACKED macro must also be defined here. Signed-off-by: Jared Rossi <[email protected]> --- pc-bios/s390-ccw/clp.h | 24 +++++++++ pc-bios/s390-ccw/clp.c | 106 ++++++++++++++++++++++++++++++++++++++ pc-bios/s390-ccw/Makefile | 2 +- 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 pc-bios/s390-ccw/clp.h create mode 100644 pc-bios/s390-ccw/clp.c diff --git a/pc-bios/s390-ccw/clp.h b/pc-bios/s390-ccw/clp.h new file mode 100644 index 0000000000..cb130e5e90 --- /dev/null +++ b/pc-bios/s390-ccw/clp.h @@ -0,0 +1,24 @@ +/* + * Call Logical Processor (CLP) architecture definitions + * + * Copyright 2025 IBM Corp. + * Author(s): Jared Rossi <[email protected]> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef CLP_H +#define CLP_H + +#ifndef QEMU_PACKED +#define QEMU_PACKED __attribute__((packed)) +#endif + +#include <stdint.h> +#include "../../include/hw/s390x/s390-pci-clp.h" + +int clp_pci(void *data); +int enable_pci_function(uint32_t *fhandle); +int enumerate_pci_functions(void); + +#endif diff --git a/pc-bios/s390-ccw/clp.c b/pc-bios/s390-ccw/clp.c new file mode 100644 index 0000000000..45d496fc18 --- /dev/null +++ b/pc-bios/s390-ccw/clp.c @@ -0,0 +1,106 @@ +/* + * Call Logical Processor (CLP) architecture + * + * Copyright 2025 IBM Corp. + * Author(s): Jared Rossi <[email protected]> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "clp.h" +#include <stdio.h> +#include <string.h> + +int clp_pci(void *data) +{ + struct { uint8_t _[2048]; } *req = data; + int cc = 3; + + asm volatile ( + " .insn rrf,0xb9a00000,0,%[req],0,2\n" + " ipm %[cc]\n" + " srl %[cc],28\n" + : [cc] "+d" (cc), "+m" (*req) + : [req] "a" (req) + : "cc"); + return cc; +} + +/* + * Get the PCI function entry for a given function ID + * Return 0 on success, 1 if the FID is not found, or a negative RC on error + */ +int find_pci_function(uint32_t fid, ClpFhListEntry *entry) +{ + int rc; + int count = 0; + int limit = PCI_MAX_FUNCTIONS; + ClpReqRspListPci rrb; + + rrb.request.hdr.len = 32; + rrb.request.hdr.cmd = 0x02; + rrb.request.resume_token = 0; + rrb.response.hdr.len = sizeof(ClpRspListPci); + + do { + rc = clp_pci(&rrb); + if (rc) { + return -rc; + } + + if (rrb.response.hdr.rsp != 0x0010) { + printf("Failed to list PCI functions: %x", rrb.response.hdr.rsp); + return -1; + } + + /* Resume token set when max enteries are returned */ + if (rrb.response.resume_token) { + count = CLP_FH_LIST_NR_ENTRIES; + rrb.request.resume_token = rrb.response.resume_token; + } else { + count = (rrb.response.hdr.len - 32) / sizeof(ClpFhListEntry); + } + + limit -= count; + + for (int i = 0; i < count; i++) { + if (rrb.response.fh_list[i].fid == fid) { + memcpy(entry, &rrb.response.fh_list[i], sizeof(ClpFhListEntry)); + return 0; + } + } + + } while (rrb.request.resume_token && limit); + + return 1; +} + +/* + * Enable the PCI function associated with a given handle + * Return 0 on success or a negative RC on error + */ +int enable_pci_function(uint32_t *fhandle) +{ + ClpReqRspSetPci rrb; + int rc; + + rrb.request.hdr.len = 32; + rrb.request.hdr.cmd = 0x05; + rrb.request.fh = *fhandle; + rrb.request.oc = 0; + rrb.request.ndas = 1; + rrb.response.hdr.len = 32; + + rc = clp_pci(&rrb); + if (rc) { + return -rc; + } + + if (rrb.response.hdr.rsp != 0x0010) { + printf("Failed to enable PCI function: %x", rrb.response.hdr.rsp); + return -1; + } + + *fhandle = rrb.response.fh; + return 0; +} diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile index 3577ac381a..89a42ae506 100644 --- a/pc-bios/s390-ccw/Makefile +++ b/pc-bios/s390-ccw/Makefile @@ -35,7 +35,7 @@ QEMU_DGFLAGS = -MMD -MP -MT $@ -MF $(@D)/$(*F).d OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o netmain.o \ virtio.o virtio-net.o virtio-scsi.o virtio-blkdev.o cio.o dasd-ipl.o \ - virtio-ccw.o + virtio-ccw.o clp.o SLOF_DIR := $(SRC_PATH)/../../roms/SLOF -- 2.49.0
