Received: by 2002:a25:6193:0:0:0:0:0 with SMTP id v141csp3587273ybb; Tue, 31 Mar 2020 08:08:49 -0700 (PDT) X-Google-Smtp-Source: ADFU+vuPbSvqRIUvjzt6Mg0jvoE6uD70zABfWfiCMH96q01L7ihZoWQO2aNfFsT4uAdYrXL0r2pX X-Received: by 2002:a4a:c819:: with SMTP id s25mr3372473ooq.6.1585667328841; Tue, 31 Mar 2020 08:08:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1585667328; cv=none; d=google.com; s=arc-20160816; b=OFUdBMI5DenNeb77CzCuKDJwSy8E59UX/Qv1X1r9Sk2iDlyQhFF+wy8Yl7yngaOK1D tJqWH7IldLulCPbNnS73YSCzMu0QALlGEaSHNPQgnVb0sSVttKYLZizt05MKNAPdanc4 U37E3je77YVzLEyTFcMcdvGv2jAtKfrUv8J9rKz9omEwhvdhytN84zv7CxL/1uBKa1N6 ZJ0gtUwGQ8+oYl2dDh5LN9O5vEGvmalhKB/+t0uIXBCJtQvgn6imXoY2ZBKwkG02i3V9 8AEiHozxmtazqSAskSY31YZ7F/ISos6Clq69bhSv3IhiyCls8ZM2kfJSJ+I15NEOFKw5 BP4Q== 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:mime-version :organization:references:in-reply-to:message-id:subject:cc:to:from :date:ironport-sdr:ironport-sdr; bh=eIvxDU8NJ4QR2kxEpfL+jgiZZzfDK9obir5Z+vp1KKM=; b=eTdsmrBIU+VZEQAUeC5us7fZ22cLVa19oadl6W/ef8RnQ5xsm28LVJ/qJgS6GBzUE8 L+4jIa22w6z3B80fPk2EVUZF79rF9hUHLMu8mgBGQTi/KW/LlYPeJ1+3CathSy4ciQWq ZqgNXWGVAjFUIU93CDx1tND1bkPYej2WLFpGHHarhpYeS4g7/WuAf71Ug509ymRw+/dt jUVYD0G8WSDa1OEstTAprIZvuVwr0gcMvTwLxclzVIoOzhHzn4Rn4gYgAdJHRC9AGUwc whV6S9Rk1B5coKhRuPoU8Po2vCSBAC3wivc36wjKNmqZq+Qk1jZMzCgXkGW+8WKkpzlB iJTQ== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e53si7875955ote.156.2020.03.31.08.08.23; Tue, 31 Mar 2020 08:08:48 -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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730592AbgCaPHo convert rfc822-to-8bit (ORCPT + 99 others); Tue, 31 Mar 2020 11:07:44 -0400 Received: from mga06.intel.com ([134.134.136.31]:2483 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726526AbgCaPHo (ORCPT ); Tue, 31 Mar 2020 11:07:44 -0400 IronPort-SDR: iWKFDj6NpMmlYhhHQC0VTGMBvB70zipW91RlRBPmvBMxpuV5QVQX4h+32KocV79eNHCSWXvLOK SEUrQdF9XKrw== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Mar 2020 08:07:43 -0700 IronPort-SDR: XszIDvHCviOzufo+EruMebCUjjCbUg0ODeQ1MIpEa0gMy4MMPBL5lvRiZXtzvMx19lkQpEozd9 YCEYVhMo1hoQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,328,1580803200"; d="scan'208";a="252274243" Received: from jacob-builder.jf.intel.com (HELO jacob-builder) ([10.7.199.155]) by orsmga006.jf.intel.com with ESMTP; 31 Mar 2020 08:07:42 -0700 Date: Tue, 31 Mar 2020 08:13:29 -0700 From: Jacob Pan To: "Tian, Kevin" Cc: Joerg Roedel , Alex Williamson , Lu Baolu , "iommu@lists.linux-foundation.org" , LKML , David Woodhouse , Jean-Philippe Brucker , "Liu, Yi L" , "Raj, Ashok" , Christoph Hellwig , Jonathan Cameron , Eric Auger , jacob.jun.pan@linux.intel.com Subject: Re: [PATCH 08/10] iommu/ioasid: Introduce notifier APIs Message-ID: <20200331081329.036ca1a5@jacob-builder> In-Reply-To: References: <1585158931-1825-1-git-send-email-jacob.jun.pan@linux.intel.com> <1585158931-1825-9-git-send-email-jacob.jun.pan@linux.intel.com> <20200327113646.3d87f17f@jacob-builder> Organization: OTC X-Mailer: Claws Mail 3.13.2 (GTK+ 2.24.30; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sat, 28 Mar 2020 06:43:37 +0000 "Tian, Kevin" wrote: > > From: Jacob Pan > > Sent: Saturday, March 28, 2020 2:37 AM > > > > On Fri, 27 Mar 2020 10:03:26 +0000 > > "Tian, Kevin" wrote: > > > > > > From: Jacob Pan > > > > Sent: Thursday, March 26, 2020 1:55 AM > > > > > > > > IOASID users fit into the publisher-subscriber pattern, a system > > > > wide blocking notifier chain can be used to inform subscribers > > > > of state changes. Notifier mechanism also abstracts publisher > > > > from knowing the private context each subcriber may have. > > > > > > > > This patch adds APIs and a global notifier chain, a further > > > > optimization might be per set notifier for ioasid_set aware > > > > users. > > > > > > > > Usage example: > > > > KVM register notifier block such that it can keep its guest-host > > > > PASID translation table in sync with any IOASID updates. > > > > > > > > VFIO publish IOASID change by performing alloc/free, bind/unbind > > > > operations. > > > > > > > > IOMMU driver gets notified when IOASID is freed by VFIO or core > > > > mm code such that PASID context can be cleaned up. > > > > > > above example looks mixed. You have KVM registers the notifier but > > > finally having IOMMU driver to get notified... ???? > > > > > Right, felt like a tale of two subscribers got mixed. I meant to > > list a few use cases with publisher and subscriber roles separate. > > I will change that to "Usage examples", and explicit state each > > role. > > > > > > > > Signed-off-by: Liu Yi L > > > > Signed-off-by: Jacob Pan > > > > --- > > > > drivers/iommu/ioasid.c | 61 > > > > ++++++++++++++++++++++++++++++++++++++++++++++++++ > > > > include/linux/ioasid.h | 40 +++++++++++++++++++++++++++++++++ > > > > 2 files changed, 101 insertions(+) > > > > > > > > diff --git a/drivers/iommu/ioasid.c b/drivers/iommu/ioasid.c > > > > index 8612fe6477dc..27dce2cb5af2 100644 > > > > --- a/drivers/iommu/ioasid.c > > > > +++ b/drivers/iommu/ioasid.c > > > > @@ -11,6 +11,22 @@ > > > > #include > > > > > > > > static DEFINE_XARRAY_ALLOC(ioasid_sets); > > > > +/* > > > > + * An IOASID could have multiple consumers. When a status > > > > change occurs, > > > > + * this notifier chain is used to keep them in sync. Each > > > > consumer of the > > > > + * IOASID service must register notifier block early to ensure > > > > no events > > > > + * are missed. > > > > + * > > > > + * This is a publisher-subscriber pattern where publisher can > > > > change the > > > > + * state of each IOASID, e.g. alloc/free, bind IOASID to a > > > > device and mm. > > > > + * On the other hand, subscribers gets notified for the state > > > > change and > > > > + * keep local states in sync. > > > > + * > > > > + * Currently, the notifier is global. A further optimization > > > > could be per > > > > + * IOASID set notifier chain. > > > > + */ > > > > +static BLOCKING_NOTIFIER_HEAD(ioasid_chain); > > > > + > > > > /** > > > > * struct ioasid_set_data - Meta data about ioasid_set > > > > * > > > > @@ -408,6 +424,7 @@ static void ioasid_free_locked(ioasid_t > > > > ioasid) { > > > > struct ioasid_data *ioasid_data; > > > > struct ioasid_set_data *sdata; > > > > + struct ioasid_nb_args args; > > > > > > > > ioasid_data = xa_load(&active_allocator->xa, ioasid); > > > > if (!ioasid_data) { > > > > @@ -415,6 +432,13 @@ static void ioasid_free_locked(ioasid_t > > > > ioasid) return; > > > > } > > > > > > > > + args.id = ioasid; > > > > + args.sid = ioasid_data->sdata->sid; > > > > + args.pdata = ioasid_data->private; > > > > + args.set_token = ioasid_data->sdata->token; > > > > + > > > > + /* Notify all users that this IOASID is being freed */ > > > > + blocking_notifier_call_chain(&ioasid_chain, > > > > IOASID_FREE, &args); active_allocator->ops->free(ioasid, > > > > active_allocator->ops->pdata); /* Custom allocator needs > > > > additional steps to free the xa element */ if > > > > (active_allocator->flags & IOASID_ALLOCATOR_CUSTOM) { @@ -624,6 > > > > +648,43 @@ int ioasid_find_sid(ioasid_t ioasid) } > > > > EXPORT_SYMBOL_GPL(ioasid_find_sid); > > > > > > > > +int ioasid_add_notifier(struct notifier_block *nb) > > > > +{ > > > > + return blocking_notifier_chain_register(&ioasid_chain, > > > > nb); +} > > > > +EXPORT_SYMBOL_GPL(ioasid_add_notifier); > > > > + > > > > +void ioasid_remove_notifier(struct notifier_block *nb) > > > > +{ > > > > + blocking_notifier_chain_unregister(&ioasid_chain, nb); > > > > +} > > > > +EXPORT_SYMBOL_GPL(ioasid_remove_notifier); > > > > > > register/unregister > > > > > Sounds good. > > > > > > + > > > > +int ioasid_notify(ioasid_t ioasid, enum ioasid_notify_val > > > > cmd) > > > > > > add a comment on when this function should be used? > > > > > Sure, how about: > > /** > > * ioasid_notify - Send notification on a given IOASID for status > > change. > > * Used by publishers when the status change may > > affect > > * subscriber's internal state. > > * > > * @ioasid: The IOASID to which the notification will send > > * @cmd: The notification event > > * > > */ > > looks good. > > > > > > > +{ > > > > + struct ioasid_data *ioasid_data; > > > > + struct ioasid_nb_args args; > > > > + int ret = 0; > > > > + > > > > + mutex_lock(&ioasid_allocator_lock); > > > > + ioasid_data = xa_load(&active_allocator->xa, ioasid); > > > > + if (!ioasid_data) { > > > > + pr_err("Trying to free unknown IOASID %u\n", > > > > ioasid); > > > > > > why is it fixed to 'free'? > > > > > Good catch, it shouldn;t be just free. It was a relic of early test > > case. > > > > > > + mutex_unlock(&ioasid_allocator_lock); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + args.id = ioasid; > > > > + args.sid = ioasid_data->sdata->sid; > > > > + args.pdata = ioasid_data->private; > > > > > > why no token info as did in ioasid_free? > > > > > Good catch, should include token as well. It is better to include > > all the data such that subscribers don't have to do any lookup > > which may cause race. > > > > > > + > > > > + ret = blocking_notifier_call_chain(&ioasid_chain, cmd, > > > > &args); > > > > + mutex_unlock(&ioasid_allocator_lock); > > > > + > > > > + return ret; > > > > +} > > > > +EXPORT_SYMBOL_GPL(ioasid_notify); > > > > + > > > > MODULE_AUTHOR("Jean-Philippe Brucker > > > philippe.brucker@arm.com>"); > > > > MODULE_AUTHOR("Jacob Pan "); > > > > MODULE_DESCRIPTION("IO Address Space ID (IOASID) allocator"); > > > > diff --git a/include/linux/ioasid.h b/include/linux/ioasid.h > > > > index e19c0ad93bd7..32d032913828 100644 > > > > --- a/include/linux/ioasid.h > > > > +++ b/include/linux/ioasid.h > > > > @@ -4,6 +4,7 @@ > > > > > > > > #include > > > > #include > > > > +#include > > > > > > > > #define INVALID_IOASID ((ioasid_t)-1) > > > > #define INVALID_IOASID_SET (-1) > > > > @@ -30,6 +31,27 @@ struct ioasid_allocator_ops { > > > > void *pdata; > > > > }; > > > > > > > > +/* Notification data when IOASID status changed */ > > > > +enum ioasid_notify_val { > > > > + IOASID_ALLOC = 1, > > > > + IOASID_FREE, > > > > + IOASID_BIND, > > > > + IOASID_UNBIND, > > > > +}; > > > > > > Curious why IOASID_ALLOC is not notified aumatically within > > > ioasid_alloc similar to ioasid_free, while leaving to the > > > publisher? BIND/UNBIND is a publisher thing but a bit strange to > > > see ALLOC/FREE with different policy here. > > > > > I don't see a use case for ALLOC notification yet. Any user does the > > allocation would the be the first and only one know about this > > IOASID. > > > > Unless we have set level notifier, which may be interested in a new > > IOASID being allocated within the set. > > then remove this type until it is actually required when supporting > set-level notifier? > Sounds good. I will change it to: /* * Notification event when IOASID status changed. Note that there is no * event for ALLOC in that the allocator is the only one knows about the * new IOASID. */ enum ioasid_notify_val { IOASID_FREE = 1, IOASID_BIND, IOASID_UNBIND, }; > > > > > > + > > > > +/** > > > > + * struct ioasid_nb_args - Argument provided by IOASID core > > > > when notifier > > > > + * is called. > > > > + * @id: the IOASID being notified > > > > + * @sid: the IOASID set @id belongs to > > > > + * @pdata: the private data attached to the IOASID > > > > + */ > > > > +struct ioasid_nb_args { > > > > + ioasid_t id; > > > > + int sid; > > > > + struct ioasid_set *set_token; > > > > + void *pdata; > > > > +}; > > > > /* Shared IOASID set for reserved for host system use */ > > > > extern int system_ioasid_sid; > > > > > > > > @@ -43,11 +65,15 @@ void *ioasid_find(int sid, ioasid_t ioasid, > > > > bool (*getter)(void *)); > > > > int ioasid_register_allocator(struct ioasid_allocator_ops > > > > *allocator); void ioasid_unregister_allocator(struct > > > > ioasid_allocator_ops *allocator); int > > > > ioasid_attach_data(ioasid_t ioasid, void *data); +int > > > > ioasid_add_notifier(struct notifier_block *nb); +void > > > > ioasid_remove_notifier(struct notifier_block *nb); void > > > > ioasid_install_capacity(ioasid_t total); int > > > > ioasid_alloc_system_set(int quota); int ioasid_alloc_set(struct > > > > ioasid_set *token, ioasid_t quota, int *sid); void > > > > ioasid_free_set(int sid, bool destroy_set); int > > > > ioasid_find_sid(ioasid_t ioasid); +int ioasid_notify(ioasid_t > > > > id, enum ioasid_notify_val cmd); + > > > > #else /* !CONFIG_IOASID */ > > > > static inline ioasid_t ioasid_alloc(int sid, ioasid_t min, > > > > ioasid_t max, void > > > > *private) @@ -73,6 +99,20 @@ static inline void > > > > *ioasid_find(int sid, ioasid_t ioasid, bool (*getter)(void *) > > > > return NULL; > > > > } > > > > > > > > +static inline int ioasid_add_notifier(struct notifier_block > > > > *nb) +{ > > > > + return -ENOTSUPP; > > > > +} > > > > + > > > > +static inline void ioasid_remove_notifier(struct notifier_block > > > > *nb) +{ > > > > +} > > > > + > > > > +int ioasid_notify(ioasid_t ioasid, enum ioasid_notify_val cmd) > > > > +{ > > > > + return -ENOTSUPP; > > > > +} > > > > + > > > > static inline int ioasid_register_allocator(struct > > > > ioasid_allocator_ops *allocator) > > > > { > > > > return -ENOTSUPP; > > > > -- > > > > 2.7.4 > > > > > > > [Jacob Pan] [Jacob Pan]