linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 03/37] iommu/sva: Manage process address spaces
       [not found] ` <1519280641-30258-3-git-send-email-xieyisheng1@huawei.com>
@ 2018-02-22  9:03   ` Yisheng Xie
  2018-02-22 13:17     ` Jean-Philippe Brucker
  0 siblings, 1 reply; 11+ messages in thread
From: Yisheng Xie @ 2018-02-22  9:03 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-arm-kernel, linux-pci, linux-acpi, devicetree, iommu, kvm,
	joro, Mark Rutland, Catalin Marinas, Will Deacon,
	Lorenzo Pieralisi, hanjun.guo, Sudeep Holla, rjw, lenb,
	Robin Murphy, bhelgaas, alex.williamson, tn, liubo95,
	thunder.leizhen, xuzaibo, ilias.apalodimas, jonathan.cameron,
	shunyong.yang, nwatters, okaya, jcrouse, rfranz, dwmw2,
	jacob.jun.pan, yi.l.liu, ashok.raj, robdclark, christian.koenig,
	bharatku, robh

Hi Jean,

On 2018/2/22 14:23, Jean-Philippe Brucker wrote:
> @@ -129,7 +439,10 @@ int iommu_sva_device_shutdown(struct device *dev)
>  int iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, int *pasid,
>  			  unsigned long flags, void *drvdata)
>  {
> +	int i, ret;
> +	struct io_mm *io_mm = NULL;
>  	struct iommu_domain *domain;
> +	struct iommu_bond *bond = NULL, *tmp;
>  	struct iommu_param *dev_param = dev->iommu_param;
>  
>  	domain = iommu_get_domain_for_dev(dev);
> @@ -145,7 +458,42 @@ int iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, int *pasid,
>  	if (flags != (IOMMU_SVA_FEAT_PASID | IOMMU_SVA_FEAT_IOPF))
>  		return -EINVAL;
>  
> -	return -ENOSYS; /* TODO */
> +	/* If an io_mm already exists, use it */
> +	spin_lock(&iommu_sva_lock);
> +	idr_for_each_entry(&iommu_pasid_idr, io_mm, i) {
> +		if (io_mm->mm != mm || !io_mm_get_locked(io_mm))
> +			continue;
> +
> +		/* Is it already bound to this device? */
> +		list_for_each_entry(tmp, &io_mm->devices, mm_head) {
> +			if (tmp->dev != dev)
> +				continue;
> +
> +			bond = tmp;
> +			refcount_inc(&bond->refs);
> +			io_mm_put_locked(io_mm);

Should io_mm->pasid still be set to *pasid when the device already bond? so driver can
always get the right pasid if it bond to a mm multi-times, without keeping the pasid itself?

Thanks
Yisheng
> +			break;
> +		}
> +		break;
> +	}
> +	spin_unlock(&iommu_sva_lock);
> +
> +	if (bond)
> +		return 0;
> +
> +	if (!io_mm) {
> +		io_mm = io_mm_alloc(domain, dev, mm);
> +		if (IS_ERR(io_mm))
> +			return PTR_ERR(io_mm);
> +	}
> +
> +	ret = io_mm_attach(domain, dev, io_mm, drvdata);
> +	if (ret)
> +		io_mm_put(io_mm);
> +	else
> +		*pasid = io_mm->pasid;
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(iommu_sva_bind_device);


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 03/37] iommu/sva: Manage process address spaces
  2018-02-22  9:03   ` [PATCH 03/37] iommu/sva: Manage process address spaces Yisheng Xie
@ 2018-02-22 13:17     ` Jean-Philippe Brucker
  0 siblings, 0 replies; 11+ messages in thread
From: Jean-Philippe Brucker @ 2018-02-22 13:17 UTC (permalink / raw)
  To: Yisheng Xie
  Cc: Mark Rutland, ilias.apalodimas, kvm, linux-pci, xuzaibo,
	jonathan.cameron, Will Deacon, okaya, robh, Lorenzo Pieralisi,
	ashok.raj, tn, joro, robdclark, bharatku, linux-acpi,
	Catalin Marinas, rfranz, lenb, devicetree, jacob.jun.pan,
	alex.williamson, yi.l.liu, thunder.leizhen, bhelgaas,
	linux-arm-kernel, shunyong.yang, dwmw2, liubo95, rjw, jcrouse,
	iommu, hanjun.guo, Sudeep Holla, Robin Murphy, christian.koenig,
	nwatters

On 22/02/18 09:03, Yisheng Xie wrote:
[...]
>> +		/* Is it already bound to this device? */
>> +		list_for_each_entry(tmp, &io_mm->devices, mm_head) {
>> +			if (tmp->dev != dev)
>> +				continue;
>> +
>> +			bond = tmp;
>> +			refcount_inc(&bond->refs);
>> +			io_mm_put_locked(io_mm);
> 
> Should io_mm->pasid still be set to *pasid when the device already bond? so driver can
> always get the right pasid if it bond to a mm multi-times, without keeping the pasid itself?

(Assuming you mean set *pasid = io_mm->pasid) I think it should, I seem to
have removed it by accident from this version

Thanks,
Jean

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 37/37] vfio: Add support for Shared Virtual Addressing
       [not found] ` <1519280641-30258-37-git-send-email-xieyisheng1@huawei.com>
@ 2018-03-19  9:47   ` Yisheng Xie
  2018-03-21 13:40     ` Jean-Philippe Brucker
  0 siblings, 1 reply; 11+ messages in thread
From: Yisheng Xie @ 2018-03-19  9:47 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-arm-kernel, linux-pci, linux-acpi, devicetree, iommu, kvm,
	joro, Mark Rutland, Catalin Marinas, Will Deacon,
	Lorenzo Pieralisi, hanjun.guo, Sudeep Holla, rjw, lenb,
	Robin Murphy, bhelgaas, alex.williamson, tn, liubo95,
	thunder.leizhen, xuzaibo, ilias.apalodimas, jonathan.cameron,
	shunyong.yang, nwatters, okaya, jcrouse, rfranz, dwmw2,
	jacob.jun.pan, yi.l.liu, ashok.raj, robdclark, christian.koenig,
	bharatku, robh

Hi Jean,

vfio can be compiled as module, however you use some functions which are not
exported.

comment inline:

[...]
> Add two new ioctl for VFIO containers. VFIO_IOMMU_BIND_PROCESS creates a
> bond between a container and a process address space, identified by a
> device-specific ID named PASID. This allows the device to target DMA
> transactions at the process virtual addresses without a need for mapping
> and unmapping buffers explicitly in the IOMMU. The process page tables are
> shared with the IOMMU, and mechanisms such as PCI ATS/PRI are used to
> handle faults. VFIO_IOMMU_UNBIND_PROCESS removes a bond created with
> VFIO_IOMMU_BIND_PROCESS.
>
> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
> ---
[...]
> +static struct mm_struct *vfio_iommu_get_mm_by_vpid(pid_t vpid)
> +{
> +	struct mm_struct *mm;
> +	struct task_struct *task;
> +
> +	rcu_read_lock();
> +	task = find_task_by_vpid(vpid);

Maybe can use?
	task = pid_task(find_vpid(params.vpid), PIDTYPE_PID)

> +	if (task)
> +		get_task_struct(task);
> +	rcu_read_unlock();
> +	if (!task)
> +		return ERR_PTR(-ESRCH);
> +
> +	/* Ensure that current has RW access on the mm */
> +	mm = mm_access(task, PTRACE_MODE_ATTACH_REALCREDS);

You will try to export mm_access, I find Felix have tried to, but seems give up:

 https://patchwork.kernel.org/patch/9744281/

Thanks
Yisheng


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue
       [not found] ` <1519280641-30258-27-git-send-email-xieyisheng1@huawei.com>
@ 2018-03-19 11:03   ` Yisheng Xie
  2018-03-21 13:24     ` Jean-Philippe Brucker
  0 siblings, 1 reply; 11+ messages in thread
From: Yisheng Xie @ 2018-03-19 11:03 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: Mark Rutland, ilias.apalodimas, kvm, linux-pci, xuzaibo,
	jonathan.cameron, Will Deacon, okaya, robh, Lorenzo Pieralisi,
	ashok.raj, tn, joro, robdclark, bharatku, linux-acpi,
	Catalin Marinas, rfranz, lenb, devicetree, jacob.jun.pan,
	alex.williamson, yi.l.liu, thunder.leizhen, bhelgaas,
	linux-arm-kernel, shunyong.yang, dwmw2, liubo95, rjw, jcrouse,
	iommu, hanjun.guo, Sudeep Holla, Robin Murphy, christian.koenig,
	nwatters

Hi Jean,

[...]
> @@ -3168,6 +3260,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>  	if (ret)
>  		return ret;
>  
> +	if (smmu->features & (ARM_SMMU_FEAT_STALLS | ARM_SMMU_FEAT_PRI)) {
> +		smmu->faultq_nb.notifier_call = arm_smmu_flush_queues;
> +		ret = iommu_fault_queue_register(&smmu->faultq_nb);
> +		if (ret)
> +			return ret;

I find a case here: CONFIG_IOMMU_FAULT=n, and smmu support feature STALLS or PRI,
the device probe will failed here, is this what we want?

Thanks
Yisheng

> +	}
> +
>  	/* And we're up. Go go go! */
>  	ret = iommu_device_sysfs_add(&smmu->iommu, dev, NULL,
>  				     "smmu3.%pa", &ioaddr);


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue
  2018-03-19 11:03   ` [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue Yisheng Xie
@ 2018-03-21 13:24     ` Jean-Philippe Brucker
  2018-03-22  1:09       ` Yisheng Xie
  0 siblings, 1 reply; 11+ messages in thread
From: Jean-Philippe Brucker @ 2018-03-21 13:24 UTC (permalink / raw)
  To: Yisheng Xie
  Cc: Mark Rutland, ilias.apalodimas, kvm, linux-pci, xuzaibo,
	jonathan.cameron, Will Deacon, okaya, robh, Lorenzo Pieralisi,
	ashok.raj, tn, joro, robdclark, bharatku, linux-acpi,
	Catalin Marinas, rfranz, lenb, devicetree, jacob.jun.pan,
	alex.williamson, yi.l.liu, thunder.leizhen, bhelgaas,
	linux-arm-kernel, shunyong.yang, dwmw2, liubo95, rjw, jcrouse,
	iommu, hanjun.guo, Sudeep Holla, Robin Murphy, christian.koenig,
	nwatters

Hi Yisheng,

On 19/03/18 11:03, Yisheng Xie wrote:
> Hi Jean,
> 
> [...]
>> @@ -3168,6 +3260,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>>  	if (ret)
>>  		return ret;
>>  
>> +	if (smmu->features & (ARM_SMMU_FEAT_STALLS | ARM_SMMU_FEAT_PRI)) {
>> +		smmu->faultq_nb.notifier_call = arm_smmu_flush_queues;
>> +		ret = iommu_fault_queue_register(&smmu->faultq_nb);
>> +		if (ret)
>> +			return ret;
> 
> I find a case here: CONFIG_IOMMU_FAULT=n, and smmu support feature STALLS or PRI,
> the device probe will failed here, is this what we want?

Since CONFIG_ARM_SMMU_V3 selects CONFIG_IOMMU_FAULT, I don't think it
can happen. I'm not sure what the best practices are, but I feel like it
would be too much work to guard against config combinations that violate
an explicit "select" in Kconfig

Thanks,
Jean

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 37/37] vfio: Add support for Shared Virtual Addressing
  2018-03-19  9:47   ` [PATCH 37/37] vfio: Add support for Shared Virtual Addressing Yisheng Xie
@ 2018-03-21 13:40     ` Jean-Philippe Brucker
  0 siblings, 0 replies; 11+ messages in thread
From: Jean-Philippe Brucker @ 2018-03-21 13:40 UTC (permalink / raw)
  To: Yisheng Xie
  Cc: Mark Rutland, ilias.apalodimas, kvm, linux-pci, xuzaibo,
	jonathan.cameron, Will Deacon, okaya, robh, Lorenzo Pieralisi,
	ashok.raj, tn, joro, robdclark, bharatku, linux-acpi,
	Catalin Marinas, rfranz, lenb, devicetree, jacob.jun.pan,
	alex.williamson, yi.l.liu, thunder.leizhen, bhelgaas,
	linux-arm-kernel, shunyong.yang, dwmw2, liubo95, rjw, jcrouse,
	iommu, hanjun.guo, Sudeep Holla, Robin Murphy, christian.koenig,
	nwatters

On 19/03/18 09:47, Yisheng Xie wrote:
> Hi Jean,
> 
> vfio can be compiled as module, however you use some functions which are not
> exported.

Oh right. I remember the kbuild test robot warning about this once, I
wonder why it didn't find this one.

> comment inline:
> 
> [...]
>> Add two new ioctl for VFIO containers. VFIO_IOMMU_BIND_PROCESS creates a
>> bond between a container and a process address space, identified by a
>> device-specific ID named PASID. This allows the device to target DMA
>> transactions at the process virtual addresses without a need for mapping
>> and unmapping buffers explicitly in the IOMMU. The process page tables are
>> shared with the IOMMU, and mechanisms such as PCI ATS/PRI are used to
>> handle faults. VFIO_IOMMU_UNBIND_PROCESS removes a bond created with
>> VFIO_IOMMU_BIND_PROCESS.
>>
>> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
>> ---
> [...]
>> +static struct mm_struct *vfio_iommu_get_mm_by_vpid(pid_t vpid)
>> +{
>> +	struct mm_struct *mm;
>> +	struct task_struct *task;
>> +
>> +	rcu_read_lock();
>> +	task = find_task_by_vpid(vpid);
> 
> Maybe can use?
> 	task = pid_task(find_vpid(params.vpid), PIDTYPE_PID)

I'd rather submit a patch requesting to export the symbol. Especially
since this function can be further simplified by using the brand new
find_get_task_by_vpid() helper, introduced by 2ee0826085d1.

>> +	if (task)
>> +		get_task_struct(task);
>> +	rcu_read_unlock();
>> +	if (!task)
>> +		return ERR_PTR(-ESRCH);
>> +
>> +	/* Ensure that current has RW access on the mm */
>> +	mm = mm_access(task, PTRACE_MODE_ATTACH_REALCREDS);
> 
> You will try to export mm_access, I find Felix have tried to, but seems give up:
> 
>  https://patchwork.kernel.org/patch/9744281/

Thanks for the pointer, I'll try to revive this.

Thanks,
Jean


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue
  2018-03-21 13:24     ` Jean-Philippe Brucker
@ 2018-03-22  1:09       ` Yisheng Xie
  2018-04-04 10:13         ` Jean-Philippe Brucker
  0 siblings, 1 reply; 11+ messages in thread
From: Yisheng Xie @ 2018-03-22  1:09 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: Mark Rutland, ilias.apalodimas, kvm, linux-pci, xuzaibo,
	jonathan.cameron, Will Deacon, okaya, robh, Lorenzo Pieralisi,
	ashok.raj, tn, joro, robdclark, bharatku, linux-acpi,
	Catalin Marinas, rfranz, lenb, devicetree, jacob.jun.pan,
	alex.williamson, yi.l.liu, thunder.leizhen, bhelgaas,
	linux-arm-kernel, shunyong.yang, dwmw2, liubo95, rjw, jcrouse,
	iommu, hanjun.guo, Sudeep Holla, Robin Murphy, christian.koenig,
	nwatters

Hi Jean,

On 2018/3/21 21:24, Jean-Philippe Brucker wrote:
> Hi Yisheng,
> 
> On 19/03/18 11:03, Yisheng Xie wrote:
>> Hi Jean,
>>
>> [...]
>>> @@ -3168,6 +3260,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>>>  	if (ret)
>>>  		return ret;
>>>  
>>> +	if (smmu->features & (ARM_SMMU_FEAT_STALLS | ARM_SMMU_FEAT_PRI)) {
>>> +		smmu->faultq_nb.notifier_call = arm_smmu_flush_queues;
>>> +		ret = iommu_fault_queue_register(&smmu->faultq_nb);
>>> +		if (ret)
>>> +			return ret;
>>
>> I find a case here: CONFIG_IOMMU_FAULT=n, and smmu support feature STALLS or PRI,
>> the device probe will failed here, is this what we want?
> 
> Since CONFIG_ARM_SMMU_V3 selects CONFIG_IOMMU_FAULT, I don't think it
> can happen. 

But CONFIG_IOMMU_FAULT can be changed after select, maybe can make it as unchangeable.

Thanks
Yisheng

> I'm not sure what the best practices are, but I feel like it
> would be too much work to guard against config combinations that violate
> an explicit "select" in Kconfig
> 
> Thanks,
> Jean
> 
> .
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue
  2018-03-22  1:09       ` Yisheng Xie
@ 2018-04-04 10:13         ` Jean-Philippe Brucker
  0 siblings, 0 replies; 11+ messages in thread
From: Jean-Philippe Brucker @ 2018-04-04 10:13 UTC (permalink / raw)
  To: Yisheng Xie
  Cc: Mark Rutland, ilias.apalodimas, kvm, linux-pci, xuzaibo,
	jonathan.cameron, Will Deacon, okaya, robh, Lorenzo Pieralisi,
	ashok.raj, tn, joro, robdclark, bharatku, linux-acpi,
	Catalin Marinas, rfranz, lenb, devicetree, jacob.jun.pan,
	alex.williamson, yi.l.liu, thunder.leizhen, bhelgaas,
	linux-arm-kernel, shunyong.yang, dwmw2, liubo95, rjw, jcrouse,
	iommu, hanjun.guo, Sudeep Holla, Robin Murphy, christian.koenig,
	nwatters

On 22/03/18 01:09, Yisheng Xie wrote:
> Hi Jean,
> 
> On 2018/3/21 21:24, Jean-Philippe Brucker wrote:
>> Hi Yisheng,
>>
>> On 19/03/18 11:03, Yisheng Xie wrote:
>>> Hi Jean,
>>>
>>> [...]
>>>> @@ -3168,6 +3260,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>>>>  	if (ret)
>>>>  		return ret;
>>>>  
>>>> +	if (smmu->features & (ARM_SMMU_FEAT_STALLS | ARM_SMMU_FEAT_PRI)) {
>>>> +		smmu->faultq_nb.notifier_call = arm_smmu_flush_queues;
>>>> +		ret = iommu_fault_queue_register(&smmu->faultq_nb);
>>>> +		if (ret)
>>>> +			return ret;
>>>
>>> I find a case here: CONFIG_IOMMU_FAULT=n, and smmu support feature STALLS or PRI,
>>> the device probe will failed here, is this what we want?
>>
>> Since CONFIG_ARM_SMMU_V3 selects CONFIG_IOMMU_FAULT, I don't think it
>> can happen. 
> 
> But CONFIG_IOMMU_FAULT can be changed after select, maybe can make it as unchangeable. Seems sensible, I don't see a reason to leave IOMMU_FAULT selectable
manually.

Thanks,
Jean

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue
  2018-03-08 17:44   ` Jonathan Cameron
@ 2018-03-14 13:08     ` Jean-Philippe Brucker
  0 siblings, 0 replies; 11+ messages in thread
From: Jean-Philippe Brucker @ 2018-03-14 13:08 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Mark Rutland, xieyisheng1, ilias.apalodimas, kvm, linux-pci,
	xuzaibo, Will Deacon, okaya, yi.l.liu, Lorenzo Pieralisi,
	ashok.raj, tn, joro, robdclark, bharatku, linux-acpi,
	Catalin Marinas, rfranz, lenb, devicetree, jacob.jun.pan,
	alex.williamson, robh+dt, thunder.leizhen, bhelgaas,
	linux-arm-kernel, shunyong.yang, dwmw2, liubo95, rjw, jcrouse,
	iommu, hanjun.guo, Sudeep Holla, Robin Murphy, christian.koenig,
	nwatters

On 08/03/18 17:44, Jonathan Cameron wrote:
>> @@ -3168,6 +3260,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>>  	if (ret)
>>  		return ret;
>>  
>> +	if (smmu->features & (ARM_SMMU_FEAT_STALLS | ARM_SMMU_FEAT_PRI)) {
>> +		smmu->faultq_nb.notifier_call = arm_smmu_flush_queues;
>> +		ret = iommu_fault_queue_register(&smmu->faultq_nb);
> Here you register only if this smmu supports stalls or pri which is fine, but
> see the unregister path.
> 
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>>  	/* And we're up. Go go go! */
>>  	ret = iommu_device_sysfs_add(&smmu->iommu, dev, NULL,
>>  				     "smmu3.%pa", &ioaddr);
>> @@ -3210,6 +3309,8 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
>>  {
>>  	struct arm_smmu_device *smmu = platform_get_drvdata(pdev);
>>  
>> +	iommu_fault_queue_unregister(&smmu->faultq_nb);
> 
> Here you unregister from the fault queue unconditionally.  That is mostly
> safe but it seems to decrement and potentially destroy the work queue that
> is in use by another smmu instance that does support page faulting.

Ah yes, we'll need to check this

Thanks,
Jean


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue
  2018-02-12 18:33 ` [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue Jean-Philippe Brucker
@ 2018-03-08 17:44   ` Jonathan Cameron
  2018-03-14 13:08     ` Jean-Philippe Brucker
  0 siblings, 1 reply; 11+ messages in thread
From: Jonathan Cameron @ 2018-03-08 17:44 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: linux-arm-kernel, linux-pci, linux-acpi, devicetree, iommu, kvm,
	joro, robh+dt, mark.rutland, catalin.marinas, will.deacon,
	lorenzo.pieralisi, hanjun.guo, sudeep.holla, rjw, lenb,
	robin.murphy, bhelgaas, alex.williamson, tn, liubo95,
	thunder.leizhen, xieyisheng1, xuzaibo, ilias.apalodimas,
	shunyong.yang, nwatters, okaya, jcrouse, rfranz, dwmw2,
	jacob.jun.pan, yi.l.liu, ashok.raj, robdclark, christian.koenig,
	bharatku

On Mon, 12 Feb 2018 18:33:42 +0000
Jean-Philippe Brucker <jean-philippe.brucker@arm.com> wrote:

> When using PRI or Stall, the PRI or event handler enqueues faults into the
> core fault queue. Register it based on the SMMU features.
> 
> When the core stops using a PASID, it notifies the SMMU to flush all
> instances of this PASID from the PRI queue. Add a way to flush the PRI and
> event queue. PRI and event thread now take a spinlock while processing the
> queue. The flush handler takes this lock to inspect the queue state.
> We avoid livelock, where the SMMU adds fault to the queue faster than we
> can consume them, by incrementing a 'batch' number on every cycle so the
> flush handler only has to wait a complete cycle (two batch increments.)
> 
> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
I think you have a potential incorrect free issue... See inline.

Jonathan
> ---
>  drivers/iommu/Kconfig       |   1 +
>  drivers/iommu/arm-smmu-v3.c | 103 +++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 103 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index d434f7085dc2..d79c68754bb9 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -354,6 +354,7 @@ config ARM_SMMU_V3
>  	depends on ARM64
>  	select IOMMU_API
>  	select IOMMU_SVA
> +	select IOMMU_FAULT
>  	select IOMMU_IO_PGTABLE_LPAE
>  	select ARM_SMMU_V3_CONTEXT
>  	select GENERIC_MSI_IRQ_DOMAIN
> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
> index 8528704627b5..c5b3a43becaf 100644
> --- a/drivers/iommu/arm-smmu-v3.c
> +++ b/drivers/iommu/arm-smmu-v3.c
> @@ -494,6 +494,10 @@ struct arm_smmu_queue {
>  
>  	u32 __iomem			*prod_reg;
>  	u32 __iomem			*cons_reg;
> +
> +	/* Event and PRI */
> +	u64				batch;
> +	wait_queue_head_t		wq;
>  };
>  
>  struct arm_smmu_cmdq {
> @@ -610,6 +614,9 @@ struct arm_smmu_device {
>  
>  	/* IOMMU core code handle */
>  	struct iommu_device		iommu;
> +
> +	/* Notifier for the fault queue */
> +	struct notifier_block		faultq_nb;
>  };
>  
>  /* SMMU private data for each master */
> @@ -1247,14 +1254,23 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
>  static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
>  {
>  	int i;
> +	int num_handled = 0;
>  	struct arm_smmu_device *smmu = dev;
>  	struct arm_smmu_queue *q = &smmu->evtq.q;
> +	size_t queue_size = 1 << q->max_n_shift;
>  	u64 evt[EVTQ_ENT_DWORDS];
>  
> +	spin_lock(&q->wq.lock);
>  	do {
>  		while (!queue_remove_raw(q, evt)) {
>  			u8 id = evt[0] >> EVTQ_0_ID_SHIFT & EVTQ_0_ID_MASK;
>  
> +			if (++num_handled == queue_size) {
> +				q->batch++;
> +				wake_up_locked(&q->wq);
> +				num_handled = 0;
> +			}
> +
>  			dev_info(smmu->dev, "event 0x%02x received:\n", id);
>  			for (i = 0; i < ARRAY_SIZE(evt); ++i)
>  				dev_info(smmu->dev, "\t0x%016llx\n",
> @@ -1272,6 +1288,11 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
>  
>  	/* Sync our overflow flag, as we believe we're up to speed */
>  	q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons);
> +
> +	q->batch++;
> +	wake_up_locked(&q->wq);
> +	spin_unlock(&q->wq.lock);
> +
>  	return IRQ_HANDLED;
>  }
>  
> @@ -1315,13 +1336,24 @@ static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64 *evt)
>  
>  static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
>  {
> +	int num_handled = 0;
>  	struct arm_smmu_device *smmu = dev;
>  	struct arm_smmu_queue *q = &smmu->priq.q;
> +	size_t queue_size = 1 << q->max_n_shift;
>  	u64 evt[PRIQ_ENT_DWORDS];
>  
> +	spin_lock(&q->wq.lock);
>  	do {
> -		while (!queue_remove_raw(q, evt))
> +		while (!queue_remove_raw(q, evt)) {
> +			spin_unlock(&q->wq.lock);
>  			arm_smmu_handle_ppr(smmu, evt);
> +			spin_lock(&q->wq.lock);
> +			if (++num_handled == queue_size) {
> +				q->batch++;
> +				wake_up_locked(&q->wq);
> +				num_handled = 0;
> +			}
> +		}
>  
>  		if (queue_sync_prod(q) == -EOVERFLOW)
>  			dev_err(smmu->dev, "PRIQ overflow detected -- requests lost\n");
> @@ -1329,9 +1361,65 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
>  
>  	/* Sync our overflow flag, as we believe we're up to speed */
>  	q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons);
> +
> +	q->batch++;
> +	wake_up_locked(&q->wq);
> +	spin_unlock(&q->wq.lock);
> +
>  	return IRQ_HANDLED;
>  }
>  
> +/*
> + * arm_smmu_flush_queue - wait until all events/PPRs currently in the queue have
> + * been consumed.
> + *
> + * Wait until the queue thread finished a batch, or until the queue is empty.
> + * Note that we don't handle overflows on q->batch. If it occurs, just wait for
> + * the queue to be empty.
> + */
> +static int arm_smmu_flush_queue(struct arm_smmu_device *smmu,
> +				struct arm_smmu_queue *q, const char *name)
> +{
> +	int ret;
> +	u64 batch;
> +
> +	spin_lock(&q->wq.lock);
> +	if (queue_sync_prod(q) == -EOVERFLOW)
> +		dev_err(smmu->dev, "%s overflow detected -- requests lost\n", name);
> +
> +	batch = q->batch;
> +	ret = wait_event_interruptible_locked(q->wq, queue_empty(q) ||
> +					      q->batch >= batch + 2);
> +	spin_unlock(&q->wq.lock);
> +
> +	return ret;
> +}
> +
> +static int arm_smmu_flush_queues(struct notifier_block *nb,
> +				 unsigned long action, void *data)
> +{
> +	struct arm_smmu_device *smmu = container_of(nb, struct arm_smmu_device,
> +						    faultq_nb);
> +	struct device *dev = data;
> +	struct arm_smmu_master_data *master = NULL;
> +
> +	if (dev)
> +		master = dev->iommu_fwspec->iommu_priv;
> +
> +	if (master) {
> +		/* TODO: add support for PRI and Stall */
> +		return 0;
> +	}
> +
> +	/* No target device, flush all queues. */
> +	if (smmu->features & ARM_SMMU_FEAT_STALLS)
> +		arm_smmu_flush_queue(smmu, &smmu->evtq.q, "evtq");
> +	if (smmu->features & ARM_SMMU_FEAT_PRI)
> +		arm_smmu_flush_queue(smmu, &smmu->priq.q, "priq");
> +
> +	return 0;
> +}
> +
>  static int arm_smmu_device_disable(struct arm_smmu_device *smmu);
>  
>  static irqreturn_t arm_smmu_gerror_handler(int irq, void *dev)
> @@ -2288,6 +2376,10 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
>  		     << Q_BASE_LOG2SIZE_SHIFT;
>  
>  	q->prod = q->cons = 0;
> +
> +	init_waitqueue_head(&q->wq);
> +	q->batch = 0;
> +
>  	return 0;
>  }
>  
> @@ -3168,6 +3260,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>  	if (ret)
>  		return ret;
>  
> +	if (smmu->features & (ARM_SMMU_FEAT_STALLS | ARM_SMMU_FEAT_PRI)) {
> +		smmu->faultq_nb.notifier_call = arm_smmu_flush_queues;
> +		ret = iommu_fault_queue_register(&smmu->faultq_nb);
Here you register only if this smmu supports stalls or pri which is fine, but
see the unregister path.

> +		if (ret)
> +			return ret;
> +	}
> +
>  	/* And we're up. Go go go! */
>  	ret = iommu_device_sysfs_add(&smmu->iommu, dev, NULL,
>  				     "smmu3.%pa", &ioaddr);
> @@ -3210,6 +3309,8 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
>  {
>  	struct arm_smmu_device *smmu = platform_get_drvdata(pdev);
>  
> +	iommu_fault_queue_unregister(&smmu->faultq_nb);

Here you unregister from the fault queue unconditionally.  That is mostly
safe but it seems to decrement and potentially destroy the work queue that
is in use by another smmu instance that does support page faulting.

> +
>  	arm_smmu_device_disable(smmu);
>  
>  	return 0;


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue
  2018-02-12 18:33 [PATCH 00/37] Shared Virtual Addressing for the IOMMU Jean-Philippe Brucker
@ 2018-02-12 18:33 ` Jean-Philippe Brucker
  2018-03-08 17:44   ` Jonathan Cameron
  0 siblings, 1 reply; 11+ messages in thread
From: Jean-Philippe Brucker @ 2018-02-12 18:33 UTC (permalink / raw)
  To: linux-arm-kernel, linux-pci, linux-acpi, devicetree, iommu, kvm
  Cc: joro, robh+dt, mark.rutland, catalin.marinas, will.deacon,
	lorenzo.pieralisi, hanjun.guo, sudeep.holla, rjw, lenb,
	robin.murphy, bhelgaas, alex.williamson, tn, liubo95,
	thunder.leizhen, xieyisheng1, xuzaibo, ilias.apalodimas,
	jonathan.cameron, shunyong.yang, nwatters, okaya, jcrouse,
	rfranz, dwmw2, jacob.jun.pan, yi.l.liu, ashok.raj, robdclark,
	christian.koenig, bharatku

When using PRI or Stall, the PRI or event handler enqueues faults into the
core fault queue. Register it based on the SMMU features.

When the core stops using a PASID, it notifies the SMMU to flush all
instances of this PASID from the PRI queue. Add a way to flush the PRI and
event queue. PRI and event thread now take a spinlock while processing the
queue. The flush handler takes this lock to inspect the queue state.
We avoid livelock, where the SMMU adds fault to the queue faster than we
can consume them, by incrementing a 'batch' number on every cycle so the
flush handler only has to wait a complete cycle (two batch increments.)

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
---
 drivers/iommu/Kconfig       |   1 +
 drivers/iommu/arm-smmu-v3.c | 103 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d434f7085dc2..d79c68754bb9 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -354,6 +354,7 @@ config ARM_SMMU_V3
 	depends on ARM64
 	select IOMMU_API
 	select IOMMU_SVA
+	select IOMMU_FAULT
 	select IOMMU_IO_PGTABLE_LPAE
 	select ARM_SMMU_V3_CONTEXT
 	select GENERIC_MSI_IRQ_DOMAIN
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 8528704627b5..c5b3a43becaf 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -494,6 +494,10 @@ struct arm_smmu_queue {
 
 	u32 __iomem			*prod_reg;
 	u32 __iomem			*cons_reg;
+
+	/* Event and PRI */
+	u64				batch;
+	wait_queue_head_t		wq;
 };
 
 struct arm_smmu_cmdq {
@@ -610,6 +614,9 @@ struct arm_smmu_device {
 
 	/* IOMMU core code handle */
 	struct iommu_device		iommu;
+
+	/* Notifier for the fault queue */
+	struct notifier_block		faultq_nb;
 };
 
 /* SMMU private data for each master */
@@ -1247,14 +1254,23 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
 static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
 {
 	int i;
+	int num_handled = 0;
 	struct arm_smmu_device *smmu = dev;
 	struct arm_smmu_queue *q = &smmu->evtq.q;
+	size_t queue_size = 1 << q->max_n_shift;
 	u64 evt[EVTQ_ENT_DWORDS];
 
+	spin_lock(&q->wq.lock);
 	do {
 		while (!queue_remove_raw(q, evt)) {
 			u8 id = evt[0] >> EVTQ_0_ID_SHIFT & EVTQ_0_ID_MASK;
 
+			if (++num_handled == queue_size) {
+				q->batch++;
+				wake_up_locked(&q->wq);
+				num_handled = 0;
+			}
+
 			dev_info(smmu->dev, "event 0x%02x received:\n", id);
 			for (i = 0; i < ARRAY_SIZE(evt); ++i)
 				dev_info(smmu->dev, "\t0x%016llx\n",
@@ -1272,6 +1288,11 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
 
 	/* Sync our overflow flag, as we believe we're up to speed */
 	q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons);
+
+	q->batch++;
+	wake_up_locked(&q->wq);
+	spin_unlock(&q->wq.lock);
+
 	return IRQ_HANDLED;
 }
 
@@ -1315,13 +1336,24 @@ static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64 *evt)
 
 static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
 {
+	int num_handled = 0;
 	struct arm_smmu_device *smmu = dev;
 	struct arm_smmu_queue *q = &smmu->priq.q;
+	size_t queue_size = 1 << q->max_n_shift;
 	u64 evt[PRIQ_ENT_DWORDS];
 
+	spin_lock(&q->wq.lock);
 	do {
-		while (!queue_remove_raw(q, evt))
+		while (!queue_remove_raw(q, evt)) {
+			spin_unlock(&q->wq.lock);
 			arm_smmu_handle_ppr(smmu, evt);
+			spin_lock(&q->wq.lock);
+			if (++num_handled == queue_size) {
+				q->batch++;
+				wake_up_locked(&q->wq);
+				num_handled = 0;
+			}
+		}
 
 		if (queue_sync_prod(q) == -EOVERFLOW)
 			dev_err(smmu->dev, "PRIQ overflow detected -- requests lost\n");
@@ -1329,9 +1361,65 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
 
 	/* Sync our overflow flag, as we believe we're up to speed */
 	q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons);
+
+	q->batch++;
+	wake_up_locked(&q->wq);
+	spin_unlock(&q->wq.lock);
+
 	return IRQ_HANDLED;
 }
 
+/*
+ * arm_smmu_flush_queue - wait until all events/PPRs currently in the queue have
+ * been consumed.
+ *
+ * Wait until the queue thread finished a batch, or until the queue is empty.
+ * Note that we don't handle overflows on q->batch. If it occurs, just wait for
+ * the queue to be empty.
+ */
+static int arm_smmu_flush_queue(struct arm_smmu_device *smmu,
+				struct arm_smmu_queue *q, const char *name)
+{
+	int ret;
+	u64 batch;
+
+	spin_lock(&q->wq.lock);
+	if (queue_sync_prod(q) == -EOVERFLOW)
+		dev_err(smmu->dev, "%s overflow detected -- requests lost\n", name);
+
+	batch = q->batch;
+	ret = wait_event_interruptible_locked(q->wq, queue_empty(q) ||
+					      q->batch >= batch + 2);
+	spin_unlock(&q->wq.lock);
+
+	return ret;
+}
+
+static int arm_smmu_flush_queues(struct notifier_block *nb,
+				 unsigned long action, void *data)
+{
+	struct arm_smmu_device *smmu = container_of(nb, struct arm_smmu_device,
+						    faultq_nb);
+	struct device *dev = data;
+	struct arm_smmu_master_data *master = NULL;
+
+	if (dev)
+		master = dev->iommu_fwspec->iommu_priv;
+
+	if (master) {
+		/* TODO: add support for PRI and Stall */
+		return 0;
+	}
+
+	/* No target device, flush all queues. */
+	if (smmu->features & ARM_SMMU_FEAT_STALLS)
+		arm_smmu_flush_queue(smmu, &smmu->evtq.q, "evtq");
+	if (smmu->features & ARM_SMMU_FEAT_PRI)
+		arm_smmu_flush_queue(smmu, &smmu->priq.q, "priq");
+
+	return 0;
+}
+
 static int arm_smmu_device_disable(struct arm_smmu_device *smmu);
 
 static irqreturn_t arm_smmu_gerror_handler(int irq, void *dev)
@@ -2288,6 +2376,10 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
 		     << Q_BASE_LOG2SIZE_SHIFT;
 
 	q->prod = q->cons = 0;
+
+	init_waitqueue_head(&q->wq);
+	q->batch = 0;
+
 	return 0;
 }
 
@@ -3168,6 +3260,13 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	if (smmu->features & (ARM_SMMU_FEAT_STALLS | ARM_SMMU_FEAT_PRI)) {
+		smmu->faultq_nb.notifier_call = arm_smmu_flush_queues;
+		ret = iommu_fault_queue_register(&smmu->faultq_nb);
+		if (ret)
+			return ret;
+	}
+
 	/* And we're up. Go go go! */
 	ret = iommu_device_sysfs_add(&smmu->iommu, dev, NULL,
 				     "smmu3.%pa", &ioaddr);
@@ -3210,6 +3309,8 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
 {
 	struct arm_smmu_device *smmu = platform_get_drvdata(pdev);
 
+	iommu_fault_queue_unregister(&smmu->faultq_nb);
+
 	arm_smmu_device_disable(smmu);
 
 	return 0;
-- 
2.15.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-04-04 10:13 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1519280641-30258-1-git-send-email-xieyisheng1@huawei.com>
     [not found] ` <1519280641-30258-3-git-send-email-xieyisheng1@huawei.com>
2018-02-22  9:03   ` [PATCH 03/37] iommu/sva: Manage process address spaces Yisheng Xie
2018-02-22 13:17     ` Jean-Philippe Brucker
     [not found] ` <1519280641-30258-37-git-send-email-xieyisheng1@huawei.com>
2018-03-19  9:47   ` [PATCH 37/37] vfio: Add support for Shared Virtual Addressing Yisheng Xie
2018-03-21 13:40     ` Jean-Philippe Brucker
     [not found] ` <1519280641-30258-27-git-send-email-xieyisheng1@huawei.com>
2018-03-19 11:03   ` [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue Yisheng Xie
2018-03-21 13:24     ` Jean-Philippe Brucker
2018-03-22  1:09       ` Yisheng Xie
2018-04-04 10:13         ` Jean-Philippe Brucker
2018-02-12 18:33 [PATCH 00/37] Shared Virtual Addressing for the IOMMU Jean-Philippe Brucker
2018-02-12 18:33 ` [PATCH 27/37] iommu/arm-smmu-v3: Register fault workqueue Jean-Philippe Brucker
2018-03-08 17:44   ` Jonathan Cameron
2018-03-14 13:08     ` Jean-Philippe Brucker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).