@samitouri / QOSamiQemu / commits / 40d80aedd5

pc-bios/s390-ccw: Introduce virtio-pci functions

Define common functionality for interacting with virtio-pci devices. Signed-off-by: Jared Rossi <jrossi@linux.ibm.com> Acked-by: Matthew Rosato <mjrosato@linux.ibm.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Eric Farman <farman@linux.ibm.com> Message-ID: <20260309003601.242634-12-jrossi@linux.ibm.com> Signed-off-by: Thomas Huth <thuth@redhat.com>

Jared Rossi committed Mar 8, 2026 at 20:35 UTC 40d80aedd5a109a74a22a84c8d17a864f38a791d
4 files changed +251 -1
pc-bios/s390-ccw/Makefile
+1 -1
@@ -35,7 +35,7 @@ QEMU_DGFLAGS = -MMD -MP -MT $@ -MF $(@D)/$(*F).d
35
36 OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o netmain.o \
37 virtio.o virtio-net.o virtio-scsi.o virtio-blkdev.o cio.o dasd-ipl.o \
38 - virtio-ccw.o clp.o pci.o
38 + virtio-ccw.o clp.o pci.o virtio-pci.o
39
40 SLOF_DIR := $(SRC_PATH)/../../roms/SLOF
41
pc-bios/s390-ccw/virtio-pci.c new
+167
@@ -0,0 +1,167 @@
1 +/*
2 + * Functionality for virtio-pci
3 + *
4 + * Copyright 2025 IBM Corp.
5 + * Author(s): Jared Rossi <jrossi@linux.ibm.com>
6 + *
7 + * SPDX-License-Identifier: GPL-2.0-or-later
8 + */
9 +
10 +#include "clp.h"
11 +#include "pci.h"
12 +#include "helper.h"
13 +#include "virtio.h"
14 +#include "bswap.h"
15 +#include "virtio-pci.h"
16 +#include "s390-time.h"
17 +#include <stdio.h>
18 +
19 +/* Variable offsets used for reads/writes to modern memory regions */
20 +VirtioPciCap c_cap; /* Common capabilities */
21 +VirtioPciCap d_cap; /* Device capabilities */
22 +VirtioPciCap n_cap; /* Notify capabilities */
23 +uint32_t notify_mult;
24 +uint16_t q_notify_offset;
25 +
26 +static int virtio_pci_set_status(uint8_t status)
27 +{
28 + int rc = vpci_write_byte(c_cap.off + VPCI_C_OFFSET_STATUS, c_cap.bar, status);
29 + if (rc) {
30 + puts("Failed to write virtio-pci status");
31 + return -EIO;
32 + }
33 +
34 + return 0;
35 +}
36 +
37 +static int virtio_pci_get_status(uint8_t *status)
38 +{
39 + int rc = vpci_read_byte(c_cap.off + VPCI_C_OFFSET_STATUS, c_cap.bar, status);
40 + if (rc) {
41 + puts("Failed to read virtio-pci status");
42 + return -EIO;
43 + }
44 +
45 + return 0;
46 +}
47 +
48 +/* virtio spec v1.3 section 4.1.2.1 */
49 +void virtio_pci_id2type(VDev *vdev, uint16_t device_id)
50 +{
51 + switch (device_id) {
52 + case 0x1042:
53 + case 0x1001:
54 + vdev->dev_type = VIRTIO_ID_BLOCK;
55 + break;
56 + default:
57 + vdev->dev_type = 0;
58 + }
59 +}
60 +
61 +int virtio_pci_reset(VDev *vdev)
62 +{
63 + int rc;
64 + uint8_t status = 0;
65 +
66 + rc = virtio_pci_set_status(status);
67 + rc |= virtio_pci_get_status(&status);
68 +
69 + if (rc || status) {
70 + puts("Failed to reset virtio-pci device");
71 + return 1;
72 + }
73 +
74 + return 0;
75 +}
76 +
77 +long virtio_pci_notify(int vq_id)
78 +{
79 + uint32_t offset = n_cap.off + notify_mult * q_notify_offset;
80 + return vpci_bswap16_write(offset, n_cap.bar, (uint16_t) vq_id);
81 +}
82 +
83 +/*
84 + * Wrappers to byte swap common data sizes then write
85 + */
86 +int vpci_write_byte(uint64_t offset, uint8_t pcias, uint8_t data)
87 +{
88 + return pci_write(virtio_get_device()->pci_fh, offset, pcias, (uint64_t) data, 1);
89 +}
90 +
91 +int vpci_bswap16_write(uint64_t offset, uint8_t pcias, uint16_t data)
92 +{
93 + uint64_t le_data = bswap16(data);
94 + return pci_write(virtio_get_device()->pci_fh, offset, pcias, le_data, 2);
95 +}
96 +
97 +int vpci_bswap32_write(uint64_t offset, uint8_t pcias, uint32_t data)
98 +{
99 + uint64_t le_data = bswap32(data);
100 + return pci_write(virtio_get_device()->pci_fh, offset, pcias, le_data, 4);
101 +}
102 +
103 +int vpci_bswap64_write(uint64_t offset, uint8_t pcias, uint64_t data)
104 +{
105 + uint64_t le_data = bswap64(data);
106 + return pci_write(virtio_get_device()->pci_fh, offset, pcias, le_data, 8);
107 +}
108 +
109 +/*
110 + * Wrappers to read common data sizes then byte swap
111 + */
112 +int vpci_read_byte(uint64_t offset, uint8_t pcias, uint8_t *buf)
113 +{
114 + return pci_read(virtio_get_device()->pci_fh, offset, pcias, buf, 1);
115 +}
116 +
117 +int vpci_read_bswap16(uint64_t offset, uint8_t pcias, uint16_t *buf)
118 +{
119 + int rc = pci_read(virtio_get_device()->pci_fh, offset, pcias, buf, 2);
120 + *buf = bswap16(*buf);
121 + return rc;
122 +}
123 +
124 +int vpci_read_bswap32(uint64_t offset, uint8_t pcias, uint32_t *buf)
125 +{
126 + int rc = pci_read(virtio_get_device()->pci_fh, offset, pcias, buf, 4);
127 + *buf = bswap32(*buf);
128 + return rc;
129 +}
130 +
131 +int vpci_read_bswap64(uint64_t offset, uint8_t pcias, uint64_t *buf)
132 +{
133 + int rc = pci_read(virtio_get_device()->pci_fh, offset, pcias, buf, 8);
134 + *buf = bswap64(*buf);
135 + return rc;
136 +}
137 +
138 +/*
139 + * Read to an arbitrary length buffer without byte swapping
140 + */
141 +int vpci_read_flex(uint64_t offset, uint8_t pcias, void *buf, int len)
142 +{
143 + uint8_t readlen;
144 + int rc;
145 + int remaining = len;
146 +
147 + /* Read bytes in powers of 2, up to a maximum of 8 bytes per read */
148 + while (remaining) {
149 + for (int i = 3; i >= 0; i--) {
150 + readlen = 1 << i;
151 + if (remaining >= readlen) {
152 + break;
153 + }
154 + }
155 +
156 + rc = pci_read(virtio_get_device()->pci_fh, offset, pcias, buf, readlen);
157 + if (rc) {
158 + return -1;
159 + }
160 +
161 + remaining -= readlen;
162 + buf += readlen;
163 + offset += readlen;
164 + }
165 +
166 + return 0;
167 +}
pc-bios/s390-ccw/virtio-pci.h new
+80
@@ -0,0 +1,80 @@
1 +/*
2 + * Definitions for virtio-pci
3 + *
4 + * Copyright 2025 IBM Corp.
5 + * Author(s): Jared Rossi <jrossi@linux.ibm.com>
6 + *
7 + * SPDX-License-Identifier: GPL-2.0-or-later
8 + */
9 +
10 +#ifndef VIRTIO_PCI_H
11 +#define VIRTIO_PCI_H
12 +
13 +/* Common configuration */
14 +#define VPCI_CAP_COMMON_CFG 1
15 +/* Notifications */
16 +#define VPCI_CAP_NOTIFY_CFG 2
17 +/* ISR access */
18 +#define VPCI_CAP_ISR_CFG 3
19 +/* Device specific configuration */
20 +#define VPCI_CAP_DEVICE_CFG 4
21 +/* PCI configuration access */
22 +#define VPCI_CAP_PCI_CFG 5
23 +/* Additional shared memory capability */
24 +#define VPCI_CAP_SHARED_MEMORY_CFG 8
25 +/* PCI vendor data configuration */
26 +#define VPCI_CAP_VENDOR_CFG 9
27 +
28 +/* Offsets within capability header */
29 +#define VPCI_CAP_VNDR 0
30 +#define VPCI_CAP_NEXT 1
31 +#define VPCI_CAP_LEN 2
32 +#define VPCI_CAP_CFG_TYPE 3
33 +#define VPCI_CAP_BAR 4
34 +#define VPCI_CAP_OFFSET 8
35 +#define VPCI_CAP_LENGTH 12
36 +
37 +#define VPCI_N_CAP_MULT 16 /* Notify multiplier, VPCI_CAP_NOTIFY_CFG only */
38 +
39 +/* Common Area Offsets for virtio-pci queue */
40 +#define VPCI_C_OFFSET_DFSELECT 0
41 +#define VPCI_C_OFFSET_DF 4
42 +#define VPCI_C_OFFSET_GFSELECT 8
43 +#define VPCI_C_OFFSET_GF 12
44 +#define VPCI_C_COMMON_NUMQ 18
45 +#define VPCI_C_OFFSET_STATUS 20
46 +#define VPCI_C_OFFSET_Q_SELECT 22
47 +#define VPCI_C_OFFSET_Q_SIZE 24
48 +#define VPCI_C_OFFSET_Q_ENABLE 28
49 +#define VPCI_C_OFFSET_Q_NOFF 30
50 +#define VPCI_C_OFFSET_Q_DESCLO 32
51 +#define VPCI_C_OFFSET_Q_DESCHI 36
52 +#define VPCI_C_OFFSET_Q_AVAILLO 40
53 +#define VPCI_C_OFFSET_Q_AVAILHI 44
54 +#define VPCI_C_OFFSET_Q_USEDLO 48
55 +#define VPCI_C_OFFSET_Q_USEDHI 52
56 +
57 +#define VIRTIO_F_VERSION_1 1 /* Feature bit 32 */
58 +
59 +struct VirtioPciCap {
60 + uint8_t bar; /* Which PCIAS it's in */
61 + uint32_t off; /* Offset within bar */
62 +};
63 +typedef struct VirtioPciCap VirtioPciCap;
64 +
65 +void virtio_pci_id2type(VDev *vdev, uint16_t device_id);
66 +int virtio_pci_reset(VDev *vdev);
67 +long virtio_pci_notify(int vq_id);
68 +
69 +int vpci_read_flex(uint64_t offset, uint8_t pcias, void *buf, int len);
70 +int vpci_read_bswap64(uint64_t offset, uint8_t pcias, uint64_t *buf);
71 +int vpci_read_bswap32(uint64_t offset, uint8_t pcias, uint32_t *buf);
72 +int vpci_read_bswap16(uint64_t offset, uint8_t pcias, uint16_t *buf);
73 +int vpci_read_byte(uint64_t offset, uint8_t pcias, uint8_t *buf);
74 +
75 +int vpci_bswap64_write(uint64_t offset, uint8_t pcias, uint64_t data);
76 +int vpci_bswap32_write(uint64_t offset, uint8_t pcias, uint32_t data);
77 +int vpci_bswap16_write(uint64_t offset, uint8_t pcias, uint16_t data);
78 +int vpci_write_byte(uint64_t offset, uint8_t pcias, uint8_t data);
79 +
80 +#endif
pc-bios/s390-ccw/virtio.h
+3
@@ -18,6 +18,8 @@
18 #define VIRTIO_CONFIG_S_DRIVER 2
19 /* Driver has used its parts of the config, and is happy */
20 #define VIRTIO_CONFIG_S_DRIVER_OK 4
21 +/* Feature negotiation complete */
22 +#define VIRTIO_CONFIG_S_FEATURES_OK 8
23 /* We've given up on this device. */
24 #define VIRTIO_CONFIG_S_FAILED 0x80
25
@@ -255,6 +257,7 @@ struct VDev {
257 uint8_t scsi_dev_heads;
258 bool scsi_device_selected;
259 ScsiDevice selected_scsi_device;
260 + uint32_t pci_fh;
261 uint32_t max_transfer;
262 uint32_t guest_features[2];
263 };