* [PATCH 0/4] generic early_ioremap support @ 2013-11-28 2:44 Mark Salter 2013-11-28 2:44 ` Mark Salter 2013-11-28 2:44 ` [PATCH 1/4] Create generic early_ioremap() support Mark Salter 0 siblings, 2 replies; 11+ messages in thread From: Mark Salter @ 2013-11-28 2:44 UTC (permalink / raw) To: linux-kernel Cc: Leif Lindholm, Mark Salter, Arnd Bergmann, Ingo Molnar, linux-arch, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86, Russell King, linux-arm-kernel, Catalin Marinas, Will Deacon This patch series takes the common bits from the x86 early ioremap implementation and creates a generic library which may be used by other architectures. The early ioremap interfaces are intended for situations where boot code needs to make temporary virtual mappings before the normal ioremap interfaces are available. Typically, this means before paging_init() has run. These patches are layered on top of generic fixmap patches which have been discussed here: http://lkml.org/lkml/2013/11/25/474 These patches (and undelying fixmap patches) may be found at: git://github.com/mosalter/linux.git (early-ioremap branch) Mark Salter (4): Create generic early_ioremap() support x86: use generic early_ioremap arm: add early_ioremap support arm64: add early_ioremap support Documentation/arm64/memory.txt | 4 +- arch/arm/Kconfig | 11 ++ arch/arm/include/asm/Kbuild | 1 + arch/arm/include/asm/fixmap.h | 18 +++ arch/arm/include/asm/io.h | 1 + arch/arm/kernel/setup.c | 3 + arch/arm/mm/Makefile | 1 + arch/arm/mm/early_ioremap.c | 93 ++++++++++++++ arch/arm/mm/mmu.c | 2 + arch/arm64/Kconfig | 1 + arch/arm64/include/asm/Kbuild | 1 + arch/arm64/include/asm/fixmap.h | 68 ++++++++++ arch/arm64/include/asm/io.h | 1 + arch/arm64/include/asm/memory.h | 1 + arch/arm64/kernel/early_printk.c | 8 +- arch/arm64/kernel/head.S | 9 +- arch/arm64/kernel/setup.c | 2 + arch/arm64/mm/ioremap.c | 77 ++++++++++++ arch/arm64/mm/mmu.c | 41 ------ arch/x86/Kconfig | 1 + arch/x86/include/asm/Kbuild | 1 + arch/x86/include/asm/fixmap.h | 6 + arch/x86/include/asm/io.h | 14 +-- arch/x86/mm/ioremap.c | 224 +-------------------------------- arch/x86/mm/pgtable_32.c | 2 +- include/asm-generic/early_ioremap.h | 40 ++++++ lib/Kconfig | 3 + lib/Makefile | 1 + lib/early_ioremap.c | 243 ++++++++++++++++++++++++++++++++++++ 29 files changed, 592 insertions(+), 286 deletions(-) create mode 100644 arch/arm/mm/early_ioremap.c create mode 100644 arch/arm64/include/asm/fixmap.h create mode 100644 include/asm-generic/early_ioremap.h create mode 100644 lib/early_ioremap.c -- 1.8.3.1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 0/4] generic early_ioremap support 2013-11-28 2:44 [PATCH 0/4] generic early_ioremap support Mark Salter @ 2013-11-28 2:44 ` Mark Salter 2013-11-28 2:44 ` [PATCH 1/4] Create generic early_ioremap() support Mark Salter 1 sibling, 0 replies; 11+ messages in thread From: Mark Salter @ 2013-11-28 2:44 UTC (permalink / raw) To: linux-kernel Cc: Leif Lindholm, Mark Salter, Arnd Bergmann, Ingo Molnar, linux-arch, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, x86, Russell King, linux-arm-kernel, Catalin Marinas, Will Deacon This patch series takes the common bits from the x86 early ioremap implementation and creates a generic library which may be used by other architectures. The early ioremap interfaces are intended for situations where boot code needs to make temporary virtual mappings before the normal ioremap interfaces are available. Typically, this means before paging_init() has run. These patches are layered on top of generic fixmap patches which have been discussed here: http://lkml.org/lkml/2013/11/25/474 These patches (and undelying fixmap patches) may be found at: git://github.com/mosalter/linux.git (early-ioremap branch) Mark Salter (4): Create generic early_ioremap() support x86: use generic early_ioremap arm: add early_ioremap support arm64: add early_ioremap support Documentation/arm64/memory.txt | 4 +- arch/arm/Kconfig | 11 ++ arch/arm/include/asm/Kbuild | 1 + arch/arm/include/asm/fixmap.h | 18 +++ arch/arm/include/asm/io.h | 1 + arch/arm/kernel/setup.c | 3 + arch/arm/mm/Makefile | 1 + arch/arm/mm/early_ioremap.c | 93 ++++++++++++++ arch/arm/mm/mmu.c | 2 + arch/arm64/Kconfig | 1 + arch/arm64/include/asm/Kbuild | 1 + arch/arm64/include/asm/fixmap.h | 68 ++++++++++ arch/arm64/include/asm/io.h | 1 + arch/arm64/include/asm/memory.h | 1 + arch/arm64/kernel/early_printk.c | 8 +- arch/arm64/kernel/head.S | 9 +- arch/arm64/kernel/setup.c | 2 + arch/arm64/mm/ioremap.c | 77 ++++++++++++ arch/arm64/mm/mmu.c | 41 ------ arch/x86/Kconfig | 1 + arch/x86/include/asm/Kbuild | 1 + arch/x86/include/asm/fixmap.h | 6 + arch/x86/include/asm/io.h | 14 +-- arch/x86/mm/ioremap.c | 224 +-------------------------------- arch/x86/mm/pgtable_32.c | 2 +- include/asm-generic/early_ioremap.h | 40 ++++++ lib/Kconfig | 3 + lib/Makefile | 1 + lib/early_ioremap.c | 243 ++++++++++++++++++++++++++++++++++++ 29 files changed, 592 insertions(+), 286 deletions(-) create mode 100644 arch/arm/mm/early_ioremap.c create mode 100644 arch/arm64/include/asm/fixmap.h create mode 100644 include/asm-generic/early_ioremap.h create mode 100644 lib/early_ioremap.c -- 1.8.3.1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/4] Create generic early_ioremap() support 2013-11-28 2:44 [PATCH 0/4] generic early_ioremap support Mark Salter 2013-11-28 2:44 ` Mark Salter @ 2013-11-28 2:44 ` Mark Salter 2013-11-28 2:44 ` Mark Salter 2013-12-16 1:48 ` Dave Young 1 sibling, 2 replies; 11+ messages in thread From: Mark Salter @ 2013-11-28 2:44 UTC (permalink / raw) To: linux-kernel Cc: Leif Lindholm, Mark Salter, Arnd Bergmann, Ingo Molnar, linux-arch This patch copies generic bits of x86 early_ioremap() support into a library for potential use by other architectures. Signed-off-by: Mark Salter <msalter@redhat.com> CC: Arnd Bergmann <arnd@arndb.de> CC: Ingo Molnar <mingo@kernel.org> CC: linux-arch@vger.kernel.org --- include/asm-generic/early_ioremap.h | 40 ++++++ lib/Kconfig | 3 + lib/Makefile | 1 + lib/early_ioremap.c | 243 ++++++++++++++++++++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 include/asm-generic/early_ioremap.h create mode 100644 lib/early_ioremap.c diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h new file mode 100644 index 0000000..e26ce80 --- /dev/null +++ b/include/asm-generic/early_ioremap.h @@ -0,0 +1,40 @@ +#ifndef _ASM_EARLY_IOREMAP_H_ +#define _ASM_EARLY_IOREMAP_H_ + +#include <linux/types.h> + +#ifdef CONFIG_GENERIC_EARLY_IOREMAP +/* + * early_ioremap() and early_iounmap() are for temporary early boot-time + * mappings, before the real ioremap() is functional. + */ +extern void __iomem *early_ioremap(resource_size_t phys_addr, + unsigned long size); +extern void __iomem *early_memremap(resource_size_t phys_addr, + unsigned long size); +extern void early_iounmap(void __iomem *addr, unsigned long size); + +/* Arch-specific initialization */ +extern void early_ioremap_init(void); + +/* Generic initialization called by architecture code */ +extern void early_ioremap_setup(void); + +/* + * Called as last step in paging_init() so library can act + * accordingly for subsequent map/unmap requests. + */ +extern void early_ioremap_reset(void); + +/* + * Weak function called by early_ioremap_reset(). It does nothing, but + * architectures may provide their own version to do any needed cleanups. + */ +extern void early_ioremap_shutdown(void); +#else +static inline void early_ioremap_init(void) { } +static inline void early_ioremap_setup(void) { } +static inline void early_ioremap_reset(void) { } +#endif + +#endif /* _ASM_EARLY_IOREMAP_H_ */ diff --git a/lib/Kconfig b/lib/Kconfig index 991c98b..5ebee09 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -42,6 +42,9 @@ config GENERIC_IO boolean default n +config GENERIC_EARLY_IOREMAP + bool + config STMP_DEVICE bool diff --git a/lib/Makefile b/lib/Makefile index a459c31..2afe05d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -188,3 +188,4 @@ quiet_cmd_build_OID_registry = GEN $@ clean-files += oid_registry_data.c obj-$(CONFIG_UCS2_STRING) += ucs2_string.o +obj-$(CONFIG_GENERIC_EARLY_IOREMAP) += early_ioremap.o diff --git a/lib/early_ioremap.c b/lib/early_ioremap.c new file mode 100644 index 0000000..54623a7 --- /dev/null +++ b/lib/early_ioremap.c @@ -0,0 +1,243 @@ +/* + * Provide common bits of early_ioremap() support for architectures needing + * temporary mappings during boot before ioremap() is available. + * + * This is mostly a direct copy of the x86 early_ioremap implementation. + * + * (C) Copyright 1995 1996 Linus Torvalds + * + */ +#include <linux/init.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <asm/fixmap.h> + +static int early_ioremap_debug __initdata; + +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 int after_paging_init __initdata; + +void __init __attribute__((weak)) early_ioremap_shutdown(void) +{ +} + +void __init early_ioremap_reset(void) +{ + early_ioremap_shutdown(); + after_paging_init = 1; +} + +/* + * Generally, ioremap() is available after paging_init() has been called. + * Architectures wanting to allow early_ioremap after paging_init() can + * define __late_set_fixmap and __late_clear_fixmap to do the right thing. + */ +#ifndef __late_set_fixmap +static inline void __init __late_set_fixmap(enum fixed_addresses idx, + phys_addr_t phys, pgprot_t prot) +{ + BUG(); +} +#endif + +#ifndef __late_clear_fixmap +static inline void __init __late_clear_fixmap(enum fixed_addresses idx) +{ + BUG(); +} +#endif + +static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata; +static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata; +static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata; + +void __init early_ioremap_setup(void) +{ + int i; + + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { + if (prev_map[i]) { + WARN_ON(1); + break; + } + } + + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) + slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i); +} + +static int __init check_early_ioremap_leak(void) +{ + int count = 0; + int i; + + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) + if (prev_map[i]) + count++; + + if (!count) + return 0; + WARN(1, KERN_WARNING + "Debug warning: early ioremap leak of %d areas detected.\n", + count); + pr_warn("please boot with early_ioremap_debug and report the dmesg.\n"); + + return 1; +} +late_initcall(check_early_ioremap_leak); + +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; + enum fixed_addresses idx; + int i, slot; + + WARN_ON(system_state != SYSTEM_BOOTING); + + slot = -1; + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { + if (!prev_map[i]) { + slot = i; + break; + } + } + + if (slot < 0) { + pr_info("%s(%08llx, %08lx) not found slot\n", + __func__, (u64)phys_addr, size); + WARN_ON(1); + return NULL; + } + + if (early_ioremap_debug) { + pr_info("%s(%08llx, %08lx) [%d] => ", + __func__, (u64)phys_addr, size, slot); + dump_stack(); + } + + /* 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 - NR_FIX_BTMAPS*slot; + while (nrpages > 0) { + if (after_paging_init) + __late_set_fixmap(idx, phys_addr, prot); + else + __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) +{ + return __early_ioremap(phys_addr, size, FIXMAP_PAGE_IO); +} + +/* Remap memory */ +void __init __iomem * +early_memremap(resource_size_t phys_addr, unsigned long size) +{ + return __early_ioremap(phys_addr, size, FIXMAP_PAGE_NORMAL); +} + +void __init early_iounmap(void __iomem *addr, unsigned long size) +{ + unsigned long virt_addr; + unsigned long offset; + unsigned int nrpages; + enum fixed_addresses idx; + int i, slot; + + 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); + dump_stack(); + } + + 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 - NR_FIX_BTMAPS*slot; + while (nrpages > 0) { + if (after_paging_init) + __late_clear_fixmap(idx); + else + __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR); + --idx; + --nrpages; + } + prev_map[slot] = NULL; +} -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 1/4] Create generic early_ioremap() support 2013-11-28 2:44 ` [PATCH 1/4] Create generic early_ioremap() support Mark Salter @ 2013-11-28 2:44 ` Mark Salter 2013-12-16 1:48 ` Dave Young 1 sibling, 0 replies; 11+ messages in thread From: Mark Salter @ 2013-11-28 2:44 UTC (permalink / raw) To: linux-kernel Cc: Leif Lindholm, Mark Salter, Arnd Bergmann, Ingo Molnar, linux-arch This patch copies generic bits of x86 early_ioremap() support into a library for potential use by other architectures. Signed-off-by: Mark Salter <msalter@redhat.com> CC: Arnd Bergmann <arnd@arndb.de> CC: Ingo Molnar <mingo@kernel.org> CC: linux-arch@vger.kernel.org --- include/asm-generic/early_ioremap.h | 40 ++++++ lib/Kconfig | 3 + lib/Makefile | 1 + lib/early_ioremap.c | 243 ++++++++++++++++++++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 include/asm-generic/early_ioremap.h create mode 100644 lib/early_ioremap.c diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h new file mode 100644 index 0000000..e26ce80 --- /dev/null +++ b/include/asm-generic/early_ioremap.h @@ -0,0 +1,40 @@ +#ifndef _ASM_EARLY_IOREMAP_H_ +#define _ASM_EARLY_IOREMAP_H_ + +#include <linux/types.h> + +#ifdef CONFIG_GENERIC_EARLY_IOREMAP +/* + * early_ioremap() and early_iounmap() are for temporary early boot-time + * mappings, before the real ioremap() is functional. + */ +extern void __iomem *early_ioremap(resource_size_t phys_addr, + unsigned long size); +extern void __iomem *early_memremap(resource_size_t phys_addr, + unsigned long size); +extern void early_iounmap(void __iomem *addr, unsigned long size); + +/* Arch-specific initialization */ +extern void early_ioremap_init(void); + +/* Generic initialization called by architecture code */ +extern void early_ioremap_setup(void); + +/* + * Called as last step in paging_init() so library can act + * accordingly for subsequent map/unmap requests. + */ +extern void early_ioremap_reset(void); + +/* + * Weak function called by early_ioremap_reset(). It does nothing, but + * architectures may provide their own version to do any needed cleanups. + */ +extern void early_ioremap_shutdown(void); +#else +static inline void early_ioremap_init(void) { } +static inline void early_ioremap_setup(void) { } +static inline void early_ioremap_reset(void) { } +#endif + +#endif /* _ASM_EARLY_IOREMAP_H_ */ diff --git a/lib/Kconfig b/lib/Kconfig index 991c98b..5ebee09 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -42,6 +42,9 @@ config GENERIC_IO boolean default n +config GENERIC_EARLY_IOREMAP + bool + config STMP_DEVICE bool diff --git a/lib/Makefile b/lib/Makefile index a459c31..2afe05d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -188,3 +188,4 @@ quiet_cmd_build_OID_registry = GEN $@ clean-files += oid_registry_data.c obj-$(CONFIG_UCS2_STRING) += ucs2_string.o +obj-$(CONFIG_GENERIC_EARLY_IOREMAP) += early_ioremap.o diff --git a/lib/early_ioremap.c b/lib/early_ioremap.c new file mode 100644 index 0000000..54623a7 --- /dev/null +++ b/lib/early_ioremap.c @@ -0,0 +1,243 @@ +/* + * Provide common bits of early_ioremap() support for architectures needing + * temporary mappings during boot before ioremap() is available. + * + * This is mostly a direct copy of the x86 early_ioremap implementation. + * + * (C) Copyright 1995 1996 Linus Torvalds + * + */ +#include <linux/init.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <asm/fixmap.h> + +static int early_ioremap_debug __initdata; + +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 int after_paging_init __initdata; + +void __init __attribute__((weak)) early_ioremap_shutdown(void) +{ +} + +void __init early_ioremap_reset(void) +{ + early_ioremap_shutdown(); + after_paging_init = 1; +} + +/* + * Generally, ioremap() is available after paging_init() has been called. + * Architectures wanting to allow early_ioremap after paging_init() can + * define __late_set_fixmap and __late_clear_fixmap to do the right thing. + */ +#ifndef __late_set_fixmap +static inline void __init __late_set_fixmap(enum fixed_addresses idx, + phys_addr_t phys, pgprot_t prot) +{ + BUG(); +} +#endif + +#ifndef __late_clear_fixmap +static inline void __init __late_clear_fixmap(enum fixed_addresses idx) +{ + BUG(); +} +#endif + +static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata; +static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata; +static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata; + +void __init early_ioremap_setup(void) +{ + int i; + + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { + if (prev_map[i]) { + WARN_ON(1); + break; + } + } + + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) + slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i); +} + +static int __init check_early_ioremap_leak(void) +{ + int count = 0; + int i; + + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) + if (prev_map[i]) + count++; + + if (!count) + return 0; + WARN(1, KERN_WARNING + "Debug warning: early ioremap leak of %d areas detected.\n", + count); + pr_warn("please boot with early_ioremap_debug and report the dmesg.\n"); + + return 1; +} +late_initcall(check_early_ioremap_leak); + +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; + enum fixed_addresses idx; + int i, slot; + + WARN_ON(system_state != SYSTEM_BOOTING); + + slot = -1; + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { + if (!prev_map[i]) { + slot = i; + break; + } + } + + if (slot < 0) { + pr_info("%s(%08llx, %08lx) not found slot\n", + __func__, (u64)phys_addr, size); + WARN_ON(1); + return NULL; + } + + if (early_ioremap_debug) { + pr_info("%s(%08llx, %08lx) [%d] => ", + __func__, (u64)phys_addr, size, slot); + dump_stack(); + } + + /* 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 - NR_FIX_BTMAPS*slot; + while (nrpages > 0) { + if (after_paging_init) + __late_set_fixmap(idx, phys_addr, prot); + else + __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) +{ + return __early_ioremap(phys_addr, size, FIXMAP_PAGE_IO); +} + +/* Remap memory */ +void __init __iomem * +early_memremap(resource_size_t phys_addr, unsigned long size) +{ + return __early_ioremap(phys_addr, size, FIXMAP_PAGE_NORMAL); +} + +void __init early_iounmap(void __iomem *addr, unsigned long size) +{ + unsigned long virt_addr; + unsigned long offset; + unsigned int nrpages; + enum fixed_addresses idx; + int i, slot; + + 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); + dump_stack(); + } + + 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 - NR_FIX_BTMAPS*slot; + while (nrpages > 0) { + if (after_paging_init) + __late_clear_fixmap(idx); + else + __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR); + --idx; + --nrpages; + } + prev_map[slot] = NULL; +} -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/4] Create generic early_ioremap() support 2013-11-28 2:44 ` [PATCH 1/4] Create generic early_ioremap() support Mark Salter 2013-11-28 2:44 ` Mark Salter @ 2013-12-16 1:48 ` Dave Young 2013-12-17 18:45 ` Mark Salter 1 sibling, 1 reply; 11+ messages in thread From: Dave Young @ 2013-12-16 1:48 UTC (permalink / raw) To: Mark Salter Cc: linux-kernel, Leif Lindholm, Arnd Bergmann, Ingo Molnar, linux-arch On 11/27/13 at 09:44pm, Mark Salter wrote: > This patch copies generic bits of x86 early_ioremap() support > into a library for potential use by other architectures. > > Signed-off-by: Mark Salter <msalter@redhat.com> > CC: Arnd Bergmann <arnd@arndb.de> > CC: Ingo Molnar <mingo@kernel.org> > CC: linux-arch@vger.kernel.org > --- > include/asm-generic/early_ioremap.h | 40 ++++++ > lib/Kconfig | 3 + > lib/Makefile | 1 + > lib/early_ioremap.c | 243 ++++++++++++++++++++++++++++++++++++ I do not understand why these should go to lib/, I feel it's slightly better move them to mm/ ditto about lib/ioremap.c, ... > 4 files changed, 287 insertions(+) > create mode 100644 include/asm-generic/early_ioremap.h > create mode 100644 lib/early_ioremap.c > > diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h > new file mode 100644 > index 0000000..e26ce80 > --- /dev/null > +++ b/include/asm-generic/early_ioremap.h > @@ -0,0 +1,40 @@ > +#ifndef _ASM_EARLY_IOREMAP_H_ > +#define _ASM_EARLY_IOREMAP_H_ > + > +#include <linux/types.h> > + > +#ifdef CONFIG_GENERIC_EARLY_IOREMAP > +/* > + * early_ioremap() and early_iounmap() are for temporary early boot-time > + * mappings, before the real ioremap() is functional. > + */ > +extern void __iomem *early_ioremap(resource_size_t phys_addr, > + unsigned long size); > +extern void __iomem *early_memremap(resource_size_t phys_addr, > + unsigned long size); > +extern void early_iounmap(void __iomem *addr, unsigned long size); > + > +/* Arch-specific initialization */ > +extern void early_ioremap_init(void); > + > +/* Generic initialization called by architecture code */ > +extern void early_ioremap_setup(void); > + > +/* > + * Called as last step in paging_init() so library can act > + * accordingly for subsequent map/unmap requests. > + */ > +extern void early_ioremap_reset(void); > + > +/* > + * Weak function called by early_ioremap_reset(). It does nothing, but > + * architectures may provide their own version to do any needed cleanups. > + */ > +extern void early_ioremap_shutdown(void); > +#else > +static inline void early_ioremap_init(void) { } > +static inline void early_ioremap_setup(void) { } > +static inline void early_ioremap_reset(void) { } > +#endif > + > +#endif /* _ASM_EARLY_IOREMAP_H_ */ > diff --git a/lib/Kconfig b/lib/Kconfig > index 991c98b..5ebee09 100644 > --- a/lib/Kconfig > +++ b/lib/Kconfig > @@ -42,6 +42,9 @@ config GENERIC_IO > boolean > default n > > +config GENERIC_EARLY_IOREMAP > + bool > + > config STMP_DEVICE > bool > > diff --git a/lib/Makefile b/lib/Makefile > index a459c31..2afe05d 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -188,3 +188,4 @@ quiet_cmd_build_OID_registry = GEN $@ > clean-files += oid_registry_data.c > > obj-$(CONFIG_UCS2_STRING) += ucs2_string.o > +obj-$(CONFIG_GENERIC_EARLY_IOREMAP) += early_ioremap.o > diff --git a/lib/early_ioremap.c b/lib/early_ioremap.c > new file mode 100644 > index 0000000..54623a7 > --- /dev/null > +++ b/lib/early_ioremap.c > @@ -0,0 +1,243 @@ > +/* > + * Provide common bits of early_ioremap() support for architectures needing > + * temporary mappings during boot before ioremap() is available. > + * > + * This is mostly a direct copy of the x86 early_ioremap implementation. > + * > + * (C) Copyright 1995 1996 Linus Torvalds > + * > + */ > +#include <linux/init.h> > +#include <linux/io.h> > +#include <linux/module.h> > +#include <linux/slab.h> > +#include <linux/mm.h> > +#include <linux/vmalloc.h> > +#include <asm/fixmap.h> > + > +static int early_ioremap_debug __initdata; > + > +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 int after_paging_init __initdata; > + > +void __init __attribute__((weak)) early_ioremap_shutdown(void) > +{ > +} > + > +void __init early_ioremap_reset(void) > +{ > + early_ioremap_shutdown(); > + after_paging_init = 1; > +} > + > +/* > + * Generally, ioremap() is available after paging_init() has been called. > + * Architectures wanting to allow early_ioremap after paging_init() can > + * define __late_set_fixmap and __late_clear_fixmap to do the right thing. > + */ > +#ifndef __late_set_fixmap > +static inline void __init __late_set_fixmap(enum fixed_addresses idx, > + phys_addr_t phys, pgprot_t prot) > +{ > + BUG(); > +} > +#endif > + > +#ifndef __late_clear_fixmap > +static inline void __init __late_clear_fixmap(enum fixed_addresses idx) > +{ > + BUG(); > +} > +#endif > + > +static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata; > +static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata; > +static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata; > + > +void __init early_ioremap_setup(void) > +{ > + int i; > + > + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { > + if (prev_map[i]) { > + WARN_ON(1); > + break; > + } > + } > + > + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) > + slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i); > +} > + > +static int __init check_early_ioremap_leak(void) > +{ > + int count = 0; > + int i; > + > + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) > + if (prev_map[i]) > + count++; > + > + if (!count) > + return 0; > + WARN(1, KERN_WARNING > + "Debug warning: early ioremap leak of %d areas detected.\n", > + count); > + pr_warn("please boot with early_ioremap_debug and report the dmesg.\n"); > + > + return 1; > +} > +late_initcall(check_early_ioremap_leak); > + > +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; > + enum fixed_addresses idx; > + int i, slot; > + > + WARN_ON(system_state != SYSTEM_BOOTING); > + > + slot = -1; > + for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { > + if (!prev_map[i]) { > + slot = i; > + break; > + } > + } > + > + if (slot < 0) { > + pr_info("%s(%08llx, %08lx) not found slot\n", > + __func__, (u64)phys_addr, size); > + WARN_ON(1); > + return NULL; > + } > + > + if (early_ioremap_debug) { > + pr_info("%s(%08llx, %08lx) [%d] => ", > + __func__, (u64)phys_addr, size, slot); > + dump_stack(); > + } > + > + /* 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 - NR_FIX_BTMAPS*slot; > + while (nrpages > 0) { > + if (after_paging_init) > + __late_set_fixmap(idx, phys_addr, prot); > + else > + __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) > +{ > + return __early_ioremap(phys_addr, size, FIXMAP_PAGE_IO); > +} > + > +/* Remap memory */ > +void __init __iomem * > +early_memremap(resource_size_t phys_addr, unsigned long size) > +{ > + return __early_ioremap(phys_addr, size, FIXMAP_PAGE_NORMAL); > +} > + > +void __init early_iounmap(void __iomem *addr, unsigned long size) > +{ > + unsigned long virt_addr; > + unsigned long offset; > + unsigned int nrpages; > + enum fixed_addresses idx; > + int i, slot; > + > + 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); > + dump_stack(); > + } > + > + 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 - NR_FIX_BTMAPS*slot; > + while (nrpages > 0) { > + if (after_paging_init) > + __late_clear_fixmap(idx); > + else > + __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR); > + --idx; > + --nrpages; > + } > + prev_map[slot] = NULL; > +} > -- > 1.8.3.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/4] Create generic early_ioremap() support 2013-12-16 1:48 ` Dave Young @ 2013-12-17 18:45 ` Mark Salter 2013-12-17 18:45 ` Mark Salter 2013-12-18 9:13 ` Dave Young 0 siblings, 2 replies; 11+ messages in thread From: Mark Salter @ 2013-12-17 18:45 UTC (permalink / raw) To: Dave Young Cc: linux-kernel, Leif Lindholm, Arnd Bergmann, Ingo Molnar, linux-arch On Mon, 2013-12-16 at 09:48 +0800, Dave Young wrote: > On 11/27/13 at 09:44pm, Mark Salter wrote: > > This patch copies generic bits of x86 early_ioremap() support > > into a library for potential use by other architectures. > > > > Signed-off-by: Mark Salter <msalter@redhat.com> > > CC: Arnd Bergmann <arnd@arndb.de> > > CC: Ingo Molnar <mingo@kernel.org> > > CC: linux-arch@vger.kernel.org > > --- > > include/asm-generic/early_ioremap.h | 40 ++++++ > > lib/Kconfig | 3 + > > lib/Makefile | 1 + > > lib/early_ioremap.c | 243 > ++++++++++++++++++++++++++++++++++++ > > I do not understand why these should go to lib/, I feel it's slightly better > move them to mm/ > > ditto about lib/ioremap.c, ... > I hadn't really thought about it. Putting these things in mm doesn't sound unreasonable, but lib seems to have become the place for a lot generic code which could also belong in mm, net, etc. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/4] Create generic early_ioremap() support 2013-12-17 18:45 ` Mark Salter @ 2013-12-17 18:45 ` Mark Salter 2013-12-18 9:13 ` Dave Young 1 sibling, 0 replies; 11+ messages in thread From: Mark Salter @ 2013-12-17 18:45 UTC (permalink / raw) To: Dave Young Cc: linux-kernel, Leif Lindholm, Arnd Bergmann, Ingo Molnar, linux-arch On Mon, 2013-12-16 at 09:48 +0800, Dave Young wrote: > On 11/27/13 at 09:44pm, Mark Salter wrote: > > This patch copies generic bits of x86 early_ioremap() support > > into a library for potential use by other architectures. > > > > Signed-off-by: Mark Salter <msalter@redhat.com> > > CC: Arnd Bergmann <arnd@arndb.de> > > CC: Ingo Molnar <mingo@kernel.org> > > CC: linux-arch@vger.kernel.org > > --- > > include/asm-generic/early_ioremap.h | 40 ++++++ > > lib/Kconfig | 3 + > > lib/Makefile | 1 + > > lib/early_ioremap.c | 243 > ++++++++++++++++++++++++++++++++++++ > > I do not understand why these should go to lib/, I feel it's slightly better > move them to mm/ > > ditto about lib/ioremap.c, ... > I hadn't really thought about it. Putting these things in mm doesn't sound unreasonable, but lib seems to have become the place for a lot generic code which could also belong in mm, net, etc. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/4] Create generic early_ioremap() support 2013-12-17 18:45 ` Mark Salter 2013-12-17 18:45 ` Mark Salter @ 2013-12-18 9:13 ` Dave Young 2013-12-18 9:13 ` Dave Young 2013-12-18 10:40 ` Arnd Bergmann 1 sibling, 2 replies; 11+ messages in thread From: Dave Young @ 2013-12-18 9:13 UTC (permalink / raw) To: Mark Salter Cc: linux-kernel, Leif Lindholm, Arnd Bergmann, Ingo Molnar, linux-arch On 12/17/13 at 01:45pm, Mark Salter wrote: > On Mon, 2013-12-16 at 09:48 +0800, Dave Young wrote: > > On 11/27/13 at 09:44pm, Mark Salter wrote: > > > This patch copies generic bits of x86 early_ioremap() support > > > into a library for potential use by other architectures. > > > > > > Signed-off-by: Mark Salter <msalter@redhat.com> > > > CC: Arnd Bergmann <arnd@arndb.de> > > > CC: Ingo Molnar <mingo@kernel.org> > > > CC: linux-arch@vger.kernel.org > > > --- > > > include/asm-generic/early_ioremap.h | 40 ++++++ > > > lib/Kconfig | 3 + > > > lib/Makefile | 1 + > > > lib/early_ioremap.c | 243 > > ++++++++++++++++++++++++++++++++++++ > > > > I do not understand why these should go to lib/, I feel it's slightly better > > move them to mm/ > > > > ditto about lib/ioremap.c, ... > > > > I hadn't really thought about it. Putting these things in mm doesn't > sound unreasonable, but lib seems to have become the place for a lot > generic code which could also belong in mm, net, etc. > IMHO, move subsystem lib code to subsystem core dir looks more reasonable. lib should be the place for general kernel stuff. I'm not specific for and object this patch, just give my opinion about the lib/.. Thanks Dave ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/4] Create generic early_ioremap() support 2013-12-18 9:13 ` Dave Young @ 2013-12-18 9:13 ` Dave Young 2013-12-18 10:40 ` Arnd Bergmann 1 sibling, 0 replies; 11+ messages in thread From: Dave Young @ 2013-12-18 9:13 UTC (permalink / raw) To: Mark Salter Cc: linux-kernel, Leif Lindholm, Arnd Bergmann, Ingo Molnar, linux-arch On 12/17/13 at 01:45pm, Mark Salter wrote: > On Mon, 2013-12-16 at 09:48 +0800, Dave Young wrote: > > On 11/27/13 at 09:44pm, Mark Salter wrote: > > > This patch copies generic bits of x86 early_ioremap() support > > > into a library for potential use by other architectures. > > > > > > Signed-off-by: Mark Salter <msalter@redhat.com> > > > CC: Arnd Bergmann <arnd@arndb.de> > > > CC: Ingo Molnar <mingo@kernel.org> > > > CC: linux-arch@vger.kernel.org > > > --- > > > include/asm-generic/early_ioremap.h | 40 ++++++ > > > lib/Kconfig | 3 + > > > lib/Makefile | 1 + > > > lib/early_ioremap.c | 243 > > ++++++++++++++++++++++++++++++++++++ > > > > I do not understand why these should go to lib/, I feel it's slightly better > > move them to mm/ > > > > ditto about lib/ioremap.c, ... > > > > I hadn't really thought about it. Putting these things in mm doesn't > sound unreasonable, but lib seems to have become the place for a lot > generic code which could also belong in mm, net, etc. > IMHO, move subsystem lib code to subsystem core dir looks more reasonable. lib should be the place for general kernel stuff. I'm not specific for and object this patch, just give my opinion about the lib/.. Thanks Dave ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/4] Create generic early_ioremap() support 2013-12-18 9:13 ` Dave Young 2013-12-18 9:13 ` Dave Young @ 2013-12-18 10:40 ` Arnd Bergmann 2013-12-18 10:40 ` Arnd Bergmann 1 sibling, 1 reply; 11+ messages in thread From: Arnd Bergmann @ 2013-12-18 10:40 UTC (permalink / raw) To: Dave Young Cc: Mark Salter, linux-kernel, Leif Lindholm, Ingo Molnar, linux-arch On Wednesday 18 December 2013, Dave Young wrote: > > > > I hadn't really thought about it. Putting these things in mm doesn't > > sound unreasonable, but lib seems to have become the place for a lot > > generic code which could also belong in mm, net, etc. > > > > IMHO, move subsystem lib code to subsystem core dir looks more reasonable. > lib should be the place for general kernel stuff. > > I'm not specific for and object this patch, just give my opinion about the lib/.. Traditionally, lib/ is for things that may or may not be used by other optional code, typically drivers, which I think is a reasonable concept. There has been some shift over the years from lib-$(CONFIG_FOO) towards obj-$(CONFIG_FOO), so it's not always used as a actual library code in the linker sense though. I would agree that moving mm related code such as early_ioremap into mm/ is a good idea. For things like the compression helpers lib/ is probably still the best place. Arnd ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/4] Create generic early_ioremap() support 2013-12-18 10:40 ` Arnd Bergmann @ 2013-12-18 10:40 ` Arnd Bergmann 0 siblings, 0 replies; 11+ messages in thread From: Arnd Bergmann @ 2013-12-18 10:40 UTC (permalink / raw) To: Dave Young Cc: Mark Salter, linux-kernel, Leif Lindholm, Ingo Molnar, linux-arch On Wednesday 18 December 2013, Dave Young wrote: > > > > I hadn't really thought about it. Putting these things in mm doesn't > > sound unreasonable, but lib seems to have become the place for a lot > > generic code which could also belong in mm, net, etc. > > > > IMHO, move subsystem lib code to subsystem core dir looks more reasonable. > lib should be the place for general kernel stuff. > > I'm not specific for and object this patch, just give my opinion about the lib/.. Traditionally, lib/ is for things that may or may not be used by other optional code, typically drivers, which I think is a reasonable concept. There has been some shift over the years from lib-$(CONFIG_FOO) towards obj-$(CONFIG_FOO), so it's not always used as a actual library code in the linker sense though. I would agree that moving mm related code such as early_ioremap into mm/ is a good idea. For things like the compression helpers lib/ is probably still the best place. Arnd ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2013-12-18 10:40 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-11-28 2:44 [PATCH 0/4] generic early_ioremap support Mark Salter 2013-11-28 2:44 ` Mark Salter 2013-11-28 2:44 ` [PATCH 1/4] Create generic early_ioremap() support Mark Salter 2013-11-28 2:44 ` Mark Salter 2013-12-16 1:48 ` Dave Young 2013-12-17 18:45 ` Mark Salter 2013-12-17 18:45 ` Mark Salter 2013-12-18 9:13 ` Dave Young 2013-12-18 9:13 ` Dave Young 2013-12-18 10:40 ` Arnd Bergmann 2013-12-18 10:40 ` Arnd Bergmann
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox