public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Baolu Lu <baolu.lu@linux.intel.com>
To: "Tian, Kevin" <kevin.tian@intel.com>,
	Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>,
	Robin Murphy <robin.murphy@arm.com>,
	Jason Gunthorpe <jgg@ziepe.ca>,
	Jean-Philippe Brucker <jean-philippe@linaro.org>,
	Nicolin Chen <nicolinc@nvidia.com>
Cc: baolu.lu@linux.intel.com, "Liu, Yi L" <yi.l.liu@intel.com>,
	Jacob Pan <jacob.jun.pan@linux.intel.com>,
	"iommu@lists.linux.dev" <iommu@lists.linux.dev>,
	"kvm@vger.kernel.org" <kvm@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v4 09/10] iommu: Make iommu_queue_iopf() more generic
Date: Mon, 11 Sep 2023 20:26:34 +0800	[thread overview]
Message-ID: <926da2a0-6b3e-cb24-23d1-1d9bce93b997@linux.intel.com> (raw)
In-Reply-To: <BN9PR11MB52768F9AEBC4BF39300E44478CF2A@BN9PR11MB5276.namprd11.prod.outlook.com>

Hi Kevin,

Thanks for looking at my patches.

On 2023/9/11 14:35, Tian, Kevin wrote:
>> From: Baolu Lu <baolu.lu@linux.intel.com>
>> Sent: Tuesday, September 5, 2023 1:20 PM
>>
>> I added below patch to address the iopf_queue_flush_dev() issue. What do
>> you think of this?
>>
>> iommu: Improve iopf_queue_flush_dev()
>>
>> The iopf_queue_flush_dev() is called by the iommu driver before releasing
>> a PASID. It ensures that all pending faults for this PASID have been
>> handled or cancelled, and won't hit the address space that reuses this
>> PASID. The driver must make sure that no new fault is added to the queue.
>>
>> The SMMUv3 driver doesn't use it because it only implements the
>> Arm-specific stall fault model where DMA transactions are held in the SMMU
>> while waiting for the OS to handle iopf's. Since a device driver must
>> complete all DMA transactions before detaching domain, there are no
>> pending iopf's with the stall model. PRI support requires adding a call to
>> iopf_queue_flush_dev() after flushing the hardware page fault queue.
>>
>> The current implementation of iopf_queue_flush_dev() is a simplified
>> version. It is only suitable for SVA case in which the processing of iopf
>> is implemented in the inner loop of the iommu subsystem.
>>
>> Improve this interface to make it also work for handling iopf out of the
>> iommu core.
>>
>> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
>> ---
>>    include/linux/iommu.h      |  4 ++--
>>    drivers/iommu/intel/svm.c  |  2 +-
>>    drivers/iommu/io-pgfault.c | 40
>> ++++++++++++++++++++++++++++++++++++--
>>    3 files changed, 41 insertions(+), 5 deletions(-)
>>
>> diff --git a/include/linux/iommu.h b/include/linux/iommu.h
>> index 77ad33ffe3ac..465e23e945d0 100644
>> --- a/include/linux/iommu.h
>> +++ b/include/linux/iommu.h
>> @@ -1275,7 +1275,7 @@ iommu_sva_domain_alloc(struct device *dev,
>> struct
>> mm_struct *mm)
>>    #ifdef CONFIG_IOMMU_IOPF
>>    int iopf_queue_add_device(struct iopf_queue *queue, struct device *dev);
>>    int iopf_queue_remove_device(struct iopf_queue *queue, struct device
>> *dev);
>> -int iopf_queue_flush_dev(struct device *dev);
>> +int iopf_queue_flush_dev(struct device *dev, ioasid_t pasid);
>>    struct iopf_queue *iopf_queue_alloc(const char *name);
>>    void iopf_queue_free(struct iopf_queue *queue);
>>    int iopf_queue_discard_partial(struct iopf_queue *queue);
>> @@ -1295,7 +1295,7 @@ iopf_queue_remove_device(struct iopf_queue
>> *queue,
>> struct device *dev)
>>    	return -ENODEV;
>>    }
>>
>> -static inline int iopf_queue_flush_dev(struct device *dev)
>> +static inline int iopf_queue_flush_dev(struct device *dev, ioasid_t pasid)
>>    {
>>    	return -ENODEV;
>>    }
>> diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
>> index 780c5bd73ec2..4c3f4533e337 100644
>> --- a/drivers/iommu/intel/svm.c
>> +++ b/drivers/iommu/intel/svm.c
>> @@ -495,7 +495,7 @@ void intel_drain_pasid_prq(struct device *dev, u32
>> pasid)
>>    		goto prq_retry;
>>    	}
>>
>> -	iopf_queue_flush_dev(dev);
>> +	iopf_queue_flush_dev(dev, pasid);
>>
>>    	/*
>>    	 * Perform steps described in VT-d spec CH7.10 to drain page
>> diff --git a/drivers/iommu/io-pgfault.c b/drivers/iommu/io-pgfault.c
>> index 3e6845bc5902..84728fb89ac7 100644
>> --- a/drivers/iommu/io-pgfault.c
>> +++ b/drivers/iommu/io-pgfault.c
>> @@ -309,17 +309,53 @@ EXPORT_SYMBOL_GPL(iommu_page_response);
>>     *
>>     * Return: 0 on success and <0 on error.
>>     */
>> -int iopf_queue_flush_dev(struct device *dev)
>> +int iopf_queue_flush_dev(struct device *dev, ioasid_t pasid)
>>    {
>>    	struct iommu_fault_param *iopf_param =
>> iopf_get_dev_fault_param(dev);
>> +	const struct iommu_ops *ops = dev_iommu_ops(dev);
>> +	struct iommu_page_response resp;
>> +	struct iopf_fault *iopf, *next;
>> +	int ret = 0;
>>
>>    	if (!iopf_param)
>>    		return -ENODEV;
>>
>>    	flush_workqueue(iopf_param->queue->wq);
>> +
>> +	mutex_lock(&iopf_param->lock);
>> +	list_for_each_entry_safe(iopf, next, &iopf_param->partial, list) {
>> +		if (!(iopf->fault.prm.flags &
>> IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) ||
>> +		    iopf->fault.prm.pasid != pasid)
>> +			break;
>> +
>> +		list_del(&iopf->list);
>> +		kfree(iopf);
>> +	}
>> +
>> +	list_for_each_entry_safe(iopf, next, &iopf_param->faults, list) {
>> +		if (!(iopf->fault.prm.flags &
>> IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) ||
>> +		    iopf->fault.prm.pasid != pasid)
>> +			continue;
>> +
>> +		memset(&resp, 0, sizeof(struct iommu_page_response));
>> +		resp.pasid = iopf->fault.prm.pasid;
>> +		resp.grpid = iopf->fault.prm.grpid;
>> +		resp.code = IOMMU_PAGE_RESP_INVALID;
>> +
>> +		if (iopf->fault.prm.flags &
>> IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID)
>> +			resp.flags = IOMMU_PAGE_RESP_PASID_VALID;
> 
> Out of curiosity. Is it a valid configuration which has REQUEST_PASID_VALID
> set but RESP_PASID_VALID cleared? I'm unclear why another response
> flag is required beyond what the request flag has told...

This seems to have uncovered a bug in VT-d driver.

The PCIe spec (Section 10.4.2.2) states:

"
If a Page Request has a PASID, the corresponding PRG Response Message
may optionally contain one as well.

If the PRG Response PASID Required bit is Clear, PRG Response Messages
do not have a PASID. If the PRG Response PASID Required bit is Set, PRG
Response Messages have a PASID if the Page Request also had one. The
Function is permitted to use the PASID value from the prefix in
conjunction with the PRG Index to match requests and responses.
"

The "PRG Response PASID Required bit" is a read-only field in the PCI
page request status register. It is represented by
"pdev->pasid_required".

So below code in VT-d driver is not correct:

542 static int intel_svm_prq_report(struct intel_iommu *iommu, struct 
device *dev,
543                                 struct page_req_dsc *desc)
544 {

[...]

556
557         if (desc->lpig)
558                 event.fault.prm.flags |= 
IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE;
559         if (desc->pasid_present) {
560                 event.fault.prm.flags |= 
IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
561                 event.fault.prm.flags |= 
IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID;
562         }
[...]

The right logic should be

	if (pdev->pasid_required)
		event.fault.prm.flags |= IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID;

Thoughts?

>> +
>> +		ret = ops->page_response(dev, iopf, &resp);
>> +		if (ret)
>> +			break;
>> +
>> +		list_del(&iopf->list);
>> +		kfree(iopf);
>> +	}
>> +	mutex_unlock(&iopf_param->lock);
>>    	iopf_put_dev_fault_param(iopf_param);
>>
>> -	return 0;
>> +	return ret;
>>    }
>>    EXPORT_SYMBOL_GPL(iopf_queue_flush_dev);
>>
> 
> This looks OK. Another nit is that the warning of "no pending PRQ"
> in iommu_page_response() should be removed given with above
> change it's expected for iommufd responses to be received after this
> flush operation in iommu core.

Yeah! Addressed.

Best regards,
baolu


  reply	other threads:[~2023-09-11 22:43 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-25  2:30 [PATCH v4 00/10] iommu: Prepare to deliver page faults to user space Lu Baolu
2023-08-25  2:30 ` [PATCH v4 01/10] iommu: Move iommu fault data to linux/iommu.h Lu Baolu
2023-08-25  7:52   ` Tian, Kevin
2023-08-25  2:30 ` [PATCH v4 02/10] iommu/arm-smmu-v3: Remove unrecoverable faults reporting Lu Baolu
2023-08-25  7:53   ` Tian, Kevin
2023-08-25  2:30 ` [PATCH v4 03/10] iommu: Remove unrecoverable fault data Lu Baolu
2023-08-25  7:53   ` Tian, Kevin
2023-08-25  2:30 ` [PATCH v4 04/10] iommu: Cleanup iopf data structure definitions Lu Baolu
2023-08-25  7:57   ` Tian, Kevin
2023-08-25  2:30 ` [PATCH v4 05/10] iommu: Merge iopf_device_param into iommu_fault_param Lu Baolu
2023-08-25  8:00   ` Tian, Kevin
2023-08-25  2:30 ` [PATCH v4 06/10] iommu: Remove iommu_[un]register_device_fault_handler() Lu Baolu
2023-08-25  2:30 ` [PATCH v4 07/10] iommu: Merge iommu_fault_event and iopf_fault Lu Baolu
2023-08-25  8:03   ` Tian, Kevin
2023-08-26  7:02     ` Baolu Lu
2023-08-30  7:33       ` Tian, Kevin
2023-08-25  2:30 ` [PATCH v4 08/10] iommu: Prepare for separating SVA and IOPF Lu Baolu
2023-08-25  8:05   ` Tian, Kevin
2023-08-25  2:30 ` [PATCH v4 09/10] iommu: Make iommu_queue_iopf() more generic Lu Baolu
2023-08-25  8:17   ` Tian, Kevin
2023-08-26  7:32     ` Baolu Lu
2023-08-30  7:34       ` Tian, Kevin
2023-08-26  8:01     ` Baolu Lu
2023-08-30  7:43       ` Tian, Kevin
2023-08-30 11:02         ` Vasant Hegde
2023-08-30 12:49           ` Jean-Philippe Brucker
2023-08-31  6:57             ` Vasant Hegde
2023-08-31  9:27         ` Baolu Lu
2023-09-01  2:49           ` Tian, Kevin
2023-09-05  5:19             ` Baolu Lu
2023-09-11  6:35               ` Tian, Kevin
2023-09-11 12:26                 ` Baolu Lu [this message]
2023-09-13  2:25                   ` Tian, Kevin
2023-09-13  2:44                     ` Baolu Lu
     [not found]       ` <BN9PR11MB527624F1CC4A545FBAE3C9C98CE6A@BN9PR11MB5276.namprd11.prod.outlook.com>
2023-08-30  8:50         ` Tian, Kevin
2023-08-31  9:42           ` Baolu Lu
2023-08-26  8:04     ` Baolu Lu
2023-08-30  7:55       ` Tian, Kevin
2023-08-31 11:24         ` Baolu Lu
2023-09-01  2:50           ` Tian, Kevin
2023-09-05  5:24             ` Baolu Lu
2023-09-11  6:57               ` Tian, Kevin
2023-09-11 12:46                 ` Baolu Lu
2023-09-13  2:34                   ` Tian, Kevin
2023-09-13  4:23                     ` Baolu Lu
2023-09-13  6:18                     ` Baolu Lu
2023-08-26  8:08     ` Baolu Lu
2023-08-25  2:30 ` [PATCH v4 10/10] iommu: Separate SVA and IOPF Lu Baolu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=926da2a0-6b3e-cb24-23d1-1d9bce93b997@linux.intel.com \
    --to=baolu.lu@linux.intel.com \
    --cc=iommu@lists.linux.dev \
    --cc=jacob.jun.pan@linux.intel.com \
    --cc=jean-philippe@linaro.org \
    --cc=jgg@ziepe.ca \
    --cc=joro@8bytes.org \
    --cc=kevin.tian@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nicolinc@nvidia.com \
    --cc=robin.murphy@arm.com \
    --cc=will@kernel.org \
    --cc=yi.l.liu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox