Skip to content

Commit 68c95ed

Browse files
committed
pc-bios/s390-ccw: Fix boot problem with virtio-net devices
When we are trying to boot from virtio-net devices, the s390-ccw bios currently leaves the virtio-net device enabled after using it. That means that the receiving virt queues will continue to happily write incoming network packets into memory. This can corrupt data of the following boot process. For example, if you set up a second guest on a virtual network and create a lot of broadcast traffic there, e.g. with: ping -i 0.02 -s 1400 -b 192.168.1.255 and then you try to boot a guest with two boot devices, a network device first (which should not be bootable) and e.g. a bootable SCSI CD second, then this guest will fail to load the kernel from the CD image: $ qemu-system-s390x -m 2G -nographic -device virtio-scsi-ccw \ -netdev tap,id=net0 -device virtio-net-ccw,netdev=net0,bootindex=1 \ -drive if=none,file=test.iso,format=raw,id=cd1 \ -device scsi-cd,drive=cd1,bootindex=2 LOADPARM=[ ] Network boot device detected Network boot starting... Using MAC address: 52:54:00:12:34:56 Requesting information via DHCP: done Using IPv4 address: 192.168.1.76 Using TFTP server: 192.168.1.1 Trying pxelinux.cfg files... TFTP error: ICMP ERROR "port unreachable" Receiving data: 0 KBytes Repeating TFTP read request... TFTP error: ICMP ERROR "port unreachable" Failed to load OS from network. Failed to IPL from this network! LOADPARM=[ ] Using virtio-scsi. ! virtio-scsi:setup:inquiry: response VS RESP=ff ! ERROR: No suitable device for IPL. Halting... We really have to shut up the virtio-net devices after we're not using it anymore. The easiest way to do this is to simply reset the device, so let's do that now. Reviewed-by: Jared Rossi <jrossi@linux.ibm.com> Reviewed-by: Eric Farman <farman@linux.ibm.com> Tested-by: Jared Rossi <jrossi@linux.ibm.com> Message-ID: <20250116115826.192047-3-thuth@redhat.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
1 parent 3936d05 commit 68c95ed

File tree

3 files changed

+29
-10
lines changed

3 files changed

+29
-10
lines changed

pc-bios/s390-ccw/netmain.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -153,19 +153,10 @@ static int tftp_load(filename_ip_t *fnip, void *buffer, int len)
153153
return rc;
154154
}
155155

156-
static int net_init(filename_ip_t *fn_ip)
156+
static int net_init_ip(filename_ip_t *fn_ip)
157157
{
158158
int rc;
159159

160-
memset(fn_ip, 0, sizeof(filename_ip_t));
161-
162-
rc = virtio_net_init(mac);
163-
if (rc < 0) {
164-
puts("Could not initialize network device");
165-
return -101;
166-
}
167-
fn_ip->fd = rc;
168-
169160
printf(" Using MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
170161
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
171162

@@ -221,11 +212,33 @@ static int net_init(filename_ip_t *fn_ip)
221212
return rc;
222213
}
223214

215+
static int net_init(filename_ip_t *fn_ip)
216+
{
217+
int rc;
218+
219+
memset(fn_ip, 0, sizeof(filename_ip_t));
220+
221+
rc = virtio_net_init(mac);
222+
if (rc < 0) {
223+
puts("Could not initialize network device");
224+
return -101;
225+
}
226+
fn_ip->fd = rc;
227+
228+
rc = net_init_ip(fn_ip);
229+
if (rc < 0) {
230+
virtio_net_deinit();
231+
}
232+
233+
return rc;
234+
}
235+
224236
static void net_release(filename_ip_t *fn_ip)
225237
{
226238
if (fn_ip->ip_version == 4) {
227239
dhcp_send_release(fn_ip->fd);
228240
}
241+
virtio_net_deinit();
229242
}
230243

231244
/**

pc-bios/s390-ccw/virtio-net.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,8 @@ int recv(int fd, void *buf, int maxlen, int flags)
140140

141141
return len;
142142
}
143+
144+
void virtio_net_deinit(void)
145+
{
146+
virtio_reset(virtio_get_device());
147+
}

pc-bios/s390-ccw/virtio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,5 +278,6 @@ int virtio_reset(VDev *vdev);
278278
int virtio_setup_ccw(VDev *vdev);
279279

280280
int virtio_net_init(void *mac_addr);
281+
void virtio_net_deinit(void);
281282

282283
#endif /* VIRTIO_H */

0 commit comments

Comments
 (0)