All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-25 17:46 ` Leif Lindholm
  0 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-25 17:46 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-doc, linux-kernel, patches, nico, Leif Lindholm

x86 and ia64 have the early_ioremap()/early_iounmap() functions, which are
useful for supporting things like UEFI, ACPI and SMBIOS, where configuration
tables need to be parsed before proper memory management is available,
regardless of highmem status.

This patchset implements a restricted form of early_ioremap(), available
before paging_init() only. Like the x86 code on which it is based, it
(p)re-uses the fixmap regions for its virtual mapping range. Up to 7
simultaneous mappings of up to 128KB can be accommodated in the available
fixmap space.

Leif Lindholm (2):
  Documentation: arm: early_ioremap
  arm: add early_ioremap support

 Documentation/arm/00-INDEX          |    2 +
 Documentation/arm/early_ioremap.txt |   12 ++
 arch/arm/Kconfig                    |    7 +
 arch/arm/include/asm/fixmap.h       |   31 +++-
 arch/arm/include/asm/io.h           |   13 ++
 arch/arm/kernel/setup.c             |    3 +
 arch/arm/mm/Makefile                |    1 +
 arch/arm/mm/early_ioremap.c         |  273 +++++++++++++++++++++++++++++++++++
 arch/arm/mm/mmu.c                   |    2 +
 9 files changed, 342 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/arm/early_ioremap.txt
 create mode 100644 arch/arm/mm/early_ioremap.c

-- 
1.7.10.4


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

* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-25 17:46 ` Leif Lindholm
  0 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-25 17:46 UTC (permalink / raw)
  To: linux-arm-kernel

x86 and ia64 have the early_ioremap()/early_iounmap() functions, which are
useful for supporting things like UEFI, ACPI and SMBIOS, where configuration
tables need to be parsed before proper memory management is available,
regardless of highmem status.

This patchset implements a restricted form of early_ioremap(), available
before paging_init() only. Like the x86 code on which it is based, it
(p)re-uses the fixmap regions for its virtual mapping range. Up to 7
simultaneous mappings of up to 128KB can be accommodated in the available
fixmap space.

Leif Lindholm (2):
  Documentation: arm: early_ioremap
  arm: add early_ioremap support

 Documentation/arm/00-INDEX          |    2 +
 Documentation/arm/early_ioremap.txt |   12 ++
 arch/arm/Kconfig                    |    7 +
 arch/arm/include/asm/fixmap.h       |   31 +++-
 arch/arm/include/asm/io.h           |   13 ++
 arch/arm/kernel/setup.c             |    3 +
 arch/arm/mm/Makefile                |    1 +
 arch/arm/mm/early_ioremap.c         |  273 +++++++++++++++++++++++++++++++++++
 arch/arm/mm/mmu.c                   |    2 +
 9 files changed, 342 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/arm/early_ioremap.txt
 create mode 100644 arch/arm/mm/early_ioremap.c

-- 
1.7.10.4

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

* [PATCH 1/2] Documentation: arm: early_ioremap
  2013-06-25 17:46 ` Leif Lindholm
@ 2013-06-25 17:46   ` Leif Lindholm
  -1 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-25 17:46 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-doc, linux-kernel, patches, nico, Leif Lindholm

This patch provides documentation of the early_ioremap() functionality,
including its implementation and usage instructions.

Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
---
 Documentation/arm/00-INDEX          |    2 ++
 Documentation/arm/early_ioremap.txt |   12 ++++++++++++
 2 files changed, 14 insertions(+)
 create mode 100644 Documentation/arm/early_ioremap.txt

diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
index 36420e1..4978456 100644
--- a/Documentation/arm/00-INDEX
+++ b/Documentation/arm/00-INDEX
@@ -24,6 +24,8 @@ SPEAr
 	- ST SPEAr platform Linux Overview
 VFP/
 	- Release notes for Linux Kernel Vector Floating Point support code
+early_ioremap.txt
+	- documentation of the early_ioremap() functionality
 empeg/
 	- Ltd's Empeg MP3 Car Audio Player
 mem_alignment
diff --git a/Documentation/arm/early_ioremap.txt b/Documentation/arm/early_ioremap.txt
new file mode 100644
index 0000000..178f791
--- /dev/null
+++ b/Documentation/arm/early_ioremap.txt
@@ -0,0 +1,12 @@
+early_ioremap() and early_iounmap() rovide a mechanism for temporarily mapping
+in small blocks of memory, identified by their physical address, into the
+fixmap virtual address block before paging_init() has been called and more
+flexible mapping functions are available.
+
+Due to its direct method, it also gets around potential need for special
+handling of regions that end up in highmem.
+
+It supports up to 7 simultaneously mapped regions of up to 128KB each.
+All regions are mapped as non-shareable device memory.
+
+Specify 'early_ioremap_debug' on the kernel commandline for verbose output.
-- 
1.7.10.4


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

* [PATCH 1/2] Documentation: arm: early_ioremap
@ 2013-06-25 17:46   ` Leif Lindholm
  0 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-25 17:46 UTC (permalink / raw)
  To: linux-arm-kernel

This patch provides documentation of the early_ioremap() functionality,
including its implementation and usage instructions.

Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
---
 Documentation/arm/00-INDEX          |    2 ++
 Documentation/arm/early_ioremap.txt |   12 ++++++++++++
 2 files changed, 14 insertions(+)
 create mode 100644 Documentation/arm/early_ioremap.txt

diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
index 36420e1..4978456 100644
--- a/Documentation/arm/00-INDEX
+++ b/Documentation/arm/00-INDEX
@@ -24,6 +24,8 @@ SPEAr
 	- ST SPEAr platform Linux Overview
 VFP/
 	- Release notes for Linux Kernel Vector Floating Point support code
+early_ioremap.txt
+	- documentation of the early_ioremap() functionality
 empeg/
 	- Ltd's Empeg MP3 Car Audio Player
 mem_alignment
diff --git a/Documentation/arm/early_ioremap.txt b/Documentation/arm/early_ioremap.txt
new file mode 100644
index 0000000..178f791
--- /dev/null
+++ b/Documentation/arm/early_ioremap.txt
@@ -0,0 +1,12 @@
+early_ioremap() and early_iounmap() rovide a mechanism for temporarily mapping
+in small blocks of memory, identified by their physical address, into the
+fixmap virtual address block before paging_init() has been called and more
+flexible mapping functions are available.
+
+Due to its direct method, it also gets around potential need for special
+handling of regions that end up in highmem.
+
+It supports up to 7 simultaneously mapped regions of up to 128KB each.
+All regions are mapped as non-shareable device memory.
+
+Specify 'early_ioremap_debug' on the kernel commandline for verbose output.
-- 
1.7.10.4

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

* [PATCH 2/2] arm: add early_ioremap support
  2013-06-25 17:46 ` Leif Lindholm
@ 2013-06-25 17:46   ` Leif Lindholm
  -1 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-25 17:46 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: linux-doc, linux-kernel, patches, nico, Leif Lindholm

This patch adds support for early_ioremap, based on the existing
mechanism in x86. Up to 7 regions of up to 128KB each can be
temporarily mapped in before paging_init, regardless of later highmem
status.

Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
---
 arch/arm/Kconfig              |    7 ++
 arch/arm/include/asm/fixmap.h |   31 ++++-
 arch/arm/include/asm/io.h     |   13 ++
 arch/arm/kernel/setup.c       |    3 +
 arch/arm/mm/Makefile          |    1 +
 arch/arm/mm/early_ioremap.c   |  273 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mm/mmu.c             |    2 +
 7 files changed, 328 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mm/early_ioremap.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 49d993c..bf8e55d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1756,6 +1756,13 @@ config UACCESS_WITH_MEMCPY
 	  However, if the CPU data cache is using a write-allocate mode,
 	  this option is unlikely to provide any performance gain.
 
+config EARLY_IOREMAP
+	depends on MMU
+	bool "Provide early_ioremap() support for kernel initialization."
+	help
+	  Provides a mechanism for kernel initialisation code to temporarily
+	  map, in a highmem-agnostic way, memory pages in before paging_init().
+
 config SECCOMP
 	bool
 	prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
index bbae919..a2a5f50 100644
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
+#include <linux/bug.h>
+
 /*
  * Nothing too fancy for now.
  *
@@ -20,13 +22,38 @@
 #define FIX_KMAP_BEGIN		0
 #define FIX_KMAP_END		(FIXADDR_SIZE >> PAGE_SHIFT)
 
+/*
+ * 224 temporary boot-time mappings, used by early_ioremap(),
+ * before ioremap() is functional.
+ *
+ * (P)re-using the FIXADDR region, which is used for highmem
+ * later on, and statically aligned to 1MB.
+ */
+#define NR_FIX_BTMAPS		32
+#define FIX_BTMAPS_SLOTS	7
+#define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
+#define FIX_BTMAP_BEGIN		FIX_KMAP_BEGIN
+#define FIX_BTMAP_END		(FIX_KMAP_END - 1)
+
+#define clear_fixmap(idx)			\
+	__set_fixmap(idx, 0, __pgprot(0))
+
 #define __fix_to_virt(x)	(FIXADDR_START + ((x) << PAGE_SHIFT))
 #define __virt_to_fix(x)	(((x) - FIXADDR_START) >> PAGE_SHIFT)
 
 extern void __this_fixmap_does_not_exist(void);
 
-static inline unsigned long fix_to_virt(const unsigned int idx)
+static __always_inline unsigned long fix_to_virt(const unsigned int idx)
 {
+	/*
+	 * this branch gets completely eliminated after inlining,
+	 * except when someone tries to use fixaddr indices in an
+	 * illegal way. (such as mixing up address types or using
+	 * out-of-range indices).
+	 *
+	 * If it doesn't get removed, the linker will complain
+	 * loudly with a reasonably clear error message..
+	 */
 	if (idx >= FIX_KMAP_END)
 		__this_fixmap_does_not_exist();
 	return __fix_to_virt(idx);
@@ -38,4 +65,4 @@ static inline unsigned int virt_to_fix(const unsigned long vaddr)
 	return __virt_to_fix(vaddr);
 }
 
-#endif
+#endif /* _ASM_FIXMAP_H */
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 652b560..c8866e3 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -397,5 +397,18 @@ extern int devmem_is_allowed(unsigned long pfn);
 extern void register_isa_ports(unsigned int mmio, unsigned int io,
 			       unsigned int io_shift);
 
+/*
+ * early_ioremap() and early_iounmap() are for temporary early boot-time
+ * mappings, before the real ioremap() is functional.
+ * A boot-time mapping is currently limited to at most 16 pages.
+ *
+ * This is all squashed by paging_init().
+ */
+extern void early_ioremap_init(void);
+extern void early_ioremap_reset(void);
+extern void __iomem *early_ioremap(resource_size_t phys_addr,
+				   unsigned long size);
+extern void early_iounmap(void __iomem *addr, unsigned long size);
+
 #endif	/* __KERNEL__ */
 #endif	/* __ASM_ARM_IO_H */
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 1522c7a..290c561 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -36,6 +36,7 @@
 #include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
+#include <asm/io.h>
 #include <asm/procinfo.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
@@ -783,6 +784,8 @@ void __init setup_arch(char **cmdline_p)
 
 	parse_early_param();
 
+	early_ioremap_init();
+
 	sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
 	sanity_check_meminfo();
 	arm_memblock_init(&meminfo, mdesc);
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 9e51be9..ae2c477 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -15,6 +15,7 @@ endif
 obj-$(CONFIG_MODULES)		+= proc-syms.o
 
 obj-$(CONFIG_ALIGNMENT_TRAP)	+= alignment.o
+obj-$(CONFIG_EARLY_IOREMAP)	+= early_ioremap.o
 obj-$(CONFIG_HIGHMEM)		+= highmem.o
 
 obj-$(CONFIG_CPU_ABRT_NOMMU)	+= abort-nommu.o
diff --git a/arch/arm/mm/early_ioremap.c b/arch/arm/mm/early_ioremap.c
new file mode 100644
index 0000000..b14f58b
--- /dev/null
+++ b/arch/arm/mm/early_ioremap.c
@@ -0,0 +1,273 @@
+/*
+ * early_ioremap() support for ARM
+ *
+ * Based on existing support in arch/x86/mm/ioremap.c
+ *
+ * Restrictions: currently only functional before paging_init()
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/fixmap.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+#include <asm/mach/map.h>
+
+static int __initdata early_ioremap_debug;
+
+static int __init early_ioremap_debug_setup(char *str)
+{
+	early_ioremap_debug = 1;
+
+	return 0;
+}
+early_param("early_ioremap_debug", early_ioremap_debug_setup);
+
+static pte_t __initdata bm_pte[PTRS_PER_PTE] __aligned(PTRS_PER_PTE * sizeof(pte_t));
+static __initdata int after_paging_init;
+
+static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+{
+	unsigned int index = pgd_index(addr);
+	pgd_t *pgd = cpu_get_pgd() + index;
+	pud_t *pud = pud_offset(pgd, addr);
+	pmd_t *pmd = pmd_offset(pud, addr);
+
+	return pmd;
+}
+
+static inline pte_t * __init early_ioremap_pte(unsigned long addr)
+{
+	return &bm_pte[pte_index(addr)];
+}
+
+static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
+
+void __init early_ioremap_init(void)
+{
+	pmd_t *pmd;
+	int i;
+	u64 desc;
+
+	if (early_ioremap_debug)
+		pr_info("early_ioremap_init()\n");
+
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN + NR_FIX_BTMAPS*i);
+		if (early_ioremap_debug)
+			pr_info("  %lu byte slot @ 0x%08x\n",
+				NR_FIX_BTMAPS * PAGE_SIZE, (u32)slot_virt[i]);
+	}
+
+	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+	desc = *pmd;
+	memset(bm_pte, 0, sizeof(bm_pte));
+
+	pmd_populate_kernel(NULL, pmd, bm_pte);
+	desc = *pmd;
+
+	BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
+		     != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
+
+	if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
+		WARN_ON(1);
+		pr_warn("pmd %p != %p\n",
+			pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
+		pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
+			fix_to_virt(FIX_BTMAP_BEGIN));
+		pr_warn("fix_to_virt(FIX_BTMAP_END):   %08lx\n",
+			fix_to_virt(FIX_BTMAP_END));
+		pr_warn("FIX_BTMAP_END:       %lu\n", FIX_BTMAP_END);
+		pr_warn("FIX_BTMAP_BEGIN:     %d\n",  FIX_BTMAP_BEGIN);
+	}
+}
+
+void __init early_ioremap_reset(void)
+{
+	after_paging_init = 1;
+}
+
+static void __init __early_set_fixmap(unsigned long idx,
+				      phys_addr_t phys, pgprot_t flags)
+{
+	unsigned long addr = __fix_to_virt(idx);
+	pte_t *pte;
+	u64 desc;
+
+	if (idx >= FIX_KMAP_END) {
+		BUG();
+		return;
+	}
+	pte = early_ioremap_pte(addr);
+
+	if (pgprot_val(flags))
+		set_pte_at(NULL, 0xfff00000, pte,
+			   pfn_pte(phys >> PAGE_SHIFT, flags));
+	else
+		pte_clear(NULL, addr, pte);
+	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+	desc = *pte;
+}
+
+static inline void __init early_set_fixmap(unsigned long idx,
+					   phys_addr_t phys, pgprot_t prot)
+{
+	__early_set_fixmap(idx, phys, prot);
+}
+
+static inline void __init early_clear_fixmap(unsigned long idx)
+{
+	__early_set_fixmap(idx, 0, __pgprot(0));
+}
+
+static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
+static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
+
+static void __init __iomem *
+__early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot)
+{
+	unsigned long offset;
+	resource_size_t last_addr;
+	unsigned int nrpages;
+	unsigned long idx;
+	int i, slot;
+
+	slot = -1;
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		if (!prev_map[i]) {
+			slot = i;
+			break;
+		}
+	}
+
+	if (slot < 0) {
+		pr_info("early_iomap(%08llx, %08lx) not found slot\n",
+			(u64)phys_addr, size);
+		WARN_ON(1);
+		return NULL;
+	}
+
+	if (early_ioremap_debug) {
+		pr_info("early_ioremap(%08llx, %08lx) [%d] => ",
+			(u64)phys_addr, size, slot);
+	}
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	prev_size[slot] = size;
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+	/*
+	 * Mappings have to fit in the FIX_BTMAP area.
+	 */
+	nrpages = size >> PAGE_SHIFT;
+	if (nrpages > NR_FIX_BTMAPS) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	/*
+	 * Ok, go for it..
+	 */
+	idx = FIX_BTMAP_BEGIN + slot * NR_FIX_BTMAPS;
+	while (nrpages > 0) {
+		early_set_fixmap(idx, phys_addr, prot);
+		phys_addr += PAGE_SIZE;
+		idx++;
+		--nrpages;
+	}
+	if (early_ioremap_debug)
+		pr_cont("%08lx + %08lx\n", offset, slot_virt[slot]);
+
+	prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]);
+	return prev_map[slot];
+}
+
+/* Remap an IO device */
+void __init __iomem *
+early_ioremap(resource_size_t phys_addr, unsigned long size)
+{
+	unsigned long prot;
+
+	if (after_paging_init) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	/*
+	 * PAGE_KERNEL depends on not-yet-initialised variables.
+	 * We don't care about coherency or executability of early_ioremap
+	 * pages anyway.
+	 */
+	prot = L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_MT_DEV_NONSHARED;
+	return __early_ioremap(phys_addr, size, prot);
+}
+
+
+void __init early_iounmap(void __iomem *addr, unsigned long size)
+{
+	unsigned long virt_addr;
+	unsigned long offset;
+	unsigned int nrpages;
+	unsigned long idx;
+	int i, slot;
+
+	if (after_paging_init) {
+		WARN_ON(1);
+		return;
+	}
+
+	slot = -1;
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		if (prev_map[i] == addr) {
+			slot = i;
+			break;
+		}
+	}
+
+	if (slot < 0) {
+		pr_info("early_iounmap(%p, %08lx) not found slot\n",
+			addr, size);
+		WARN_ON(1);
+		return;
+	}
+
+	if (prev_size[slot] != size) {
+		pr_info("early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n",
+			addr, size, slot, prev_size[slot]);
+		WARN_ON(1);
+		return;
+	}
+
+	if (early_ioremap_debug)
+		pr_info("early_iounmap(%p, %08lx) [%d]\n", addr, size, slot);
+
+	virt_addr = (unsigned long)addr;
+	if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)) {
+		WARN_ON(1);
+		return;
+	}
+	offset = virt_addr & ~PAGE_MASK;
+	nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT;
+
+	idx = FIX_BTMAP_BEGIN + slot * NR_FIX_BTMAPS;
+	while (nrpages > 0) {
+		early_clear_fixmap(idx);
+		idx++;
+		--nrpages;
+	}
+	prev_map[slot] = NULL;
+}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e0d8565..c953b20 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -28,6 +28,7 @@
 #include <asm/highmem.h>
 #include <asm/system_info.h>
 #include <asm/traps.h>
+#include <asm/io.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -1306,4 +1307,5 @@ void __init paging_init(struct machine_desc *mdesc)
 
 	empty_zero_page = virt_to_page(zero_page);
 	__flush_dcache_page(NULL, empty_zero_page);
+	early_ioremap_reset();
 }
-- 
1.7.10.4


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

* [PATCH 2/2] arm: add early_ioremap support
@ 2013-06-25 17:46   ` Leif Lindholm
  0 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-25 17:46 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds support for early_ioremap, based on the existing
mechanism in x86. Up to 7 regions of up to 128KB each can be
temporarily mapped in before paging_init, regardless of later highmem
status.

Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
---
 arch/arm/Kconfig              |    7 ++
 arch/arm/include/asm/fixmap.h |   31 ++++-
 arch/arm/include/asm/io.h     |   13 ++
 arch/arm/kernel/setup.c       |    3 +
 arch/arm/mm/Makefile          |    1 +
 arch/arm/mm/early_ioremap.c   |  273 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mm/mmu.c             |    2 +
 7 files changed, 328 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mm/early_ioremap.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 49d993c..bf8e55d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1756,6 +1756,13 @@ config UACCESS_WITH_MEMCPY
 	  However, if the CPU data cache is using a write-allocate mode,
 	  this option is unlikely to provide any performance gain.
 
+config EARLY_IOREMAP
+	depends on MMU
+	bool "Provide early_ioremap() support for kernel initialization."
+	help
+	  Provides a mechanism for kernel initialisation code to temporarily
+	  map, in a highmem-agnostic way, memory pages in before paging_init().
+
 config SECCOMP
 	bool
 	prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
index bbae919..a2a5f50 100644
--- a/arch/arm/include/asm/fixmap.h
+++ b/arch/arm/include/asm/fixmap.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
+#include <linux/bug.h>
+
 /*
  * Nothing too fancy for now.
  *
@@ -20,13 +22,38 @@
 #define FIX_KMAP_BEGIN		0
 #define FIX_KMAP_END		(FIXADDR_SIZE >> PAGE_SHIFT)
 
+/*
+ * 224 temporary boot-time mappings, used by early_ioremap(),
+ * before ioremap() is functional.
+ *
+ * (P)re-using the FIXADDR region, which is used for highmem
+ * later on, and statically aligned to 1MB.
+ */
+#define NR_FIX_BTMAPS		32
+#define FIX_BTMAPS_SLOTS	7
+#define TOTAL_FIX_BTMAPS	(NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
+#define FIX_BTMAP_BEGIN		FIX_KMAP_BEGIN
+#define FIX_BTMAP_END		(FIX_KMAP_END - 1)
+
+#define clear_fixmap(idx)			\
+	__set_fixmap(idx, 0, __pgprot(0))
+
 #define __fix_to_virt(x)	(FIXADDR_START + ((x) << PAGE_SHIFT))
 #define __virt_to_fix(x)	(((x) - FIXADDR_START) >> PAGE_SHIFT)
 
 extern void __this_fixmap_does_not_exist(void);
 
-static inline unsigned long fix_to_virt(const unsigned int idx)
+static __always_inline unsigned long fix_to_virt(const unsigned int idx)
 {
+	/*
+	 * this branch gets completely eliminated after inlining,
+	 * except when someone tries to use fixaddr indices in an
+	 * illegal way. (such as mixing up address types or using
+	 * out-of-range indices).
+	 *
+	 * If it doesn't get removed, the linker will complain
+	 * loudly with a reasonably clear error message..
+	 */
 	if (idx >= FIX_KMAP_END)
 		__this_fixmap_does_not_exist();
 	return __fix_to_virt(idx);
@@ -38,4 +65,4 @@ static inline unsigned int virt_to_fix(const unsigned long vaddr)
 	return __virt_to_fix(vaddr);
 }
 
-#endif
+#endif /* _ASM_FIXMAP_H */
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 652b560..c8866e3 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -397,5 +397,18 @@ extern int devmem_is_allowed(unsigned long pfn);
 extern void register_isa_ports(unsigned int mmio, unsigned int io,
 			       unsigned int io_shift);
 
+/*
+ * early_ioremap() and early_iounmap() are for temporary early boot-time
+ * mappings, before the real ioremap() is functional.
+ * A boot-time mapping is currently limited to at most 16 pages.
+ *
+ * This is all squashed by paging_init().
+ */
+extern void early_ioremap_init(void);
+extern void early_ioremap_reset(void);
+extern void __iomem *early_ioremap(resource_size_t phys_addr,
+				   unsigned long size);
+extern void early_iounmap(void __iomem *addr, unsigned long size);
+
 #endif	/* __KERNEL__ */
 #endif	/* __ASM_ARM_IO_H */
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 1522c7a..290c561 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -36,6 +36,7 @@
 #include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
+#include <asm/io.h>
 #include <asm/procinfo.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
@@ -783,6 +784,8 @@ void __init setup_arch(char **cmdline_p)
 
 	parse_early_param();
 
+	early_ioremap_init();
+
 	sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
 	sanity_check_meminfo();
 	arm_memblock_init(&meminfo, mdesc);
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 9e51be9..ae2c477 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -15,6 +15,7 @@ endif
 obj-$(CONFIG_MODULES)		+= proc-syms.o
 
 obj-$(CONFIG_ALIGNMENT_TRAP)	+= alignment.o
+obj-$(CONFIG_EARLY_IOREMAP)	+= early_ioremap.o
 obj-$(CONFIG_HIGHMEM)		+= highmem.o
 
 obj-$(CONFIG_CPU_ABRT_NOMMU)	+= abort-nommu.o
diff --git a/arch/arm/mm/early_ioremap.c b/arch/arm/mm/early_ioremap.c
new file mode 100644
index 0000000..b14f58b
--- /dev/null
+++ b/arch/arm/mm/early_ioremap.c
@@ -0,0 +1,273 @@
+/*
+ * early_ioremap() support for ARM
+ *
+ * Based on existing support in arch/x86/mm/ioremap.c
+ *
+ * Restrictions: currently only functional before paging_init()
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/fixmap.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+#include <asm/mach/map.h>
+
+static int __initdata early_ioremap_debug;
+
+static int __init early_ioremap_debug_setup(char *str)
+{
+	early_ioremap_debug = 1;
+
+	return 0;
+}
+early_param("early_ioremap_debug", early_ioremap_debug_setup);
+
+static pte_t __initdata bm_pte[PTRS_PER_PTE] __aligned(PTRS_PER_PTE * sizeof(pte_t));
+static __initdata int after_paging_init;
+
+static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+{
+	unsigned int index = pgd_index(addr);
+	pgd_t *pgd = cpu_get_pgd() + index;
+	pud_t *pud = pud_offset(pgd, addr);
+	pmd_t *pmd = pmd_offset(pud, addr);
+
+	return pmd;
+}
+
+static inline pte_t * __init early_ioremap_pte(unsigned long addr)
+{
+	return &bm_pte[pte_index(addr)];
+}
+
+static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
+
+void __init early_ioremap_init(void)
+{
+	pmd_t *pmd;
+	int i;
+	u64 desc;
+
+	if (early_ioremap_debug)
+		pr_info("early_ioremap_init()\n");
+
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN + NR_FIX_BTMAPS*i);
+		if (early_ioremap_debug)
+			pr_info("  %lu byte slot @ 0x%08x\n",
+				NR_FIX_BTMAPS * PAGE_SIZE, (u32)slot_virt[i]);
+	}
+
+	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+	desc = *pmd;
+	memset(bm_pte, 0, sizeof(bm_pte));
+
+	pmd_populate_kernel(NULL, pmd, bm_pte);
+	desc = *pmd;
+
+	BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
+		     != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
+
+	if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
+		WARN_ON(1);
+		pr_warn("pmd %p != %p\n",
+			pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
+		pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
+			fix_to_virt(FIX_BTMAP_BEGIN));
+		pr_warn("fix_to_virt(FIX_BTMAP_END):   %08lx\n",
+			fix_to_virt(FIX_BTMAP_END));
+		pr_warn("FIX_BTMAP_END:       %lu\n", FIX_BTMAP_END);
+		pr_warn("FIX_BTMAP_BEGIN:     %d\n",  FIX_BTMAP_BEGIN);
+	}
+}
+
+void __init early_ioremap_reset(void)
+{
+	after_paging_init = 1;
+}
+
+static void __init __early_set_fixmap(unsigned long idx,
+				      phys_addr_t phys, pgprot_t flags)
+{
+	unsigned long addr = __fix_to_virt(idx);
+	pte_t *pte;
+	u64 desc;
+
+	if (idx >= FIX_KMAP_END) {
+		BUG();
+		return;
+	}
+	pte = early_ioremap_pte(addr);
+
+	if (pgprot_val(flags))
+		set_pte_at(NULL, 0xfff00000, pte,
+			   pfn_pte(phys >> PAGE_SHIFT, flags));
+	else
+		pte_clear(NULL, addr, pte);
+	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+	desc = *pte;
+}
+
+static inline void __init early_set_fixmap(unsigned long idx,
+					   phys_addr_t phys, pgprot_t prot)
+{
+	__early_set_fixmap(idx, phys, prot);
+}
+
+static inline void __init early_clear_fixmap(unsigned long idx)
+{
+	__early_set_fixmap(idx, 0, __pgprot(0));
+}
+
+static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
+static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
+
+static void __init __iomem *
+__early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot)
+{
+	unsigned long offset;
+	resource_size_t last_addr;
+	unsigned int nrpages;
+	unsigned long idx;
+	int i, slot;
+
+	slot = -1;
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		if (!prev_map[i]) {
+			slot = i;
+			break;
+		}
+	}
+
+	if (slot < 0) {
+		pr_info("early_iomap(%08llx, %08lx) not found slot\n",
+			(u64)phys_addr, size);
+		WARN_ON(1);
+		return NULL;
+	}
+
+	if (early_ioremap_debug) {
+		pr_info("early_ioremap(%08llx, %08lx) [%d] => ",
+			(u64)phys_addr, size, slot);
+	}
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	prev_size[slot] = size;
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+	/*
+	 * Mappings have to fit in the FIX_BTMAP area.
+	 */
+	nrpages = size >> PAGE_SHIFT;
+	if (nrpages > NR_FIX_BTMAPS) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	/*
+	 * Ok, go for it..
+	 */
+	idx = FIX_BTMAP_BEGIN + slot * NR_FIX_BTMAPS;
+	while (nrpages > 0) {
+		early_set_fixmap(idx, phys_addr, prot);
+		phys_addr += PAGE_SIZE;
+		idx++;
+		--nrpages;
+	}
+	if (early_ioremap_debug)
+		pr_cont("%08lx + %08lx\n", offset, slot_virt[slot]);
+
+	prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]);
+	return prev_map[slot];
+}
+
+/* Remap an IO device */
+void __init __iomem *
+early_ioremap(resource_size_t phys_addr, unsigned long size)
+{
+	unsigned long prot;
+
+	if (after_paging_init) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	/*
+	 * PAGE_KERNEL depends on not-yet-initialised variables.
+	 * We don't care about coherency or executability of early_ioremap
+	 * pages anyway.
+	 */
+	prot = L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_MT_DEV_NONSHARED;
+	return __early_ioremap(phys_addr, size, prot);
+}
+
+
+void __init early_iounmap(void __iomem *addr, unsigned long size)
+{
+	unsigned long virt_addr;
+	unsigned long offset;
+	unsigned int nrpages;
+	unsigned long idx;
+	int i, slot;
+
+	if (after_paging_init) {
+		WARN_ON(1);
+		return;
+	}
+
+	slot = -1;
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		if (prev_map[i] == addr) {
+			slot = i;
+			break;
+		}
+	}
+
+	if (slot < 0) {
+		pr_info("early_iounmap(%p, %08lx) not found slot\n",
+			addr, size);
+		WARN_ON(1);
+		return;
+	}
+
+	if (prev_size[slot] != size) {
+		pr_info("early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n",
+			addr, size, slot, prev_size[slot]);
+		WARN_ON(1);
+		return;
+	}
+
+	if (early_ioremap_debug)
+		pr_info("early_iounmap(%p, %08lx) [%d]\n", addr, size, slot);
+
+	virt_addr = (unsigned long)addr;
+	if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)) {
+		WARN_ON(1);
+		return;
+	}
+	offset = virt_addr & ~PAGE_MASK;
+	nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT;
+
+	idx = FIX_BTMAP_BEGIN + slot * NR_FIX_BTMAPS;
+	while (nrpages > 0) {
+		early_clear_fixmap(idx);
+		idx++;
+		--nrpages;
+	}
+	prev_map[slot] = NULL;
+}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e0d8565..c953b20 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -28,6 +28,7 @@
 #include <asm/highmem.h>
 #include <asm/system_info.h>
 #include <asm/traps.h>
+#include <asm/io.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -1306,4 +1307,5 @@ void __init paging_init(struct machine_desc *mdesc)
 
 	empty_zero_page = virt_to_page(zero_page);
 	__flush_dcache_page(NULL, empty_zero_page);
+	early_ioremap_reset();
 }
-- 
1.7.10.4

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

* Re: [PATCH 0/2] arm: add early_ioremap() support
  2013-06-25 17:46 ` Leif Lindholm
@ 2013-06-26 18:52   ` Arnd Bergmann
  -1 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2013-06-26 18:52 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Leif Lindholm, nico, patches, linux-kernel, linux-doc,
	Russell King - ARM Linux

On Tuesday 25 June 2013, Leif Lindholm wrote:
> x86 and ia64 have the early_ioremap()/early_iounmap() functions, which are
> useful for supporting things like UEFI, ACPI and SMBIOS, where configuration
> tables need to be parsed before proper memory management is available,
> regardless of highmem status.
> 
> This patchset implements a restricted form of early_ioremap(), available
> before paging_init() only. Like the x86 code on which it is based, it
> (p)re-uses the fixmap regions for its virtual mapping range. Up to 7
> simultaneous mappings of up to 128KB can be accommodated in the available
> fixmap space.

+rmk

I made a similar suggestion to extending the use of fixmap recently, see
"Re: SCU registers mapping for CA9/CA5 cores". Russell pointed out that
fixmap is intentionally limited to just kmap_atomic uses at the moment
and changing that would potentially have a significant impact when we
run out of pages in the fixmap area.

The method we use on ARM normally is the iotable_init() function, which
requires hardcoding a virtual address at the moment.

It might be nicer to change that code than to put early_ioremap into
fixmap. Note that early_ioremap in fixmap is a bit of a kludge on x86
as well because it is very much /not/ a fixed mapping like the rest
of fixmap, they just use it because it's convenient.

Extending the iotable mechanism on ARM would be the convenient
solution for us I think.

	Arnd

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

* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-26 18:52   ` Arnd Bergmann
  0 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2013-06-26 18:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 25 June 2013, Leif Lindholm wrote:
> x86 and ia64 have the early_ioremap()/early_iounmap() functions, which are
> useful for supporting things like UEFI, ACPI and SMBIOS, where configuration
> tables need to be parsed before proper memory management is available,
> regardless of highmem status.
> 
> This patchset implements a restricted form of early_ioremap(), available
> before paging_init() only. Like the x86 code on which it is based, it
> (p)re-uses the fixmap regions for its virtual mapping range. Up to 7
> simultaneous mappings of up to 128KB can be accommodated in the available
> fixmap space.

+rmk

I made a similar suggestion to extending the use of fixmap recently, see
"Re: SCU registers mapping for CA9/CA5 cores". Russell pointed out that
fixmap is intentionally limited to just kmap_atomic uses at the moment
and changing that would potentially have a significant impact when we
run out of pages in the fixmap area.

The method we use on ARM normally is the iotable_init() function, which
requires hardcoding a virtual address at the moment.

It might be nicer to change that code than to put early_ioremap into
fixmap. Note that early_ioremap in fixmap is a bit of a kludge on x86
as well because it is very much /not/ a fixed mapping like the rest
of fixmap, they just use it because it's convenient.

Extending the iotable mechanism on ARM would be the convenient
solution for us I think.

	Arnd

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

* Re: [PATCH 0/2] arm: add early_ioremap() support
  2013-06-26 18:52   ` Arnd Bergmann
@ 2013-06-26 19:23     ` Leif Lindholm
  -1 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-26 19:23 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, nico, patches, linux-kernel, linux-doc,
	Russell King - ARM Linux

On Wed, Jun 26, 2013 at 08:52:09PM +0200, Arnd Bergmann wrote:
> I made a similar suggestion to extending the use of fixmap recently, see
> "Re: SCU registers mapping for CA9/CA5 cores". Russell pointed out that
> fixmap is intentionally limited to just kmap_atomic uses at the moment
> and changing that would potentially have a significant impact when we
> run out of pages in the fixmap area.
 
Is this an issue here, since (unlike x86) this early_ioremap only works
before paging_init()?

> The method we use on ARM normally is the iotable_init() function, which
> requires hardcoding a virtual address at the moment.
> 
> It might be nicer to change that code than to put early_ioremap into
> fixmap. Note that early_ioremap in fixmap is a bit of a kludge on x86
> as well because it is very much /not/ a fixed mapping like the rest
> of fixmap, they just use it because it's convenient.
 
Yes, but they also only use it (at least the bits where I looked) for
temporary mappings very early in the boot process. That is certainly
how I use it. So at least my intention was to use it before kmap is
even available.

> Extending the iotable mechanism on ARM would be the convenient
> solution for us I think.

Could that easily be extended to give similar semantics sufficiently
that we can progress with merging more of the UEFI and ACPI support 
together as common code with x86/ia64?

/
    Leif

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

* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-26 19:23     ` Leif Lindholm
  0 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-26 19:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 26, 2013 at 08:52:09PM +0200, Arnd Bergmann wrote:
> I made a similar suggestion to extending the use of fixmap recently, see
> "Re: SCU registers mapping for CA9/CA5 cores". Russell pointed out that
> fixmap is intentionally limited to just kmap_atomic uses at the moment
> and changing that would potentially have a significant impact when we
> run out of pages in the fixmap area.
 
Is this an issue here, since (unlike x86) this early_ioremap only works
before paging_init()?

> The method we use on ARM normally is the iotable_init() function, which
> requires hardcoding a virtual address at the moment.
> 
> It might be nicer to change that code than to put early_ioremap into
> fixmap. Note that early_ioremap in fixmap is a bit of a kludge on x86
> as well because it is very much /not/ a fixed mapping like the rest
> of fixmap, they just use it because it's convenient.
 
Yes, but they also only use it (at least the bits where I looked) for
temporary mappings very early in the boot process. That is certainly
how I use it. So at least my intention was to use it before kmap is
even available.

> Extending the iotable mechanism on ARM would be the convenient
> solution for us I think.

Could that easily be extended to give similar semantics sufficiently
that we can progress with merging more of the UEFI and ACPI support 
together as common code with x86/ia64?

/
    Leif

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

* Re: [PATCH 0/2] arm: add early_ioremap() support
  2013-06-26 19:23     ` Leif Lindholm
@ 2013-06-26 21:23       ` Arnd Bergmann
  -1 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2013-06-26 21:23 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: linux-arm-kernel, nico, patches, linux-kernel, linux-doc,
	Russell King - ARM Linux

On Wednesday 26 June 2013, Leif Lindholm wrote:
> On Wed, Jun 26, 2013 at 08:52:09PM +0200, Arnd Bergmann wrote:
> > I made a similar suggestion to extending the use of fixmap recently, see
> > "Re: SCU registers mapping for CA9/CA5 cores". Russell pointed out that
> > fixmap is intentionally limited to just kmap_atomic uses at the moment
> > and changing that would potentially have a significant impact when we
> > run out of pages in the fixmap area.
>  
> Is this an issue here, since (unlike x86) this early_ioremap only works
> before paging_init()?

The main problem is that the total fixmap size is only around 900kb,
and we want to reserve at least 64kb per cpu for kmap_atomic.
If you want to fit multiple 128kb mappings in there, you run out of
space really fast.


> > Extending the iotable mechanism on ARM would be the convenient
> > solution for us I think.
> 
> Could that easily be extended to give similar semantics sufficiently
> that we can progress with merging more of the UEFI and ACPI support 
> together as common code with x86/ia64?

I don't know what the requirements are, but the idea with iotable
is that the mappings stay around at run time, while it seems you want
to discard them at some point.

	Arnd

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

* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-26 21:23       ` Arnd Bergmann
  0 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2013-06-26 21:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 26 June 2013, Leif Lindholm wrote:
> On Wed, Jun 26, 2013 at 08:52:09PM +0200, Arnd Bergmann wrote:
> > I made a similar suggestion to extending the use of fixmap recently, see
> > "Re: SCU registers mapping for CA9/CA5 cores". Russell pointed out that
> > fixmap is intentionally limited to just kmap_atomic uses at the moment
> > and changing that would potentially have a significant impact when we
> > run out of pages in the fixmap area.
>  
> Is this an issue here, since (unlike x86) this early_ioremap only works
> before paging_init()?

The main problem is that the total fixmap size is only around 900kb,
and we want to reserve at least 64kb per cpu for kmap_atomic.
If you want to fit multiple 128kb mappings in there, you run out of
space really fast.


> > Extending the iotable mechanism on ARM would be the convenient
> > solution for us I think.
> 
> Could that easily be extended to give similar semantics sufficiently
> that we can progress with merging more of the UEFI and ACPI support 
> together as common code with x86/ia64?

I don't know what the requirements are, but the idea with iotable
is that the mappings stay around at run time, while it seems you want
to discard them at some point.

	Arnd

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

* Re: [PATCH 0/2] arm: add early_ioremap() support
  2013-06-26 21:23       ` Arnd Bergmann
@ 2013-06-26 21:34         ` Leif Lindholm
  -1 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-26 21:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, nico, patches, linux-kernel, linux-doc,
	Russell King - ARM Linux

On Wed, Jun 26, 2013 at 11:23:50PM +0200, Arnd Bergmann wrote:
> > Is this an issue here, since (unlike x86) this early_ioremap only works
> > before paging_init()?
> 
> The main problem is that the total fixmap size is only around 900kb,
> and we want to reserve at least 64kb per cpu for kmap_atomic.
> If you want to fit multiple 128kb mappings in there, you run out of
> space really fast.
 
Sorry, I still don't get it. Are you saying that kmap_atomic is
available before kmap_init() (in paging_init())?

If not, all of my mappings are discarded (well, abandoned to be more
correct), so I don't see how it affects kmap.

> > > Extending the iotable mechanism on ARM would be the convenient
> > > solution for us I think.
> > 
> > Could that easily be extended to give similar semantics sufficiently
> > that we can progress with merging more of the UEFI and ACPI support 
> > together as common code with x86/ia64?
> 
> I don't know what the requirements are, but the idea with iotable
> is that the mappings stay around at run time, while it seems you want
> to discard them at some point.
 
Indeed - almost immediately.

x86 early_ioremap can coexist with kmap; the intent of my
implementation is to use the kmap region only before kmap is available.

/
    Leif

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

* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-26 21:34         ` Leif Lindholm
  0 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-26 21:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 26, 2013 at 11:23:50PM +0200, Arnd Bergmann wrote:
> > Is this an issue here, since (unlike x86) this early_ioremap only works
> > before paging_init()?
> 
> The main problem is that the total fixmap size is only around 900kb,
> and we want to reserve at least 64kb per cpu for kmap_atomic.
> If you want to fit multiple 128kb mappings in there, you run out of
> space really fast.
 
Sorry, I still don't get it. Are you saying that kmap_atomic is
available before kmap_init() (in paging_init())?

If not, all of my mappings are discarded (well, abandoned to be more
correct), so I don't see how it affects kmap.

> > > Extending the iotable mechanism on ARM would be the convenient
> > > solution for us I think.
> > 
> > Could that easily be extended to give similar semantics sufficiently
> > that we can progress with merging more of the UEFI and ACPI support 
> > together as common code with x86/ia64?
> 
> I don't know what the requirements are, but the idea with iotable
> is that the mappings stay around at run time, while it seems you want
> to discard them at some point.
 
Indeed - almost immediately.

x86 early_ioremap can coexist with kmap; the intent of my
implementation is to use the kmap region only before kmap is available.

/
    Leif

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

* Re: [PATCH 0/2] arm: add early_ioremap() support
  2013-06-26 21:34         ` Leif Lindholm
@ 2013-06-26 22:13           ` Arnd Bergmann
  -1 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2013-06-26 22:13 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: linux-arm-kernel, nico, patches, linux-kernel, linux-doc,
	Russell King - ARM Linux

On Wednesday 26 June 2013, Leif Lindholm wrote:
> On Wed, Jun 26, 2013 at 11:23:50PM +0200, Arnd Bergmann wrote:
> > > Is this an issue here, since (unlike x86) this early_ioremap only works
> > > before paging_init()?
> > 
> > The main problem is that the total fixmap size is only around 900kb,
> > and we want to reserve at least 64kb per cpu for kmap_atomic.
> > If you want to fit multiple 128kb mappings in there, you run out of
> > space really fast.
>  
> Sorry, I still don't get it. Are you saying that kmap_atomic is
> available before kmap_init() (in paging_init())?
> 
> If not, all of my mappings are discarded (well, abandoned to be more
> correct), so I don't see how it affects kmap.

Sorry, I was under the assumption that the mappings are meant to
stay around.

> > > > Extending the iotable mechanism on ARM would be the convenient
> > > > solution for us I think.
> > > 
> > > Could that easily be extended to give similar semantics sufficiently
> > > that we can progress with merging more of the UEFI and ACPI support 
> > > together as common code with x86/ia64?
> > 
> > I don't know what the requirements are, but the idea with iotable
> > is that the mappings stay around at run time, while it seems you want
> > to discard them at some point.
>  
> Indeed - almost immediately.
> 
> x86 early_ioremap can coexist with kmap; the intent of my
> implementation is to use the kmap region only before kmap is available.

So if you never plan to use fixmap and early_ioremap at the same time,
why even bother using the fixmap code? Wouldn't it be easier to just
use the same memory area and ensure we never use fixmap before 
we're done with early_ioremap?

	Arnd

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

* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-26 22:13           ` Arnd Bergmann
  0 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2013-06-26 22:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 26 June 2013, Leif Lindholm wrote:
> On Wed, Jun 26, 2013 at 11:23:50PM +0200, Arnd Bergmann wrote:
> > > Is this an issue here, since (unlike x86) this early_ioremap only works
> > > before paging_init()?
> > 
> > The main problem is that the total fixmap size is only around 900kb,
> > and we want to reserve at least 64kb per cpu for kmap_atomic.
> > If you want to fit multiple 128kb mappings in there, you run out of
> > space really fast.
>  
> Sorry, I still don't get it. Are you saying that kmap_atomic is
> available before kmap_init() (in paging_init())?
> 
> If not, all of my mappings are discarded (well, abandoned to be more
> correct), so I don't see how it affects kmap.

Sorry, I was under the assumption that the mappings are meant to
stay around.

> > > > Extending the iotable mechanism on ARM would be the convenient
> > > > solution for us I think.
> > > 
> > > Could that easily be extended to give similar semantics sufficiently
> > > that we can progress with merging more of the UEFI and ACPI support 
> > > together as common code with x86/ia64?
> > 
> > I don't know what the requirements are, but the idea with iotable
> > is that the mappings stay around at run time, while it seems you want
> > to discard them at some point.
>  
> Indeed - almost immediately.
> 
> x86 early_ioremap can coexist with kmap; the intent of my
> implementation is to use the kmap region only before kmap is available.

So if you never plan to use fixmap and early_ioremap at the same time,
why even bother using the fixmap code? Wouldn't it be easier to just
use the same memory area and ensure we never use fixmap before 
we're done with early_ioremap?

	Arnd

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

* Re: [PATCH 0/2] arm: add early_ioremap() support
  2013-06-26 22:13           ` Arnd Bergmann
@ 2013-06-26 23:25             ` Leif Lindholm
  -1 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-26 23:25 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, nico, patches, linux-kernel, linux-doc,
	Russell King - ARM Linux

On Thu, Jun 27, 2013 at 12:13:55AM +0200, Arnd Bergmann wrote:
> > Sorry, I still don't get it. Are you saying that kmap_atomic is
> > available before kmap_init() (in paging_init())?
> > 
> > If not, all of my mappings are discarded (well, abandoned to be more
> > correct), so I don't see how it affects kmap.
> 
> Sorry, I was under the assumption that the mappings are meant to
> stay around.
 
Ok, just so I'm not completely lost :)

No, the purpose is just like for x86 - do early parsing of things like
the UEFI system and configuration tables, DMI and ACPI, in order to
populate global structs and stuff.

> > Indeed - almost immediately.
> > 
> > x86 early_ioremap can coexist with kmap; the intent of my
> > implementation is to use the kmap region only before kmap is available.
> 
> So if you never plan to use fixmap and early_ioremap at the same time,
> why even bother using the fixmap code? Wouldn't it be easier to just
> use the same memory area and ensure we never use fixmap before 
> we're done with early_ioremap?

Well, I did have a crazy idea that much/most of the early_ioremap code
could be made generic and shared between x86 and arm (and any other
32-bit architecture). Using the fixmap macros would make that possible
with a minimum of ifdefs.

If we ever wanted early_ioremap() to work like on x86, beyond kmap_init()
(but not beyond the "booting" system state), using the same macros would
help there too. I had no need for that for my EFI patches.

/
    Leif

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

* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-26 23:25             ` Leif Lindholm
  0 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-26 23:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 27, 2013 at 12:13:55AM +0200, Arnd Bergmann wrote:
> > Sorry, I still don't get it. Are you saying that kmap_atomic is
> > available before kmap_init() (in paging_init())?
> > 
> > If not, all of my mappings are discarded (well, abandoned to be more
> > correct), so I don't see how it affects kmap.
> 
> Sorry, I was under the assumption that the mappings are meant to
> stay around.
 
Ok, just so I'm not completely lost :)

No, the purpose is just like for x86 - do early parsing of things like
the UEFI system and configuration tables, DMI and ACPI, in order to
populate global structs and stuff.

> > Indeed - almost immediately.
> > 
> > x86 early_ioremap can coexist with kmap; the intent of my
> > implementation is to use the kmap region only before kmap is available.
> 
> So if you never plan to use fixmap and early_ioremap at the same time,
> why even bother using the fixmap code? Wouldn't it be easier to just
> use the same memory area and ensure we never use fixmap before 
> we're done with early_ioremap?

Well, I did have a crazy idea that much/most of the early_ioremap code
could be made generic and shared between x86 and arm (and any other
32-bit architecture). Using the fixmap macros would make that possible
with a minimum of ifdefs.

If we ever wanted early_ioremap() to work like on x86, beyond kmap_init()
(but not beyond the "booting" system state), using the same macros would
help there too. I had no need for that for my EFI patches.

/
    Leif

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

* Re: [PATCH 0/2] arm: add early_ioremap() support
  2013-06-26 23:25             ` Leif Lindholm
@ 2013-06-27  8:47               ` Arnd Bergmann
  -1 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2013-06-27  8:47 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Leif Lindholm, Russell King - ARM Linux, patches, linux-doc,
	linux-kernel, nico

On Thursday 27 June 2013 01:25:06 Leif Lindholm wrote:
> On Thu, Jun 27, 2013 at 12:13:55AM +0200, Arnd Bergmann wrote:
> > > Sorry, I still don't get it. Are you saying that kmap_atomic is
> > > available before kmap_init() (in paging_init())?
> > > 
> > > If not, all of my mappings are discarded (well, abandoned to be more
> > > correct), so I don't see how it affects kmap.
> > 
> > Sorry, I was under the assumption that the mappings are meant to
> > stay around.
>  
> Ok, just so I'm not completely lost 
> 
> No, the purpose is just like for x86 - do early parsing of things like
> the UEFI system and configuration tables, DMI and ACPI, in order to
> populate global structs and stuff.

But are those tables actually in MMIO registers? I thought they
are just memory, and in that case using any form of ioremap is
wrong on ARM. Why do you even have to map them? Can't the boot
loader pass those tables in regular addressable memory?

> > > Indeed - almost immediately.
> > > 
> > > x86 early_ioremap can coexist with kmap; the intent of my
> > > implementation is to use the kmap region only before kmap is available.
> > 
> > So if you never plan to use fixmap and early_ioremap at the same time,
> > why even bother using the fixmap code? Wouldn't it be easier to just
> > use the same memory area and ensure we never use fixmap before 
> > we're done with early_ioremap?
> 
> Well, I did have a crazy idea that much/most of the early_ioremap code
> could be made generic and shared between x86 and arm (and any other
> 32-bit architecture). Using the fixmap macros would make that possible
> with a minimum of ifdefs.
> 
> If we ever wanted early_ioremap() to work like on x86, beyond kmap_init()
> (but not beyond the "booting" system state), using the same macros would
> help there too. I had no need for that for my EFI patches.

I guess I need to look at the EFI patches first. It sounds to me
like you shouldn't actually be using early_ioremap here or on another
architecture.

	Arnd

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

* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-27  8:47               ` Arnd Bergmann
  0 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2013-06-27  8:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 27 June 2013 01:25:06 Leif Lindholm wrote:
> On Thu, Jun 27, 2013 at 12:13:55AM +0200, Arnd Bergmann wrote:
> > > Sorry, I still don't get it. Are you saying that kmap_atomic is
> > > available before kmap_init() (in paging_init())?
> > > 
> > > If not, all of my mappings are discarded (well, abandoned to be more
> > > correct), so I don't see how it affects kmap.
> > 
> > Sorry, I was under the assumption that the mappings are meant to
> > stay around.
>  
> Ok, just so I'm not completely lost 
> 
> No, the purpose is just like for x86 - do early parsing of things like
> the UEFI system and configuration tables, DMI and ACPI, in order to
> populate global structs and stuff.

But are those tables actually in MMIO registers? I thought they
are just memory, and in that case using any form of ioremap is
wrong on ARM. Why do you even have to map them? Can't the boot
loader pass those tables in regular addressable memory?

> > > Indeed - almost immediately.
> > > 
> > > x86 early_ioremap can coexist with kmap; the intent of my
> > > implementation is to use the kmap region only before kmap is available.
> > 
> > So if you never plan to use fixmap and early_ioremap at the same time,
> > why even bother using the fixmap code? Wouldn't it be easier to just
> > use the same memory area and ensure we never use fixmap before 
> > we're done with early_ioremap?
> 
> Well, I did have a crazy idea that much/most of the early_ioremap code
> could be made generic and shared between x86 and arm (and any other
> 32-bit architecture). Using the fixmap macros would make that possible
> with a minimum of ifdefs.
> 
> If we ever wanted early_ioremap() to work like on x86, beyond kmap_init()
> (but not beyond the "booting" system state), using the same macros would
> help there too. I had no need for that for my EFI patches.

I guess I need to look at the EFI patches first. It sounds to me
like you shouldn't actually be using early_ioremap here or on another
architecture.

	Arnd

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

* Re: [PATCH 0/2] arm: add early_ioremap() support
  2013-06-27  8:47               ` Arnd Bergmann
@ 2013-06-27  9:29                 ` Leif Lindholm
  -1 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-27  9:29 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Russell King - ARM Linux, patches, linux-doc,
	linux-kernel, nico

On Thu, Jun 27, 2013 at 10:47:21AM +0200, Arnd Bergmann wrote:
> > No, the purpose is just like for x86 - do early parsing of things like
> > the UEFI system and configuration tables, DMI and ACPI, in order to
> > populate global structs and stuff.
> 
> But are those tables actually in MMIO registers? I thought they
> are just memory, and in that case using any form of ioremap is
> wrong on ARM. Why do you even have to map them? Can't the boot
> loader pass those tables in regular addressable memory?
 
Don't get too stuck on the name - x86 frequently uses *ioremap() in
many places when just accessing memory, and that has carried into EFI,
ACPI and DMI subsystems, which we now want to use on ARM. In fact, they
have early_memremap(), but don't use it for either EFI or ACPI.

The ia64 implementation actually performs a lookup in the EFI memmap
to decide whether early_ioremap() returns cacheable memory or not
(and falls back to noncacheable before memory map is available).

That said, I had somehow managed to get into my mind that the kernel
used -fno-unaligned-access, so thought MT_DEV_NONSHARED was safe.
Clearly it isn't, so that will need to change, making the semantic
match even worse...

As for the need of mapping - some of these descriptors are needed very
early in the boot process. Also, depending on platform, they may reside
at any offset from start of RAM (<2^32 physical address), rendering
__va()/__phys_to_virt()/... unusable.

> > Well, I did have a crazy idea that much/most of the early_ioremap code
> > could be made generic and shared between x86 and arm (and any other
> > 32-bit architecture). Using the fixmap macros would make that possible
> > with a minimum of ifdefs.
> > 
> > If we ever wanted early_ioremap() to work like on x86, beyond kmap_init()
> > (but not beyond the "booting" system state), using the same macros would
> > help there too. I had no need for that for my EFI patches.
> 
> I guess I need to look at the EFI patches first. It sounds to me
> like you shouldn't actually be using early_ioremap here or on another
> architecture.

No, but I had been kind of hoping not having to rework the early memory
initialisation for three subsystems on two other platforms in order to
be able to merge common code between them. And it would have felt silly
to invent a new mechanism just for ARM, preventing that option.

/
    Leif

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

* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-27  9:29                 ` Leif Lindholm
  0 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2013-06-27  9:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 27, 2013 at 10:47:21AM +0200, Arnd Bergmann wrote:
> > No, the purpose is just like for x86 - do early parsing of things like
> > the UEFI system and configuration tables, DMI and ACPI, in order to
> > populate global structs and stuff.
> 
> But are those tables actually in MMIO registers? I thought they
> are just memory, and in that case using any form of ioremap is
> wrong on ARM. Why do you even have to map them? Can't the boot
> loader pass those tables in regular addressable memory?
 
Don't get too stuck on the name - x86 frequently uses *ioremap() in
many places when just accessing memory, and that has carried into EFI,
ACPI and DMI subsystems, which we now want to use on ARM. In fact, they
have early_memremap(), but don't use it for either EFI or ACPI.

The ia64 implementation actually performs a lookup in the EFI memmap
to decide whether early_ioremap() returns cacheable memory or not
(and falls back to noncacheable before memory map is available).

That said, I had somehow managed to get into my mind that the kernel
used -fno-unaligned-access, so thought MT_DEV_NONSHARED was safe.
Clearly it isn't, so that will need to change, making the semantic
match even worse...

As for the need of mapping - some of these descriptors are needed very
early in the boot process. Also, depending on platform, they may reside
at any offset from start of RAM (<2^32 physical address), rendering
__va()/__phys_to_virt()/... unusable.

> > Well, I did have a crazy idea that much/most of the early_ioremap code
> > could be made generic and shared between x86 and arm (and any other
> > 32-bit architecture). Using the fixmap macros would make that possible
> > with a minimum of ifdefs.
> > 
> > If we ever wanted early_ioremap() to work like on x86, beyond kmap_init()
> > (but not beyond the "booting" system state), using the same macros would
> > help there too. I had no need for that for my EFI patches.
> 
> I guess I need to look at the EFI patches first. It sounds to me
> like you shouldn't actually be using early_ioremap here or on another
> architecture.

No, but I had been kind of hoping not having to rework the early memory
initialisation for three subsystems on two other platforms in order to
be able to merge common code between them. And it would have felt silly
to invent a new mechanism just for ARM, preventing that option.

/
    Leif

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

* Re: [PATCH 0/2] arm: add early_ioremap() support
  2013-06-27  9:29                 ` Leif Lindholm
@ 2013-06-27 11:55                   ` Arnd Bergmann
  -1 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2013-06-27 11:55 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: linux-arm-kernel, Russell King - ARM Linux, patches, linux-doc,
	linux-kernel, nico

On Thursday 27 June 2013, Leif Lindholm wrote:
> On Thu, Jun 27, 2013 at 10:47:21AM +0200, Arnd Bergmann wrote:
> > > No, the purpose is just like for x86 - do early parsing of things like
> > > the UEFI system and configuration tables, DMI and ACPI, in order to
> > > populate global structs and stuff.
> > 
> > But are those tables actually in MMIO registers? I thought they
> > are just memory, and in that case using any form of ioremap is
> > wrong on ARM. Why do you even have to map them? Can't the boot
> > loader pass those tables in regular addressable memory?
>  
> Don't get too stuck on the name - x86 frequently uses *ioremap() in
> many places when just accessing memory, and that has carried into EFI,
> ACPI and DMI subsystems, which we now want to use on ARM. In fact, they
> have early_memremap(), but don't use it for either EFI or ACPI.

The difference of course is that x86 doesn't use page table flags
to tell the difference between MMIO and memory. It is not harmful
on x86 to access memory through ioremap, but it is on most
other architectures. You get either unspecified behavior due to
conflicting cache flags or you get a hard checkstop based on how
the CPU treats this. If you want to make the EFI code architecture
independent, I think you should change the EFI code.

> The ia64 implementation actually performs a lookup in the EFI memmap
> to decide whether early_ioremap() returns cacheable memory or not
> (and falls back to noncacheable before memory map is available).
> 
> That said, I had somehow managed to get into my mind that the kernel
> used -fno-unaligned-access, so thought MT_DEV_NONSHARED was safe.
> Clearly it isn't, so that will need to change, making the semantic
> match even worse...
> 
> As for the need of mapping - some of these descriptors are needed very
> early in the boot process. Also, depending on platform, they may reside
> at any offset from start of RAM (<2^32 physical address), rendering
> __va()/__phys_to_virt()/... unusable.

Can you explain why they are needed this early?

Also, can't we define the boot protocol to require these tables
within the first GB of RAM?

> > > Well, I did have a crazy idea that much/most of the early_ioremap code
> > > could be made generic and shared between x86 and arm (and any other
> > > 32-bit architecture). Using the fixmap macros would make that possible
> > > with a minimum of ifdefs.
> > > 
> > > If we ever wanted early_ioremap() to work like on x86, beyond kmap_init()
> > > (but not beyond the "booting" system state), using the same macros would
> > > help there too. I had no need for that for my EFI patches.
> > 
> > I guess I need to look at the EFI patches first. It sounds to me
> > like you shouldn't actually be using early_ioremap here or on another
> > architecture.
> 
> No, but I had been kind of hoping not having to rework the early memory
> initialisation for three subsystems on two other platforms in order to
> be able to merge common code between them. And it would have felt silly
> to invent a new mechanism just for ARM, preventing that option.

Well, if you can get around the "early" requirement, things can become
much easier, you can basically 

#define early_ioremap(addr, size) ioremap(addr, size)
#define early_memremap(addr, size) ioremap_cached(addr, size)

and just need to fix the places where the common code mistakenly calls
early_ioremap instead of early_memremap.

Chances are that even if you can't avoid the requirement for early
maps entirely that you only really have to worry about a small number
of callers, for which you can then introduce architecture specific
functions that do one thing in an appropriate way. On ARM, this may
end up being __va(), kmap_atomic() or iotable_init() depending on
the requirements.

	Arnd

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

* [PATCH 0/2] arm: add early_ioremap() support
@ 2013-06-27 11:55                   ` Arnd Bergmann
  0 siblings, 0 replies; 31+ messages in thread
From: Arnd Bergmann @ 2013-06-27 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 27 June 2013, Leif Lindholm wrote:
> On Thu, Jun 27, 2013 at 10:47:21AM +0200, Arnd Bergmann wrote:
> > > No, the purpose is just like for x86 - do early parsing of things like
> > > the UEFI system and configuration tables, DMI and ACPI, in order to
> > > populate global structs and stuff.
> > 
> > But are those tables actually in MMIO registers? I thought they
> > are just memory, and in that case using any form of ioremap is
> > wrong on ARM. Why do you even have to map them? Can't the boot
> > loader pass those tables in regular addressable memory?
>  
> Don't get too stuck on the name - x86 frequently uses *ioremap() in
> many places when just accessing memory, and that has carried into EFI,
> ACPI and DMI subsystems, which we now want to use on ARM. In fact, they
> have early_memremap(), but don't use it for either EFI or ACPI.

The difference of course is that x86 doesn't use page table flags
to tell the difference between MMIO and memory. It is not harmful
on x86 to access memory through ioremap, but it is on most
other architectures. You get either unspecified behavior due to
conflicting cache flags or you get a hard checkstop based on how
the CPU treats this. If you want to make the EFI code architecture
independent, I think you should change the EFI code.

> The ia64 implementation actually performs a lookup in the EFI memmap
> to decide whether early_ioremap() returns cacheable memory or not
> (and falls back to noncacheable before memory map is available).
> 
> That said, I had somehow managed to get into my mind that the kernel
> used -fno-unaligned-access, so thought MT_DEV_NONSHARED was safe.
> Clearly it isn't, so that will need to change, making the semantic
> match even worse...
> 
> As for the need of mapping - some of these descriptors are needed very
> early in the boot process. Also, depending on platform, they may reside
> at any offset from start of RAM (<2^32 physical address), rendering
> __va()/__phys_to_virt()/... unusable.

Can you explain why they are needed this early?

Also, can't we define the boot protocol to require these tables
within the first GB of RAM?

> > > Well, I did have a crazy idea that much/most of the early_ioremap code
> > > could be made generic and shared between x86 and arm (and any other
> > > 32-bit architecture). Using the fixmap macros would make that possible
> > > with a minimum of ifdefs.
> > > 
> > > If we ever wanted early_ioremap() to work like on x86, beyond kmap_init()
> > > (but not beyond the "booting" system state), using the same macros would
> > > help there too. I had no need for that for my EFI patches.
> > 
> > I guess I need to look at the EFI patches first. It sounds to me
> > like you shouldn't actually be using early_ioremap here or on another
> > architecture.
> 
> No, but I had been kind of hoping not having to rework the early memory
> initialisation for three subsystems on two other platforms in order to
> be able to merge common code between them. And it would have felt silly
> to invent a new mechanism just for ARM, preventing that option.

Well, if you can get around the "early" requirement, things can become
much easier, you can basically 

#define early_ioremap(addr, size) ioremap(addr, size)
#define early_memremap(addr, size) ioremap_cached(addr, size)

and just need to fix the places where the common code mistakenly calls
early_ioremap instead of early_memremap.

Chances are that even if you can't avoid the requirement for early
maps entirely that you only really have to worry about a small number
of callers, for which you can then introduce architecture specific
functions that do one thing in an appropriate way. On ARM, this may
end up being __va(), kmap_atomic() or iotable_init() depending on
the requirements.

	Arnd

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

* Re: [PATCH 1/2] Documentation: arm: early_ioremap
  2013-06-25 17:46   ` Leif Lindholm
@ 2013-06-30  3:14     ` Rob Landley
  -1 siblings, 0 replies; 31+ messages in thread
From: Rob Landley @ 2013-06-30  3:14 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: linux-arm-kernel, linux-doc, linux-kernel, patches, nico, Leif Lindholm

On 06/25/2013 12:46:40 PM, Leif Lindholm wrote:
> This patch provides documentation of the early_ioremap()  
> functionality,
> including its implementation and usage instructions.
> 
> Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
> ---
>  Documentation/arm/00-INDEX          |    2 ++
>  Documentation/arm/early_ioremap.txt |   12 ++++++++++++
>  2 files changed, 14 insertions(+)
>  create mode 100644 Documentation/arm/early_ioremap.txt
> 
> diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
> index 36420e1..4978456 100644
> --- a/Documentation/arm/00-INDEX
> +++ b/Documentation/arm/00-INDEX
> @@ -24,6 +24,8 @@ SPEAr
>  	- ST SPEAr platform Linux Overview
>  VFP/
>  	- Release notes for Linux Kernel Vector Floating Point support  
> code
> +early_ioremap.txt
> +	- documentation of the early_ioremap() functionality
>  empeg/
>  	- Ltd's Empeg MP3 Car Audio Player
>  mem_alignment
> diff --git a/Documentation/arm/early_ioremap.txt  
> b/Documentation/arm/early_ioremap.txt
> new file mode 100644
> index 0000000..178f791
> --- /dev/null
> +++ b/Documentation/arm/early_ioremap.txt
> @@ -0,0 +1,12 @@
> +early_ioremap() and early_iounmap() rovide a mechanism for  
> temporarily mapping

Typo: provide

> +in small blocks of memory, identified by their physical address,  
> into the
> +fixmap virtual address block before paging_init() has been called  
> and more
> +flexible mapping functions are available.
> +
> +Due to its direct method, it also gets around potential need for  
> special
> +handling of regions that end up in highmem.
> +
> +It supports up to 7 simultaneously mapped regions of up to 128KB  
> each.
> +All regions are mapped as non-shareable device memory.
> +
> +Specify 'early_ioremap_debug' on the kernel commandline for verbose  
> output.
> --
> 1.7.10.4

Minor quibble: this explains what it does, but nothing about how to use  
it. Do these mappings persist if you don't unmap them, or does  
paging_init() clear them?

Oh well:

Acked-by: Rob Landley <rob@landley.net>

Rob

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

* [PATCH 1/2] Documentation: arm: early_ioremap
@ 2013-06-30  3:14     ` Rob Landley
  0 siblings, 0 replies; 31+ messages in thread
From: Rob Landley @ 2013-06-30  3:14 UTC (permalink / raw)
  To: linux-arm-kernel

On 06/25/2013 12:46:40 PM, Leif Lindholm wrote:
> This patch provides documentation of the early_ioremap()  
> functionality,
> including its implementation and usage instructions.
> 
> Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
> ---
>  Documentation/arm/00-INDEX          |    2 ++
>  Documentation/arm/early_ioremap.txt |   12 ++++++++++++
>  2 files changed, 14 insertions(+)
>  create mode 100644 Documentation/arm/early_ioremap.txt
> 
> diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX
> index 36420e1..4978456 100644
> --- a/Documentation/arm/00-INDEX
> +++ b/Documentation/arm/00-INDEX
> @@ -24,6 +24,8 @@ SPEAr
>  	- ST SPEAr platform Linux Overview
>  VFP/
>  	- Release notes for Linux Kernel Vector Floating Point support  
> code
> +early_ioremap.txt
> +	- documentation of the early_ioremap() functionality
>  empeg/
>  	- Ltd's Empeg MP3 Car Audio Player
>  mem_alignment
> diff --git a/Documentation/arm/early_ioremap.txt  
> b/Documentation/arm/early_ioremap.txt
> new file mode 100644
> index 0000000..178f791
> --- /dev/null
> +++ b/Documentation/arm/early_ioremap.txt
> @@ -0,0 +1,12 @@
> +early_ioremap() and early_iounmap() rovide a mechanism for  
> temporarily mapping

Typo: provide

> +in small blocks of memory, identified by their physical address,  
> into the
> +fixmap virtual address block before paging_init() has been called  
> and more
> +flexible mapping functions are available.
> +
> +Due to its direct method, it also gets around potential need for  
> special
> +handling of regions that end up in highmem.
> +
> +It supports up to 7 simultaneously mapped regions of up to 128KB  
> each.
> +All regions are mapped as non-shareable device memory.
> +
> +Specify 'early_ioremap_debug' on the kernel commandline for verbose  
> output.
> --
> 1.7.10.4

Minor quibble: this explains what it does, but nothing about how to use  
it. Do these mappings persist if you don't unmap them, or does  
paging_init() clear them?

Oh well:

Acked-by: Rob Landley <rob@landley.net>

Rob

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

* [PATCH 0/2] arm: add early_ioremap support
  2014-07-09  9:47 ` Will Deacon
@ 2014-07-09 10:02   ` Leif Lindholm
  0 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2014-07-09 10:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 09, 2014 at 10:47:30AM +0100, Will Deacon wrote:
> On Wed, Jul 09, 2014 at 10:39:50AM +0100, Leif Lindholm wrote:
> > early_ioremap()/early_memremap() create temporary virtual mappings
> > in the fixmap region during boot time. Part of the support now exists
> > in core code, but depends on the generic fixmap support.
> > 
> > This set converts arm to use the generic fixmap support, and adds the
> > architecture-specific part of early_ioremap support.
> > 
> > The fixmap/kmap changes in 3.15 complicated things slightly compared
> > to previous iterations of these patches - this version works around
> > that by introducing local macros in arm/mm/highmem.c.
> > 
> > Tested on TC2 and software models, with/without LPAE.
> > 
> > Mark Salter (2):
> >   arm: use generic fixmap.h
> >   arm: add early_ioremap support
> 
> Curious: why are you sending these patches instead of Mark?

Well, it used to form part of the larger UEFI patchset, which I'm
still marshalling the 32-bit parts of (and which will follow later,
but I will treat them separately from here on).
Also, I did the hacky rework to Mark's original patches for the kmap
changes.

/
    Leif

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

* [PATCH 0/2] arm: add early_ioremap support
  2014-07-09  9:42 ` Russell King - ARM Linux
@ 2014-07-09  9:58   ` Leif Lindholm
  0 siblings, 0 replies; 31+ messages in thread
From: Leif Lindholm @ 2014-07-09  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 09, 2014 at 10:42:42AM +0100, Russell King - ARM Linux wrote:
> On Wed, Jul 09, 2014 at 10:39:50AM +0100, Leif Lindholm wrote:
> > early_ioremap()/early_memremap() create temporary virtual mappings
> > in the fixmap region during boot time. Part of the support now exists
> > in core code, but depends on the generic fixmap support.
> 
> Does this mean that the changes upon which this patch depends are
> already merged in mainline, or are they queued in some other tree?

Yes, they went into 3.15.

/
    Leif

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

* [PATCH 0/2] arm: add early_ioremap support
  2014-07-09  9:39 [PATCH 0/2] arm: add early_ioremap support Leif Lindholm
  2014-07-09  9:42 ` Russell King - ARM Linux
@ 2014-07-09  9:47 ` Will Deacon
  2014-07-09 10:02   ` Leif Lindholm
  1 sibling, 1 reply; 31+ messages in thread
From: Will Deacon @ 2014-07-09  9:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 09, 2014 at 10:39:50AM +0100, Leif Lindholm wrote:
> early_ioremap()/early_memremap() create temporary virtual mappings
> in the fixmap region during boot time. Part of the support now exists
> in core code, but depends on the generic fixmap support.
> 
> This set converts arm to use the generic fixmap support, and adds the
> architecture-specific part of early_ioremap support.
> 
> The fixmap/kmap changes in 3.15 complicated things slightly compared
> to previous iterations of these patches - this version works around
> that by introducing local macros in arm/mm/highmem.c.
> 
> Tested on TC2 and software models, with/without LPAE.
> 
> Mark Salter (2):
>   arm: use generic fixmap.h
>   arm: add early_ioremap support

Curious: why are you sending these patches instead of Mark?

Will

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

* [PATCH 0/2] arm: add early_ioremap support
  2014-07-09  9:39 [PATCH 0/2] arm: add early_ioremap support Leif Lindholm
@ 2014-07-09  9:42 ` Russell King - ARM Linux
  2014-07-09  9:58   ` Leif Lindholm
  2014-07-09  9:47 ` Will Deacon
  1 sibling, 1 reply; 31+ messages in thread
From: Russell King - ARM Linux @ 2014-07-09  9:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 09, 2014 at 10:39:50AM +0100, Leif Lindholm wrote:
> early_ioremap()/early_memremap() create temporary virtual mappings
> in the fixmap region during boot time. Part of the support now exists
> in core code, but depends on the generic fixmap support.

Does this mean that the changes upon which this patch depends are
already merged in mainline, or are they queued in some other tree?

Thanks.

-- 
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.

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

* [PATCH 0/2] arm: add early_ioremap support
@ 2014-07-09  9:39 Leif Lindholm
  2014-07-09  9:42 ` Russell King - ARM Linux
  2014-07-09  9:47 ` Will Deacon
  0 siblings, 2 replies; 31+ messages in thread
From: Leif Lindholm @ 2014-07-09  9:39 UTC (permalink / raw)
  To: linux-arm-kernel

early_ioremap()/early_memremap() create temporary virtual mappings
in the fixmap region during boot time. Part of the support now exists
in core code, but depends on the generic fixmap support.

This set converts arm to use the generic fixmap support, and adds the
architecture-specific part of early_ioremap support.

The fixmap/kmap changes in 3.15 complicated things slightly compared
to previous iterations of these patches - this version works around
that by introducing local macros in arm/mm/highmem.c.

Tested on TC2 and software models, with/without LPAE.

Mark Salter (2):
  arm: use generic fixmap.h
  arm: add early_ioremap support

 arch/arm/Kconfig              |   11 ++++++
 arch/arm/include/asm/Kbuild   |    1 +
 arch/arm/include/asm/fixmap.h |   45 +++++++++++++--------
 arch/arm/include/asm/io.h     |    1 +
 arch/arm/kernel/setup.c       |    3 ++
 arch/arm/mm/Makefile          |    1 +
 arch/arm/mm/early_ioremap.c   |   86 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mm/highmem.c         |   13 ++++---
 arch/arm/mm/init.c            |    2 +-
 arch/arm/mm/mmu.c             |    2 +
 10 files changed, 143 insertions(+), 22 deletions(-)
 create mode 100644 arch/arm/mm/early_ioremap.c

-- 
1.7.10.4

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

end of thread, other threads:[~2014-07-09 10:02 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-25 17:46 [PATCH 0/2] arm: add early_ioremap() support Leif Lindholm
2013-06-25 17:46 ` Leif Lindholm
2013-06-25 17:46 ` [PATCH 1/2] Documentation: arm: early_ioremap Leif Lindholm
2013-06-25 17:46   ` Leif Lindholm
2013-06-30  3:14   ` Rob Landley
2013-06-30  3:14     ` Rob Landley
2013-06-25 17:46 ` [PATCH 2/2] arm: add early_ioremap support Leif Lindholm
2013-06-25 17:46   ` Leif Lindholm
2013-06-26 18:52 ` [PATCH 0/2] arm: add early_ioremap() support Arnd Bergmann
2013-06-26 18:52   ` Arnd Bergmann
2013-06-26 19:23   ` Leif Lindholm
2013-06-26 19:23     ` Leif Lindholm
2013-06-26 21:23     ` Arnd Bergmann
2013-06-26 21:23       ` Arnd Bergmann
2013-06-26 21:34       ` Leif Lindholm
2013-06-26 21:34         ` Leif Lindholm
2013-06-26 22:13         ` Arnd Bergmann
2013-06-26 22:13           ` Arnd Bergmann
2013-06-26 23:25           ` Leif Lindholm
2013-06-26 23:25             ` Leif Lindholm
2013-06-27  8:47             ` Arnd Bergmann
2013-06-27  8:47               ` Arnd Bergmann
2013-06-27  9:29               ` Leif Lindholm
2013-06-27  9:29                 ` Leif Lindholm
2013-06-27 11:55                 ` Arnd Bergmann
2013-06-27 11:55                   ` Arnd Bergmann
2014-07-09  9:39 [PATCH 0/2] arm: add early_ioremap support Leif Lindholm
2014-07-09  9:42 ` Russell King - ARM Linux
2014-07-09  9:58   ` Leif Lindholm
2014-07-09  9:47 ` Will Deacon
2014-07-09 10:02   ` Leif Lindholm

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.