* [PATCH v1 0/7] s390x: Add support for virtio-net-pci boot device
@ 2026-08-18 20:53 Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 1/7] pc-bios/s390-ccw: Split virtio-ccw and generic virtio net Zhuoying Cai
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Zhuoying Cai @ 2026-08-18 20:53 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, pbonzini
This series enables network booting via virtio-net-pci on s390x.
Refactor virtio-net to separate virtio-ccw specific logic and
create generic virtio-net helpers, 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: Split virtio-ccw and generic virtio net
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 | 64 +---------------------
pc-bios/s390-ccw/virtio-ccw.c | 62 +++++++++++++++++++++
pc-bios/s390-ccw/virtio-ccw.h | 1 +
pc-bios/s390-ccw/virtio-net.c | 69 +++++++++++++++++++-----
pc-bios/s390-ccw/virtio-pci.c | 43 +++++++++++++++
pc-bios/s390-ccw/virtio-pci.h | 2 +
pc-bios/s390-ccw/virtio.c | 27 +++++++---
pc-bios/s390-ccw/virtio.h | 5 ++
tests/functional/s390x/test_pxelinux.py | 71 ++++++++++++++++++++-----
tests/qtest/meson.build | 1 +
tests/qtest/pxe-test.c | 1 +
13 files changed, 254 insertions(+), 94 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v1 1/7] pc-bios/s390-ccw: Split virtio-ccw and generic virtio net
2026-08-18 20:53 [PATCH v1 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
@ 2026-08-18 20:53 ` Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 2/7] pc-bios/s390-ccw: Add dynamic net header size handling Zhuoying Cai
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Zhuoying Cai @ 2026-08-18 20:53 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, pbonzini
Refactor network device setup to separate virtio-ccw from
generic virtio-net logic for easier reuse of existing virtio
functions with non-CCW devices.
Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
---
pc-bios/s390-ccw/netmain.c | 64 +----------------------------------
pc-bios/s390-ccw/virtio-ccw.c | 62 +++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/virtio-ccw.h | 1 +
pc-bios/s390-ccw/virtio-net.c | 10 ++++++
pc-bios/s390-ccw/virtio.h | 1 +
5 files changed, 75 insertions(+), 63 deletions(-)
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index 791854fce0..e2f2278b8d 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -489,68 +489,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,7 +497,7 @@ int netmain(void)
sclp_setup();
puts("Network boot starting...");
- if (!virtio_setup()) {
+ if (!virtio_net_setup()) {
puts("No virtio 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..403bd8a785 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
diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c
index f58f7ffc55..0ee51653ab 100644
--- a/pc-bios/s390-ccw/virtio-net.c
+++ b/pc-bios/s390-ccw/virtio-net.c
@@ -146,3 +146,13 @@ void virtio_net_deinit(void)
{
virtio_reset(virtio_get_device());
}
+
+bool virtio_net_setup(void)
+{
+ switch (virtio_get_device()->ipl_type) {
+ case S390_IPL_TYPE_CCW:
+ return virtio_ccw_net_setup();
+ default:
+ return false;
+ }
+}
diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h
index aa307025e0..04dbc65dbd 100644
--- a/pc-bios/s390-ccw/virtio.h
+++ b/pc-bios/s390-ccw/virtio.h
@@ -290,6 +290,7 @@ int virtio_setup_ccw(VDev *vdev);
/* virtio-net.c */
int virtio_net_init(void *mac_addr);
void virtio_net_deinit(void);
+bool virtio_net_setup(void);
/* virtio-blkdev.c */
int virtio_blk_setup_device(VDev *vdev);
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 2/7] pc-bios/s390-ccw: Add dynamic net header size handling
2026-08-18 20:53 [PATCH v1 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 1/7] pc-bios/s390-ccw: Split virtio-ccw and generic virtio net Zhuoying Cai
@ 2026-08-18 20:53 ` Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 3/7] pc-bios/s390-ccw: Introduce virtio_tswap helpers Zhuoying Cai
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Zhuoying Cai @ 2026-08-18 20:53 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, 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 | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c
index 0ee51653ab..3a9ae789cf 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,10 +29,15 @@
#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 */
+/* Header sizes for different modes */
+#define VIRTIO_NET_HDR_SIZE_LEGACY 10 /* Without num_buffers */
+#define VIRTIO_NET_HDR_SIZE_V1 12 /* With num_buffers */
+
struct VirtioNetHdr {
uint8_t flags;
uint8_t gso_type;
@@ -39,11 +45,12 @@ struct VirtioNetHdr {
uint16_t gso_size;
uint16_t csum_start;
uint16_t csum_offset;
- /*uint16_t num_buffers;*/ /* Only with VIRTIO_NET_F_MRG_RXBUF or VIRTIO1 */
+ uint16_t num_buffers; /* Only with VIRTIO_NET_F_MRG_RXBUF or VIRTIO1 */
};
typedef struct VirtioNetHdr VirtioNetHdr;
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 +69,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);
@@ -82,9 +94,9 @@ int send(int fd, const void *buf, int len, int flags)
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));
+ memset(&tx_hdr, 0, virtio_net_hdr_size);
- 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 +120,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] 8+ messages in thread
* [PATCH v1 3/7] pc-bios/s390-ccw: Introduce virtio_tswap helpers
2026-08-18 20:53 [PATCH v1 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 1/7] pc-bios/s390-ccw: Split virtio-ccw and generic virtio net Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 2/7] pc-bios/s390-ccw: Add dynamic net header size handling Zhuoying Cai
@ 2026-08-18 20:53 ` Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 4/7] pc-bios/s390-ccw: Add support for virtio-net-pci IPL Zhuoying Cai
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Zhuoying Cai @ 2026-08-18 20:53 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, pbonzini
Replace the repeated pattern:
be_ipl() ? x : bswapN(x)
with helpers that conditionally byte-swap based on the virtio transport
endianness.
Signed-off-by: Zhuoying Cai <zycai@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 04dbc65dbd..3c84a480d9 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] 8+ messages in thread
* [PATCH v1 4/7] pc-bios/s390-ccw: Add support for virtio-net-pci IPL
2026-08-18 20:53 [PATCH v1 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
` (2 preceding siblings ...)
2026-08-18 20:53 ` [PATCH v1 3/7] pc-bios/s390-ccw: Introduce virtio_tswap helpers Zhuoying Cai
@ 2026-08-18 20:53 ` Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x Zhuoying Cai
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Zhuoying Cai @ 2026-08-18 20:53 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, pbonzini
Enable network booting via virtio-net-pci by implementing PCI transport
support for virtio-net.
This patch also adds 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/virtio-net.c | 37 +++++++++++++++++++++++-------
pc-bios/s390-ccw/virtio-pci.c | 43 +++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/virtio-pci.h | 2 ++
4 files changed, 75 insertions(+), 8 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 8bc6e8eaa3..0eeb53a2bf 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -328,6 +328,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/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c
index 3a9ae789cf..209f98a0e3 100644
--- a/pc-bios/s390-ccw/virtio-net.c
+++ b/pc-bios/s390-ccw/virtio-net.c
@@ -62,7 +62,16 @@ 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:
+ virtio_ccw_setup(vdev);
+ break;
+ case S390_IPL_TYPE_PCI:
+ virtio_pci_setup(vdev);
+ 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");
@@ -115,22 +124,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) {
@@ -144,8 +161,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 */
@@ -164,6 +183,8 @@ bool virtio_net_setup(void)
switch (virtio_get_device()->ipl_type) {
case S390_IPL_TYPE_CCW:
return virtio_ccw_net_setup();
+ case S390_IPL_TYPE_PCI:
+ return virtio_pci_net_setup();
default:
return false;
}
diff --git a/pc-bios/s390-ccw/virtio-pci.c b/pc-bios/s390-ccw/virtio-pci.c
index f501252c81..c7d62766b8 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;
@@ -458,3 +476,28 @@ int virtio_pci_setup_device(void)
return 0;
}
+
+static bool find_pci_net_dev(void)
+{
+ if (!virtio_is_supported(virtio_get_device())) {
+ return false;
+ }
+
+ if (virtio_get_device_type() != VIRTIO_ID_NET) {
+ return false;
+ }
+
+ return true;
+}
+
+bool virtio_pci_net_setup(void)
+{
+ bool found = false;
+
+ if (have_iplb || store_iplb(&iplb)) {
+ IPL_assert(iplb.pbt == S390_IPL_TYPE_PCI, "IPL_TYPE_PCI expected");
+ found = find_pci_net_dev();
+ }
+
+ return found;
+}
diff --git a/pc-bios/s390-ccw/virtio-pci.h b/pc-bios/s390-ccw/virtio-pci.h
index 33b683bd92..2c3136fd05 100644
--- a/pc-bios/s390-ccw/virtio-pci.h
+++ b/pc-bios/s390-ccw/virtio-pci.h
@@ -70,6 +70,8 @@ long virtio_pci_notify(VRing *vr);
bool virtio_pci_is_supported(VDev *vdev);
int virtio_pci_setup(VDev *vdev);
int virtio_pci_setup_device(void);
+bool virtio_pci_is_supported(VDev *vdev);
+bool virtio_pci_net_setup(void);
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);
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v1 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x
2026-08-18 20:53 [PATCH v1 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
` (3 preceding siblings ...)
2026-08-18 20:53 ` [PATCH v1 4/7] pc-bios/s390-ccw: Add support for virtio-net-pci IPL Zhuoying Cai
@ 2026-08-18 20:53 ` Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 6/7] tests/qtest: Add s390x virtio net PCI test to pxe-test.c Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 7/7] tests/functional/s390x: Add tests for virtio net PCI in test_pxelinux.py Zhuoying Cai
6 siblings, 0 replies; 8+ messages in thread
From: Zhuoying Cai @ 2026-08-18 20:53 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, pbonzini
s390x PCI IPL devices require a "loadparm" property. Add it to virtio-net-pci
to support booting from it on s390x.
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] 8+ messages in thread
* [PATCH v1 6/7] tests/qtest: Add s390x virtio net PCI test to pxe-test.c
2026-08-18 20:53 [PATCH v1 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
` (4 preceding siblings ...)
2026-08-18 20:53 ` [PATCH v1 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x Zhuoying Cai
@ 2026-08-18 20:53 ` Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 7/7] tests/functional/s390x: Add tests for virtio net PCI in test_pxelinux.py Zhuoying Cai
6 siblings, 0 replies; 8+ messages in thread
From: Zhuoying Cai @ 2026-08-18 20:53 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, 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>
---
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 f7c7d06620..94e2555935 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -281,6 +281,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 a3f900fbea..d4b74e28cd 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] 8+ messages in thread
* [PATCH v1 7/7] tests/functional/s390x: Add tests for virtio net PCI in test_pxelinux.py
2026-08-18 20:53 [PATCH v1 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
` (5 preceding siblings ...)
2026-08-18 20:53 ` [PATCH v1 6/7] tests/qtest: Add s390x virtio net PCI test to pxe-test.c Zhuoying Cai
@ 2026-08-18 20:53 ` Zhuoying Cai
6 siblings, 0 replies; 8+ messages in thread
From: Zhuoying Cai @ 2026-08-18 20:53 UTC (permalink / raw)
To: qemu-devel, qemu-s390x
Cc: mst, jrossi, zycai, borntraeger, jjherne, cohuck, farman,
mjrosato, pasic, farosas, lvivier, 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>
---
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] 8+ messages in thread
end of thread, other threads:[~2026-08-18 20:55 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-18 20:53 [PATCH v1 0/7] s390x: Add support for virtio-net-pci boot device Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 1/7] pc-bios/s390-ccw: Split virtio-ccw and generic virtio net Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 2/7] pc-bios/s390-ccw: Add dynamic net header size handling Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 3/7] pc-bios/s390-ccw: Introduce virtio_tswap helpers Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 4/7] pc-bios/s390-ccw: Add support for virtio-net-pci IPL Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 5/7] hw/virtio: Add "loadparm" property to virtio net PCI devices booting on s390x Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 6/7] tests/qtest: Add s390x virtio net PCI test to pxe-test.c Zhuoying Cai
2026-08-18 20:53 ` [PATCH v1 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.