From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B5D11211A28 for ; Fri, 24 Apr 2026 04:08:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.173 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777003684; cv=none; b=hnSZdog6LcWQ0k6S6gcKaECXI45GmPw5jzCO/kBwI/IsQi3N+pawHKuypNl4d5H5i96bjXjmAzwWSOf5RVW5axj5Hddx4UA3b/RhvUvdsvRBUy3mMN/KaRZenNSFdmaymFIiSDyDShoOlv/edPSnGn361vYAQMSMVhLOFbAB8nw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777003684; c=relaxed/simple; bh=1jqgqePiCpWS5lWhDTPGPcI+gdO+taxTOjKbPiuxaMs=; h=Message-ID:From:To:Cc:Date:Subject:In-Reply-To:References: MIME-Version:Content-Type; b=a4qkKPcl5SpuXR8AM/faWWgTTodgaLfbgCi1YGAGVCri4dnvqkFCE1oJckY6Zw4AjuXxfYNXLgj0APPsM+bwHJVCc/mUr75eH8skPhFaK89KUYyGvmFGYtyRCR9YX/wYnyr6UZswZJfdZNfLGWAsiujORmamooim8FwbE5e/3jI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YtRT9oGK; arc=none smtp.client-ip=209.85.210.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YtRT9oGK" Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-82f8892d4d6so3259462b3a.0 for ; Thu, 23 Apr 2026 21:08:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777003682; x=1777608482; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :subject:date:cc:to:from:message-id:from:to:cc:subject:date :message-id:reply-to; bh=ebTz24LbM5JUkJMnX0UTG9L5NdW7NGB2BYBIfLQKtDU=; b=YtRT9oGKYRVqxoSqTc112dQCC5Q+uU1+jpdKmrrEqD9IVNf/bc++i7h+u6Ko+ncthR cgiadn1gxK2qBYPgL4cqqMafkWYg2LyM+dqYLhVXWee1MUZjyegL+KlP0xHIgm/A1zh9 Lpl30WY/meGKql8hg88IVeZNomoz7iIjEE+KWvHHNL9sTZtu04XyLGNJ6DI7WccoDWi+ hqnbtiVe/F8U1cCWHB/spzbX7x2mgAJ6xTFX93Gz+hm1t3vHITu3TPtsvfI3e0SvTrtj MsqGqrUCq8MxDy8ioYm7xI1Wy4DSYRAniyaFi5GAev1xT1rlEMpgSycmdxOJQl9hbjUw zgIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777003682; x=1777608482; h=content-transfer-encoding:mime-version:references:in-reply-to :subject:date:cc:to:from:message-id:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ebTz24LbM5JUkJMnX0UTG9L5NdW7NGB2BYBIfLQKtDU=; b=gtm6o19+QM0mm8YnPHG8wcVVjD2N4x6390lZGUuVU2tjoVKiu+M0LfZc70pjC/XqiN kQ686tWawGuYMx3FCg4NgSI0SzwgnG0YSnBdquH4M1niMtLv4MTlZbV/QDZb62RgNI5L JfY9U59vnSc05bw8oAqdNAks7v8oT8tFUQ59cHR0jOBYYXFuN63I+Y83VM+9aM+4O60c 8h9qCbPKxmORBWaRJ7rkSrx5dZA6HaQ7rE/NXLPvokyY7PnXdmUiNLoOn+496HtE5bfZ JeRx2ARAE5WrhS/+lKraKBJMlME8KPE6ljkYhrT2pNUOJ2QlF6PDxL4FkiY9ZwMl5kcY MSpw== X-Forwarded-Encrypted: i=1; AFNElJ9/IVbCPqB/JrCQZrLYB9zZ/0RFegDPV5svD6vYq5L4jG90qseNJ73NP/gDrCQtQKeIZyGkCfkG7pZtvP0=@vger.kernel.org X-Gm-Message-State: AOJu0Yyg6zxfTsN7hY8uvMwZGrjM8EAc6WDSY7EaLV60CzO68WMOUnMD UeK7Rry4T/EKEZD4HgM8AKqXzTaC0nLMEtKN1SKhSLz97AhndQVrkHdI X-Gm-Gg: AeBDiet1S6L1SGmU6koWty0EqoTNUjI28/HpZBVr1eM0Gq84Y8DWIVSldCrfbQhCH6Z 5L7+C/N+PYC3JodezYK45wskkbNU7eHvn9//pjiFPHKY5lvNzsrb804w9GLZVydwOIBmjSMsBFD oz3/lGz0i0Fv0R7HFU0Dp58QSJ2IGSuKNsPcK821tLL0v3I+U2N88om+RLPrR1jhl+Yxv1c4aib 5u9OeD7QP4w8KD04o9rNxHB5K4DC9SQIawkXP0Fr3jltXgn7hfclbrLDeENkA/B/VuI2uAm0kK5 NnV2fIsFEMzrkDVdJa40f/GNKlve6s0YQ1AYj7hNPnQzZpNhD3+fGjhkH+uLKnDFRgEGTRYR1g9 fPR1wN5xnznxSzJn/fSkGD5vgJ2vijLq40vnHfbxJAnj82icb90RBc2DLXlPJD42a5tWXpl2Gsg uKV3LxC4Jd3vgTbF6boQCBLGorKrRx1eBCMEeGLbg= X-Received: by 2002:a05:6a00:aa08:b0:82c:66f2:1226 with SMTP id d2e1a72fcca58-82f8c8e4febmr30231789b3a.38.1777003681389; Thu, 23 Apr 2026 21:08:01 -0700 (PDT) Received: from [127.0.1.1] ([188.253.126.216]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8e9d2f9asm23197324b3a.19.2026.04.23.21.07.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Apr 2026 21:08:00 -0700 (PDT) Message-ID: <69eaeca0.050a0220.408e2.027b@mx.google.com> From: JiaJia To: Peter Hilber Cc: mst@redhat.com, jasowang@redhat.com, xuanzhuo@linux.alibaba.com, eperezma@redhat.com, virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, physicalmtea@gmail.com Date: Fri, 24 Apr 2026 11:14:53 +0800 Subject: [PATCH v2] virtio: rtc: tear down old virtqueues before restore In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit virtio_device_restore() resets the device and restores the negotiated features before calling ->restore(). viortc_freeze() intentionally leaves the existing virtqueues in place so the alarm queue can still wake the system, but viortc_restore() immediately calls viortc_init_vqs() without first deleting those old queues. If virtqueue reinitialization fails on virtio-pci, the transport error path can run vp_del_vqs() against a newly allocated vp_dev->vqs array while vdev->vqs still contains the old virtqueues. vp_del_vqs() then looks up queue state through the new array and can dereference a NULL info pointer in vp_del_vq(), crashing the guest kernel during restore. Delete the stale virtqueues before rebuilding them. If restore fails before virtio_device_ready(), reuse the remove path to stop the device. Once the device is ready, return errors directly instead of deleting the virtqueues again. Signed-off-by: JiaJia --- Hi Peter, thanks for taking a look and for pointing this out. I took another look at the restore path and agree that deleting the virtqueues from that error path can race with `viortc_cb_alarmq()` once the device has been readied. This v2 follows the direction you suggested. It factors out `__viortc_remove()`, reuses that path for restore failures before `virtio_device_ready()`, routes `viortc_init_vqs()` failures in probe through `err_reset_vdev` for consistent teardown, drops the `viortc_del_vqs()` helper and the `viortc_msg_xfer()` NULL-vq guard, and avoids deleting the virtqueues again after `virtio_device_ready()`. Thanks, JiaJia v2: - reuse the remove path for restore failures before virtio_device_ready() - route viortc_init_vqs() failures in probe through err_reset_vdev - drop the viortc_del_vqs() helper and the viortc_msg_xfer() NULL-vq guard - avoid deleting virtqueues again after virtio_device_ready() drivers/virtio/virtio_rtc_driver.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/virtio/virtio_rtc_driver.c b/drivers/virtio/virtio_rtc_driver.c index a57d5e06e..4419735b0 100644 --- a/drivers/virtio/virtio_rtc_driver.c +++ b/drivers/virtio/virtio_rtc_driver.c @@ -1257,6 +1257,15 @@ static int viortc_init_vqs(struct viortc_dev *viortc) return 0; } +static void __viortc_remove(struct viortc_dev *viortc) +{ + struct virtio_device *vdev = viortc->vdev; + + viortc_clocks_deinit(viortc); + virtio_reset_device(vdev); + vdev->config->del_vqs(vdev); +} + /** * viortc_probe() - probe a virtio_rtc virtio device * @vdev: virtio device @@ -1282,7 +1291,7 @@ static int viortc_probe(struct virtio_device *vdev) ret = viortc_init_vqs(viortc); if (ret) - return ret; + goto err_reset_vdev; virtio_device_ready(vdev); @@ -1329,10 +1338,7 @@ static void viortc_remove(struct virtio_device *vdev) { struct viortc_dev *viortc = vdev->priv; - viortc_clocks_deinit(viortc); - - virtio_reset_device(vdev); - vdev->config->del_vqs(vdev); + __viortc_remove(viortc); } static int viortc_freeze(struct virtio_device *dev) @@ -1353,9 +1359,11 @@ static int viortc_restore(struct virtio_device *dev) bool notify = false; int ret; + dev->config->del_vqs(dev); + ret = viortc_init_vqs(viortc); if (ret) - return ret; + goto err_remove; alarm_viortc_vq = &viortc->vqs[VIORTC_ALARMQ]; alarm_vq = alarm_viortc_vq->vq; @@ -1364,7 +1372,7 @@ static int viortc_restore(struct virtio_device *dev) ret = viortc_populate_vq(viortc, alarm_viortc_vq, VIORTC_ALARMQ_BUF_CAP, false); if (ret) - return ret; + goto err_remove; notify = virtqueue_kick_prepare(alarm_vq); } @@ -1372,8 +1380,12 @@ static int viortc_restore(struct virtio_device *dev) virtio_device_ready(dev); if (notify && !virtqueue_notify(alarm_vq)) - ret = -EIO; + return -EIO; + + return 0; +err_remove: + __viortc_remove(viortc); return ret; } -- 2.34.1