mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE
@ 2018-08-01  8:38 Lucas Stach
  2018-08-01  8:38 ` [PATCH 1/3] PCI: link PCI devices with potentially existing OF nodes Lucas Stach
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Lucas Stach @ 2018-08-01  8:38 UTC (permalink / raw)
  To: barebox

When replacing a section with a PTE, we must make sure that the newly
initialized PTE entries are flushed from the cache before changing the
entry in the TTB. Otherwise a L1 TLB miss causes the hardware pagetable
walker to walk into a PTE with undefined content, causing exactly that
behaviour.

Move all the necessary cache flushing to arm_create_pte(), to avoid any
caller getting this wrong in the future.

Fixes: e3e54c644180 (ARM: mmu: Implement on-demand PTE allocation)
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 arch/arm/cpu/mmu.c | 77 +++++++++++++++++++---------------------------
 1 file changed, 32 insertions(+), 45 deletions(-)

diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index ae189ecdeb16..712c3930fb71 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -85,34 +85,6 @@ static void arm_mmu_not_initialized_error(void)
 	panic("MMU not initialized\n");
 }
 
-/*
- * Create a second level translation table for the given virtual address.
- * We initially create a flat uncached mapping on it.
- * Not yet exported, but may be later if someone finds use for it.
- */
-static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
-{
-	u32 *table;
-	int i;
-
-	virt = ALIGN_DOWN(virt, PGDIR_SIZE);
-
-	table = xmemalign(PTRS_PER_PTE * sizeof(u32),
-			  PTRS_PER_PTE * sizeof(u32));
-
-	if (!ttb)
-		arm_mmu_not_initialized_error();
-
-	ttb[pgd_index(virt)] = (unsigned long)table | PMD_TYPE_TABLE;
-
-	for (i = 0; i < PTRS_PER_PTE; i++) {
-		table[i] = virt | PTE_TYPE_SMALL | flags;
-		virt += PAGE_SIZE;
-	}
-
-	return table;
-}
-
 static bool pgd_type_table(u32 pgd)
 {
 	return (pgd & PMD_TYPE_MASK) == PMD_TYPE_TABLE;
@@ -152,6 +124,38 @@ static void dma_inv_range(unsigned long start, unsigned long end)
 	__dma_inv_range(start, end);
 }
 
+/*
+ * Create a second level translation table for the given virtual address.
+ * We initially create a flat uncached mapping on it.
+ * Not yet exported, but may be later if someone finds use for it.
+ */
+static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
+{
+	u32 *table;
+	int i, ttb_idx;
+
+	virt = ALIGN_DOWN(virt, PGDIR_SIZE);
+
+	table = xmemalign(PTRS_PER_PTE * sizeof(u32),
+			  PTRS_PER_PTE * sizeof(u32));
+
+	if (!ttb)
+		arm_mmu_not_initialized_error();
+
+	ttb_idx = pgd_index(virt);
+
+	for (i = 0; i < PTRS_PER_PTE; i++) {
+		table[i] = virt | PTE_TYPE_SMALL | flags;
+		virt += PAGE_SIZE;
+	}
+	dma_flush_range(table, PTRS_PER_PTE * sizeof(u32));
+
+	ttb[ttb_idx] = (unsigned long)table | PMD_TYPE_TABLE;
+	dma_flush_range(ttb, sizeof(u32));
+
+	return table;
+}
+
 int arch_remap_range(void *start, size_t size, unsigned flags)
 {
 	u32 addr = (u32)start;
@@ -227,12 +231,6 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
 				table = arm_create_pte(addr, pte_flags_cached);
 				pte = find_pte(addr);
 				BUG_ON(!pte);
-				/*
-				 * We just split this section and
-				 * modified it's Level 1 descriptor,
-				 * so it needs to be flushed.
-				 */
-				dma_flush_range(pgd, sizeof(*pgd));
 			}
 
 			for (i = 0; i < num_ptes; i++) {
@@ -240,17 +238,6 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
 				pte[i] |= pte_flags | PTE_TYPE_SMALL;
 			}
 
-			if (table) {
-				/*
-				 * If we just created a new page
-				 * table, the whole table would have
-				 * to be flushed, not just PTEs that
-				 * we touched when re-mapping.
-				 */
-				pte = table;
-				num_ptes = PTRS_PER_PTE;
-			}
-
 			dma_flush_range(pte, num_ptes * sizeof(u32));
 		}
 
-- 
2.18.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 1/3] PCI: link PCI devices with potentially existing OF nodes
  2018-08-01  8:38 [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE Lucas Stach
@ 2018-08-01  8:38 ` Lucas Stach
  2018-08-08  7:28   ` Sascha Hauer
  2018-08-01  8:38 ` [PATCH 2/3] pci: add quirk infrastructure Lucas Stach
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Lucas Stach @ 2018-08-01  8:38 UTC (permalink / raw)
  To: barebox

The document "PCI Bus Binding to: IEEE Std 1275-1994 Standard for Boot
(Initialization Configuration) Firmware" describes how the PCI topology
can be described in the DT, in order to augment the PCI devices with
additional information via DT properties.

This patch links OF nodes to the corresponding PCI devices if they
exist, allowing PCI device drivers to query DT information like any
platform device.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 drivers/pci/pci.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b2570eb15181..bd8b7278ef19 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -331,6 +331,31 @@ static void postscan_setup_bridge(struct pci_dev *dev)
 	}
 }
 
+static struct device_node *
+pci_of_match_device(struct device_d *parent, unsigned int devfn)
+{
+	struct device_node *np;
+	u32 reg;
+
+	if (!IS_ENABLED(CONFIG_OFTREE) || !parent->device_node)
+		return NULL;
+
+	for_each_child_of_node(parent->device_node, np) {
+		if (!of_property_read_u32_array(np, "reg", &reg, 1)) {
+			/*
+			 * Only match device/function pair of the device
+			 * address, other properties are defined by the
+			 * PCI/OF node topology.
+			 */
+			reg = (reg >> 8) & 0xffff;
+			if (reg == devfn)
+				return np;
+		}
+	}
+
+	return NULL;
+}
+
 unsigned int pci_scan_bus(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
@@ -368,6 +393,11 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
 		dev->vendor = l & 0xffff;
 		dev->device = (l >> 16) & 0xffff;
 		dev->dev.parent = bus->parent;
+		dev->dev.device_node = pci_of_match_device(bus->parent, devfn);
+		if (dev->dev.device_node)
+			pr_debug("found DT node %s for device %04x:%04x\n",
+				 dev->dev.device_node->full_name,
+				 dev->vendor, dev->device);
 
 		/* non-destructively determine if device can be a master: */
 		pci_read_config_byte(dev, PCI_COMMAND, &cmd);
-- 
2.18.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 2/3] pci: add quirk infrastructure
  2018-08-01  8:38 [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE Lucas Stach
  2018-08-01  8:38 ` [PATCH 1/3] PCI: link PCI devices with potentially existing OF nodes Lucas Stach
@ 2018-08-01  8:38 ` Lucas Stach
  2018-08-01  8:38 ` [PATCH 3/3] ARM: imx6: gw54xx: add fixup for PCIe switch Lucas Stach
  2018-08-01  9:01 ` [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE Lucas Stach
  3 siblings, 0 replies; 7+ messages in thread
From: Lucas Stach @ 2018-08-01  8:38 UTC (permalink / raw)
  To: barebox

This is a cut down version of the Linux kernel PCI quirk infrastructure,
which allows to register and execute some fixups before the driver is
loaded.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 arch/arm/lib32/barebox.lds.S | 12 +++++++
 drivers/pci/pci.c            | 63 +++++++++++++++++++++++++++++++++---
 include/linux/pci.h          | 54 +++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+), 4 deletions(-)

diff --git a/arch/arm/lib32/barebox.lds.S b/arch/arm/lib32/barebox.lds.S
index 594bf5683796..7230e5f31f80 100644
--- a/arch/arm/lib32/barebox.lds.S
+++ b/arch/arm/lib32/barebox.lds.S
@@ -106,6 +106,18 @@ SECTIONS
 	__usymtab : { BAREBOX_SYMS }
 	__usymtab_end = .;
 
+#ifdef CONFIG_PCI
+	__start_pci_fixups_early = .;
+	.pci_fixup_early : { KEEP(*(.pci_fixup_early)) }
+	__end_pci_fixups_early = .;
+	__start_pci_fixups_header = .;
+	.pci_fixup_header : { KEEP(*(.pci_fixup_header)) }
+	__end_pci_fixups_header = .;
+	__start_pci_fixups_enable = .;
+	.pci_fixup_enable : { KEEP(*(.pci_fixup_enable)) }
+	__end_pci_fixups_enable = .;
+#endif
+
 	.oftables : { BAREBOX_CLK_TABLE() }
 
 	.dtb : { BAREBOX_DTB() }
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index bd8b7278ef19..d206c538481c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -253,6 +253,8 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 		}
 	}
 
+	pci_fixup_device(pci_fixup_header, dev);
+
 	pci_write_config_byte(dev, PCI_COMMAND, cmd);
 	list_add_tail(&dev->bus_list, &dev->bus->devices);
 }
@@ -412,6 +414,10 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
 		class >>= 8;
 		dev->hdr_type = hdr_type;
 
+		pci_fixup_device(pci_fixup_early, dev);
+		/* the fixup may have changed the device class */
+		class = dev->class >> 8;
+
 		pr_debug("class = %08x, hdr_type = %08x\n", class, hdr_type);
 		pr_debug("%02x:%02x [%04x:%04x]\n", bus->number, dev->devfn,
 		    dev->vendor, dev->device);
@@ -519,12 +525,61 @@ EXPORT_SYMBOL(pci_clear_master);
  */
 int pci_enable_device(struct pci_dev *dev)
 {
+	int ret;
 	u32 t;
 
 	pci_read_config_dword(dev, PCI_COMMAND, &t);
-	return pci_write_config_dword(dev, PCI_COMMAND, t
-				| PCI_COMMAND_IO
-				| PCI_COMMAND_MEMORY
-				);
+	ret = pci_write_config_dword(dev, PCI_COMMAND,
+				     t | PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+	if (ret)
+		return ret;
+
+	pci_fixup_device(pci_fixup_enable, dev);
+
+	return 0;
 }
 EXPORT_SYMBOL(pci_enable_device);
+
+static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
+			  struct pci_fixup *end)
+{
+	for (; f < end; f++)
+		if ((f->class == (u32) (dev->class >> f->class_shift) ||
+		     f->class == (u32) PCI_ANY_ID) &&
+		    (f->vendor == dev->vendor ||
+		     f->vendor == (u16) PCI_ANY_ID) &&
+		    (f->device == dev->device ||
+		     f->device == (u16) PCI_ANY_ID)) {
+			f->hook(dev);
+		}
+}
+
+extern struct pci_fixup __start_pci_fixups_early[];
+extern struct pci_fixup __end_pci_fixups_early[];
+extern struct pci_fixup __start_pci_fixups_header[];
+extern struct pci_fixup __end_pci_fixups_header[];
+extern struct pci_fixup __start_pci_fixups_enable[];
+extern struct pci_fixup __end_pci_fixups_enable[];
+
+void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
+{
+	struct pci_fixup *start, *end;
+
+	switch (pass) {
+	case pci_fixup_early:
+		start = __start_pci_fixups_early;
+		end = __end_pci_fixups_early;
+		break;
+	case pci_fixup_header:
+		start = __start_pci_fixups_header;
+		end = __end_pci_fixups_header;
+		break;
+	case pci_fixup_enable:
+		start = __start_pci_fixups_enable;
+		end = __end_pci_fixups_enable;
+		break;
+	default:
+		unreachable();
+	}
+	pci_do_fixups(dev, start, end);
+}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 152ba10a04d9..82f27f21b247 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -29,6 +29,7 @@
 
 #include <linux/pci_ids.h>
 
+#define PCI_ANY_ID (~0)
 
 /*
  * The PCI interface treats multi-function devices as independent
@@ -299,4 +300,57 @@ int pci_enable_device(struct pci_dev *dev);
 
 extern void __iomem *pci_iomap(struct pci_dev *dev, int bar);
 
+/*
+ * The world is not perfect and supplies us with broken PCI devices.
+ * For at least a part of these bugs we need a work-around, so both
+ * generic (drivers/pci/quirks.c) and per-architecture code can define
+ * fixup hooks to be called for particular buggy devices.
+ */
+
+struct pci_fixup {
+	u16 vendor;			/* Or PCI_ANY_ID */
+	u16 device;			/* Or PCI_ANY_ID */
+	u32 class;			/* Or PCI_ANY_ID */
+	unsigned int class_shift;	/* should be 0, 8, 16 */
+	void (*hook)(struct pci_dev *dev);
+};
+
+enum pci_fixup_pass {
+	pci_fixup_early,	/* Before probing BARs */
+	pci_fixup_header,	/* After reading configuration header */
+	pci_fixup_enable,	/* pci_enable_device() time */
+};
+
+/* Anonymous variables would be nice... */
+#define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class,	\
+				  class_shift, hook)			\
+	static const struct pci_fixup __PASTE(__pci_fixup_##name,__LINE__) __used	\
+	__attribute__((__section__(#section), aligned((sizeof(void *)))))    \
+		= { vendor, device, class, class_shift, hook };
+
+#define DECLARE_PCI_FIXUP_CLASS_EARLY(vendor, device, class,		\
+					 class_shift, hook)		\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,			\
+		hook, vendor, device, class, class_shift, hook)
+#define DECLARE_PCI_FIXUP_CLASS_HEADER(vendor, device, class,		\
+					 class_shift, hook)		\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,			\
+		hook, vendor, device, class, class_shift, hook)
+#define DECLARE_PCI_FIXUP_CLASS_ENABLE(vendor, device, class,		\
+					 class_shift, hook)		\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,			\
+		hook, vendor, device, class, class_shift, hook)
+
+#define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,			\
+		hook, vendor, device, PCI_ANY_ID, 0, hook)
+#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,			\
+		hook, vendor, device, PCI_ANY_ID, 0, hook)
+#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,			\
+		hook, vendor, device, PCI_ANY_ID, 0, hook)
+
+void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
+
 #endif /* LINUX_PCI_H */
-- 
2.18.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 3/3] ARM: imx6: gw54xx: add fixup for PCIe switch
  2018-08-01  8:38 [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE Lucas Stach
  2018-08-01  8:38 ` [PATCH 1/3] PCI: link PCI devices with potentially existing OF nodes Lucas Stach
  2018-08-01  8:38 ` [PATCH 2/3] pci: add quirk infrastructure Lucas Stach
@ 2018-08-01  8:38 ` Lucas Stach
  2018-08-01  9:01 ` [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE Lucas Stach
  3 siblings, 0 replies; 7+ messages in thread
From: Lucas Stach @ 2018-08-01  8:38 UTC (permalink / raw)
  To: barebox

After the PCIe switch has been scanned its GPIOs need to be
configured as output-high to release the devices behind the
switch from their reset state and make them discoverable to
the bus scan.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 arch/arm/boards/gateworks-ventana/board.c | 29 +++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/arch/arm/boards/gateworks-ventana/board.c b/arch/arm/boards/gateworks-ventana/board.c
index 3ff142ee4298..6f9e0343bed5 100644
--- a/arch/arm/boards/gateworks-ventana/board.c
+++ b/arch/arm/boards/gateworks-ventana/board.c
@@ -17,6 +17,7 @@
 #include <i2c/i2c.h>
 #include <init.h>
 #include <linux/marvell_phy.h>
+#include <linux/pci.h>
 #include <linux/phy.h>
 #include <mach/bbu.h>
 #include <mach/imx6.h>
@@ -111,3 +112,31 @@ static int gw54xx_coredevices_init(void)
 	return 0;
 }
 coredevice_initcall(gw54xx_coredevices_init);
+
+/*
+ * fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High
+ * as they are used for slots1-7 PERST#
+ */
+static void ventana_pciesw_early_fixup(struct pci_dev *dev)
+{
+	u32 dw;
+
+	if (!of_machine_is_compatible("gw,ventana"))
+		return;
+
+	if (dev->devfn != 0)
+		return;
+
+	pci_read_config_dword(dev, 0x62c, &dw);
+	dw |= 0xaaa8; // GPIO1-7 outputs
+	pci_write_config_dword(dev, 0x62c, dw);
+
+	pci_read_config_dword(dev, 0x644, &dw);
+	dw |= 0xfe;   // GPIO1-7 output high
+	pci_write_config_dword(dev, 0x644, dw);
+
+	mdelay(100);
+}
+DECLARE_PCI_FIXUP_EARLY(0x10b5, 0x8609, ventana_pciesw_early_fixup);
+DECLARE_PCI_FIXUP_EARLY(0x10b5, 0x8606, ventana_pciesw_early_fixup);
+DECLARE_PCI_FIXUP_EARLY(0x10b5, 0x8604, ventana_pciesw_early_fixup);
-- 
2.18.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE
  2018-08-01  8:38 [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE Lucas Stach
                   ` (2 preceding siblings ...)
  2018-08-01  8:38 ` [PATCH 3/3] ARM: imx6: gw54xx: add fixup for PCIe switch Lucas Stach
@ 2018-08-01  9:01 ` Lucas Stach
  3 siblings, 0 replies; 7+ messages in thread
From: Lucas Stach @ 2018-08-01  9:01 UTC (permalink / raw)
  To: barebox

Please ignore this patch, it's already part of master and has been
resent due to PEBKAC.

Am Mittwoch, den 01.08.2018, 10:38 +0200 schrieb Lucas Stach:
> When replacing a section with a PTE, we must make sure that the newly
> initialized PTE entries are flushed from the cache before changing the
> entry in the TTB. Otherwise a L1 TLB miss causes the hardware pagetable
> walker to walk into a PTE with undefined content, causing exactly that
> behaviour.
> 
> Move all the necessary cache flushing to arm_create_pte(), to avoid any
> caller getting this wrong in the future.
> 
> Fixes: e3e54c644180 (ARM: mmu: Implement on-demand PTE allocation)
> > Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
> ---
>  arch/arm/cpu/mmu.c | 77 +++++++++++++++++++---------------------------
>  1 file changed, 32 insertions(+), 45 deletions(-)
> 
> diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
> index ae189ecdeb16..712c3930fb71 100644
> --- a/arch/arm/cpu/mmu.c
> +++ b/arch/arm/cpu/mmu.c
> @@ -85,34 +85,6 @@ static void arm_mmu_not_initialized_error(void)
> >  	panic("MMU not initialized\n");
>  }
>  
> -/*
> - * Create a second level translation table for the given virtual address.
> - * We initially create a flat uncached mapping on it.
> - * Not yet exported, but may be later if someone finds use for it.
> - */
> -static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
> -{
> > -	u32 *table;
> > -	int i;
> -
> > -	virt = ALIGN_DOWN(virt, PGDIR_SIZE);
> -
> > -	table = xmemalign(PTRS_PER_PTE * sizeof(u32),
> > -			  PTRS_PER_PTE * sizeof(u32));
> -
> > -	if (!ttb)
> > -		arm_mmu_not_initialized_error();
> -
> > -	ttb[pgd_index(virt)] = (unsigned long)table | PMD_TYPE_TABLE;
> -
> > -	for (i = 0; i < PTRS_PER_PTE; i++) {
> > -		table[i] = virt | PTE_TYPE_SMALL | flags;
> > -		virt += PAGE_SIZE;
> > -	}
> -
> > -	return table;
> -}
> -
>  static bool pgd_type_table(u32 pgd)
>  {
> >  	return (pgd & PMD_TYPE_MASK) == PMD_TYPE_TABLE;
> @@ -152,6 +124,38 @@ static void dma_inv_range(unsigned long start, unsigned long end)
> >  	__dma_inv_range(start, end);
>  }
>  
> +/*
> + * Create a second level translation table for the given virtual address.
> + * We initially create a flat uncached mapping on it.
> + * Not yet exported, but may be later if someone finds use for it.
> + */
> +static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
> +{
> > +	u32 *table;
> > +	int i, ttb_idx;
> +
> > +	virt = ALIGN_DOWN(virt, PGDIR_SIZE);
> +
> > +	table = xmemalign(PTRS_PER_PTE * sizeof(u32),
> > +			  PTRS_PER_PTE * sizeof(u32));
> +
> > +	if (!ttb)
> > +		arm_mmu_not_initialized_error();
> +
> > +	ttb_idx = pgd_index(virt);
> +
> > +	for (i = 0; i < PTRS_PER_PTE; i++) {
> > +		table[i] = virt | PTE_TYPE_SMALL | flags;
> > +		virt += PAGE_SIZE;
> > +	}
> > +	dma_flush_range(table, PTRS_PER_PTE * sizeof(u32));
> +
> > +	ttb[ttb_idx] = (unsigned long)table | PMD_TYPE_TABLE;
> > +	dma_flush_range(ttb, sizeof(u32));
> +
> > +	return table;
> +}
> +
>  int arch_remap_range(void *start, size_t size, unsigned flags)
>  {
> >  	u32 addr = (u32)start;
> @@ -227,12 +231,6 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
> >  				table = arm_create_pte(addr, pte_flags_cached);
> >  				pte = find_pte(addr);
> >  				BUG_ON(!pte);
> > -				/*
> > -				 * We just split this section and
> > -				 * modified it's Level 1 descriptor,
> > -				 * so it needs to be flushed.
> > -				 */
> > -				dma_flush_range(pgd, sizeof(*pgd));
> >  			}
>  
> >  			for (i = 0; i < num_ptes; i++) {
> @@ -240,17 +238,6 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
> >  				pte[i] |= pte_flags | PTE_TYPE_SMALL;
> >  			}
>  
> > -			if (table) {
> > -				/*
> > -				 * If we just created a new page
> > -				 * table, the whole table would have
> > -				 * to be flushed, not just PTEs that
> > -				 * we touched when re-mapping.
> > -				 */
> > -				pte = table;
> > -				num_ptes = PTRS_PER_PTE;
> > -			}
> -
> >  			dma_flush_range(pte, num_ptes * sizeof(u32));
> >  		}
>  

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 1/3] PCI: link PCI devices with potentially existing OF nodes
  2018-08-01  8:38 ` [PATCH 1/3] PCI: link PCI devices with potentially existing OF nodes Lucas Stach
@ 2018-08-08  7:28   ` Sascha Hauer
  0 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2018-08-08  7:28 UTC (permalink / raw)
  To: Lucas Stach; +Cc: barebox

On Wed, Aug 01, 2018 at 10:38:29AM +0200, Lucas Stach wrote:
> The document "PCI Bus Binding to: IEEE Std 1275-1994 Standard for Boot
> (Initialization Configuration) Firmware" describes how the PCI topology
> can be described in the DT, in order to augment the PCI devices with
> additional information via DT properties.
> 
> This patch links OF nodes to the corresponding PCI devices if they
> exist, allowing PCI device drivers to query DT information like any
> platform device.
> 
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
> ---
>  drivers/pci/pci.c | 30 ++++++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index b2570eb15181..bd8b7278ef19 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -331,6 +331,31 @@ static void postscan_setup_bridge(struct pci_dev *dev)
>  	}
>  }
>  
> +static struct device_node *
> +pci_of_match_device(struct device_d *parent, unsigned int devfn)
> +{
> +	struct device_node *np;
> +	u32 reg;
> +
> +	if (!IS_ENABLED(CONFIG_OFTREE) || !parent->device_node)
> +		return NULL;
> +
> +	for_each_child_of_node(parent->device_node, np) {
> +		if (!of_property_read_u32_array(np, "reg", &reg, 1)) {
> +			/*
> +			 * Only match device/function pair of the device
> +			 * address, other properties are defined by the
> +			 * PCI/OF node topology.
> +			 */
> +			reg = (reg >> 8) & 0xffff;
> +			if (reg == devfn)
> +				return np;
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
>  unsigned int pci_scan_bus(struct pci_bus *bus)
>  {
>  	struct pci_dev *dev;
> @@ -368,6 +393,11 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
>  		dev->vendor = l & 0xffff;
>  		dev->device = (l >> 16) & 0xffff;
>  		dev->dev.parent = bus->parent;
> +		dev->dev.device_node = pci_of_match_device(bus->parent, devfn);
> +		if (dev->dev.device_node)
> +			pr_debug("found DT node %s for device %04x:%04x\n",
> +				 dev->dev.device_node->full_name,
> +				 dev->vendor, dev->device);
>  
>  		/* non-destructively determine if device can be a master: */
>  		pci_read_config_byte(dev, PCI_COMMAND, &cmd);
> -- 
> 2.18.0
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE
@ 2018-07-25 15:01 Lucas Stach
  0 siblings, 0 replies; 7+ messages in thread
From: Lucas Stach @ 2018-07-25 15:01 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

When replacing a section with a PTE, we must make sure that the newly
initialized PTE entries are flushed from the cache before changing the
entry in the TTB. Otherwise a L1 TLB miss causes the hardware pagetable
walker to walk into a PTE with undefined content, causing exactly that
behaviour.

Move all the necessary cache flushing to arm_create_pte(), to avoid any
caller getting this wrong in the future.

Fixes: e3e54c644180 (ARM: mmu: Implement on-demand PTE allocation)
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 arch/arm/cpu/mmu.c | 77 +++++++++++++++++++---------------------------
 1 file changed, 32 insertions(+), 45 deletions(-)

diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index ae189ecdeb16..712c3930fb71 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -85,34 +85,6 @@ static void arm_mmu_not_initialized_error(void)
 	panic("MMU not initialized\n");
 }
 
-/*
- * Create a second level translation table for the given virtual address.
- * We initially create a flat uncached mapping on it.
- * Not yet exported, but may be later if someone finds use for it.
- */
-static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
-{
-	u32 *table;
-	int i;
-
-	virt = ALIGN_DOWN(virt, PGDIR_SIZE);
-
-	table = xmemalign(PTRS_PER_PTE * sizeof(u32),
-			  PTRS_PER_PTE * sizeof(u32));
-
-	if (!ttb)
-		arm_mmu_not_initialized_error();
-
-	ttb[pgd_index(virt)] = (unsigned long)table | PMD_TYPE_TABLE;
-
-	for (i = 0; i < PTRS_PER_PTE; i++) {
-		table[i] = virt | PTE_TYPE_SMALL | flags;
-		virt += PAGE_SIZE;
-	}
-
-	return table;
-}
-
 static bool pgd_type_table(u32 pgd)
 {
 	return (pgd & PMD_TYPE_MASK) == PMD_TYPE_TABLE;
@@ -152,6 +124,38 @@ static void dma_inv_range(unsigned long start, unsigned long end)
 	__dma_inv_range(start, end);
 }
 
+/*
+ * Create a second level translation table for the given virtual address.
+ * We initially create a flat uncached mapping on it.
+ * Not yet exported, but may be later if someone finds use for it.
+ */
+static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
+{
+	u32 *table;
+	int i, ttb_idx;
+
+	virt = ALIGN_DOWN(virt, PGDIR_SIZE);
+
+	table = xmemalign(PTRS_PER_PTE * sizeof(u32),
+			  PTRS_PER_PTE * sizeof(u32));
+
+	if (!ttb)
+		arm_mmu_not_initialized_error();
+
+	ttb_idx = pgd_index(virt);
+
+	for (i = 0; i < PTRS_PER_PTE; i++) {
+		table[i] = virt | PTE_TYPE_SMALL | flags;
+		virt += PAGE_SIZE;
+	}
+	dma_flush_range(table, PTRS_PER_PTE * sizeof(u32));
+
+	ttb[ttb_idx] = (unsigned long)table | PMD_TYPE_TABLE;
+	dma_flush_range(ttb, sizeof(u32));
+
+	return table;
+}
+
 int arch_remap_range(void *start, size_t size, unsigned flags)
 {
 	u32 addr = (u32)start;
@@ -227,12 +231,6 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
 				table = arm_create_pte(addr, pte_flags_cached);
 				pte = find_pte(addr);
 				BUG_ON(!pte);
-				/*
-				 * We just split this section and
-				 * modified it's Level 1 descriptor,
-				 * so it needs to be flushed.
-				 */
-				dma_flush_range(pgd, sizeof(*pgd));
 			}
 
 			for (i = 0; i < num_ptes; i++) {
@@ -240,17 +238,6 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
 				pte[i] |= pte_flags | PTE_TYPE_SMALL;
 			}
 
-			if (table) {
-				/*
-				 * If we just created a new page
-				 * table, the whole table would have
-				 * to be flushed, not just PTEs that
-				 * we touched when re-mapping.
-				 */
-				pte = table;
-				num_ptes = PTRS_PER_PTE;
-			}
-
 			dma_flush_range(pte, num_ptes * sizeof(u32));
 		}
 
-- 
2.18.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

end of thread, other threads:[~2018-08-08  7:28 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-01  8:38 [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE Lucas Stach
2018-08-01  8:38 ` [PATCH 1/3] PCI: link PCI devices with potentially existing OF nodes Lucas Stach
2018-08-08  7:28   ` Sascha Hauer
2018-08-01  8:38 ` [PATCH 2/3] pci: add quirk infrastructure Lucas Stach
2018-08-01  8:38 ` [PATCH 3/3] ARM: imx6: gw54xx: add fixup for PCIe switch Lucas Stach
2018-08-01  9:01 ` [PATCH] ARM: mmu: fix cache flushing when replacing a section with a PTE Lucas Stach
  -- strict thread matches above, loose matches on Subject: below --
2018-07-25 15:01 Lucas Stach

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox