Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
Re: vmd: Alpine VM no longer boots after sysupgrade -s (vioblk_notifyq errors)
To:
R??mi Bougard <rb@unicsdev.com>
Cc:
tech@openbsd.org
Date:
Fri, 29 May 2026 16:50:37 +0200

Download raw body.

Thread
On Fri, May 29, 2026 at 12:34:17PM +0200, R??mi Bougard wrote:
> Since a last sysupgrade -s this morning, my Alpine Linux VM no longer boots under vmd.

This is a known problem after a recent commit.

> Can someone help ?

This is the current diff to fix vmd, but not final yet.
Can you test it?

bluhm

diff refs/heads/master refs/heads/vmd-errata
commit - 8563f41508594d8b3f824527f23a7a1bb9c70a71
commit + 9597b051c8f924783792899f5b4d700271ac31d2
blob - 3b1b37133c24556b7b2d5db51d037861aaf0a515
blob + 6c44608f6eb7d455ae440d0acefa2e874de14cea
--- usr.sbin/vmd/virtio.c
+++ usr.sbin/vmd/virtio.c
@@ -196,7 +196,7 @@ virtio_update_qa(struct virtio_dev *dev)
 {
 	struct virtio_vq_info *vq_info = NULL;
 	void *hva = NULL;
-	uint32_t expected_avail, expected_used, availoff, usedoff;
+	uint64_t availoff, usedoff, availsz, usedsz;

 	if (dev->driver_feature & VIRTIO_F_VERSION_1) {
 		if (dev->pci_cfg.queue_select >= dev->num_queues) {
@@ -213,24 +213,38 @@ virtio_update_qa(struct virtio_dev *dev)
 		vq_info->qs = dev->pci_cfg.queue_size;
 		vq_info->mask = vq_info->qs - 1;

-		/* Only enable the queue if the avail and used pointers are valid */
+		/*
+		 * Require the available (driver) and used (device) area to be
+		 * similar to Virtio 0.9 but support Virtio 1.x alignment.
+		 */
 		if (dev->pci_cfg.queue_avail < dev->pci_cfg.queue_desc ||
 		    dev->pci_cfg.queue_used < dev->pci_cfg.queue_desc) {
 			vq_info->vq_enabled = 0;
 			return;
 		}

-		/* Require the avail and used pointers to be set as per Virtio 0.9 */
-		expected_avail = sizeof(struct vring_desc) * vq_info->qs;
-		expected_used = VIRTQUEUE_ALIGN(expected_avail +
-		    sizeof(uint16_t) * (2 + vq_info->qs));
 		availoff = dev->pci_cfg.queue_avail - dev->pci_cfg.queue_desc;
 		usedoff = dev->pci_cfg.queue_used - dev->pci_cfg.queue_desc;
-		if (availoff != expected_avail || usedoff != expected_used) {
+		if (availoff > UINT32_MAX || usedoff > UINT32_MAX ||
+		    (usedoff & 3) != 0) {
 			vq_info->vq_enabled = 0;
 			return;
 		}

+		availsz = sizeof(uint16_t) * (2 + vq_info->qs);
+		usedsz = (sizeof(uint16_t) * 2) +
+		    (sizeof(struct vring_used_elem) * vq_info->qs);
+		hva = hvaddr_mem(dev->pci_cfg.queue_desc + availoff, availsz);
+		if (hva == NULL) {
+			vq_info->vq_enabled = 0;
+			return;
+		}
+		hva = hvaddr_mem(dev->pci_cfg.queue_desc + usedoff, usedsz);
+		if (hva == NULL) {
+			vq_info->vq_enabled = 0;
+			return;
+		}
+
 		if (vq_info->qs > 0 && vq_info->qs % 2 == 0) {
 			vq_info->vq_availoffset = availoff;
 			vq_info->vq_usedoffset = usedoff;