linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RESEND v8] PCI: imx6: limit DBI register length
@ 2019-07-26 14:40 Stefan Agner
  2019-07-26 16:32 ` Lucas Stach
  2019-08-15 10:56 ` Lorenzo Pieralisi
  0 siblings, 2 replies; 3+ messages in thread
From: Stefan Agner @ 2019-07-26 14:40 UTC (permalink / raw)
  To: hongxing.zhu, l.stach
  Cc: lorenzo.pieralisi, jingoohan1, gustavo.pimentel, tpiepho,
	leonard.crestez, bhelgaas, linux-pci, linux-kernel, Stefan Agner

Define the length of the DBI registers and limit config space to its
length. This makes sure that the kernel does not access registers
beyond that point, avoiding the following abort on a i.MX 6Quad:
  # cat /sys/devices/soc0/soc/1ffc000.pcie/pci0000\:00/0000\:00\:00.0/config
  [  100.021433] Unhandled fault: imprecise external abort (0x1406) at 0xb6ea7000
  ...
  [  100.056423] PC is at dw_pcie_read+0x50/0x84
  [  100.060790] LR is at dw_pcie_rd_own_conf+0x44/0x48
  ...

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
Changes in v3:
- Rebase on pci/dwc
Changes in v4:
- Rebase on pci/dwc
Changes in v5:
- Rebased ontop of pci/dwc
- Use DBI length of 0x200
Changes in v6:
- Use pci_dev.cfg_size mechanism to limit config space (this made patch 1
  of previous versions of this patchset obsolete).
Changes in v7:
- Restrict fixup to Synopsys/0xabcd
- Apply cfg_size limitation only if dbi_length is specified
Changes in v8:
- Restrict fixup for Synopsys/0xabcd and class PCI bridge
- Check device driver to be pci-imx6

 drivers/pci/controller/dwc/pci-imx6.c | 33 +++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 9b5cb5b70389..8b8efa3063f5 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -57,6 +57,7 @@ enum imx6_pcie_variants {
 struct imx6_pcie_drvdata {
 	enum imx6_pcie_variants variant;
 	u32 flags;
+	int dbi_length;
 };
 
 struct imx6_pcie {
@@ -1212,6 +1213,7 @@ static const struct imx6_pcie_drvdata drvdata[] = {
 		.variant = IMX6Q,
 		.flags = IMX6_PCIE_FLAG_IMX6_PHY |
 			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,
+		.dbi_length = 0x200,
 	},
 	[IMX6SX] = {
 		.variant = IMX6SX,
@@ -1254,6 +1256,37 @@ static struct platform_driver imx6_pcie_driver = {
 	.shutdown = imx6_pcie_shutdown,
 };
 
+static void imx6_pcie_quirk(struct pci_dev *dev)
+{
+	struct pci_bus *bus = dev->bus;
+	struct pcie_port *pp = bus->sysdata;
+
+	/* Bus parent is the PCI bridge, its parent is this platform driver */
+	if (!bus->dev.parent || !bus->dev.parent->parent)
+		return;
+
+	/* Make sure we only quirk devices associated with this driver */
+	if (bus->dev.parent->parent->driver != &imx6_pcie_driver.driver)
+		return;
+
+	if (bus->number == pp->root_bus_nr) {
+		struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+		struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
+
+		/*
+		 * Limit config length to avoid the kernel reading beyond
+		 * the register set and causing an abort on i.MX 6Quad
+		 */
+		if (imx6_pcie->drvdata->dbi_length) {
+			dev->cfg_size = imx6_pcie->drvdata->dbi_length;
+			dev_info(&dev->dev, "Limiting cfg_size to %d\n",
+					dev->cfg_size);
+		}
+	}
+}
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd,
+			PCI_CLASS_BRIDGE_PCI, 8, imx6_pcie_quirk);
+
 static int __init imx6_pcie_init(void)
 {
 #ifdef CONFIG_ARM
-- 
2.22.0


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

* Re: [PATCH RESEND v8] PCI: imx6: limit DBI register length
  2019-07-26 14:40 [PATCH RESEND v8] PCI: imx6: limit DBI register length Stefan Agner
@ 2019-07-26 16:32 ` Lucas Stach
  2019-08-15 10:56 ` Lorenzo Pieralisi
  1 sibling, 0 replies; 3+ messages in thread
From: Lucas Stach @ 2019-07-26 16:32 UTC (permalink / raw)
  To: Stefan Agner, hongxing.zhu
  Cc: lorenzo.pieralisi, jingoohan1, gustavo.pimentel, tpiepho,
	leonard.crestez, bhelgaas, linux-pci, linux-kernel

Am Freitag, den 26.07.2019, 16:40 +0200 schrieb Stefan Agner:
> Define the length of the DBI registers and limit config space to its
> length. This makes sure that the kernel does not access registers
> beyond that point, avoiding the following abort on a i.MX 6Quad:
>   # cat /sys/devices/soc0/soc/1ffc000.pcie/pci0000\:00/0000\:00\:00.0/config
>   [  100.021433] Unhandled fault: imprecise external abort (0x1406) at 0xb6ea7000
>   ...
>   [  100.056423] PC is at dw_pcie_read+0x50/0x84
>   [  100.060790] LR is at dw_pcie_rd_own_conf+0x44/0x48
>   ...
> 
> Signed-off-by: Stefan Agner <stefan@agner.ch>

Reviewed-by: Lucas Stach <l.stach@pengutronix.de>

> ---
> Changes in v3:
> - Rebase on pci/dwc
> Changes in v4:
> - Rebase on pci/dwc
> Changes in v5:
> - Rebased ontop of pci/dwc
> - Use DBI length of 0x200
> Changes in v6:
> - Use pci_dev.cfg_size mechanism to limit config space (this made patch 1
>   of previous versions of this patchset obsolete).
> Changes in v7:
> - Restrict fixup to Synopsys/0xabcd
> - Apply cfg_size limitation only if dbi_length is specified
> Changes in v8:
> - Restrict fixup for Synopsys/0xabcd and class PCI bridge
> - Check device driver to be pci-imx6
> 
>  drivers/pci/controller/dwc/pci-imx6.c | 33 +++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
> 
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 9b5cb5b70389..8b8efa3063f5 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -57,6 +57,7 @@ enum imx6_pcie_variants {
>  struct imx6_pcie_drvdata {
> >  	enum imx6_pcie_variants variant;
> >  	u32 flags;
> > +	int dbi_length;
>  };
>  
>  struct imx6_pcie {
> @@ -1212,6 +1213,7 @@ static const struct imx6_pcie_drvdata drvdata[] = {
> >  		.variant = IMX6Q,
> >  		.flags = IMX6_PCIE_FLAG_IMX6_PHY |
> >  			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,
> > +		.dbi_length = 0x200,
> >  	},
> >  	[IMX6SX] = {
> >  		.variant = IMX6SX,
> @@ -1254,6 +1256,37 @@ static struct platform_driver imx6_pcie_driver = {
> >  	.shutdown = imx6_pcie_shutdown,
>  };
>  
> +static void imx6_pcie_quirk(struct pci_dev *dev)
> +{
> > +	struct pci_bus *bus = dev->bus;
> > +	struct pcie_port *pp = bus->sysdata;
> +
> > +	/* Bus parent is the PCI bridge, its parent is this platform driver */
> > +	if (!bus->dev.parent || !bus->dev.parent->parent)
> > +		return;
> +
> > +	/* Make sure we only quirk devices associated with this driver */
> > +	if (bus->dev.parent->parent->driver != &imx6_pcie_driver.driver)
> > +		return;
> +
> > +	if (bus->number == pp->root_bus_nr) {
> > +		struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +		struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
> +
> > +		/*
> > +		 * Limit config length to avoid the kernel reading beyond
> > +		 * the register set and causing an abort on i.MX 6Quad
> > +		 */
> > +		if (imx6_pcie->drvdata->dbi_length) {
> > +			dev->cfg_size = imx6_pcie->drvdata->dbi_length;
> > +			dev_info(&dev->dev, "Limiting cfg_size to %d\n",
> > +					dev->cfg_size);
> > +		}
> > +	}
> +}
> +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd,
> > +			PCI_CLASS_BRIDGE_PCI, 8, imx6_pcie_quirk);
> +
>  static int __init imx6_pcie_init(void)
>  {
>  #ifdef CONFIG_ARM

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

* Re: [PATCH RESEND v8] PCI: imx6: limit DBI register length
  2019-07-26 14:40 [PATCH RESEND v8] PCI: imx6: limit DBI register length Stefan Agner
  2019-07-26 16:32 ` Lucas Stach
@ 2019-08-15 10:56 ` Lorenzo Pieralisi
  1 sibling, 0 replies; 3+ messages in thread
From: Lorenzo Pieralisi @ 2019-08-15 10:56 UTC (permalink / raw)
  To: Stefan Agner
  Cc: hongxing.zhu, l.stach, jingoohan1, gustavo.pimentel, tpiepho,
	leonard.crestez, bhelgaas, linux-pci, linux-kernel

On Fri, Jul 26, 2019 at 04:40:07PM +0200, Stefan Agner wrote:
> Define the length of the DBI registers and limit config space to its
> length. This makes sure that the kernel does not access registers
> beyond that point, avoiding the following abort on a i.MX 6Quad:
>   # cat /sys/devices/soc0/soc/1ffc000.pcie/pci0000\:00/0000\:00\:00.0/config
>   [  100.021433] Unhandled fault: imprecise external abort (0x1406) at 0xb6ea7000
>   ...
>   [  100.056423] PC is at dw_pcie_read+0x50/0x84
>   [  100.060790] LR is at dw_pcie_rd_own_conf+0x44/0x48
>   ...
> 
> Signed-off-by: Stefan Agner <stefan@agner.ch>
> ---
> Changes in v3:
> - Rebase on pci/dwc
> Changes in v4:
> - Rebase on pci/dwc
> Changes in v5:
> - Rebased ontop of pci/dwc
> - Use DBI length of 0x200
> Changes in v6:
> - Use pci_dev.cfg_size mechanism to limit config space (this made patch 1
>   of previous versions of this patchset obsolete).
> Changes in v7:
> - Restrict fixup to Synopsys/0xabcd
> - Apply cfg_size limitation only if dbi_length is specified
> Changes in v8:
> - Restrict fixup for Synopsys/0xabcd and class PCI bridge
> - Check device driver to be pci-imx6
> 
>  drivers/pci/controller/dwc/pci-imx6.c | 33 +++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)

Applied to pci/imx for v5.4.

Thanks,
Lorenzo

> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 9b5cb5b70389..8b8efa3063f5 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -57,6 +57,7 @@ enum imx6_pcie_variants {
>  struct imx6_pcie_drvdata {
>  	enum imx6_pcie_variants variant;
>  	u32 flags;
> +	int dbi_length;
>  };
>  
>  struct imx6_pcie {
> @@ -1212,6 +1213,7 @@ static const struct imx6_pcie_drvdata drvdata[] = {
>  		.variant = IMX6Q,
>  		.flags = IMX6_PCIE_FLAG_IMX6_PHY |
>  			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,
> +		.dbi_length = 0x200,
>  	},
>  	[IMX6SX] = {
>  		.variant = IMX6SX,
> @@ -1254,6 +1256,37 @@ static struct platform_driver imx6_pcie_driver = {
>  	.shutdown = imx6_pcie_shutdown,
>  };
>  
> +static void imx6_pcie_quirk(struct pci_dev *dev)
> +{
> +	struct pci_bus *bus = dev->bus;
> +	struct pcie_port *pp = bus->sysdata;
> +
> +	/* Bus parent is the PCI bridge, its parent is this platform driver */
> +	if (!bus->dev.parent || !bus->dev.parent->parent)
> +		return;
> +
> +	/* Make sure we only quirk devices associated with this driver */
> +	if (bus->dev.parent->parent->driver != &imx6_pcie_driver.driver)
> +		return;
> +
> +	if (bus->number == pp->root_bus_nr) {
> +		struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> +		struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
> +
> +		/*
> +		 * Limit config length to avoid the kernel reading beyond
> +		 * the register set and causing an abort on i.MX 6Quad
> +		 */
> +		if (imx6_pcie->drvdata->dbi_length) {
> +			dev->cfg_size = imx6_pcie->drvdata->dbi_length;
> +			dev_info(&dev->dev, "Limiting cfg_size to %d\n",
> +					dev->cfg_size);
> +		}
> +	}
> +}
> +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd,
> +			PCI_CLASS_BRIDGE_PCI, 8, imx6_pcie_quirk);
> +
>  static int __init imx6_pcie_init(void)
>  {
>  #ifdef CONFIG_ARM
> -- 
> 2.22.0
> 

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

end of thread, other threads:[~2019-08-15 10:56 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-26 14:40 [PATCH RESEND v8] PCI: imx6: limit DBI register length Stefan Agner
2019-07-26 16:32 ` Lucas Stach
2019-08-15 10:56 ` Lorenzo Pieralisi

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).