iommu.lists.linux-foundation.org archive mirror
 help / color / mirror / Atom feed
From: Bjorn Helgaas <helgaas@kernel.org>
To: Rajat Jain <rajatja@google.com>
Cc: Todd Broch <tbroch@google.com>,
	linux-pci@vger.kernel.org, lalithambika.krishnakumar@intel.com,
	Heikki Krogerus <heikki.krogerus@linux.intel.com>,
	Diego Rivas <diegorivas@google.com>,
	Jean-Philippe Brucker <jean-philippe@linaro.org>,
	Furquan Shaikh <furquan@google.com>,
	Raj Ashok <ashok.raj@intel.com>,
	Saravana Kannan <saravanak@google.com>,
	linux-acpi@vger.kernel.org,
	Christian Kellner <christian@kellner.me>,
	Mattias Nissler <mnissler@google.com>,
	Jesse Barnes <jsbarnes@google.com>, Len Brown <lenb@kernel.org>,
	Rajat Jain <rajatxjain@gmail.com>,
	Prashant Malani <pmalani@google.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Aaron Durbin <adurbin@google.com>,
	Alex Williamson <alex.williamson@redhat.com>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Mika Westerberg <mika.westerberg@linux.intel.com>,
	Bernie Keany <bernie.keany@intel.com>,
	Duncan Laurie <dlaurie@google.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	"Rafael J. Wysocki" <rjw@rjwysocki.net>,
	linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org,
	Arnd Bergmann <arnd@arndb.de>,
	oohall@gmail.com, Benson Leung <bleung@google.com>,
	David Woodhouse <dwmw2@infradead.org>,
	Alex Levin <levinale@google.com>
Subject: Re: [PATCH v5] PCI/ACS: Enable PCI_ACS_TB and disable only when needed for ATS
Date: Wed, 16 Sep 2020 16:49:32 -0500	[thread overview]
Message-ID: <20200916214932.GA1587255@bjorn-Precision-5520> (raw)
In-Reply-To: <20200714201540.3139140-1-rajatja@google.com>

On Tue, Jul 14, 2020 at 01:15:40PM -0700, Rajat Jain wrote:
> The ACS "Translation Blocking" bit blocks the translated addresses from
> the devices. We don't expect such traffic from devices unless ATS is
> enabled on them. A device sending such traffic without ATS enabled,
> indicates malicious intent, and thus should be blocked.
> 
> Enable PCI_ACS_TB by default for all devices, and it stays enabled until
> atleast one of the devices downstream wants to enable ATS. It gets
> disabled to enable ATS on a device downstream it, and then gets enabled
> back on once all the downstream devices don't need ATS.
> 
> Signed-off-by: Rajat Jain <rajatja@google.com>

I applied v4 of this patch instead because I think the complexity of
this one, where we have to walk up the tree and disable TB in upstream
bridges, is too high.  It's always tricky to modify the state of
device Y when we're doing something for device X.

> ---
> Note that I'm ignoring the devices that require quirks to enable or
> disable ACS, instead of using the standard way for ACS configuration.
> The reason is that it would require adding yet another quirk table or
> quirk function pointer, that I don't know how to implement for those
> devices, and will neither have the devices to test that code.
> 
> v5: Enable TB and disable ATS for all devices on boot. Disable TB later
>     only if needed to enable ATS on downstream devices.
> v4: Add braces to avoid warning from kernel robot
>     print warning for only external-facing devices.
> v3: print warning if ACS_TB not supported on external-facing/untrusted ports.
>     Minor code comments fixes.
> v2: Commit log change
> 
>  drivers/pci/ats.c   |  5 ++++
>  drivers/pci/pci.c   | 57 +++++++++++++++++++++++++++++++++++++++++++++
>  drivers/pci/pci.h   |  2 ++
>  drivers/pci/probe.c |  2 +-
>  include/linux/pci.h |  2 ++
>  5 files changed, 67 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
> index b761c1f72f67..e2ea9083f30f 100644
> --- a/drivers/pci/ats.c
> +++ b/drivers/pci/ats.c
> @@ -28,6 +28,9 @@ void pci_ats_init(struct pci_dev *dev)
>  		return;
>  
>  	dev->ats_cap = pos;
> +
> +	dev->ats_enabled = 1; /* To avoid WARN_ON from pci_disable_ats() */
> +	pci_disable_ats(dev);
>  }
>  
>  /**
> @@ -82,6 +85,7 @@ int pci_enable_ats(struct pci_dev *dev, int ps)
>  	}
>  	pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl);
>  
> +	pci_disable_acs_trans_blocking(dev);
>  	dev->ats_enabled = 1;
>  	return 0;
>  }
> @@ -102,6 +106,7 @@ void pci_disable_ats(struct pci_dev *dev)
>  	ctrl &= ~PCI_ATS_CTRL_ENABLE;
>  	pci_write_config_word(dev, dev->ats_cap + PCI_ATS_CTRL, ctrl);
>  
> +	pci_enable_acs_trans_blocking(dev);
>  	dev->ats_enabled = 0;
>  }
>  EXPORT_SYMBOL_GPL(pci_disable_ats);
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 73a862782214..614e3c1e8c56 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -876,6 +876,9 @@ static void pci_std_enable_acs(struct pci_dev *dev)
>  	/* Upstream Forwarding */
>  	ctrl |= (cap & PCI_ACS_UF);
>  
> +	/* Translation Blocking */
> +	ctrl |= (cap & PCI_ACS_TB);
> +
>  	pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
>  }
>  
> @@ -904,6 +907,60 @@ static void pci_enable_acs(struct pci_dev *dev)
>  	pci_disable_acs_redir(dev);
>  }
>  
> +void pci_disable_acs_trans_blocking(struct pci_dev *pdev)
> +{
> +	u16 cap, ctrl, pos;
> +	struct pci_dev *dev;
> +
> +	if (!pci_acs_enable)
> +		return;
> +
> +	for (dev = pdev; dev; dev = pci_upstream_bridge(pdev)) {
> +
> +		pos = dev->acs_cap;
> +		if (!pos)
> +			continue;
> +
> +		/*
> +		 * Disable translation blocking when first downstream
> +		 * device that needs it (for ATS) wants to enable ATS
> +		 */
> +		if (++dev->ats_dependencies == 1) {
> +			pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
> +			pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
> +			ctrl &= ~(cap & PCI_ACS_TB);
> +			pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
> +		}
> +	}
> +}
> +
> +void pci_enable_acs_trans_blocking(struct pci_dev *pdev)
> +{
> +	u16 cap, ctrl, pos;
> +	struct pci_dev *dev;
> +
> +	if (!pci_acs_enable)
> +		return;
> +
> +	for (dev = pdev; dev; dev = pci_upstream_bridge(pdev)) {
> +
> +		pos = dev->acs_cap;
> +		if (!pos)
> +			continue;
> +
> +		/*
> +		 * Enable translation blocking when last downstream device
> +		 * that depends on it (for ATS), doesn't need ATS anymore
> +		 */
> +		if (--dev->ats_dependencies == 0) {
> +			pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
> +			pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
> +			ctrl |= (cap & PCI_ACS_TB);
> +			pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
> +		}
> +	}
> +}
> +
>  /**
>   * pci_restore_bars - restore a device's BAR values (e.g. after wake-up)
>   * @dev: PCI device to have its BARs restored
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 12fb79fbe29d..f5d8ecb6ba96 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -552,6 +552,8 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
>  	return -ENOTTY;
>  }
>  #endif
> +void pci_disable_acs_trans_blocking(struct pci_dev *dev);
> +void pci_enable_acs_trans_blocking(struct pci_dev *dev);
>  
>  /* PCI error reporting and recovery */
>  pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 8c40c00413e7..e2ff3a94e621 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -2387,10 +2387,10 @@ static void pci_init_capabilities(struct pci_dev *dev)
>  	pci_vpd_init(dev);		/* Vital Product Data */
>  	pci_configure_ari(dev);		/* Alternative Routing-ID Forwarding */
>  	pci_iov_init(dev);		/* Single Root I/O Virtualization */
> +	pci_acs_init(dev);		/* Access Control Services */
>  	pci_ats_init(dev);		/* Address Translation Services */
>  	pci_pri_init(dev);		/* Page Request Interface */
>  	pci_pasid_init(dev);		/* Process Address Space ID */
> -	pci_acs_init(dev);		/* Access Control Services */
>  	pci_ptm_init(dev);		/* Precision Time Measurement */
>  	pci_aer_init(dev);		/* Advanced Error Reporting */
>  	pci_dpc_init(dev);		/* Downstream Port Containment */
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 7a40cd5caed0..31da4355f0fd 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -480,6 +480,8 @@ struct pci_dev {
>  	u16		ats_cap;	/* ATS Capability offset */
>  	u8		ats_stu;	/* ATS Smallest Translation Unit */
>  #endif
> +	/* Total number of downstream devices below a bridge that need ATS */
> +	u8		ats_dependencies;
>  #ifdef CONFIG_PCI_PRI
>  	u16		pri_cap;	/* PRI Capability offset */
>  	u32		pri_reqs_alloc; /* Number of PRI requests allocated */
> -- 
> 2.27.0.389.gc38d7665816-goog
> 
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

      parent reply	other threads:[~2020-09-16 21:49 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-14 20:15 [PATCH v5] PCI/ACS: Enable PCI_ACS_TB and disable only when needed for ATS Rajat Jain via iommu
2020-07-14 20:24 ` Rajat Jain
2020-08-02  0:30   ` Rajat Jain via iommu
2020-08-17 22:50     ` Rajat Jain
2020-09-10 21:31       ` Rajat Jain via iommu
2020-08-02  0:18 ` Rajat Jain via iommu
2020-09-16 21:49 ` Bjorn Helgaas [this message]

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=20200916214932.GA1587255@bjorn-Precision-5520 \
    --to=helgaas@kernel.org \
    --cc=adurbin@google.com \
    --cc=alex.williamson@redhat.com \
    --cc=arnd@arndb.de \
    --cc=ashok.raj@intel.com \
    --cc=bernie.keany@intel.com \
    --cc=bhelgaas@google.com \
    --cc=bleung@google.com \
    --cc=christian@kellner.me \
    --cc=diegorivas@google.com \
    --cc=dlaurie@google.com \
    --cc=dwmw2@infradead.org \
    --cc=furquan@google.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=iommu@lists.linux-foundation.org \
    --cc=jean-philippe@linaro.org \
    --cc=jsbarnes@google.com \
    --cc=lalithambika.krishnakumar@intel.com \
    --cc=lenb@kernel.org \
    --cc=levinale@google.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=mika.westerberg@linux.intel.com \
    --cc=mnissler@google.com \
    --cc=oohall@gmail.com \
    --cc=pmalani@google.com \
    --cc=rajatja@google.com \
    --cc=rajatxjain@gmail.com \
    --cc=rjw@rjwysocki.net \
    --cc=saravanak@google.com \
    --cc=suzuki.poulose@arm.com \
    --cc=tbroch@google.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;
as well as URLs for NNTP newsgroup(s).