* [PATCH v2 0/7] s390x: Add support for virtio-net-pci boot device
@ 2026-09-03 16:24 Zhuoying Cai
2026-09-03 16:24 ` [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw Zhuoying Cai
` (6 more replies)
0 siblings, 7 replies; 19+ messages in thread
From: Zhuoying Cai @ 2026-09-03 16:24 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, jdaley, pbonzini
changlog v1->v2
pc-bios/s390-ccw: Move CCW net setup to virtio-ccw
- Removed the virtio_net_setup() dispatcher; netmain.c now calls
virtio_ccw_net_setup() directly
- Improved the error message to be CCW-specific
pc-bios/s390-ccw: Add dynamic net header size handling
- Defined VirtioNetHdrMrgRxbuf, which includes VirtioNetHdr and a
num_buffers field
- Defined header size constants using the sizeof() each struct
pc-bios/s390-ccw: Introduce virtio_tswap helpers
- Edited the commit message to mention that only 16-bit helper function
is used in this commit
- Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
- Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
pc-bios/s390-ccw: Add support for virtio-net-pci IPL
- Updated the commit message to change "adds" to "extends" when
describing endianness handling
- Removed net specific setup/find for PCI device
- Checked for virtio initialization failures during network device
initialization
hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x
- Edited the commit message to avoid implying that PCI netboot will fail
if a valid loadparm is not provided.
tests/qtest: Add s390x virtio net PCI test to pxe-test.c
tests/functional/s390x: Add tests for virtio net PCI in test_pxelinux.py
- Tested-by: Joshua Daley <jdaley@linux.ibm.com>
----------------------------------------------------------------------
This series enables network booting via virtio-net-pci on s390x.
Refactor virtio-net to separate virtio-ccw specific logic and add
support for booting from virtio-net-pci devices with proper endianness
handling. Add support for the loadparm property during network boot.
Add corresponding test coverage to verify correct network boot
functionality with virtio-net-pci devices.
Zhuoying Cai (7):
pc-bios/s390-ccw: Move CCW net setup to virtio-ccw
pc-bios/s390-ccw: Add dynamic net header size handling
pc-bios/s390-ccw: Introduce virtio_tswap helpers
pc-bios/s390-ccw: Add support for virtio-net-pci IPL
hw/virtio: Add "loadparm" property to virtio net PCI devices booting
on s390x
tests/qtest: Add s390x virtio net PCI test to pxe-test.c
tests/functional/s390x: Add tests for virtio net PCI in
test_pxelinux.py
hw/virtio/virtio-net-pci.c | 1 +
pc-bios/s390-ccw/main.c | 1 +
pc-bios/s390-ccw/netmain.c | 74 ++++---------------------
pc-bios/s390-ccw/virtio-ccw.c | 62 +++++++++++++++++++++
pc-bios/s390-ccw/virtio-ccw.h | 1 +
pc-bios/s390-ccw/virtio-net.c | 67 ++++++++++++++++++----
pc-bios/s390-ccw/virtio-pci.c | 18 ++++++
pc-bios/s390-ccw/virtio.c | 27 +++++++--
pc-bios/s390-ccw/virtio.h | 4 ++
tests/functional/s390x/test_pxelinux.py | 71 ++++++++++++++++++++----
tests/qtest/meson.build | 1 +
tests/qtest/pxe-test.c | 1 +
12 files changed, 234 insertions(+), 94 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw
2026-09-03 16:24 [PATCH v2 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
@ 2026-09-03 16:24 ` Zhuoying Cai
2026-09-09 12:49 ` Jason J. Herne
` (2 more replies)
2026-09-03 16:24 ` [PATCH v2 2/7] pc-bios/s390-ccw: Add dynamic net header size handling Zhuoying Cai
` (5 subsequent siblings)
6 siblings, 3 replies; 19+ messages in thread
From: Zhuoying Cai @ 2026-09-03 16:24 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, jdaley, pbonzini
Move CCW-specific virtio_setup() and find_net_dev() to virtio-ccw.c
to decouple the generic net boot logic from the CCW transport.
Also update the error message on failure to specify "ccw net device".
Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
---
pc-bios/s390-ccw/netmain.c | 67 ++---------------------------------
pc-bios/s390-ccw/virtio-ccw.c | 62 ++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/virtio-ccw.h | 1 +
3 files changed, 66 insertions(+), 64 deletions(-)
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index ccd1c30013..bcb62bf6ca 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -35,6 +35,7 @@
#include "s390-ccw.h"
#include "cio.h"
#include "virtio.h"
+#include "virtio-ccw.h"
#include "s390-time.h"
#define DEFAULT_BOOT_RETRIES 10
@@ -489,68 +490,6 @@ static int net_try_direct_tftp_load(filename_ip_t *fn_ip)
return rc;
}
-static bool find_net_dev(Schib *schib, int dev_no)
-{
- int i, r;
-
- for (i = 0; i < 0x10000; i++) {
- net_schid.sch_no = i;
- r = stsch_err(net_schid, schib);
- if (r == 3 || r == -EIO) {
- break;
- }
- if (!schib->pmcw.dnv) {
- continue;
- }
- enable_subchannel(net_schid);
- if (!virtio_is_supported(virtio_get_device())) {
- continue;
- }
- if (virtio_get_device_type() != VIRTIO_ID_NET) {
- continue;
- }
- if (dev_no < 0 || schib->pmcw.dev == dev_no) {
- return true;
- }
- }
-
- return false;
-}
-
-static bool virtio_setup(void)
-{
- Schib schib;
- int ssid;
- bool found = false;
- uint16_t dev_no;
-
- /*
- * We unconditionally enable mss support. In every sane configuration,
- * this will succeed; and even if it doesn't, stsch_err() can deal
- * with the consequences.
- */
- enable_mss_facility();
-
- if (have_iplb || store_iplb(iplb)) {
- IPL_assert(iplb->pbt == S390_IPL_TYPE_CCW, "IPL_TYPE_CCW expected");
- dev_no = iplb->ccw.devno;
- debug_print_int("device no. ", dev_no);
- net_schid.ssid = iplb->ccw.ssid & 0x3;
- debug_print_int("ssid ", net_schid.ssid);
- found = find_net_dev(&schib, dev_no);
- } else {
- for (ssid = 0; ssid < 0x3; ssid++) {
- net_schid.ssid = ssid;
- found = find_net_dev(&schib, -1);
- if (found) {
- break;
- }
- }
- }
-
- return found;
-}
-
int netmain(void)
{
filename_ip_t fn_ip;
@@ -559,8 +498,8 @@ int netmain(void)
sclp_setup();
puts("Network boot starting...");
- if (!virtio_setup()) {
- puts("No virtio net device found.");
+ if (!virtio_ccw_net_setup()) {
+ puts("No valid virtio ccw net device found.");
return -1;
}
diff --git a/pc-bios/s390-ccw/virtio-ccw.c b/pc-bios/s390-ccw/virtio-ccw.c
index 5cb2158ed2..5bf67738e4 100644
--- a/pc-bios/s390-ccw/virtio-ccw.c
+++ b/pc-bios/s390-ccw/virtio-ccw.c
@@ -237,3 +237,65 @@ int virtio_ccw_setup(VDev *vdev)
return 0;
}
+
+static bool find_ccw_net_dev(Schib *schib, int dev_no)
+{
+ int i, r;
+
+ for (i = 0; i < 0x10000; i++) {
+ net_schid.sch_no = i;
+ r = stsch_err(net_schid, schib);
+ if (r == 3 || r == -EIO) {
+ break;
+ }
+ if (!schib->pmcw.dnv) {
+ continue;
+ }
+ enable_subchannel(net_schid);
+ if (!virtio_is_supported(virtio_get_device())) {
+ continue;
+ }
+ if (virtio_get_device_type() != VIRTIO_ID_NET) {
+ continue;
+ }
+ if (dev_no < 0 || schib->pmcw.dev == dev_no) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool virtio_ccw_net_setup(void)
+{
+ Schib schib;
+ int ssid;
+ bool found = false;
+ uint16_t dev_no;
+
+ /*
+ * We unconditionally enable mss support. In every sane configuration,
+ * this will succeed; and even if it doesn't, stsch_err() can deal
+ * with the consequences.
+ */
+ enable_mss_facility();
+
+ if (have_iplb || store_iplb(iplb)) {
+ IPL_assert(iplb->pbt == S390_IPL_TYPE_CCW, "IPL_TYPE_CCW expected");
+ dev_no = iplb->ccw.devno;
+ debug_print_int("device no. ", dev_no);
+ net_schid.ssid = iplb->ccw.ssid & 0x3;
+ debug_print_int("ssid ", net_schid.ssid);
+ found = find_ccw_net_dev(&schib, dev_no);
+ } else {
+ for (ssid = 0; ssid < 0x3; ssid++) {
+ net_schid.ssid = ssid;
+ found = find_ccw_net_dev(&schib, -1);
+ if (found) {
+ break;
+ }
+ }
+ }
+
+ return found;
+}
diff --git a/pc-bios/s390-ccw/virtio-ccw.h b/pc-bios/s390-ccw/virtio-ccw.h
index a506767eaa..c330e02f99 100644
--- a/pc-bios/s390-ccw/virtio-ccw.h
+++ b/pc-bios/s390-ccw/virtio-ccw.h
@@ -20,5 +20,6 @@ int virtio_ccw_run(VDev *vdev, int vqid, VirtioCmd *cmd);
long virtio_ccw_notify(SubChannelId schid, int vq_idx, long cookie);
int virtio_ccw_setup(VDev *vdev);
int virtio_ccw_reset(VDev *vdev);
+bool virtio_ccw_net_setup(void);
#endif
--
2.55.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 2/7] pc-bios/s390-ccw: Add dynamic net header size handling
2026-09-03 16:24 [PATCH v2 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
2026-09-03 16:24 ` [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw Zhuoying Cai
@ 2026-09-03 16:24 ` Zhuoying Cai
2026-09-08 18:32 ` Jared Rossi
2026-09-09 15:08 ` Matthew Rosato
2026-09-03 16:24 ` [PATCH v2 3/7] pc-bios/s390-ccw: Introduce virtio_tswap helpers Zhuoying Cai
` (4 subsequent siblings)
6 siblings, 2 replies; 19+ messages in thread
From: Zhuoying Cai @ 2026-09-03 16:24 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, jdaley, pbonzini
The virtio-net device used a fixed header size that did not account for
the num_buffers field used in VirtIO 1.0 or for the mergeable receive
buffers feature.
Use dynamic header sizing: 10 bytes for legacy mode and 12 bytes for
VirtIO 1.0 or when VIRTIO_NET_F_MRG_RXBUF is enabled. This ensures
correct packet handling across different VirtIO configurations.
Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
---
pc-bios/s390-ccw/virtio-net.c | 30 ++++++++++++++++++++++++------
1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c
index f58f7ffc55..afa728bc32 100644
--- a/pc-bios/s390-ccw/virtio-net.c
+++ b/pc-bios/s390-ccw/virtio-net.c
@@ -20,6 +20,7 @@
#include "s390-ccw.h"
#include "virtio.h"
#include "virtio-ccw.h"
+#include "virtio-pci.h"
#include "s390-time.h"
#include "helper.h"
@@ -28,6 +29,7 @@
#endif
#define VIRTIO_NET_F_MAC_BIT (1 << 5)
+#define VIRTIO_NET_F_MRG_RXBUF_BIT (1 << 15)
#define VQ_RX 0 /* Receive queue */
#define VQ_TX 1 /* Transmit queue */
@@ -43,7 +45,18 @@ struct VirtioNetHdr {
};
typedef struct VirtioNetHdr VirtioNetHdr;
+struct VirtioNetHdrMrgRxbuf {
+ struct VirtioNetHdr hdr;
+ uint16_t num_buffers; /* Only with VIRTIO_NET_F_MRG_RXBUF or VIRTIO1 */
+};
+typedef struct VirtioNetHdrMrgRxbuf VirtioNetHdrMrgRxbuf;
+
+/* Header sizes for different modes */
+#define VIRTIO_NET_HDR_SIZE_LEGACY sizeof(VirtioNetHdr)
+#define VIRTIO_NET_HDR_SIZE_V1 sizeof(VirtioNetHdrMrgRxbuf)
+
static uint16_t rx_last_idx; /* Last index in receive queue "used" ring */
+static int virtio_net_hdr_size;
int virtio_net_init(void *mac_addr)
{
@@ -62,12 +75,17 @@ int virtio_net_init(void *mac_addr)
return -1;
}
+ virtio_net_hdr_size = ((vdev->guest_features[1] & VIRTIO_F_VERSION_1) ||
+ (vdev->guest_features[0] & VIRTIO_NET_F_MRG_RXBUF_BIT))
+ ? VIRTIO_NET_HDR_SIZE_V1
+ : VIRTIO_NET_HDR_SIZE_LEGACY;
+
memcpy(mac_addr, vdev->config.net.mac, ETH_ALEN);
for (i = 0; i < 64; i++) {
- buf = malloc(ETH_MTU_SIZE + sizeof(VirtioNetHdr));
+ buf = malloc(ETH_MTU_SIZE + virtio_net_hdr_size);
IPL_assert(buf != NULL, "Can not allocate memory for receive buffers");
- vring_send_buf(rxvq, buf, ETH_MTU_SIZE + sizeof(VirtioNetHdr),
+ vring_send_buf(rxvq, buf, ETH_MTU_SIZE + virtio_net_hdr_size,
VRING_DESC_F_WRITE);
}
vring_notify(rxvq);
@@ -77,14 +95,14 @@ int virtio_net_init(void *mac_addr)
int send(int fd, const void *buf, int len, int flags)
{
- VirtioNetHdr tx_hdr;
+ VirtioNetHdrMrgRxbuf tx_hdr;
VDev *vdev = virtio_get_device();
VRing *txvq = &vdev->vrings[VQ_TX];
/* Set up header - we do not use anything special, so simply clear it */
memset(&tx_hdr, 0, sizeof(tx_hdr));
- vring_send_buf(txvq, &tx_hdr, sizeof(tx_hdr), VRING_DESC_F_NEXT);
+ vring_send_buf(txvq, &tx_hdr, virtio_net_hdr_size, VRING_DESC_F_NEXT);
vring_send_buf(txvq, (void *)buf, len, VRING_HIDDEN_IS_CHAIN);
while (!vr_poll(txvq)) {
yield();
@@ -108,13 +126,13 @@ int recv(int fd, void *buf, int maxlen, int flags)
return 0;
}
- len = rxvq->used->ring[rx_last_idx % rxvq->num].len - sizeof(VirtioNetHdr);
+ len = rxvq->used->ring[rx_last_idx % rxvq->num].len - virtio_net_hdr_size;
if (len > maxlen) {
puts("virtio-net: Receive buffer too small");
len = maxlen;
}
id = rxvq->used->ring[rx_last_idx % rxvq->num].id % rxvq->num;
- pkt = (uint8_t *)(rxvq->desc[id].addr + sizeof(VirtioNetHdr));
+ pkt = (uint8_t *)(rxvq->desc[id].addr + virtio_net_hdr_size);
#if DEBUG_VIRTIO_NET /* Dump packet */
int i;
--
2.55.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 3/7] pc-bios/s390-ccw: Introduce virtio_tswap helpers
2026-09-03 16:24 [PATCH v2 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
2026-09-03 16:24 ` [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw Zhuoying Cai
2026-09-03 16:24 ` [PATCH v2 2/7] pc-bios/s390-ccw: Add dynamic net header size handling Zhuoying Cai
@ 2026-09-03 16:24 ` Zhuoying Cai
2026-09-11 15:19 ` Jared Rossi
2026-09-03 16:24 ` [PATCH v2 4/7] pc-bios/s390-ccw: Add support for virtio-net-pci IPL Zhuoying Cai
` (3 subsequent siblings)
6 siblings, 1 reply; 19+ messages in thread
From: Zhuoying Cai @ 2026-09-03 16:24 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, jdaley, pbonzini
Replace the repeated pattern:
be_ipl() ? x : bswapN(x)
with helpers that conditionally byte-swap based on the virtio transport
endianness.
While only the 16-bit helper is used immediately, the 32-bit and 64-bit
variants are added here for later use.
Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
---
pc-bios/s390-ccw/virtio.c | 27 +++++++++++++++++++++------
pc-bios/s390-ccw/virtio.h | 4 ++++
2 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index a0d249db24..037c00a3e1 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -97,7 +97,7 @@ void vring_init(VRing *vr, VqInfo *info)
vr->avail->idx = 0;
/* We're running with interrupts off anyways, so don't bother */
- vr->used->flags = be_ipl() ? VRING_USED_F_NO_NOTIFY : bswap16(VRING_USED_F_NO_NOTIFY);
+ vr->used->flags = virtio_tswap16(VRING_USED_F_NO_NOTIFY);
vr->used->idx = 0;
vr->used_idx = 0;
vr->next_idx = 0;
@@ -140,6 +140,22 @@ bool be_ipl(void)
}
}
+/* Conditionally byte-swap between virtio-endian and s390x native big-endian. */
+uint16_t virtio_tswap16(uint16_t x)
+{
+ return be_ipl() ? x : bswap16(x);
+}
+
+uint32_t virtio_tswap32(uint32_t x)
+{
+ return be_ipl() ? x : bswap32(x);
+}
+
+uint64_t virtio_tswap64(uint64_t x)
+{
+ return be_ipl() ? x : bswap64(x);
+}
+
/*
* Format the virtio ring descriptor endianness
* Return the available index increment in the appropriate endianness
@@ -156,12 +172,11 @@ void vring_send_buf(VRing *vr, void *p, int len, int flags)
{
uint16_t avail_idx;
- avail_idx = be_ipl() ? vr->avail->idx : bswap16(vr->avail->idx);
+ avail_idx = virtio_tswap16(vr->avail->idx);
/* For follow-up chains we need to keep the first entry point */
if (!(flags & VRING_HIDDEN_IS_CHAIN)) {
- vr->avail->ring[avail_idx % vr->num] = be_ipl() ? vr->next_idx :
- bswap16(vr->next_idx);
+ vr->avail->ring[avail_idx % vr->num] = virtio_tswap16(vr->next_idx);
}
vr->desc[vr->next_idx].addr = (unsigned long)p;
@@ -179,7 +194,7 @@ void vring_send_buf(VRing *vr, void *p, int len, int flags)
/* Chains only have a single ID */
if (!(flags & VRING_DESC_F_NEXT)) {
avail_idx++;
- vr->avail->idx = be_ipl() ? avail_idx : bswap16(avail_idx);
+ vr->avail->idx = virtio_tswap16(avail_idx);
}
}
@@ -187,7 +202,7 @@ int vr_poll(VRing *vr)
{
uint16_t used_idx;
- used_idx = be_ipl() ? vr->used->idx : bswap16(vr->used->idx);
+ used_idx = virtio_tswap16(vr->used->idx);
if (used_idx == vr->used_idx) {
vring_notify(vr);
yield();
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
index aa307025e0..645dc288b1 100644
--- a/pc-bios/s390-ccw/virtio.h
+++ b/pc-bios/s390-ccw/virtio.h
@@ -287,6 +287,10 @@ int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd);
int virtio_reset(VDev *vdev);
int virtio_setup_ccw(VDev *vdev);
+uint16_t virtio_tswap16(uint16_t x);
+uint32_t virtio_tswap32(uint32_t x);
+uint64_t virtio_tswap64(uint64_t x);
+
/* virtio-net.c */
int virtio_net_init(void *mac_addr);
void virtio_net_deinit(void);
--
2.55.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 4/7] pc-bios/s390-ccw: Add support for virtio-net-pci IPL
2026-09-03 16:24 [PATCH v2 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
` (2 preceding siblings ...)
2026-09-03 16:24 ` [PATCH v2 3/7] pc-bios/s390-ccw: Introduce virtio_tswap helpers Zhuoying Cai
@ 2026-09-03 16:24 ` Zhuoying Cai
2026-09-09 13:28 ` Jason J. Herne
2026-09-03 16:24 ` [PATCH v2 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x Zhuoying Cai
` (2 subsequent siblings)
6 siblings, 1 reply; 19+ messages in thread
From: Zhuoying Cai @ 2026-09-03 16:24 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, jdaley, pbonzini
Enable network booting via virtio-net-pci by implementing PCI transport
support for virtio-net.
This patch also extends endianness handling for virtio PCI ring operations in
little-endian to ensure correct behavior on s390x.
Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
---
pc-bios/s390-ccw/main.c | 1 +
pc-bios/s390-ccw/netmain.c | 9 +++++++-
pc-bios/s390-ccw/virtio-net.c | 41 ++++++++++++++++++++++++++++-------
pc-bios/s390-ccw/virtio-pci.c | 18 +++++++++++++++
4 files changed, 60 insertions(+), 9 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 8fc1cbf653..28cab3b411 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -332,6 +332,7 @@ static void ipl_pci_device(void)
}
switch (vdev->dev_type) {
+ case VIRTIO_ID_NET:
case VIRTIO_ID_BLOCK:
if (virtio_setup() == 0) {
zipl_load(); /* only return on error */
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index bcb62bf6ca..e42e049063 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -498,7 +498,14 @@ int netmain(void)
sclp_setup();
puts("Network boot starting...");
- if (!virtio_ccw_net_setup()) {
+ /*
+ * CCW devices require subchannel enumeration here.
+ * PCI devices don't require specific setup: the transport is already
+ * initialized by ipl_pci_device(), and virtio_is_supported() is checked
+ * later in virtio_net_init().
+ */
+ if (virtio_get_device()->ipl_type == S390_IPL_TYPE_CCW &&
+ !virtio_ccw_net_setup()) {
puts("No valid virtio ccw net device found.");
return -1;
}
diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c
index afa728bc32..418759565d 100644
--- a/pc-bios/s390-ccw/virtio-net.c
+++ b/pc-bios/s390-ccw/virtio-net.c
@@ -68,7 +68,22 @@ int virtio_net_init(void *mac_addr)
rx_last_idx = 0;
vdev->guest_features[0] = VIRTIO_NET_F_MAC_BIT;
- virtio_ccw_setup(vdev);
+ switch (virtio_get_device()->ipl_type) {
+ case S390_IPL_TYPE_CCW:
+ if (virtio_ccw_setup(vdev)) {
+ puts("Setup failed for virtio-net-ccw");
+ return -1;
+ }
+ break;
+ case S390_IPL_TYPE_PCI:
+ if (virtio_pci_setup(vdev)) {
+ puts("Setup failed for virtio-net-pci");
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
if (!(vdev->guest_features[0] & VIRTIO_NET_F_MAC_BIT)) {
puts("virtio-net device does not support the MAC address feature");
@@ -121,22 +136,30 @@ int recv(int fd, void *buf, int maxlen, int flags)
VRing *rxvq = &vdev->vrings[VQ_RX];
int len, id;
uint8_t *pkt;
+ uint16_t rx_used_idx, rx_avail_idx;
+ uint32_t rx_used_len, rx_used_id;
+ uint64_t rx_desc_addr;
- if (rx_last_idx == rxvq->used->idx) {
+ rx_used_idx = virtio_tswap16(rxvq->used->idx);
+ if (rx_last_idx == rx_used_idx) {
return 0;
}
- len = rxvq->used->ring[rx_last_idx % rxvq->num].len - virtio_net_hdr_size;
+ rx_used_len = virtio_tswap32(rxvq->used->ring[rx_last_idx % rxvq->num].len);
+ rx_used_id = virtio_tswap32(rxvq->used->ring[rx_last_idx % rxvq->num].id);
+
+ len = rx_used_len - virtio_net_hdr_size;
if (len > maxlen) {
puts("virtio-net: Receive buffer too small");
len = maxlen;
}
- id = rxvq->used->ring[rx_last_idx % rxvq->num].id % rxvq->num;
- pkt = (uint8_t *)(rxvq->desc[id].addr + virtio_net_hdr_size);
+ id = rx_used_id % rxvq->num;
+ rx_desc_addr = virtio_tswap64(rxvq->desc[id].addr);
+ pkt = (uint8_t *)(rx_desc_addr + virtio_net_hdr_size);
#if DEBUG_VIRTIO_NET /* Dump packet */
int i;
- printf("\nbuf %p: len=%i\n", (void *)rxvq->desc[id].addr, len);
+ printf("\nbuf %p: len=%i\n", (void *)rx_desc_addr, len);
for (i = 0; i < 64; i++) {
printf(" %02x", pkt[i]);
if ((i % 16) == 15) {
@@ -150,8 +173,10 @@ int recv(int fd, void *buf, int maxlen, int flags)
memcpy(buf, pkt, len);
/* Mark buffer as available to the host again */
- rxvq->avail->ring[rxvq->avail->idx % rxvq->num] = id;
- rxvq->avail->idx = rxvq->avail->idx + 1;
+ rx_avail_idx = virtio_tswap16(rxvq->avail->idx);
+ rxvq->avail->ring[rx_avail_idx % rxvq->num] = virtio_tswap16(id);
+ rx_avail_idx++;
+ rxvq->avail->idx = virtio_tswap16(rx_avail_idx);
vring_notify(rxvq);
/* Move index to next entry */
diff --git a/pc-bios/s390-ccw/virtio-pci.c b/pc-bios/s390-ccw/virtio-pci.c
index f501252c81..147a82895f 100644
--- a/pc-bios/s390-ccw/virtio-pci.c
+++ b/pc-bios/s390-ccw/virtio-pci.c
@@ -52,6 +52,10 @@ void virtio_pci_id2type(VDev *vdev, uint16_t device_id)
case 0x1001:
vdev->dev_type = VIRTIO_ID_BLOCK;
break;
+ case 0x1041:
+ case 0x1000:
+ vdev->dev_type = VIRTIO_ID_NET;
+ break;
default:
vdev->dev_type = 0;
}
@@ -199,6 +203,14 @@ static int virtio_pci_get_blk_config(void)
return rc;
}
+static int virtio_pci_get_net_config(void)
+{
+ VirtioNetConfig *cfg = &virtio_get_device()->config.net;
+ int rc = vpci_read_flex(d_cap.off, d_cap.bar, cfg, sizeof(VirtioNetConfig));
+
+ return rc;
+}
+
static int virtio_pci_negotiate(void)
{
int i, rc;
@@ -330,6 +342,7 @@ bool virtio_pci_is_supported(VDev *vdev)
if (vdev->vendor_id == PCI_VENDOR_VIRTIO) {
switch (vdev->dev_type) {
case VIRTIO_ID_BLOCK:
+ case VIRTIO_ID_NET:
return true;
default:
return false;
@@ -384,6 +397,11 @@ int virtio_pci_setup(VDev *vdev)
vdev->cmd_vr_idx = 0;
virtio_pci_get_blk_config();
break;
+ case VIRTIO_ID_NET:
+ vdev->nr_vqs = 2;
+ vdev->cmd_vr_idx = 0;
+ virtio_pci_get_net_config();
+ break;
default:
puts("Unsupported virtio device");
return -ENODEV;
--
2.55.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x
2026-09-03 16:24 [PATCH v2 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
` (3 preceding siblings ...)
2026-09-03 16:24 ` [PATCH v2 4/7] pc-bios/s390-ccw: Add support for virtio-net-pci IPL Zhuoying Cai
@ 2026-09-03 16:24 ` Zhuoying Cai
2026-09-09 13:30 ` Jason J. Herne
2026-09-11 15:17 ` Jared Rossi
2026-09-03 16:24 ` [PATCH v2 6/7] tests/qtest: Add s390x virtio net PCI test to pxe-test.c Zhuoying Cai
2026-09-03 16:24 ` [PATCH v2 7/7] tests/functional/s390x: Add tests for virtio net PCI in test_pxelinux.py Zhuoying Cai
6 siblings, 2 replies; 19+ messages in thread
From: Zhuoying Cai @ 2026-09-03 16:24 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, jdaley, pbonzini
Add optional loadparm property to virtio-net-pci to allow boot entry
selection on s390x, consistent with virtio-blk-pci.
Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
---
hw/virtio/virtio-net-pci.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c
index fd3e0303f5..893d1905a9 100644
--- a/hw/virtio/virtio-net-pci.c
+++ b/hw/virtio/virtio-net-pci.c
@@ -77,6 +77,7 @@ static void virtio_net_pci_class_init(ObjectClass *klass, const void *data)
k->sriov_vf_user_creatable = true;
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
device_class_set_props(dc, virtio_net_properties);
+ pci_qdev_property_add_specifics(dc);
vpciklass->realize = virtio_net_pci_realize;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 6/7] tests/qtest: Add s390x virtio net PCI test to pxe-test.c
2026-09-03 16:24 [PATCH v2 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
` (4 preceding siblings ...)
2026-09-03 16:24 ` [PATCH v2 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x Zhuoying Cai
@ 2026-09-03 16:24 ` Zhuoying Cai
2026-09-11 15:36 ` Matthew Rosato
2026-09-03 16:24 ` [PATCH v2 7/7] tests/functional/s390x: Add tests for virtio net PCI in test_pxelinux.py Zhuoying Cai
6 siblings, 1 reply; 19+ messages in thread
From: Zhuoying Cai @ 2026-09-03 16:24 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, jdaley, pbonzini
Add test coverage for virtio-net-pci network booting on s390x by
including it in the PXE test suite. The test verifies that PXE
network booting works correctly with virtio-net-pci devices.
Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
Tested-by: Joshua Daley <jdaley@linux.ibm.com>
---
tests/qtest/meson.build | 1 +
tests/qtest/pxe-test.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 50a1a5272f..654e145fbe 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -289,6 +289,7 @@ qtests_aarch64 = \
'migration-test']
qtests_s390x = \
+ (slirp.found() ? ['pxe-test'] : []) + \
qtests_filter + \
['boot-serial-test',
'drive_del-test',
diff --git a/tests/qtest/pxe-test.c b/tests/qtest/pxe-test.c
index e85dec5a4e..bfa3b98cad 100644
--- a/tests/qtest/pxe-test.c
+++ b/tests/qtest/pxe-test.c
@@ -60,6 +60,7 @@ static testdef_t ppc64_tests_slow[] = {
static testdef_t s390x_tests[] = {
{ "s390-ccw-virtio", "virtio-net-ccw" },
+ { "s390-ccw-virtio", "virtio-net-pci" },
{ NULL },
};
--
2.55.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 7/7] tests/functional/s390x: Add tests for virtio net PCI in test_pxelinux.py
2026-09-03 16:24 [PATCH v2 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
` (5 preceding siblings ...)
2026-09-03 16:24 ` [PATCH v2 6/7] tests/qtest: Add s390x virtio net PCI test to pxe-test.c Zhuoying Cai
@ 2026-09-03 16:24 ` Zhuoying Cai
6 siblings, 0 replies; 19+ messages in thread
From: Zhuoying Cai @ 2026-09-03 16:24 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, jdaley, pbonzini
Add test coverage for virtio-net-pci network booting on s390x by
extending the pxelinux functional tests.
This patch adds PCI variants of all existing pxelinux tests to verify
that virtio-net-pci devices work correctly for network booting.
Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
Tested-by: Joshua Daley <jdaley@linux.ibm.com>
---
tests/functional/s390x/test_pxelinux.py | 71 ++++++++++++++++++++-----
1 file changed, 59 insertions(+), 12 deletions(-)
diff --git a/tests/functional/s390x/test_pxelinux.py b/tests/functional/s390x/test_pxelinux.py
index c00cce6a5a..7223364852 100755
--- a/tests/functional/s390x/test_pxelinux.py
+++ b/tests/functional/s390x/test_pxelinux.py
@@ -50,7 +50,8 @@ class S390PxeLinux(QemuSystemTest):
'/images/kernel.img'),
'480859574f3f44caa6cd35c62d70e1ac0609134e22ce2a954bbed9b110c06e0b')
- def pxelinux_launch(self, pl_name='default', extra_opts=None):
+ def pxelinux_launch(self, pl_name='default', extra_opts=None,
+ dev='virtio-net-ccw'):
'''Create a pxelinux.cfg file in the right location and launch QEMU'''
self.require_netdev('user')
self.set_machine('s390-ccw-virtio')
@@ -74,7 +75,7 @@ def pxelinux_launch(self, pl_name='default', extra_opts=None):
with open(cfg_fname, 'w', encoding='utf-8') as f:
f.write(PXELINUX_CFG_CONTENTS)
- virtio_net_dev = 'virtio-net-ccw,netdev=n1,bootindex=1'
+ virtio_net_dev = f'{dev},netdev=n1,bootindex=1'
if extra_opts:
virtio_net_dev += ',' + extra_opts
@@ -85,9 +86,9 @@ def pxelinux_launch(self, pl_name='default', extra_opts=None):
self.vm.launch()
- def test_default(self):
+ def do_test_default(self, dev):
'''Check whether the guest uses the "default" file name'''
- self.pxelinux_launch()
+ self.pxelinux_launch(dev=dev)
# The kernel prints its arguments to the console, so we can use
# this to check whether the kernel parameters are correctly handled:
wait_for_console_pattern(self, 'testoption=teststring')
@@ -95,36 +96,82 @@ def test_default(self):
wait_for_console_pattern(self, 'Unpacking initramfs...')
wait_for_console_pattern(self, 'Run /init as init process')
- def test_mac(self):
+ def do_test_mac(self, dev):
'''Check whether the guest uses file name based on its MAC address'''
self.pxelinux_launch(pl_name='01-02-ca-fe-ba-be-42',
- extra_opts='mac=02:ca:fe:ba:be:42,loadparm=3')
+ extra_opts='mac=02:ca:fe:ba:be:42,loadparm=3',
+ dev=dev)
wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x')
- def test_uuid(self):
+ def do_test_uuid(self, dev):
'''Check whether the guest uses file name based on its UUID'''
# Also add a non-bootable disk to check the fallback to network boot:
self.vm.add_args('-blockdev', 'null-co,size=65536,node-name=d1',
'-device', 'virtio-blk,drive=d1,bootindex=0,loadparm=1',
'-uuid', '550e8400-e29b-11d4-a716-446655441234')
- self.pxelinux_launch(pl_name='550e8400-e29b-11d4-a716-446655441234')
+ self.pxelinux_launch(pl_name='550e8400-e29b-11d4-a716-446655441234',
+ dev=dev)
wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)')
- def test_ip(self):
+ def do_test_ip(self, dev):
'''Check whether the guest uses file name based on its IP address'''
self.vm.add_args('-M', 'loadparm=3')
- self.pxelinux_launch(pl_name='0A00020F')
+ self.pxelinux_launch(pl_name='0A00020F', dev=dev)
wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x')
- def test_menu(self):
+ def do_test_menu(self, dev):
'''Check whether the boot menu works for pxelinux.cfg booting'''
self.vm.add_args('-boot', 'menu=on,splash-time=10')
- self.pxelinux_launch(pl_name='0A00')
+ self.pxelinux_launch(pl_name='0A00', dev=dev)
wait_for_console_pattern(self, '[1] Nonexisting')
wait_for_console_pattern(self, '[2] Debian')
wait_for_console_pattern(self, '[3] Fedora')
wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)')
+ def test_default(self):
+ '''pxelinux.cfg "default" lookup via virtio-net-ccw'''
+ self.do_test_default('virtio-net-ccw')
+
+ def test_default_pci(self):
+ '''pxelinux.cfg "default" lookup via virtio-net-pci'''
+ self.require_device('virtio-net-pci')
+ self.do_test_default('virtio-net-pci')
+
+ def test_mac(self):
+ '''pxelinux.cfg MAC-address-based file lookup via virtio-net-ccw'''
+ self.do_test_mac('virtio-net-ccw')
+
+ def test_mac_pci(self):
+ '''pxelinux.cfg MAC-address-based file lookup via virtio-net-pci'''
+ self.require_device('virtio-net-pci')
+ self.do_test_mac('virtio-net-pci')
+
+ def test_uuid(self):
+ '''pxelinux.cfg UUID-based file lookup via virtio-net-ccw'''
+ self.do_test_uuid('virtio-net-ccw')
+
+ def test_uuid_pci(self):
+ '''pxelinux.cfg UUID-based file lookup via virtio-net-pci'''
+ self.require_device('virtio-net-pci')
+ self.do_test_uuid('virtio-net-pci')
+
+ def test_ip(self):
+ '''pxelinux.cfg IP-address-based file lookup via virtio-net-ccw'''
+ self.do_test_ip('virtio-net-ccw')
+
+ def test_ip_pci(self):
+ '''pxelinux.cfg IP-address-based file lookup via virtio-net-pci'''
+ self.require_device('virtio-net-pci')
+ self.do_test_ip('virtio-net-pci')
+
+ def test_menu(self):
+ '''pxelinux.cfg interactive boot menu via virtio-net-ccw'''
+ self.do_test_menu('virtio-net-ccw')
+
+ def test_menu_pci(self):
+ '''pxelinux.cfg interactive boot menu via virtio-net-pci'''
+ self.require_device('virtio-net-pci')
+ self.do_test_menu('virtio-net-pci')
if __name__ == '__main__':
QemuSystemTest.main()
--
2.55.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/7] pc-bios/s390-ccw: Add dynamic net header size handling
2026-09-03 16:24 ` [PATCH v2 2/7] pc-bios/s390-ccw: Add dynamic net header size handling Zhuoying Cai
@ 2026-09-08 18:32 ` Jared Rossi
2026-09-09 13:44 ` Zhuoying Cai
2026-09-09 15:08 ` Matthew Rosato
1 sibling, 1 reply; 19+ messages in thread
From: Jared Rossi @ 2026-09-08 18:32 UTC (permalink / raw)
To: Zhuoying Cai, qemu-devel, qemu-s390x
Cc: mst, borntraeger, jjherne, cohuck, farman, mjrosato, pasic,
farosas, lvivier, jdaley, pbonzini
On 9/3/26 12:24 PM, Zhuoying Cai wrote:
> The virtio-net device used a fixed header size that did not account for
> the num_buffers field used in VirtIO 1.0 or for the mergeable receive
> buffers feature.
>
> Use dynamic header sizing: 10 bytes for legacy mode and 12 bytes for
> VirtIO 1.0 or when VIRTIO_NET_F_MRG_RXBUF is enabled. This ensures
> correct packet handling across different VirtIO configurations.
>
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
> ---
> pc-bios/s390-ccw/virtio-net.c | 30 ++++++++++++++++++++++++------
> 1 file changed, 24 insertions(+), 6 deletions(-)
>
> diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c
> index f58f7ffc55..afa728bc32 100644
> --- a/pc-bios/s390-ccw/virtio-net.c
> +++ b/pc-bios/s390-ccw/virtio-net.c
> @@ -20,6 +20,7 @@
> #include "s390-ccw.h"
> #include "virtio.h"
> #include "virtio-ccw.h"
> +#include "virtio-pci.h"
> #include "s390-time.h"
> #include "helper.h"
>
> @@ -28,6 +29,7 @@
> #endif
>
> #define VIRTIO_NET_F_MAC_BIT (1 << 5)
> +#define VIRTIO_NET_F_MRG_RXBUF_BIT (1 << 15)
We define this new feature bit, but it looks like we never set it.
The existing virtio_net_init() code has only:
vdev->guest_features[0] = VIRTIO_NET_F_MAC_BIT;
Should it be updated to VIRTIO_NET_F_MAC_BIT | VIRTIO_NET_F_MRG_RXBUF_BIT?
Is the new feature bit something we want to unconditionally request, only
request for PCI, or do we simply not care about it?
>
> #define VQ_RX 0 /* Receive queue */
> #define VQ_TX 1 /* Transmit queue */
> @@ -43,7 +45,18 @@ struct VirtioNetHdr {
> };
> typedef struct VirtioNetHdr VirtioNetHdr;
>
> +struct VirtioNetHdrMrgRxbuf {
> + struct VirtioNetHdr hdr;
> + uint16_t num_buffers; /* Only with VIRTIO_NET_F_MRG_RXBUF or VIRTIO1 */
> +};
> +typedef struct VirtioNetHdrMrgRxbuf VirtioNetHdrMrgRxbuf;
> +
> +/* Header sizes for different modes */
> +#define VIRTIO_NET_HDR_SIZE_LEGACY sizeof(VirtioNetHdr)
> +#define VIRTIO_NET_HDR_SIZE_V1 sizeof(VirtioNetHdrMrgRxbuf)
> +
> static uint16_t rx_last_idx; /* Last index in receive queue "used" ring */
> +static int virtio_net_hdr_size;
>
> int virtio_net_init(void *mac_addr)
> {
> @@ -62,12 +75,17 @@ int virtio_net_init(void *mac_addr)
> return -1;
> }
>
> + virtio_net_hdr_size = ((vdev->guest_features[1] & VIRTIO_F_VERSION_1) ||
> + (vdev->guest_features[0] & VIRTIO_NET_F_MRG_RXBUF_BIT))
Because we do not set VIRTIO_NET_F_MRG_RXBUF in net_init(), only the first
half of this check can ever return true.
Maybe that is correct, but in that case we can simplify this to just
vdev->guest_features[1] & VIRTIO_F_VERSION_1, right?
Regards,
Jared Rossi
> + ? VIRTIO_NET_HDR_SIZE_V1
> + : VIRTIO_NET_HDR_SIZE_LEGACY;
> +
> memcpy(mac_addr, vdev->config.net.mac, ETH_ALEN);
>
> for (i = 0; i < 64; i++) {
> - buf = malloc(ETH_MTU_SIZE + sizeof(VirtioNetHdr));
> + buf = malloc(ETH_MTU_SIZE + virtio_net_hdr_size);
> IPL_assert(buf != NULL, "Can not allocate memory for receive buffers");
> - vring_send_buf(rxvq, buf, ETH_MTU_SIZE + sizeof(VirtioNetHdr),
> + vring_send_buf(rxvq, buf, ETH_MTU_SIZE + virtio_net_hdr_size,
> VRING_DESC_F_WRITE);
> }
> vring_notify(rxvq);
> @@ -77,14 +95,14 @@ int virtio_net_init(void *mac_addr)
>
> int send(int fd, const void *buf, int len, int flags)
> {
> - VirtioNetHdr tx_hdr;
> + VirtioNetHdrMrgRxbuf tx_hdr;
> VDev *vdev = virtio_get_device();
> VRing *txvq = &vdev->vrings[VQ_TX];
>
> /* Set up header - we do not use anything special, so simply clear it */
> memset(&tx_hdr, 0, sizeof(tx_hdr));
>
> - vring_send_buf(txvq, &tx_hdr, sizeof(tx_hdr), VRING_DESC_F_NEXT);
> + vring_send_buf(txvq, &tx_hdr, virtio_net_hdr_size, VRING_DESC_F_NEXT);
> vring_send_buf(txvq, (void *)buf, len, VRING_HIDDEN_IS_CHAIN);
> while (!vr_poll(txvq)) {
> yield();
> @@ -108,13 +126,13 @@ int recv(int fd, void *buf, int maxlen, int flags)
> return 0;
> }
>
> - len = rxvq->used->ring[rx_last_idx % rxvq->num].len - sizeof(VirtioNetHdr);
> + len = rxvq->used->ring[rx_last_idx % rxvq->num].len - virtio_net_hdr_size;
> if (len > maxlen) {
> puts("virtio-net: Receive buffer too small");
> len = maxlen;
> }
> id = rxvq->used->ring[rx_last_idx % rxvq->num].id % rxvq->num;
> - pkt = (uint8_t *)(rxvq->desc[id].addr + sizeof(VirtioNetHdr));
> + pkt = (uint8_t *)(rxvq->desc[id].addr + virtio_net_hdr_size);
>
> #if DEBUG_VIRTIO_NET /* Dump packet */
> int i;
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw
2026-09-03 16:24 ` [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw Zhuoying Cai
@ 2026-09-09 12:49 ` Jason J. Herne
2026-09-09 15:10 ` Matthew Rosato
2026-09-11 15:15 ` Jared Rossi
2 siblings, 0 replies; 19+ messages in thread
From: Jason J. Herne @ 2026-09-09 12:49 UTC (permalink / raw)
To: Zhuoying Cai, qemu-devel, qemu-s390x
Cc: mst, jrossi, borntraeger, cohuck, farman, mjrosato, pasic,
farosas, lvivier, jdaley, pbonzini
On 9/3/26 12:24 PM, Zhuoying Cai wrote:
> Move CCW-specific virtio_setup() and find_net_dev() to virtio-ccw.c
> to decouple the generic net boot logic from the CCW transport.
> Also update the error message on failure to specify "ccw net device".
>
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
> ---
> pc-bios/s390-ccw/netmain.c | 67 ++---------------------------------
> pc-bios/s390-ccw/virtio-ccw.c | 62 ++++++++++++++++++++++++++++++++
> pc-bios/s390-ccw/virtio-ccw.h | 1 +
> 3 files changed, 66 insertions(+), 64 deletions(-)
>
LGTM
Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 4/7] pc-bios/s390-ccw: Add support for virtio-net-pci IPL
2026-09-03 16:24 ` [PATCH v2 4/7] pc-bios/s390-ccw: Add support for virtio-net-pci IPL Zhuoying Cai
@ 2026-09-09 13:28 ` Jason J. Herne
0 siblings, 0 replies; 19+ messages in thread
From: Jason J. Herne @ 2026-09-09 13:28 UTC (permalink / raw)
To: Zhuoying Cai, qemu-devel, qemu-s390x
Cc: mst, jrossi, borntraeger, cohuck, farman, mjrosato, pasic,
farosas, lvivier, jdaley, pbonzini
On 9/3/26 12:24 PM, Zhuoying Cai wrote:
> Enable network booting via virtio-net-pci by implementing PCI transport
> support for virtio-net.
>
> This patch also extends endianness handling for virtio PCI ring operations in
> little-endian to ensure correct behavior on s390x.
>
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
> ---
> pc-bios/s390-ccw/main.c | 1 +
> pc-bios/s390-ccw/netmain.c | 9 +++++++-
> pc-bios/s390-ccw/virtio-net.c | 41 ++++++++++++++++++++++++++++-------
> pc-bios/s390-ccw/virtio-pci.c | 18 +++++++++++++++
> 4 files changed, 60 insertions(+), 9 deletions(-)
>
> diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
> index 8fc1cbf653..28cab3b411 100644
> --- a/pc-bios/s390-ccw/main.c
> +++ b/pc-bios/s390-ccw/main.c
> @@ -332,6 +332,7 @@ static void ipl_pci_device(void)
> }
>
> switch (vdev->dev_type) {
> + case VIRTIO_ID_NET:
> case VIRTIO_ID_BLOCK:
> if (virtio_setup() == 0) {
> zipl_load(); /* only return on error */
> diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
> index bcb62bf6ca..e42e049063 100644
> --- a/pc-bios/s390-ccw/netmain.c
> +++ b/pc-bios/s390-ccw/netmain.c
> @@ -498,7 +498,14 @@ int netmain(void)
> sclp_setup();
> puts("Network boot starting...");
>
> - if (!virtio_ccw_net_setup()) {
> + /*
> + * CCW devices require subchannel enumeration here.
> + * PCI devices don't require specific setup: the transport is already
> + * initialized by ipl_pci_device(), and virtio_is_supported() is checked
> + * later in virtio_net_init().
> + */
> + if (virtio_get_device()->ipl_type == S390_IPL_TYPE_CCW &&
> + !virtio_ccw_net_setup()) {
> puts("No valid virtio ccw net device found.");
> return -1;
> }
> diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c
> index afa728bc32..418759565d 100644
> --- a/pc-bios/s390-ccw/virtio-net.c
> +++ b/pc-bios/s390-ccw/virtio-net.c
> @@ -68,7 +68,22 @@ int virtio_net_init(void *mac_addr)
> rx_last_idx = 0;
>
> vdev->guest_features[0] = VIRTIO_NET_F_MAC_BIT;
> - virtio_ccw_setup(vdev);
> + switch (virtio_get_device()->ipl_type) {
> + case S390_IPL_TYPE_CCW:
> + if (virtio_ccw_setup(vdev)) {
> + puts("Setup failed for virtio-net-ccw");
> + return -1;
> + }
> + break;
> + case S390_IPL_TYPE_PCI:
> + if (virtio_pci_setup(vdev)) {
> + puts("Setup failed for virtio-net-pci");
> + return -1;
> + }
> + break;
> + default:
> + return -1;
> + }
>
> if (!(vdev->guest_features[0] & VIRTIO_NET_F_MAC_BIT)) {
> puts("virtio-net device does not support the MAC address feature");
> @@ -121,22 +136,30 @@ int recv(int fd, void *buf, int maxlen, int flags)
> VRing *rxvq = &vdev->vrings[VQ_RX];
> int len, id;
> uint8_t *pkt;
> + uint16_t rx_used_idx, rx_avail_idx;
> + uint32_t rx_used_len, rx_used_id;
> + uint64_t rx_desc_addr;
>
> - if (rx_last_idx == rxvq->used->idx) {
> + rx_used_idx = virtio_tswap16(rxvq->used->idx);
> + if (rx_last_idx == rx_used_idx) {
> return 0;
> }
>
> - len = rxvq->used->ring[rx_last_idx % rxvq->num].len - virtio_net_hdr_size;
> + rx_used_len = virtio_tswap32(rxvq->used->ring[rx_last_idx % rxvq->num].len);
> + rx_used_id = virtio_tswap32(rxvq->used->ring[rx_last_idx % rxvq->num].id);
> +
> + len = rx_used_len - virtio_net_hdr_size;
> if (len > maxlen) {
> puts("virtio-net: Receive buffer too small");
> len = maxlen;
> }
> - id = rxvq->used->ring[rx_last_idx % rxvq->num].id % rxvq->num;
> - pkt = (uint8_t *)(rxvq->desc[id].addr + virtio_net_hdr_size);
> + id = rx_used_id % rxvq->num;
> + rx_desc_addr = virtio_tswap64(rxvq->desc[id].addr);
> + pkt = (uint8_t *)(rx_desc_addr + virtio_net_hdr_size);
>
> #if DEBUG_VIRTIO_NET /* Dump packet */
> int i;
> - printf("\nbuf %p: len=%i\n", (void *)rxvq->desc[id].addr, len);
> + printf("\nbuf %p: len=%i\n", (void *)rx_desc_addr, len);
> for (i = 0; i < 64; i++) {
> printf(" %02x", pkt[i]);
> if ((i % 16) == 15) {
> @@ -150,8 +173,10 @@ int recv(int fd, void *buf, int maxlen, int flags)
> memcpy(buf, pkt, len);
>
> /* Mark buffer as available to the host again */
> - rxvq->avail->ring[rxvq->avail->idx % rxvq->num] = id;
> - rxvq->avail->idx = rxvq->avail->idx + 1;
> + rx_avail_idx = virtio_tswap16(rxvq->avail->idx);
> + rxvq->avail->ring[rx_avail_idx % rxvq->num] = virtio_tswap16(id);
> + rx_avail_idx++;
> + rxvq->avail->idx = virtio_tswap16(rx_avail_idx);
> vring_notify(rxvq);
>
> /* Move index to next entry */
> diff --git a/pc-bios/s390-ccw/virtio-pci.c b/pc-bios/s390-ccw/virtio-pci.c
> index f501252c81..147a82895f 100644
> --- a/pc-bios/s390-ccw/virtio-pci.c
> +++ b/pc-bios/s390-ccw/virtio-pci.c
> @@ -52,6 +52,10 @@ void virtio_pci_id2type(VDev *vdev, uint16_t device_id)
> case 0x1001:
> vdev->dev_type = VIRTIO_ID_BLOCK;
> break;
> + case 0x1041:
> + case 0x1000:
> + vdev->dev_type = VIRTIO_ID_NET;
> + break;
> default:
> vdev->dev_type = 0;
> }
> @@ -199,6 +203,14 @@ static int virtio_pci_get_blk_config(void)
> return rc;
> }
>
> +static int virtio_pci_get_net_config(void)
> +{
> + VirtioNetConfig *cfg = &virtio_get_device()->config.net;
> + int rc = vpci_read_flex(d_cap.off, d_cap.bar, cfg, sizeof(VirtioNetConfig));
> +
> + return rc;
> +}
> +
Simplify to this:
static int virtio_pci_get_net_config(void)
{
VirtioNetConfig *cfg = &virtio_get_device()->config.net;
return vpci_read_flex(d_cap.off, d_cap.bar, cfg,
sizeof(VirtioNetConfig));
}
> static int virtio_pci_negotiate(void)
> {
> int i, rc;
> @@ -330,6 +342,7 @@ bool virtio_pci_is_supported(VDev *vdev)
> if (vdev->vendor_id == PCI_VENDOR_VIRTIO) {
> switch (vdev->dev_type) {
> case VIRTIO_ID_BLOCK:
> + case VIRTIO_ID_NET:
> return true;
> default:
> return false;
> @@ -384,6 +397,11 @@ int virtio_pci_setup(VDev *vdev)
> vdev->cmd_vr_idx = 0;
> virtio_pci_get_blk_config();
> break;
> + case VIRTIO_ID_NET:
> + vdev->nr_vqs = 2;
> + vdev->cmd_vr_idx = 0;
cmd_vr_idx is never actually used for net devices. I'm thinking we want
to skip setting it here. It's actually already set to 0 above, in common
code, before we know what device type we're dealing with.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x
2026-09-03 16:24 ` [PATCH v2 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x Zhuoying Cai
@ 2026-09-09 13:30 ` Jason J. Herne
2026-09-11 15:17 ` Jared Rossi
1 sibling, 0 replies; 19+ messages in thread
From: Jason J. Herne @ 2026-09-09 13:30 UTC (permalink / raw)
To: Zhuoying Cai, qemu-devel, qemu-s390x
Cc: mst, jrossi, borntraeger, cohuck, farman, mjrosato, pasic,
farosas, lvivier, jdaley, pbonzini
On 9/3/26 12:24 PM, Zhuoying Cai wrote:
> Add optional loadparm property to virtio-net-pci to allow boot entry
> selection on s390x, consistent with virtio-blk-pci.
>
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
> ---
> hw/virtio/virtio-net-pci.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c
> index fd3e0303f5..893d1905a9 100644
> --- a/hw/virtio/virtio-net-pci.c
> +++ b/hw/virtio/virtio-net-pci.c
> @@ -77,6 +77,7 @@ static void virtio_net_pci_class_init(ObjectClass *klass, const void *data)
> k->sriov_vf_user_creatable = true;
> set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
> device_class_set_props(dc, virtio_net_properties);
> + pci_qdev_property_add_specifics(dc);
> vpciklass->realize = virtio_net_pci_realize;
> }
>
Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/7] pc-bios/s390-ccw: Add dynamic net header size handling
2026-09-08 18:32 ` Jared Rossi
@ 2026-09-09 13:44 ` Zhuoying Cai
0 siblings, 0 replies; 19+ messages in thread
From: Zhuoying Cai @ 2026-09-09 13:44 UTC (permalink / raw)
To: Jared Rossi, qemu-devel, qemu-s390x
Cc: mst, borntraeger, jjherne, cohuck, farman, mjrosato, pasic,
farosas, lvivier, jdaley, pbonzini
On 9/8/26 2:32 PM, Jared Rossi wrote:
>
>
> On 9/3/26 12:24 PM, Zhuoying Cai wrote:
>> The virtio-net device used a fixed header size that did not account for
>> the num_buffers field used in VirtIO 1.0 or for the mergeable receive
>> buffers feature.
>>
>> Use dynamic header sizing: 10 bytes for legacy mode and 12 bytes for
>> VirtIO 1.0 or when VIRTIO_NET_F_MRG_RXBUF is enabled. This ensures
>> correct packet handling across different VirtIO configurations.
>>
>> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
>> ---
>> pc-bios/s390-ccw/virtio-net.c | 30 ++++++++++++++++++++++++------
>> 1 file changed, 24 insertions(+), 6 deletions(-)
>>
>> diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c
>> index f58f7ffc55..afa728bc32 100644
>> --- a/pc-bios/s390-ccw/virtio-net.c
>> +++ b/pc-bios/s390-ccw/virtio-net.c
>> @@ -20,6 +20,7 @@
>> #include "s390-ccw.h"
>> #include "virtio.h"
>> #include "virtio-ccw.h"
>> +#include "virtio-pci.h"
>> #include "s390-time.h"
>> #include "helper.h"
>>
>> @@ -28,6 +29,7 @@
>> #endif
>>
>> #define VIRTIO_NET_F_MAC_BIT (1 << 5)
>> +#define VIRTIO_NET_F_MRG_RXBUF_BIT (1 << 15)
>
> We define this new feature bit, but it looks like we never set it.
>
> The existing virtio_net_init() code has only:
>
> vdev->guest_features[0] = VIRTIO_NET_F_MAC_BIT;
>
> Should it be updated to VIRTIO_NET_F_MAC_BIT | VIRTIO_NET_F_MRG_RXBUF_BIT?
>
> Is the new feature bit something we want to unconditionally request, only
> request for PCI, or do we simply not care about it?
As of now, we do not care about VIRTIO_NET_F_MRG_RXBUF_BIT. I added it
because the num_buffers field in VirtioNetHdrMrgRxbuf is present when
either condition is true, and we might want to use it in the future.
>>
>> #define VQ_RX 0 /* Receive queue */
>> #define VQ_TX 1 /* Transmit queue */
>> @@ -43,7 +45,18 @@ struct VirtioNetHdr {
>> };
>> typedef struct VirtioNetHdr VirtioNetHdr;
>>
>> +struct VirtioNetHdrMrgRxbuf {
>> + struct VirtioNetHdr hdr;
>> + uint16_t num_buffers; /* Only with VIRTIO_NET_F_MRG_RXBUF or VIRTIO1 */
>> +};
>> +typedef struct VirtioNetHdrMrgRxbuf VirtioNetHdrMrgRxbuf;
>> +
>> +/* Header sizes for different modes */
>> +#define VIRTIO_NET_HDR_SIZE_LEGACY sizeof(VirtioNetHdr)
>> +#define VIRTIO_NET_HDR_SIZE_V1 sizeof(VirtioNetHdrMrgRxbuf)
>> +
>> static uint16_t rx_last_idx; /* Last index in receive queue "used" ring */
>> +static int virtio_net_hdr_size;
>>
>> int virtio_net_init(void *mac_addr)
>> {
>> @@ -62,12 +75,17 @@ int virtio_net_init(void *mac_addr)
>> return -1;
>> }
>>
>> + virtio_net_hdr_size = ((vdev->guest_features[1] & VIRTIO_F_VERSION_1) ||
>> + (vdev->guest_features[0] & VIRTIO_NET_F_MRG_RXBUF_BIT))
>
> Because we do not set VIRTIO_NET_F_MRG_RXBUF in net_init(), only the first
> half of this check can ever return true.
>
> Maybe that is correct, but in that case we can simplify this to just
> vdev->guest_features[1] & VIRTIO_F_VERSION_1, right?
>
Since VIRTIO_NET_F_MRG_RXBUF is neither negotiated nor used today, I can
remove it entirely and simplify the check to vdev->guest_features[1] &
VIRTIO_F_VERSION_1.
> Regards,
> Jared Rossi
>> + ? VIRTIO_NET_HDR_SIZE_V1
>> + : VIRTIO_NET_HDR_SIZE_LEGACY;
>> +
>> memcpy(mac_addr, vdev->config.net.mac, ETH_ALEN);
>>
>> for (i = 0; i < 64; i++) {
>> - buf = malloc(ETH_MTU_SIZE + sizeof(VirtioNetHdr));
>> + buf = malloc(ETH_MTU_SIZE + virtio_net_hdr_size);
>> IPL_assert(buf != NULL, "Can not allocate memory for receive buffers");
>> - vring_send_buf(rxvq, buf, ETH_MTU_SIZE + sizeof(VirtioNetHdr),
>> + vring_send_buf(rxvq, buf, ETH_MTU_SIZE + virtio_net_hdr_size,
>> VRING_DESC_F_WRITE);
>> }
>> vring_notify(rxvq);
>> @@ -77,14 +95,14 @@ int virtio_net_init(void *mac_addr)
>>
>> int send(int fd, const void *buf, int len, int flags)
>> {
>> - VirtioNetHdr tx_hdr;
>> + VirtioNetHdrMrgRxbuf tx_hdr;
>> VDev *vdev = virtio_get_device();
>> VRing *txvq = &vdev->vrings[VQ_TX];
>>
>> /* Set up header - we do not use anything special, so simply clear it */
>> memset(&tx_hdr, 0, sizeof(tx_hdr));
>>
>> - vring_send_buf(txvq, &tx_hdr, sizeof(tx_hdr), VRING_DESC_F_NEXT);
>> + vring_send_buf(txvq, &tx_hdr, virtio_net_hdr_size, VRING_DESC_F_NEXT);
>> vring_send_buf(txvq, (void *)buf, len, VRING_HIDDEN_IS_CHAIN);
>> while (!vr_poll(txvq)) {
>> yield();
>> @@ -108,13 +126,13 @@ int recv(int fd, void *buf, int maxlen, int flags)
>> return 0;
>> }
>>
>> - len = rxvq->used->ring[rx_last_idx % rxvq->num].len - sizeof(VirtioNetHdr);
>> + len = rxvq->used->ring[rx_last_idx % rxvq->num].len - virtio_net_hdr_size;
>> if (len > maxlen) {
>> puts("virtio-net: Receive buffer too small");
>> len = maxlen;
>> }
>> id = rxvq->used->ring[rx_last_idx % rxvq->num].id % rxvq->num;
>> - pkt = (uint8_t *)(rxvq->desc[id].addr + sizeof(VirtioNetHdr));
>> + pkt = (uint8_t *)(rxvq->desc[id].addr + virtio_net_hdr_size);
>>
>> #if DEBUG_VIRTIO_NET /* Dump packet */
>> int i;
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/7] pc-bios/s390-ccw: Add dynamic net header size handling
2026-09-03 16:24 ` [PATCH v2 2/7] pc-bios/s390-ccw: Add dynamic net header size handling Zhuoying Cai
2026-09-08 18:32 ` Jared Rossi
@ 2026-09-09 15:08 ` Matthew Rosato
1 sibling, 0 replies; 19+ messages in thread
From: Matthew Rosato @ 2026-09-09 15:08 UTC (permalink / raw)
To: Zhuoying Cai, qemu-devel, qemu-s390x
Cc: mst, jrossi, borntraeger, jjherne, cohuck, farman, pasic, farosas,
lvivier, jdaley, pbonzini
On 9/3/26 12:24 PM, Zhuoying Cai wrote:
> The virtio-net device used a fixed header size that did not account for
> the num_buffers field used in VirtIO 1.0 or for the mergeable receive
> buffers feature.
>
> Use dynamic header sizing: 10 bytes for legacy mode and 12 bytes for
> VirtIO 1.0 or when VIRTIO_NET_F_MRG_RXBUF is enabled. This ensures
> correct packet handling across different VirtIO configurations.
>
Since you're already touching this patch based on Jared's comment, maybe
add a small blurb here that you are replicating the same structure
mappings as defined in the uapi.
Thanks,
Matt
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw
2026-09-03 16:24 ` [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw Zhuoying Cai
2026-09-09 12:49 ` Jason J. Herne
@ 2026-09-09 15:10 ` Matthew Rosato
2026-09-11 15:15 ` Jared Rossi
2 siblings, 0 replies; 19+ messages in thread
From: Matthew Rosato @ 2026-09-09 15:10 UTC (permalink / raw)
To: Zhuoying Cai, qemu-devel, qemu-s390x
Cc: mst, jrossi, borntraeger, jjherne, cohuck, farman, pasic, farosas,
lvivier, jdaley, pbonzini
On 9/3/26 12:24 PM, Zhuoying Cai wrote:
> Move CCW-specific virtio_setup() and find_net_dev() to virtio-ccw.c
> to decouple the generic net boot logic from the CCW transport.
> Also update the error message on failure to specify "ccw net device".
>
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw
2026-09-03 16:24 ` [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw Zhuoying Cai
2026-09-09 12:49 ` Jason J. Herne
2026-09-09 15:10 ` Matthew Rosato
@ 2026-09-11 15:15 ` Jared Rossi
2 siblings, 0 replies; 19+ messages in thread
From: Jared Rossi @ 2026-09-11 15:15 UTC (permalink / raw)
To: Zhuoying Cai, qemu-devel, qemu-s390x
Cc: mst, borntraeger, jjherne, cohuck, farman, mjrosato, pasic,
farosas, lvivier, jdaley, pbonzini
On 9/3/26 12:24 PM, Zhuoying Cai wrote:
> Move CCW-specific virtio_setup() and find_net_dev() to virtio-ccw.c
> to decouple the generic net boot logic from the CCW transport.
> Also update the error message on failure to specify "ccw net device".
>
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
Reviewed-by: Jared Rossi <jrossi@linux.ibm.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x
2026-09-03 16:24 ` [PATCH v2 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x Zhuoying Cai
2026-09-09 13:30 ` Jason J. Herne
@ 2026-09-11 15:17 ` Jared Rossi
1 sibling, 0 replies; 19+ messages in thread
From: Jared Rossi @ 2026-09-11 15:17 UTC (permalink / raw)
To: Zhuoying Cai, qemu-devel, qemu-s390x
Cc: mst, borntraeger, jjherne, cohuck, farman, mjrosato, pasic,
farosas, lvivier, jdaley, pbonzini
On 9/3/26 12:24 PM, Zhuoying Cai wrote:
> Add optional loadparm property to virtio-net-pci to allow boot entry
> selection on s390x, consistent with virtio-blk-pci.
>
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
> ---
Reviewed-by: Jared Rossi <jrossi@linux.ibm.com>
> hw/virtio/virtio-net-pci.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c
> index fd3e0303f5..893d1905a9 100644
> --- a/hw/virtio/virtio-net-pci.c
> +++ b/hw/virtio/virtio-net-pci.c
> @@ -77,6 +77,7 @@ static void virtio_net_pci_class_init(ObjectClass *klass, const void *data)
> k->sriov_vf_user_creatable = true;
> set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
> device_class_set_props(dc, virtio_net_properties);
> + pci_qdev_property_add_specifics(dc);
> vpciklass->realize = virtio_net_pci_realize;
> }
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/7] pc-bios/s390-ccw: Introduce virtio_tswap helpers
2026-09-03 16:24 ` [PATCH v2 3/7] pc-bios/s390-ccw: Introduce virtio_tswap helpers Zhuoying Cai
@ 2026-09-11 15:19 ` Jared Rossi
0 siblings, 0 replies; 19+ messages in thread
From: Jared Rossi @ 2026-09-11 15:19 UTC (permalink / raw)
To: Zhuoying Cai, qemu-devel, qemu-s390x
Cc: mst, borntraeger, jjherne, cohuck, farman, mjrosato, pasic,
farosas, lvivier, jdaley, pbonzini
On 9/3/26 12:24 PM, Zhuoying Cai wrote:
> Replace the repeated pattern:
>
> be_ipl() ? x : bswapN(x)
>
> with helpers that conditionally byte-swap based on the virtio transport
> endianness.
>
> While only the 16-bit helper is used immediately, the 32-bit and 64-bit
> variants are added here for later use.
>
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
> Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
> Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
> ---
Reviewed-by: Jared Rossi <jrossi@linux.ibm.com>
> pc-bios/s390-ccw/virtio.c | 27 +++++++++++++++++++++------
> pc-bios/s390-ccw/virtio.h | 4 ++++
> 2 files changed, 25 insertions(+), 6 deletions(-)
>
> diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
> index a0d249db24..037c00a3e1 100644
> --- a/pc-bios/s390-ccw/virtio.c
> +++ b/pc-bios/s390-ccw/virtio.c
> @@ -97,7 +97,7 @@ void vring_init(VRing *vr, VqInfo *info)
> vr->avail->idx = 0;
>
> /* We're running with interrupts off anyways, so don't bother */
> - vr->used->flags = be_ipl() ? VRING_USED_F_NO_NOTIFY : bswap16(VRING_USED_F_NO_NOTIFY);
> + vr->used->flags = virtio_tswap16(VRING_USED_F_NO_NOTIFY);
> vr->used->idx = 0;
> vr->used_idx = 0;
> vr->next_idx = 0;
> @@ -140,6 +140,22 @@ bool be_ipl(void)
> }
> }
>
> +/* Conditionally byte-swap between virtio-endian and s390x native big-endian. */
> +uint16_t virtio_tswap16(uint16_t x)
> +{
> + return be_ipl() ? x : bswap16(x);
> +}
> +
> +uint32_t virtio_tswap32(uint32_t x)
> +{
> + return be_ipl() ? x : bswap32(x);
> +}
> +
> +uint64_t virtio_tswap64(uint64_t x)
> +{
> + return be_ipl() ? x : bswap64(x);
> +}
> +
> /*
> * Format the virtio ring descriptor endianness
> * Return the available index increment in the appropriate endianness
> @@ -156,12 +172,11 @@ void vring_send_buf(VRing *vr, void *p, int len, int flags)
> {
> uint16_t avail_idx;
>
> - avail_idx = be_ipl() ? vr->avail->idx : bswap16(vr->avail->idx);
> + avail_idx = virtio_tswap16(vr->avail->idx);
>
> /* For follow-up chains we need to keep the first entry point */
> if (!(flags & VRING_HIDDEN_IS_CHAIN)) {
> - vr->avail->ring[avail_idx % vr->num] = be_ipl() ? vr->next_idx :
> - bswap16(vr->next_idx);
> + vr->avail->ring[avail_idx % vr->num] = virtio_tswap16(vr->next_idx);
> }
>
> vr->desc[vr->next_idx].addr = (unsigned long)p;
> @@ -179,7 +194,7 @@ void vring_send_buf(VRing *vr, void *p, int len, int flags)
> /* Chains only have a single ID */
> if (!(flags & VRING_DESC_F_NEXT)) {
> avail_idx++;
> - vr->avail->idx = be_ipl() ? avail_idx : bswap16(avail_idx);
> + vr->avail->idx = virtio_tswap16(avail_idx);
> }
> }
>
> @@ -187,7 +202,7 @@ int vr_poll(VRing *vr)
> {
> uint16_t used_idx;
>
> - used_idx = be_ipl() ? vr->used->idx : bswap16(vr->used->idx);
> + used_idx = virtio_tswap16(vr->used->idx);
> if (used_idx == vr->used_idx) {
> vring_notify(vr);
> yield();
> diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
> index aa307025e0..645dc288b1 100644
> --- a/pc-bios/s390-ccw/virtio.h
> +++ b/pc-bios/s390-ccw/virtio.h
> @@ -287,6 +287,10 @@ int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd);
> int virtio_reset(VDev *vdev);
> int virtio_setup_ccw(VDev *vdev);
>
> +uint16_t virtio_tswap16(uint16_t x);
> +uint32_t virtio_tswap32(uint32_t x);
> +uint64_t virtio_tswap64(uint64_t x);
> +
> /* virtio-net.c */
> int virtio_net_init(void *mac_addr);
> void virtio_net_deinit(void);
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 6/7] tests/qtest: Add s390x virtio net PCI test to pxe-test.c
2026-09-03 16:24 ` [PATCH v2 6/7] tests/qtest: Add s390x virtio net PCI test to pxe-test.c Zhuoying Cai
@ 2026-09-11 15:36 ` Matthew Rosato
0 siblings, 0 replies; 19+ messages in thread
From: Matthew Rosato @ 2026-09-11 15:36 UTC (permalink / raw)
To: Zhuoying Cai, qemu-devel, qemu-s390x
Cc: mst, jrossi, borntraeger, jjherne, cohuck, farman, pasic, farosas,
lvivier, jdaley, pbonzini
On 9/3/26 12:24 PM, Zhuoying Cai wrote:
> Add test coverage for virtio-net-pci network booting on s390x by
> including it in the PXE test suite. The test verifies that PXE
> network booting works correctly with virtio-net-pci devices.
>
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
> Tested-by: Joshua Daley <jdaley@linux.ibm.com>
Realized I shared some findings off-list, but never included them here.
> ---
> tests/qtest/meson.build | 1 +
> tests/qtest/pxe-test.c | 1 +
> 2 files changed, 2 insertions(+)
>
> diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
> index 50a1a5272f..654e145fbe 100644
> --- a/tests/qtest/meson.build
> +++ b/tests/qtest/meson.build
> @@ -289,6 +289,7 @@ qtests_aarch64 = \
> 'migration-test']
>
> qtests_s390x = \
> + (slirp.found() ? ['pxe-test'] : []) + \
AFAICT this patch not only adds pci testing, but re-enables pxe-test for
virtio-net-ccw. Sounds like this got accidentally removed along the way?
If that's the case I think this should be its own fix patch.
Alternatively, at least mention it in the commit subject/message.
> qtests_filter + \
> ['boot-serial-test',
> 'drive_del-test',
> diff --git a/tests/qtest/pxe-test.c b/tests/qtest/pxe-test.c
> index e85dec5a4e..bfa3b98cad 100644
> --- a/tests/qtest/pxe-test.c
> +++ b/tests/qtest/pxe-test.c
> @@ -60,6 +60,7 @@ static testdef_t ppc64_tests_slow[] = {
>
> static testdef_t s390x_tests[] = {
> { "s390-ccw-virtio", "virtio-net-ccw" },
> + { "s390-ccw-virtio", "virtio-net-pci" },
I noticed that if I attempt to run this test using a bios that is not
built with this series included, the virtio-net-pci test does not fail
gracefully.
Joy investigated, turns out instead of detecting the condition (no
suitable device found) the tests simply get killed by timeout; would be
good to detect this condition for s390x if possible.
Thanks,
Matt
> { NULL },
> };
>
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-09-11 15:38 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03 16:24 [PATCH v2 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
2026-09-03 16:24 ` [PATCH v2 1/7] pc-bios/s390-ccw: Move CCW net setup to virtio-ccw Zhuoying Cai
2026-09-09 12:49 ` Jason J. Herne
2026-09-09 15:10 ` Matthew Rosato
2026-09-11 15:15 ` Jared Rossi
2026-09-03 16:24 ` [PATCH v2 2/7] pc-bios/s390-ccw: Add dynamic net header size handling Zhuoying Cai
2026-09-08 18:32 ` Jared Rossi
2026-09-09 13:44 ` Zhuoying Cai
2026-09-09 15:08 ` Matthew Rosato
2026-09-03 16:24 ` [PATCH v2 3/7] pc-bios/s390-ccw: Introduce virtio_tswap helpers Zhuoying Cai
2026-09-11 15:19 ` Jared Rossi
2026-09-03 16:24 ` [PATCH v2 4/7] pc-bios/s390-ccw: Add support for virtio-net-pci IPL Zhuoying Cai
2026-09-09 13:28 ` Jason J. Herne
2026-09-03 16:24 ` [PATCH v2 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x Zhuoying Cai
2026-09-09 13:30 ` Jason J. Herne
2026-09-11 15:17 ` Jared Rossi
2026-09-03 16:24 ` [PATCH v2 6/7] tests/qtest: Add s390x virtio net PCI test to pxe-test.c Zhuoying Cai
2026-09-11 15:36 ` Matthew Rosato
2026-09-03 16:24 ` [PATCH v2 7/7] tests/functional/s390x: Add tests for virtio net PCI in test_pxelinux.py Zhuoying Cai
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.