Message ID | 20230711010642.19707-4-baolu.lu@linux.intel.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a6b2:0:b0:3e4:2afc:c1 with SMTP id c18csp185246vqm; Mon, 10 Jul 2023 18:45:36 -0700 (PDT) X-Google-Smtp-Source: APBJJlFx6XLvP3NxwzHXIcwirRqwXtvmrkROJrZOoR6sJd6BdRzAAIDhSszI3kA0xs8uYNIQVR3d X-Received: by 2002:a17:906:7692:b0:982:a454:6d20 with SMTP id o18-20020a170906769200b00982a4546d20mr14488973ejm.54.1689039936042; Mon, 10 Jul 2023 18:45:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689039936; cv=none; d=google.com; s=arc-20160816; b=mx6iLK8hY/zErxxmWAUTBntDbFhimHl4jJOmMDNushWVcNbk8+E4AIcdAFYYCeXY5x cHZLxH5pQK2hE0uZ5uC4HB0G7LhbnjMlh0CGhR3ZghwOv4yq+UWeBXmAbijeDFJYBmBg u8eLJvNChQDfVMbWexftdRxD7w8MomuaHUniLDF7gvrtVeQb3zR2O3lbWj0fEtrfXURx NTKg/EPgp0S4P5qb2l1/ln95YkQQEN4QQV/VDRKs2V8WgRnqHUVqE96nduJ5UgTFS79U N0AlNsYYS3MPpK0cASZQ0fAy+OcDRCQepN4i+eGJhWGlxTPsUi6IhweOIv427Hoj8MVM PJ2A== 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=t7tmbblwW2vt+fhexqDOQ2szdZb2XfXFtHJH5dEBfn4=; fh=5v0QJkujOnxKSzhmeWiMX/0q9X35NwMz+SRMkKa4moc=; b=FwRM39oUxG2BPLWlmp850E1senIDFypjjHvwoK1jM43QrrITVx+LkOXJsoI6qZlb+O iC8hZGXkWFvMXf/W0UqVRN4vv6BrSF+ltV5fyH2/2hZclynaCCSjHL1X28+sXZFc2HuL /rsBpkM8wOAIdcv05+pH9ixykoyJ0eMwPe84zq2vYvTP4PBPAFaFm5AqYYg30PmsnEb9 4GoeOMQMBER1Wehr/0mSUmjxqxUl968vPu4g0jPL71gj8iX1U5Tx2W6D4CmTKJDpNuql Bp0GEYz7RKsnezhijrs9ZFXwqeebkKhMIursCxUspa/pOXhM2od/iiYXBP1XNd6Y6JiZ 0DWQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=T8v2tepW; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id a17-20020a170906469100b00992a9c402cbsi981505ejr.20.2023.07.10.18.45.13; Mon, 10 Jul 2023 18:45:36 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=T8v2tepW; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231179AbjGKBI5 (ORCPT <rfc822;gnulinuxfreebsd@gmail.com> + 99 others); Mon, 10 Jul 2023 21:08:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50568 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231127AbjGKBIy (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 10 Jul 2023 21:08:54 -0400 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8AD8AE4C; Mon, 10 Jul 2023 18:08:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1689037728; x=1720573728; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=oKqphfPLpxwX/axdCJ/TL8Nqz/Tmz3XMJfkFpiYRxCo=; b=T8v2tepWHIHNYjA9mHSUUdyqAnymV/eV6uLuAKGf4hhftRy01LpX1uzG zFwaUd58zk20TU5ff2eKFDvPsQlNdEKbkTl02D2j7g8iN0AtqB+0UOVFn vLq42pMBjMyKmzmjwLfP3JrZ/5RjBnCzfnOG+YcVw/Tm+d4y3/fLXhg/C ACCvJTXMm7kpyWhYQt85HAfTAF/Aj/37J6w1LYMwLIF10BxCmrv456Ft2 3KFd59xkOGrydmhbLBz1O9ikLpl3Wpaxdye8ozaxa89fig74VMCjFbI2v /lW4kvdhqC8MYvXqQfXaCYZ7F9Wd95KoGdvzanIXRd0qtWmSxwHlUC9zO Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10767"; a="344816083" X-IronPort-AV: E=Sophos;i="6.01,195,1684825200"; d="scan'208";a="344816083" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Jul 2023 18:08:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10767"; a="810999840" X-IronPort-AV: E=Sophos;i="6.01,195,1684825200"; d="scan'208";a="810999840" Received: from allen-box.sh.intel.com ([10.239.159.127]) by FMSMGA003.fm.intel.com with ESMTP; 10 Jul 2023 18:08:44 -0700 From: Lu Baolu <baolu.lu@linux.intel.com> To: Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>, Robin Murphy <robin.murphy@arm.com>, Jason Gunthorpe <jgg@ziepe.ca>, Kevin Tian <kevin.tian@intel.com>, Jean-Philippe Brucker <jean-philippe@linaro.org>, Nicolin Chen <nicolinc@nvidia.com> Cc: Yi Liu <yi.l.liu@intel.com>, Jacob Pan <jacob.jun.pan@linux.intel.com>, iommu@lists.linux.dev, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Lu Baolu <baolu.lu@linux.intel.com> Subject: [PATCH 3/9] iommu: Add common code to handle IO page faults Date: Tue, 11 Jul 2023 09:06:36 +0800 Message-Id: <20230711010642.19707-4-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230711010642.19707-1-baolu.lu@linux.intel.com> References: <20230711010642.19707-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_NONE,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1771086740168516671 X-GMAIL-MSGID: 1771086740168516671 |
Series |
iommu: Prepare to deliver page faults to user space
|
|
Commit Message
Baolu Lu
July 11, 2023, 1:06 a.m. UTC
The individual iommu drivers report iommu faults by calling
iommu_report_device_fault(), where a pre-registered device fault handler
is called to route the fault to another fault handler installed on the
corresponding iommu domain.
The pre-registered device fault handler is static and won't be dynamic
as the fault handler is eventually per iommu domain. Replace the device
fault handler with a static common code to avoid unnecessary code.
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/iommu.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
Comments
> From: Lu Baolu <baolu.lu@linux.intel.com> > Sent: Tuesday, July 11, 2023 9:07 AM > > +static int iommu_handle_io_pgfault(struct device *dev, > + struct iommu_fault *fault) > +{ > + struct iommu_domain *domain; > + > + if (fault->type != IOMMU_FAULT_PAGE_REQ) > + return -EINVAL; > + > + if (fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) > + domain = iommu_get_domain_for_dev_pasid(dev, fault- > >prm.pasid, 0); > + else > + domain = iommu_get_domain_for_dev(dev); > + > + if (!domain || !domain->iopf_handler) > + return -ENODEV; > + > + if (domain->iopf_handler == iommu_sva_handle_iopf) > + return iommu_queue_iopf(fault, dev); You can avoid the special check by directly making iommu_queue_iopf as the iopf_handler for sva domain. > + > + return domain->iopf_handler(fault, dev, domain->fault_data); > +} btw is there value of moving the group handling logic from iommu_queue_iopf() to this common function? I wonder whether there is any correctness issue if not forwarding partial request to iommufd. If not this can also help reduce notifications to the user until the group is ready.
Hi Lu, On Tue, 11 Jul 2023 09:06:36 +0800, Lu Baolu <baolu.lu@linux.intel.com> wrote: > The individual iommu drivers report iommu faults by calling > iommu_report_device_fault(), where a pre-registered device fault handler > is called to route the fault to another fault handler installed on the > corresponding iommu domain. > > The pre-registered device fault handler is static and won't be dynamic > as the fault handler is eventually per iommu domain. Replace the device > fault handler with a static common code to avoid unnecessary code. > > Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> > --- > drivers/iommu/iommu.c | 24 +++++++++++++++++++++++- > 1 file changed, 23 insertions(+), 1 deletion(-) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index da340f11c5f5..41328f03e8b4 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -1278,6 +1278,28 @@ int iommu_unregister_device_fault_handler(struct > device *dev) } > EXPORT_SYMBOL_GPL(iommu_unregister_device_fault_handler); > > +static int iommu_handle_io_pgfault(struct device *dev, > + struct iommu_fault *fault) > +{ > + struct iommu_domain *domain; > + > + if (fault->type != IOMMU_FAULT_PAGE_REQ) > + return -EINVAL; > + > + if (fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) > + domain = iommu_get_domain_for_dev_pasid(dev, > fault->prm.pasid, 0); > + else > + domain = iommu_get_domain_for_dev(dev); we don't support IOPF w/o PASID yet, right? > + > + if (!domain || !domain->iopf_handler) > + return -ENODEV; > + > + if (domain->iopf_handler == iommu_sva_handle_iopf) > + return iommu_queue_iopf(fault, dev); Just wondering why have a special treatment for SVA domain. Can iommu_queue_iopf() be used as SVA domain->iopf_handler? > + > + return domain->iopf_handler(fault, dev, domain->fault_data); > +} > + > /** > * iommu_report_device_fault() - Report fault event to device driver > * @dev: the device > @@ -1320,7 +1342,7 @@ int iommu_report_device_fault(struct device *dev, > struct iommu_fault_event *evt) mutex_unlock(&fparam->lock); > } > > - ret = fparam->handler(&evt->fault, fparam->data); > + ret = iommu_handle_io_pgfault(dev, &evt->fault); > if (ret && evt_pending) { > mutex_lock(&fparam->lock); > list_del(&evt_pending->list); Thanks, Jacob
On 2023/7/11 14:12, Tian, Kevin wrote: >> From: Lu Baolu <baolu.lu@linux.intel.com> >> Sent: Tuesday, July 11, 2023 9:07 AM >> >> +static int iommu_handle_io_pgfault(struct device *dev, >> + struct iommu_fault *fault) >> +{ >> + struct iommu_domain *domain; >> + >> + if (fault->type != IOMMU_FAULT_PAGE_REQ) >> + return -EINVAL; >> + >> + if (fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) >> + domain = iommu_get_domain_for_dev_pasid(dev, fault- >>> prm.pasid, 0); >> + else >> + domain = iommu_get_domain_for_dev(dev); >> + >> + if (!domain || !domain->iopf_handler) >> + return -ENODEV; >> + >> + if (domain->iopf_handler == iommu_sva_handle_iopf) >> + return iommu_queue_iopf(fault, dev); > > You can avoid the special check by directly making iommu_queue_iopf > as the iopf_handler for sva domain. Yeah, good catch! > >> + >> + return domain->iopf_handler(fault, dev, domain->fault_data); >> +} > > btw is there value of moving the group handling logic from > iommu_queue_iopf() to this common function? > > I wonder whether there is any correctness issue if not forwarding > partial request to iommufd. If not this can also help reduce > notifications to the user until the group is ready. I don't think there's any correctness issue. But it should be better if we can inject the page faults to vm guests as soon as possible. There's no requirement to put page requests to vIOMMU's hardware page request queue at the granularity of a fault group. Thoughts? Best regards, baolu
On 2023/7/12 4:50, Jacob Pan wrote: > Hi Lu, > > On Tue, 11 Jul 2023 09:06:36 +0800, Lu Baolu <baolu.lu@linux.intel.com> > wrote: > >> The individual iommu drivers report iommu faults by calling >> iommu_report_device_fault(), where a pre-registered device fault handler >> is called to route the fault to another fault handler installed on the >> corresponding iommu domain. >> >> The pre-registered device fault handler is static and won't be dynamic >> as the fault handler is eventually per iommu domain. Replace the device >> fault handler with a static common code to avoid unnecessary code. >> >> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> >> --- >> drivers/iommu/iommu.c | 24 +++++++++++++++++++++++- >> 1 file changed, 23 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c >> index da340f11c5f5..41328f03e8b4 100644 >> --- a/drivers/iommu/iommu.c >> +++ b/drivers/iommu/iommu.c >> @@ -1278,6 +1278,28 @@ int iommu_unregister_device_fault_handler(struct >> device *dev) } >> EXPORT_SYMBOL_GPL(iommu_unregister_device_fault_handler); >> >> +static int iommu_handle_io_pgfault(struct device *dev, >> + struct iommu_fault *fault) >> +{ >> + struct iommu_domain *domain; >> + >> + if (fault->type != IOMMU_FAULT_PAGE_REQ) >> + return -EINVAL; >> + >> + if (fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) >> + domain = iommu_get_domain_for_dev_pasid(dev, >> fault->prm.pasid, 0); >> + else >> + domain = iommu_get_domain_for_dev(dev); > we don't support IOPF w/o PASID yet, right? It's the individual driver that decides whether iopf w/o pasid is supported or not. The iommu core doesn't need to make such assumption. > >> + >> + if (!domain || !domain->iopf_handler) >> + return -ENODEV; >> + >> + if (domain->iopf_handler == iommu_sva_handle_iopf) >> + return iommu_queue_iopf(fault, dev); > Just wondering why have a special treatment for SVA domain. Can > iommu_queue_iopf() be used as SVA domain->iopf_handler? Yes. I will make this change according to Kevin's suggestion in this thread. > >> + >> + return domain->iopf_handler(fault, dev, domain->fault_data); >> +} >> + >> /** >> * iommu_report_device_fault() - Report fault event to device driver >> * @dev: the device >> @@ -1320,7 +1342,7 @@ int iommu_report_device_fault(struct device *dev, >> struct iommu_fault_event *evt) mutex_unlock(&fparam->lock); >> } >> >> - ret = fparam->handler(&evt->fault, fparam->data); >> + ret = iommu_handle_io_pgfault(dev, &evt->fault); >> if (ret && evt_pending) { >> mutex_lock(&fparam->lock); >> list_del(&evt_pending->list); > > > Thanks, > > Jacob > Best regards, baolu
On Wed, Jul 12, 2023 at 10:32:13AM +0800, Baolu Lu wrote: > > btw is there value of moving the group handling logic from > > iommu_queue_iopf() to this common function? > > > > I wonder whether there is any correctness issue if not forwarding > > partial request to iommufd. If not this can also help reduce > > notifications to the user until the group is ready. > > I don't think there's any correctness issue. But it should be better if > we can inject the page faults to vm guests as soon as possible. There's > no requirement to put page requests to vIOMMU's hardware page request > queue at the granularity of a fault group. Thoughts? Not sure I understand you correctly, but we can't inject partial fault groups: if the HW PRI queue overflows, the last fault in a group may be lost, so the non-last faults in that group already injected won't be completed (until PRGI reuse), leaking PRI request credits and guest resources. Thanks, Jean
On 2023/7/12 17:45, Jean-Philippe Brucker wrote: > On Wed, Jul 12, 2023 at 10:32:13AM +0800, Baolu Lu wrote: >>> btw is there value of moving the group handling logic from >>> iommu_queue_iopf() to this common function? >>> >>> I wonder whether there is any correctness issue if not forwarding >>> partial request to iommufd. If not this can also help reduce >>> notifications to the user until the group is ready. >> >> I don't think there's any correctness issue. But it should be better if >> we can inject the page faults to vm guests as soon as possible. There's >> no requirement to put page requests to vIOMMU's hardware page request >> queue at the granularity of a fault group. Thoughts? > > Not sure I understand you correctly, but we can't inject partial fault > groups: if the HW PRI queue overflows, the last fault in a group may be > lost, so the non-last faults in that group already injected won't be > completed (until PRGI reuse), leaking PRI request credits and guest > resources. Yeah, that's how vIOMMU injects the faults. On host/hypervisor side, my understanding is that faults should be uploaded as soon as possible. Best regards, baolu
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index da340f11c5f5..41328f03e8b4 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1278,6 +1278,28 @@ int iommu_unregister_device_fault_handler(struct device *dev) } EXPORT_SYMBOL_GPL(iommu_unregister_device_fault_handler); +static int iommu_handle_io_pgfault(struct device *dev, + struct iommu_fault *fault) +{ + struct iommu_domain *domain; + + if (fault->type != IOMMU_FAULT_PAGE_REQ) + return -EINVAL; + + if (fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) + domain = iommu_get_domain_for_dev_pasid(dev, fault->prm.pasid, 0); + else + domain = iommu_get_domain_for_dev(dev); + + if (!domain || !domain->iopf_handler) + return -ENODEV; + + if (domain->iopf_handler == iommu_sva_handle_iopf) + return iommu_queue_iopf(fault, dev); + + return domain->iopf_handler(fault, dev, domain->fault_data); +} + /** * iommu_report_device_fault() - Report fault event to device driver * @dev: the device @@ -1320,7 +1342,7 @@ int iommu_report_device_fault(struct device *dev, struct iommu_fault_event *evt) mutex_unlock(&fparam->lock); } - ret = fparam->handler(&evt->fault, fparam->data); + ret = iommu_handle_io_pgfault(dev, &evt->fault); if (ret && evt_pending) { mutex_lock(&fparam->lock); list_del(&evt_pending->list);