Received: by 2002:a25:86ce:0:0:0:0:0 with SMTP id y14csp406467ybm; Wed, 22 May 2019 05:21:58 -0700 (PDT) X-Google-Smtp-Source: APXvYqxvOAkKCMdqxToC8sFhe0YSHUCpvWBFQyKumrLAzqxMATr0guxGqxVsMPfNH6HNVh/JxNxq X-Received: by 2002:a63:1061:: with SMTP id 33mr1831060pgq.328.1558527718856; Wed, 22 May 2019 05:21:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1558527718; cv=none; d=google.com; s=arc-20160816; b=0/9HgAwD1Qr2cptgsauiqZ6ggNJeUIbPBsnos0j7UC+pVgJmMriKt6OLQwwvXVdRc0 tEzi2y+EN5hoOHBgwisfASISW1vPFMeBMw6zqDGhF7PSGmUlnFiGzOV9saR8TiKdjORj f+PtxDhTwBDV5ZIRFZyxqdfRPth3mErUw9Wn7HpwlJfHskJFV8nG7mxx97NJfcuqhFgS MmZ9uahfck5fsydief95YAQ6RfmzwHCmHXmpkFq70Ugz9/MXht2lLFE5y3M49xep+dJt W5W9nm+DmYmJ2Hrx+6j0V7HsB3mNbFWzPn84in31999SWeTOG4Cz2bvkPoX9EEbZWa9y mK8Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject; bh=4wPwTFpRJZDGLepCW54DS+6bb8wMemE0uSedMVZSThM=; b=aGdx7cbYARtT+u7Ff1idclWM8Kg1pWPbscGEAm+lGQGB2+c7m60Gk8J1C+8yM/QZd7 JIXmlCBOZYpJVz2Jtm8HQW7Mi7OZKy0viGG2ijKy9zXarnYgPyPH+LqaN3+XW/CKByN6 2KgR5rzsbEa9jV2v6pZdriju0iA7bHYZbufTvutGajLTWEq3+IvFB78yNbx1awTwkVJv Q11ca4TFDxPU+vGmO+jqyO89MYokbAowdskKRD3qAiMENbOFipVmL/Vt82VOAema2MRC +muljJFpySBuo6831u5pc51HxI3UAukx5yyposjxT8Z+nVcEBwVqk0CqYgXiKDxrIR5y sKvg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i23si7724162pgh.26.2019.05.22.05.21.43; Wed, 22 May 2019 05:21:58 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729408AbfEVMUF (ORCPT + 99 others); Wed, 22 May 2019 08:20:05 -0400 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:49338 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728438AbfEVMUF (ORCPT ); Wed, 22 May 2019 08:20:05 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A234780D; Wed, 22 May 2019 05:20:04 -0700 (PDT) Received: from [10.1.196.129] (ostrya.cambridge.arm.com [10.1.196.129]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 247863F575; Wed, 22 May 2019 05:20:03 -0700 (PDT) Subject: Re: [PATCH v3 03/16] iommu: Add I/O ASID allocator To: Jacob Pan , Auger Eric Cc: "Tian, Kevin" , Raj Ashok , iommu@lists.linux-foundation.org, LKML , Alex Williamson , Andriy Shevchenko , David Woodhouse References: <1556922737-76313-1-git-send-email-jacob.jun.pan@linux.intel.com> <1556922737-76313-4-git-send-email-jacob.jun.pan@linux.intel.com> <20190521100300.4f224e68@jacob-builder> From: Jean-Philippe Brucker Message-ID: <836caf0d-699e-33ba-5303-b1c9c949c9ca@arm.com> Date: Wed, 22 May 2019 13:19:39 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 In-Reply-To: <20190521100300.4f224e68@jacob-builder> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 21/05/2019 18:03, Jacob Pan wrote: > On Tue, 21 May 2019 10:21:55 +0200 > Auger Eric wrote: >>> +config IOASID >>> + bool >> don't we want a tristate here too? >> >> Also refering to the past discussions we could add "# The IOASID >> library may also be used by non-IOMMU_API users" > I agree. For device driver modules to use ioasid w/o iommu, this does > not have to be built-in. > Jean, would you agree? Yes we can make it tristate. There is a couple of things missing to build it as a module: * Add MODULE_LICENSE("GPL") to ioasid.c * Use #if IS_ENABLED(CONFIG_IOASID) in ioasid.h rather than #ifdef CONFIG_IOASID >>> + help >>> + Enable the I/O Address Space ID allocator. A single ID >>> space shared >>> + between different users. >>> + >>> # IOMMU_API always gets selected by whoever wants it. >>> config IOMMU_API >>> bool >>> diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile >>> index 8c71a15..0efac6f 100644 >>> --- a/drivers/iommu/Makefile >>> +++ b/drivers/iommu/Makefile >>> @@ -7,6 +7,7 @@ obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o >>> obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o >>> obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o >>> obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o >>> +obj-$(CONFIG_IOASID) += ioasid.o >>> obj-$(CONFIG_IOMMU_IOVA) += iova.o >>> obj-$(CONFIG_OF_IOMMU) += of_iommu.o >>> obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o >>> diff --git a/drivers/iommu/ioasid.c b/drivers/iommu/ioasid.c >>> new file mode 100644 >>> index 0000000..99f5e0a >>> --- /dev/null >>> +++ b/drivers/iommu/ioasid.c >>> @@ -0,0 +1,140 @@ >>> +// SPDX-License-Identifier: GPL-2.0 >>> +/* >>> + * I/O Address Space ID allocator. There is one global IOASID >>> space, split into >>> + * subsets. Users create a subset with DECLARE_IOASID_SET, then >>> allocate and >>> + * free IOASIDs with ioasid_alloc and ioasid_free. >>> + */ >>> +#include >>> +#include >>> +#include >>> +#include nit: sort alphabetically >>> + >>> +struct ioasid_data { >>> + ioasid_t id; >>> + struct ioasid_set *set; >>> + void *private; >>> + struct rcu_head rcu; >>> +}; >>> + >>> +static DEFINE_XARRAY_ALLOC(ioasid_xa); >>> + >>> +/** >>> + * ioasid_set_data - Set private data for an allocated ioasid >>> + * @ioasid: the ID to set data >>> + * @data: the private data >>> + * >>> + * For IOASID that is already allocated, private data can be set >>> + * via this API. Future lookup can be done via ioasid_find. >>> + */ >>> +int ioasid_set_data(ioasid_t ioasid, void *data) >>> +{ >>> + struct ioasid_data *ioasid_data; >>> + int ret = 0; >>> + >>> + ioasid_data = xa_load(&ioasid_xa, ioasid); >>> + if (ioasid_data) >>> + ioasid_data->private = data; I think we might be in trouble if this function runs concurrently with ioasid_free(). ioasid_data may be freed between xa_load() and this assignment. It's probably not a valid use at the moment but we might as well make this code robust (or describe the constraints of ioasid_set_data() in the comment). I'm still uneasy about this, but I think we need the following sequence: xa_lock(); ioasid_data = xa_load() if (ioasid_data) rcu_assign_pointer(ioasid_data->private, data); else ret = -ENOENT; xa_unlock(); >>> + else >>> + ret = -ENOENT; >>> + >>> + /* getter may use the private data */ >>> + synchronize_rcu(); If I understand correctly, this allows our caller to safely free the old data, if any? Is there any other reason to have a synchronize_rcu()? Otherwise the comment could be more precise: /* Wait for readers to stop accessing the old private data so the caller can free it. */ >>> + >>> + return ret; >>> +} >>> +EXPORT_SYMBOL_GPL(ioasid_set_data); [...] >>> +void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid, >>> + bool (*getter)(void *)) >>> +{ >>> + void *priv = NULL; >>> + struct ioasid_data *ioasid_data; >>> + >>> + rcu_read_lock(); >>> + ioasid_data = xa_load(&ioasid_xa, ioasid); >>> + if (!ioasid_data) { >>> + priv = ERR_PTR(-ENOENT); >>> + goto unlock; >>> + } >>> + if (set && ioasid_data->set != set) { >>> + /* data found but does not belong to the set */ >>> + priv = ERR_PTR(-EACCES); >>> + goto unlock; >>> + } >>> + /* Now IOASID and its set is verified, we can return the >>> private data */ >>> + priv = ioasid_data->private; And here, I suppose we need: priv = rcu_dereference(ioasid_data->private); Thanks, Jean >>> + if (getter && !getter(priv)) >>> + priv = NULL; >>> +unlock: >>> + rcu_read_unlock(); >>> + >>> + return priv; >>> +}