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