From: Jared Rossi <jrossi@linux.ibm.com>
Define selected s390x PCI instructions.
Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>
---
pc-bios/s390-ccw/Makefile | 2 +-
pc-bios/s390-ccw/pci.c | 118 ++++++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/pci.h | 39 +++++++++++++
3 files changed, 158 insertions(+), 1 deletion(-)
create mode 100644 pc-bios/s390-ccw/pci.c
create mode 100644 pc-bios/s390-ccw/pci.h
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 9c29548f84..a62fc9d766 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 clp.o
+ virtio-ccw.o clp.o pci.o
SLOF_DIR := $(SRC_PATH)/../../roms/SLOF
diff --git a/pc-bios/s390-ccw/pci.c b/pc-bios/s390-ccw/pci.c
new file mode 100644
index 0000000000..247070e5f0
--- /dev/null
+++ b/pc-bios/s390-ccw/pci.c
@@ -0,0 +1,118 @@
+/*
+ * s390x PCI functionality
+ *
+ * Copyright 2025 IBM Corp.
+ * Author(s): Jared Rossi <jrossi@linux.ibm.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "clp.h"
+#include "pci.h"
+#include "bswap.h"
+#include <stdio.h>
+#include <stdbool.h>
+
+/* PCI load */
+static inline int pcilg(uint64_t *data, uint64_t req, uint64_t offset,
+ uint8_t *status)
+{
+ union register_pair req_off = {.even = req, .odd = offset};
+ int cc = -1;
+ uint64_t __data;
+
+ asm volatile (
+ " .insn rre,0xb9d20000,%[data],%[req_off]\n"
+ " ipm %[cc]\n"
+ " srl %[cc],28\n"
+ : [cc] "+d" (cc), [data] "=d" (__data),
+ [req_off] "+d" (req_off.pair) :: "cc");
+ *status = req_off.even >> 24 & 0xff;
+ *data = __data;
+ return cc;
+}
+
+/* PCI store */
+static inline int pcistg(uint64_t data, uint64_t req, uint64_t offset,
+ uint8_t *status)
+{
+ union register_pair req_off = {.even = req, .odd = offset};
+ int cc = -1;
+
+ asm volatile (
+ " .insn rre,0xb9d00000,%[data],%[req_off]\n"
+ " ipm %[cc]\n"
+ " srl %[cc],28\n"
+ : [cc] "+d" (cc), [req_off] "+d" (req_off.pair)
+ : [data] "d" (data)
+ : "cc");
+ *status = req_off.even >> 24 & 0xff;
+ return cc;
+}
+
+int pci_write(uint32_t fhandle, uint64_t offset, uint8_t pcias, uint64_t data,
+ uint8_t len)
+{
+
+ uint64_t req = ZPCI_CREATE_REQ(fhandle, pcias, len);
+ uint8_t status;
+ int rc;
+
+ /* len must be non-zero power of 2 with a maximum of 8 bytes per write */
+ switch (len) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ rc = pcistg(data, req, offset, &status);
+ break;
+ default:
+ return -1;
+ }
+
+ /* Error condition detected */
+ if (rc != 0) {
+ printf("PCI store failed with status condition %d, return code %d\n",
+ status, rc);
+ return -1;
+ }
+
+ return 0;
+}
+
+int pci_read(uint32_t fhandle, uint64_t offset, uint8_t pcias, void *buf,
+ uint8_t len)
+{
+ uint64_t req, data;
+ uint8_t status;
+ int rc;
+
+ req = ZPCI_CREATE_REQ(fhandle, pcias, len);
+ rc = pcilg(&data, req, offset, &status);
+
+ /* Error condition detected */
+ if (rc != 0) {
+ printf("PCI load failed with status condition %d, return code %d\n",
+ status, rc);
+ return -1;
+ }
+
+ switch (len) {
+ case 1:
+ *(uint8_t *)buf = data;
+ break;
+ case 2:
+ *(uint16_t *)buf = data;
+ break;
+ case 4:
+ *(uint32_t *)buf = data;
+ break;
+ case 8:
+ *(uint64_t *)buf = data;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/pc-bios/s390-ccw/pci.h b/pc-bios/s390-ccw/pci.h
new file mode 100644
index 0000000000..40a0bf9dcb
--- /dev/null
+++ b/pc-bios/s390-ccw/pci.h
@@ -0,0 +1,39 @@
+/*
+ * s390x PCI definitions
+ *
+ * Copyright 2025 IBM Corp.
+ * Author(s): Jared Rossi <jrossi@linux.ibm.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PCI_H
+#define PCI_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "clp.h"
+
+#define ZPCI_CREATE_REQ(handle, space, len) \
+ ((uint64_t) handle << 32 | space << 16 | len)
+
+union register_pair {
+ unsigned __int128 pair;
+ struct {
+ unsigned long even;
+ unsigned long odd;
+ };
+};
+
+#define PCIST_DISABLED 0x0
+#define PCIST_ENABLED 0x1
+
+#define PCI_CFGBAR 0xF /* Base Address Register for config space */
+#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
+
+int pci_write(uint32_t fhandle, uint64_t offset, uint8_t pcias, uint64_t data,
+ uint8_t len);
+int pci_read(uint32_t fhandle, uint64_t offset, uint8_t pcias, void *buf,
+ uint8_t len);
+
+#endif
--
2.52.0