Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp1058310pxb; Wed, 6 Apr 2022 07:46:04 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxdrKFwj76FCbrhiHdbl8C7UggrpWblZy2KqnUSUQJWBlyRi+FayZxsdkqD48ksSDzhdqq9 X-Received: by 2002:a63:f452:0:b0:382:7af1:6ad6 with SMTP id p18-20020a63f452000000b003827af16ad6mr7371389pgk.500.1649256363897; Wed, 06 Apr 2022 07:46:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649256363; cv=none; d=google.com; s=arc-20160816; b=pZng1+HxRX/SKyM/6UChrI8o6/Tt16Srn4fNcvaqK9hRm5LY3HaEsJcQcuIIltkSgU yhTQIbMd/gEyjukLke09tKl3cnWVSch40PyMXkWhfZvVDaukSNj24Jqj5lliI4QDsOgP GZ1/OducboF3CpbqmqYcQu4j1KiX+sPJyVI91P1LcUFp//cStMig6R7rQ8xW0y6J0/hv 2wIvXxPIS0k91h7EycCr4+MG6//9UbeIifEipMljc7ownhfNVBcFK7UKb6Ie6HdECkiC 6X+KBnNZryWL8ZKGuoQfj9NOdYiScMRZkvrFPDrzcxo9h5v9Zp3Jex133Obx0bQeUTqB uRqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=RXRl5yVraFjtAHNeuo8Tj/7VeEPbPvmJda7LXPVTN00=; b=n7awG21C5KTfUUJZbNZDJtqUdqXLHRJrReaM+6jE3ZayQ2VMQ9914yzQxxRKI7s6Op Nt3tM57ktFw9YsqEjH92uQtT92PVnJRb3oqm6hAfN7ji9w7C14k4uz15hQBNGzxLBTUf t8nB3VJVwGz6E/hjOhu+fR5SMYUMP23wrqc7WJvXY6iH3p4R6lH4MvaYewtfMYbMoKpR fieA/HEOByq2QOhFLC/KYD2lcyo/dCb1Ci9bFjhAfhWIiQZQ+ycaZp9lIBRFAQHAUe3b R+mzqJCo0ZN/JHjakjBMNtrflMN56CoH8RCfhSBtLqefyehLvfkTgckrXnxqjuATeV4X /f2A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="RikE92o/"; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id me17-20020a17090b17d100b001c6edf679b4si5360549pjb.46.2022.04.06.07.46.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 Apr 2022 07:46:03 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="RikE92o/"; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E2C3D6C098A; Wed, 6 Apr 2022 05:48:10 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229814AbiDFMg5 (ORCPT + 99 others); Wed, 6 Apr 2022 08:36:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49168 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231450AbiDFMeS (ORCPT ); Wed, 6 Apr 2022 08:34:18 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2C1641B29C3 for ; Wed, 6 Apr 2022 01:36:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1649234201; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RXRl5yVraFjtAHNeuo8Tj/7VeEPbPvmJda7LXPVTN00=; b=RikE92o/kxvWj/75Bxg+5qCSXgMeey8Qg6d3qciE8i9a0yibFBXxNWiBSr6ZfJ/wqIoq/p mpHk5XDGV45RM3z5YI4lvPi+21VpuL8mjV6EIRu+PT7/TBsHe8kQg6Pt9h3FyTPKEiJpaJ dAYcwlMbYR3/6h5l4F0CwnBijmdw/6E= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-652-ipVoKGptOI24T9gwiW2-gA-1; Wed, 06 Apr 2022 04:36:38 -0400 X-MC-Unique: ipVoKGptOI24T9gwiW2-gA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id EBC763822204; Wed, 6 Apr 2022 08:36:37 +0000 (UTC) Received: from localhost.localdomain (ovpn-12-58.pek2.redhat.com [10.72.12.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 97A9F1121319; Wed, 6 Apr 2022 08:36:20 +0000 (UTC) From: Jason Wang To: mst@redhat.com, jasowang@redhat.com Cc: virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, maz@kernel.org, tglx@linutronix.de, peterz@infradead.org, sgarzare@redhat.com, "Paul E. McKenney" Subject: [PATCH V2 5/5] virtio: harden vring IRQ Date: Wed, 6 Apr 2022 16:35:38 +0800 Message-Id: <20220406083538.16274-6-jasowang@redhat.com> In-Reply-To: <20220406083538.16274-1-jasowang@redhat.com> References: <20220406083538.16274-1-jasowang@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This is a rework on the previous IRQ hardening that is done for virtio-pci where several drawbacks were found and were reverted: 1) try to use IRQF_NO_AUTOEN which is not friendly to affinity managed IRQ that is used by some device such as virtio-blk 2) done only for PCI transport In this patch, we tries to borrow the idea from the INTX IRQ hardening in the reverted commit 080cd7c3ac87 ("virtio-pci: harden INTX interrupts") by introducing a global device_ready variable for each virtio_device. Then we can to toggle it during virtio_reset_device()/virtio_device_ready(). A virtio_synchornize_vqs() is used in both virtio_device_ready() and virtio_reset_device() to synchronize with the vring callbacks. With this, vring_interrupt() can return check and early if driver_ready is false. Note that the hardening is only done for vring interrupt since the config interrupt hardening is already done in commit 22b7050a024d7 ("virtio: defer config changed notifications"). But the method that is used by config interrupt can't be reused by the vring interrupt handler because it uses spinlock to do the synchronization which is expensive. Cc: Thomas Gleixner Cc: Peter Zijlstra Cc: "Paul E. McKenney" Cc: Marc Zyngier Signed-off-by: Jason Wang --- drivers/virtio/virtio.c | 11 +++++++++++ drivers/virtio/virtio_ring.c | 9 ++++++++- include/linux/virtio.h | 2 ++ include/linux/virtio_config.h | 8 ++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 8dde44ea044a..2f3a6f8e3d9c 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -220,6 +220,17 @@ static int virtio_features_ok(struct virtio_device *dev) * */ void virtio_reset_device(struct virtio_device *dev) { + if (READ_ONCE(dev->driver_ready)) { + /* + * The below virtio_synchronize_vqs() guarantees that any + * interrupt for this line arriving after + * virtio_synchronize_vqs() has completed is guaranteed to see + * driver_ready == false. + */ + WRITE_ONCE(dev->driver_ready, false); + virtio_synchronize_vqs(dev); + } + dev->config->reset(dev); } EXPORT_SYMBOL_GPL(virtio_reset_device); diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index cfb028ca238e..a4592e55c9f8 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -2127,10 +2127,17 @@ static inline bool more_used(const struct vring_virtqueue *vq) return vq->packed_ring ? more_used_packed(vq) : more_used_split(vq); } -irqreturn_t vring_interrupt(int irq, void *_vq) +irqreturn_t vring_interrupt(int irq, void *v) { + struct virtqueue *_vq = v; + struct virtio_device *vdev = _vq->vdev; struct vring_virtqueue *vq = to_vvq(_vq); + if (!READ_ONCE(vdev->driver_ready)) { + dev_warn_once(&vdev->dev, "virtio vring IRQ raised before DRIVER_OK"); + return IRQ_NONE; + } + if (!more_used(vq)) { pr_debug("virtqueue interrupt with no work for %p\n", vq); return IRQ_NONE; diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 5464f398912a..dfa2638a293e 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -95,6 +95,7 @@ dma_addr_t virtqueue_get_used_addr(struct virtqueue *vq); * @failed: saved value for VIRTIO_CONFIG_S_FAILED bit (for restore) * @config_enabled: configuration change reporting enabled * @config_change_pending: configuration change reported while disabled + * @driver_ready: whehter the driver is ready (e.g for vring callbacks) * @config_lock: protects configuration change reporting * @dev: underlying device. * @id: the device type identification (used to match it with a driver). @@ -109,6 +110,7 @@ struct virtio_device { bool failed; bool config_enabled; bool config_change_pending; + bool driver_ready; spinlock_t config_lock; spinlock_t vqs_list_lock; /* Protects VQs list access */ struct device dev; diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 08b73d9bbff2..c9e207bf2c9c 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -246,6 +246,14 @@ void virtio_device_ready(struct virtio_device *dev) { unsigned status = dev->config->get_status(dev); + virtio_synchronize_vqs(dev); + /* + * The above virtio_synchronize_vqs() make sure + * vring_interrupt() will see the driver specific setup if it + * see driver_ready as true. + */ + WRITE_ONCE(dev->driver_ready, true); + BUG_ON(status & VIRTIO_CONFIG_S_DRIVER_OK); dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK); } -- 2.25.1