From: jrossi@linux.ibm.com
To: qemu-devel@nongnu.org, qemu-s390x@nongnu.org, thuth@redhat.com,
mst@redhat.com
Cc: jjherne@linux.ibm.com, alifm@linux.ibm.com, farman@linux.ibm.com,
mjrosato@linux.ibm.com, jrossi@linux.ibm.com,
zycai@linux.ibm.com
Subject: [PATCH v5 11/15] pc-bios/s390-ccw: Introduce virtio-pci functions
Date: Sun, 8 Mar 2026 20:35:57 -0400 [thread overview]
Message-ID: <20260309003601.242634-12-jrossi@linux.ibm.com> (raw)
In-Reply-To: <20260309003601.242634-1-jrossi@linux.ibm.com>
From: Jared Rossi <jrossi@linux.ibm.com>
Define common functionality for interacting with virtio-pci devices.
Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>
---
pc-bios/s390-ccw/Makefile | 2 +-
pc-bios/s390-ccw/virtio-pci.c | 167 ++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/virtio-pci.h | 80 ++++++++++++++++
pc-bios/s390-ccw/virtio.h | 3 +
4 files changed, 251 insertions(+), 1 deletion(-)
create mode 100644 pc-bios/s390-ccw/virtio-pci.c
create mode 100644 pc-bios/s390-ccw/virtio-pci.h
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index a62fc9d766..3e5dfb64d5 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 pci.o
+ virtio-ccw.o clp.o pci.o virtio-pci.o
SLOF_DIR := $(SRC_PATH)/../../roms/SLOF
diff --git a/pc-bios/s390-ccw/virtio-pci.c b/pc-bios/s390-ccw/virtio-pci.c
new file mode 100644
index 0000000000..f6ce7ec766
--- /dev/null
+++ b/pc-bios/s390-ccw/virtio-pci.c
@@ -0,0 +1,167 @@
+/*
+ * Functionality for virtio-pci
+ *
+ * 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 "helper.h"
+#include "virtio.h"
+#include "bswap.h"
+#include "virtio-pci.h"
+#include "s390-time.h"
+#include <stdio.h>
+
+/* Variable offsets used for reads/writes to modern memory regions */
+VirtioPciCap c_cap; /* Common capabilities */
+VirtioPciCap d_cap; /* Device capabilities */
+VirtioPciCap n_cap; /* Notify capabilities */
+uint32_t notify_mult;
+uint16_t q_notify_offset;
+
+static int virtio_pci_set_status(uint8_t status)
+{
+ int rc = vpci_write_byte(c_cap.off + VPCI_C_OFFSET_STATUS, c_cap.bar, status);
+ if (rc) {
+ puts("Failed to write virtio-pci status");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int virtio_pci_get_status(uint8_t *status)
+{
+ int rc = vpci_read_byte(c_cap.off + VPCI_C_OFFSET_STATUS, c_cap.bar, status);
+ if (rc) {
+ puts("Failed to read virtio-pci status");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* virtio spec v1.3 section 4.1.2.1 */
+void virtio_pci_id2type(VDev *vdev, uint16_t device_id)
+{
+ switch (device_id) {
+ case 0x1042:
+ case 0x1001:
+ vdev->dev_type = VIRTIO_ID_BLOCK;
+ break;
+ default:
+ vdev->dev_type = 0;
+ }
+}
+
+int virtio_pci_reset(VDev *vdev)
+{
+ int rc;
+ uint8_t status = 0;
+
+ rc = virtio_pci_set_status(status);
+ rc |= virtio_pci_get_status(&status);
+
+ if (rc || status) {
+ puts("Failed to reset virtio-pci device");
+ return 1;
+ }
+
+ return 0;
+}
+
+long virtio_pci_notify(int vq_id)
+{
+ uint32_t offset = n_cap.off + notify_mult * q_notify_offset;
+ return vpci_bswap16_write(offset, n_cap.bar, (uint16_t) vq_id);
+}
+
+/*
+ * Wrappers to byte swap common data sizes then write
+ */
+int vpci_write_byte(uint64_t offset, uint8_t pcias, uint8_t data)
+{
+ return pci_write(virtio_get_device()->pci_fh, offset, pcias, (uint64_t) data, 1);
+}
+
+int vpci_bswap16_write(uint64_t offset, uint8_t pcias, uint16_t data)
+{
+ uint64_t le_data = bswap16(data);
+ return pci_write(virtio_get_device()->pci_fh, offset, pcias, le_data, 2);
+}
+
+int vpci_bswap32_write(uint64_t offset, uint8_t pcias, uint32_t data)
+{
+ uint64_t le_data = bswap32(data);
+ return pci_write(virtio_get_device()->pci_fh, offset, pcias, le_data, 4);
+}
+
+int vpci_bswap64_write(uint64_t offset, uint8_t pcias, uint64_t data)
+{
+ uint64_t le_data = bswap64(data);
+ return pci_write(virtio_get_device()->pci_fh, offset, pcias, le_data, 8);
+}
+
+/*
+ * Wrappers to read common data sizes then byte swap
+ */
+int vpci_read_byte(uint64_t offset, uint8_t pcias, uint8_t *buf)
+{
+ return pci_read(virtio_get_device()->pci_fh, offset, pcias, buf, 1);
+}
+
+int vpci_read_bswap16(uint64_t offset, uint8_t pcias, uint16_t *buf)
+{
+ int rc = pci_read(virtio_get_device()->pci_fh, offset, pcias, buf, 2);
+ *buf = bswap16(*buf);
+ return rc;
+}
+
+int vpci_read_bswap32(uint64_t offset, uint8_t pcias, uint32_t *buf)
+{
+ int rc = pci_read(virtio_get_device()->pci_fh, offset, pcias, buf, 4);
+ *buf = bswap32(*buf);
+ return rc;
+}
+
+int vpci_read_bswap64(uint64_t offset, uint8_t pcias, uint64_t *buf)
+{
+ int rc = pci_read(virtio_get_device()->pci_fh, offset, pcias, buf, 8);
+ *buf = bswap64(*buf);
+ return rc;
+}
+
+/*
+ * Read to an arbitrary length buffer without byte swapping
+ */
+int vpci_read_flex(uint64_t offset, uint8_t pcias, void *buf, int len)
+{
+ uint8_t readlen;
+ int rc;
+ int remaining = len;
+
+ /* Read bytes in powers of 2, up to a maximum of 8 bytes per read */
+ while (remaining) {
+ for (int i = 3; i >= 0; i--) {
+ readlen = 1 << i;
+ if (remaining >= readlen) {
+ break;
+ }
+ }
+
+ rc = pci_read(virtio_get_device()->pci_fh, offset, pcias, buf, readlen);
+ if (rc) {
+ return -1;
+ }
+
+ remaining -= readlen;
+ buf += readlen;
+ offset += readlen;
+ }
+
+ return 0;
+}
diff --git a/pc-bios/s390-ccw/virtio-pci.h b/pc-bios/s390-ccw/virtio-pci.h
new file mode 100644
index 0000000000..54c524f698
--- /dev/null
+++ b/pc-bios/s390-ccw/virtio-pci.h
@@ -0,0 +1,80 @@
+/*
+ * Definitions for virtio-pci
+ *
+ * Copyright 2025 IBM Corp.
+ * Author(s): Jared Rossi <jrossi@linux.ibm.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef VIRTIO_PCI_H
+#define VIRTIO_PCI_H
+
+/* Common configuration */
+#define VPCI_CAP_COMMON_CFG 1
+/* Notifications */
+#define VPCI_CAP_NOTIFY_CFG 2
+/* ISR access */
+#define VPCI_CAP_ISR_CFG 3
+/* Device specific configuration */
+#define VPCI_CAP_DEVICE_CFG 4
+/* PCI configuration access */
+#define VPCI_CAP_PCI_CFG 5
+/* Additional shared memory capability */
+#define VPCI_CAP_SHARED_MEMORY_CFG 8
+/* PCI vendor data configuration */
+#define VPCI_CAP_VENDOR_CFG 9
+
+/* Offsets within capability header */
+#define VPCI_CAP_VNDR 0
+#define VPCI_CAP_NEXT 1
+#define VPCI_CAP_LEN 2
+#define VPCI_CAP_CFG_TYPE 3
+#define VPCI_CAP_BAR 4
+#define VPCI_CAP_OFFSET 8
+#define VPCI_CAP_LENGTH 12
+
+#define VPCI_N_CAP_MULT 16 /* Notify multiplier, VPCI_CAP_NOTIFY_CFG only */
+
+/* Common Area Offsets for virtio-pci queue */
+#define VPCI_C_OFFSET_DFSELECT 0
+#define VPCI_C_OFFSET_DF 4
+#define VPCI_C_OFFSET_GFSELECT 8
+#define VPCI_C_OFFSET_GF 12
+#define VPCI_C_COMMON_NUMQ 18
+#define VPCI_C_OFFSET_STATUS 20
+#define VPCI_C_OFFSET_Q_SELECT 22
+#define VPCI_C_OFFSET_Q_SIZE 24
+#define VPCI_C_OFFSET_Q_ENABLE 28
+#define VPCI_C_OFFSET_Q_NOFF 30
+#define VPCI_C_OFFSET_Q_DESCLO 32
+#define VPCI_C_OFFSET_Q_DESCHI 36
+#define VPCI_C_OFFSET_Q_AVAILLO 40
+#define VPCI_C_OFFSET_Q_AVAILHI 44
+#define VPCI_C_OFFSET_Q_USEDLO 48
+#define VPCI_C_OFFSET_Q_USEDHI 52
+
+#define VIRTIO_F_VERSION_1 1 /* Feature bit 32 */
+
+struct VirtioPciCap {
+ uint8_t bar; /* Which PCIAS it's in */
+ uint32_t off; /* Offset within bar */
+};
+typedef struct VirtioPciCap VirtioPciCap;
+
+void virtio_pci_id2type(VDev *vdev, uint16_t device_id);
+int virtio_pci_reset(VDev *vdev);
+long virtio_pci_notify(int vq_id);
+
+int vpci_read_flex(uint64_t offset, uint8_t pcias, void *buf, int len);
+int vpci_read_bswap64(uint64_t offset, uint8_t pcias, uint64_t *buf);
+int vpci_read_bswap32(uint64_t offset, uint8_t pcias, uint32_t *buf);
+int vpci_read_bswap16(uint64_t offset, uint8_t pcias, uint16_t *buf);
+int vpci_read_byte(uint64_t offset, uint8_t pcias, uint8_t *buf);
+
+int vpci_bswap64_write(uint64_t offset, uint8_t pcias, uint64_t data);
+int vpci_bswap32_write(uint64_t offset, uint8_t pcias, uint32_t data);
+int vpci_bswap16_write(uint64_t offset, uint8_t pcias, uint16_t data);
+int vpci_write_byte(uint64_t offset, uint8_t pcias, uint8_t data);
+
+#endif
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
index c3cb5a6ee3..1ef64675f4 100644
--- a/pc-bios/s390-ccw/virtio.h
+++ b/pc-bios/s390-ccw/virtio.h
@@ -18,6 +18,8 @@
#define VIRTIO_CONFIG_S_DRIVER 2
/* Driver has used its parts of the config, and is happy */
#define VIRTIO_CONFIG_S_DRIVER_OK 4
+/* Feature negotiation complete */
+#define VIRTIO_CONFIG_S_FEATURES_OK 8
/* We've given up on this device. */
#define VIRTIO_CONFIG_S_FAILED 0x80
@@ -255,6 +257,7 @@ struct VDev {
uint8_t scsi_dev_heads;
bool scsi_device_selected;
ScsiDevice selected_scsi_device;
+ uint32_t pci_fh;
uint32_t max_transfer;
uint32_t guest_features[2];
};
--
2.52.0
next prev parent reply other threads:[~2026-03-09 0:37 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-09 0:35 [PATCH v5 00/15] s390x: Add support for virtio-blk-pci IPL device jrossi
2026-03-09 0:35 ` [PATCH v5 01/15] pc-bios/s390-ccw: Fix misattributed function prototypes jrossi
2026-03-09 0:35 ` [PATCH v5 02/15] pc-bios/s390-ccw: Remove redundant vring schid attribute jrossi
2026-03-09 0:35 ` [PATCH v5 03/15] pc-bios/s390-ccw: Always reset virtio device on failed boot attempt jrossi
2026-03-09 0:35 ` [PATCH v5 04/15] s390x: Remove duplicate definitions of IPL types jrossi
2026-03-09 0:35 ` [PATCH v5 05/15] pc-bios/s390-ccw: Store device type independent of sense data jrossi
2026-03-09 0:35 ` [PATCH v5 06/15] pc-bios/s390-ccw: Split virtio-ccw and generic virtio jrossi
2026-03-10 5:28 ` Thomas Huth
2026-03-09 0:35 ` [PATCH v5 07/15] include/hw/s390x: Move CLP definitions for easier BIOS access jrossi
2026-03-09 0:35 ` [PATCH v5 08/15] pc-bios/s390-ccw: Introduce CLP Architecture jrossi
2026-03-09 13:21 ` Matthew Rosato
2026-03-09 17:16 ` Farhan Ali
2026-03-09 0:35 ` [PATCH v5 09/15] s390x: Add definitions for PCI IPL type jrossi
2026-03-09 0:35 ` [PATCH v5 10/15] pc-bios/s390-ccw: Introduce PCI device jrossi
2026-03-09 11:56 ` Thomas Huth
2026-03-09 13:29 ` Matthew Rosato
2026-03-09 17:09 ` Farhan Ali
2026-03-09 0:35 ` jrossi [this message]
2026-03-09 11:59 ` [PATCH v5 11/15] pc-bios/s390-ccw: Introduce virtio-pci functions Thomas Huth
2026-03-09 13:53 ` Matthew Rosato
2026-03-09 22:27 ` Eric Farman
2026-03-09 0:35 ` [PATCH v5 12/15] pc-bios/s390-ccw: Add support for virtio-blk-pci IPL jrossi
2026-03-09 0:35 ` [PATCH v5 13/15] s390x: Build IPLB for virtio-pci devices jrossi
2026-03-09 0:36 ` [PATCH v5 14/15] hw: Add "loadparm" property to virtio block PCI devices booting on s390x jrossi
2026-03-09 0:36 ` [PATCH v5 15/15] tests/qtest: Add s390x PCI boot test to cdrom-test.c jrossi
2026-03-09 16:49 ` Thomas Huth
2026-03-09 16:53 ` Thomas Huth
2026-03-09 17:11 ` Thomas Huth
2026-03-09 18:01 ` Jared Rossi
2026-03-09 14:00 ` [PATCH v5 00/15] s390x: Add support for virtio-blk-pci IPL device Matthew Rosato
2026-03-09 15:40 ` Thomas Huth
2026-03-09 16:17 ` Matthew Rosato
2026-03-23 16:55 ` Thomas Huth
2026-03-24 17:59 ` Jared Rossi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260309003601.242634-12-jrossi@linux.ibm.com \
--to=jrossi@linux.ibm.com \
--cc=alifm@linux.ibm.com \
--cc=farman@linux.ibm.com \
--cc=jjherne@linux.ibm.com \
--cc=mjrosato@linux.ibm.com \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-s390x@nongnu.org \
--cc=thuth@redhat.com \
--cc=zycai@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.