Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp1203662pxj; Fri, 21 May 2021 08:42:45 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwkty3iz3VCBKzR1uwlnq7e6gegt5deuiLeeZtTfEgoKLGDt52lunIaAKMzoZFyBXl+e/+8 X-Received: by 2002:a6b:e719:: with SMTP id b25mr11182122ioh.49.1621611765678; Fri, 21 May 2021 08:42:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621611765; cv=none; d=google.com; s=arc-20160816; b=cxZM/atQV5fYMiBsmW8RbTNoowM/XHJTTbBWDzNZ1wnHbL8tyDeyktVhp5wMEFngla XKUTuuPcJAspp+RZnjvAVSa29tAWAXC/KtqfJ2TiETGy3rsZ5sLT0luRACyHU/eLiQ5U dvyY8Hyy5fX/wxGSSNnuP6bKU4ealmejAIOuUxmFNWrqXuGshHAbBKGaYVL7J1829ef7 U+Uy5zI4ZoiIE8htDKtcKXzfrAW+H7CW2UEtoGsO07MkjuxUC/VoAmoh+kdv4RN79Dvy IbUjXvas9XCsJgUIV2gGDJm/6kaTGoIcrJXeMO1h6FWxdsO3qeebF/IE0uH+8nlUkWH8 iVzQ== 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; bh=qIU4qSal+m78Cj0ZB5o8NNi/UKs+JUH6yCF96Epcvs8=; b=EazH32Vn++mgNHiXoitO95v1jC3yVcqapPP+lb8/aZIOd4EbjFUVW8OYaiwTPCchaM K1G7v8t5ODz40ZdlW1BwFozUdTxfrmRI4W6QGxsLHsF4u/Dqsv5pqEILrNFU94m+XfbV ipO2TDAd4ZQANXnmL2V76oYDxbCER5KJhuvGgYP7Ve0sTWHHmc2HY/O6EvaDaS1TPov/ osroVXv1sdkfUGSaOFUhziUEBSdPuuAtvr4OxZxLx86KzHF3B3eK2xj06VCWe43NZJQA wdvQLj81iXDkZ59LyvJ9QQTzDSAKJEx1seB73AQjAJpiq24GGdvotyetAShyqp+INam7 zOIg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id m17si5687262ilg.130.2021.05.21.08.42.31; Fri, 21 May 2021 08:42:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234234AbhETRAK (ORCPT + 99 others); Thu, 20 May 2021 13:00:10 -0400 Received: from mail.kernel.org ([198.145.29.99]:56832 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234162AbhETQ7F (ORCPT ); Thu, 20 May 2021 12:59:05 -0400 Received: from disco-boy.misterjones.org (disco-boy.misterjones.org [51.254.78.96]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2AF6D613CC; Thu, 20 May 2021 16:57:42 +0000 (UTC) Received: from 78.163-31-62.static.virginmediabusiness.co.uk ([62.31.163.78] helo=why.lan) by disco-boy.misterjones.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1ljlgg-002d7b-T8; Thu, 20 May 2021 17:38:19 +0100 From: Marc Zyngier To: linux-kernel@vger.kernel.org Cc: Thomas Gleixner , Michael Ellerman , Benjamin Herrenschmidt , Paul Mackerras , Ley Foon Tan , Chris Zankel , Max Filippov , Vineet Gupta , Thomas Bogendoerfer , Robert Jarzmik , Russell King , Krzysztof Kozlowski , Yoshinori Sato , Rich Felker , Geert Uytterhoeven , Alex Deucher , =?UTF-8?q?Christian=20K=C3=B6nig?= , David Airlie , Daniel Vetter , Rob Clark , Linus Walleij , Lee Jones , Lorenzo Pieralisi , Rob Herring , Bjorn Helgaas , Bartosz Golaszewski , kernel-team@android.com Subject: [PATCH 20/39] irqdomain: Protect the linear revmap with RCU Date: Thu, 20 May 2021 17:37:32 +0100 Message-Id: <20210520163751.27325-21-maz@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210520163751.27325-1-maz@kernel.org> References: <20210520163751.27325-1-maz@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SA-Exim-Connect-IP: 62.31.163.78 X-SA-Exim-Rcpt-To: linux-kernel@vger.kernel.org, tglx@linutronix.de, mpe@ellerman.id.au, benh@kernel.crashing.org, paulus@samba.org, ley.foon.tan@intel.com, chris@zankel.net, jcmvbkbc@gmail.com, vgupta@synopsys.com, tsbogend@alpha.franken.de, robert.jarzmik@free.fr, linux@armlinux.org.uk, krzysztof.kozlowski@canonical.com, ysato@users.sourceforge.jp, dalias@libc.org, geert@linux-m68k.org, alexander.deucher@amd.com, christian.koenig@amd.com, airlied@linux.ie, daniel@ffwll.ch, robdclark@gmail.com, linus.walleij@linaro.org, lee.jones@linaro.org, lorenzo.pieralisi@arm.com, robh@kernel.org, bhelgaas@google.com, bgolaszewski@baylibre.com, kernel-team@android.com X-SA-Exim-Mail-From: maz@kernel.org X-SA-Exim-Scanned: No (on disco-boy.misterjones.org); SAEximRunCond expanded to false Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org It is pretty odd that the radix tree uses RCU while the linear portion doesn't, leading to potential surprises for the users, depending on how the irqdomain has been created. Fix this by moving the update of the linear revmap under the mutex, and the lookup under the RCU read-side lock. The mutex name is updated to reflect that it doesn't only cover the radix-tree anymore. Signed-off-by: Marc Zyngier --- include/linux/irqdomain.h | 5 +++-- kernel/irq/irqdomain.c | 38 ++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 340cc04611dd..2b696c9bcaaf 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -151,6 +151,7 @@ struct irq_domain_chip_generic; * Revmap data, used internally by irq_domain * @revmap_size: Size of the linear map table @revmap[] * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map + * @revmap_mutex: Lock for the revmap * @revmap: Linear table of irq_data pointers */ struct irq_domain { @@ -173,8 +174,8 @@ struct irq_domain { irq_hw_number_t hwirq_max; unsigned int revmap_size; struct radix_tree_root revmap_tree; - struct mutex revmap_tree_mutex; - struct irq_data *revmap[]; + struct mutex revmap_mutex; + struct irq_data __rcu *revmap[]; }; /* Irq domain flags */ diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index ed2ffffc6fc6..8e55bb8c3073 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -213,7 +213,7 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size, /* Fill structure */ INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL); - mutex_init(&domain->revmap_tree_mutex); + mutex_init(&domain->revmap_mutex); domain->ops = ops; domain->host_data = host_data; domain->hwirq_max = hwirq_max; @@ -505,13 +505,12 @@ static void irq_domain_set_mapping(struct irq_domain *domain, if (irq_domain_is_nomap(domain)) return; - if (hwirq < domain->revmap_size) { - domain->revmap[hwirq] = irq_data; - } else { - mutex_lock(&domain->revmap_tree_mutex); + mutex_lock(&domain->revmap_mutex); + if (hwirq < domain->revmap_size) + rcu_assign_pointer(domain->revmap[hwirq], irq_data); + else radix_tree_insert(&domain->revmap_tree, hwirq, irq_data); - mutex_unlock(&domain->revmap_tree_mutex); - } + mutex_unlock(&domain->revmap_mutex); } static void irq_domain_clear_mapping(struct irq_domain *domain, @@ -902,12 +901,12 @@ unsigned int irq_find_mapping(struct irq_domain *domain, return 0; } + rcu_read_lock(); /* Check if the hwirq is in the linear revmap. */ if (hwirq < domain->revmap_size) - return domain->revmap[hwirq]->irq; - - rcu_read_lock(); - data = radix_tree_lookup(&domain->revmap_tree, hwirq); + data = rcu_dereference(domain->revmap[hwirq]); + else + data = radix_tree_lookup(&domain->revmap_tree, hwirq); rcu_read_unlock(); return data ? data->irq : 0; } @@ -1490,18 +1489,17 @@ static void irq_domain_fix_revmap(struct irq_data *d) if (irq_domain_is_nomap(d->domain)) return; + /* Fix up the revmap. */ + mutex_lock(&d->domain->revmap_mutex); if (d->hwirq < d->domain->revmap_size) { /* Not using radix tree */ - d->domain->revmap[d->hwirq] = d; - return; + rcu_assign_pointer(d->domain->revmap[d->hwirq], d); + } else { + slot = radix_tree_lookup_slot(&d->domain->revmap_tree, d->hwirq); + if (slot) + radix_tree_replace_slot(&d->domain->revmap_tree, slot, d); } - - /* Fix up the revmap. */ - mutex_lock(&d->domain->revmap_tree_mutex); - slot = radix_tree_lookup_slot(&d->domain->revmap_tree, d->hwirq); - if (slot) - radix_tree_replace_slot(&d->domain->revmap_tree, slot, d); - mutex_unlock(&d->domain->revmap_tree_mutex); + mutex_unlock(&d->domain->revmap_mutex); } /** -- 2.30.2