From b3ba41f28f7fe147c23bfadf6280b3492c9696b1 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Sat, 23 Nov 2013 14:36:42 -0500 Subject: ARM: mm: Fix max_mapnr with recent max*pfn updates With commit 26ba47b1 {ARM: 7805/1: mm: change max*pfn to include the physical offset of memory}, the max_pfn already contain PHYS_PFN_OFFSET, so it shouldn't be taken into account again. While at it, use use set_max_mapnr() helper. Cc: Russell King Cc: Catalin Marinas Cc: Nicolas Pitre Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- arch/arm/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 3e8f106ee5f..4c7bab44bf5 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -587,7 +587,7 @@ void __init mem_init(void) extern u32 itcm_end; #endif - max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map; + set_max_mapnr(pfn_to_page(max_pfn) - mem_map); /* this will put all unused low memory onto the freelists */ free_unused_memmap(&meminfo); -- cgit v1.2.3-18-g5258 From 8e58caefd96c8ee249ab26a2fe00aab3785df9ea Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Sat, 23 Nov 2013 14:42:18 -0500 Subject: ARM: mm: Don't allow resizing of memblock data until "low" memory is not mapped If allowed by call to memblock_allow_resize() - The Memblock core will try to allocate additional memory and rearrange its internal data in case, if there are more then INIT_MEMBLOCK_REGIONS(128) memory regions of any type have been allocated. If this happens before Low memory is mapped (which is done now by map_lowmem()) the system will hang, because the Memblock core will try to operate with virtual addresses which aren't mapped yet. In ARM code, the memblock resizing is allowed (memblock_allow_resize()) from arm_memblock_init() which is called before map_lowmem(), so this may lead to an error as described above. Hence, allow Memblock resizing later during init, from bootmem_init() when all appropriate mappings are ready. Cc: Russell King Cc: Catalin Marinas Cc: Nicolas Pitre Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- arch/arm/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 4c7bab44bf5..ea66341779d 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -384,7 +384,6 @@ void __init arm_memblock_init(struct meminfo *mi, dma_contiguous_reserve(min(arm_dma_limit, arm_lowmem_limit)); arm_memblock_steal_permitted = false; - memblock_allow_resize(); memblock_dump_all(); } @@ -392,6 +391,7 @@ void __init bootmem_init(void) { unsigned long min, max_low, max_high; + memblock_allow_resize(); max_low = max_high = 0; find_limits(&min, &max_low, &max_high); -- cgit v1.2.3-18-g5258 From 84f452b1e8fc73ac0e31254c66e3e2260ce5263d Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Sun, 30 Jun 2013 00:28:46 -0400 Subject: ARM: mm: Remove bootmem code and switch to NO_BOOTMEM Now with dma_mask series merged and max*pfn has consistent meaning on ARM as rest of the arch's thanks to RMK's mega series, lets switch ARM code to NO_BOOTMEM. With NO_BOOTMEM change, now we use memblock allocator to reserve space for crash kernel to have one less dependency with nobootmem allocator wrapper. Tested with both flat memory and sparse (faked) memory models with highmem enabled. Cc: Russell King Cc: Catalin Marinas Cc: Nicolas Pitre Signed-off-by: Santosh Shilimkar --- arch/arm/Kconfig | 1 + arch/arm/kernel/setup.c | 2 +- arch/arm/mm/init.c | 58 ++----------------------------------------------- 3 files changed, 4 insertions(+), 57 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c1f1a7eee95..51411dbff40 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -62,6 +62,7 @@ config ARM select IRQ_FORCED_THREADING select KTIME_SCALAR select MODULES_USE_ELF_REL + select NO_BOOTMEM select OLD_SIGACTION select OLD_SIGSUSPEND3 select PERF_USE_VMALLOC diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 6a1b8a81b1a..e9f629f2176 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -817,7 +817,7 @@ static void __init reserve_crashkernel(void) if (ret) return; - ret = reserve_bootmem(crash_base, crash_size, BOOTMEM_EXCLUSIVE); + ret = memblock_reserve(crash_base, crash_size); if (ret < 0) { printk(KERN_WARNING "crashkernel reservation failed - " "memory is in use (0x%lx)\n", (unsigned long)crash_base); diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index ea66341779d..6dd66a999d9 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -145,58 +145,6 @@ static void __init find_limits(unsigned long *min, unsigned long *max_low, *max_high = bank_pfn_end(&mi->bank[mi->nr_banks - 1]); } -static void __init arm_bootmem_init(unsigned long start_pfn, - unsigned long end_pfn) -{ - struct memblock_region *reg; - unsigned int boot_pages; - phys_addr_t bitmap; - pg_data_t *pgdat; - - /* - * Allocate the bootmem bitmap page. This must be in a region - * of memory which has already been mapped. - */ - boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); - bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES, - __pfn_to_phys(end_pfn)); - - /* - * Initialise the bootmem allocator, handing the - * memory banks over to bootmem. - */ - node_set_online(0); - pgdat = NODE_DATA(0); - init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn); - - /* Free the lowmem regions from memblock into bootmem. */ - for_each_memblock(memory, reg) { - unsigned long start = memblock_region_memory_base_pfn(reg); - unsigned long end = memblock_region_memory_end_pfn(reg); - - if (end >= end_pfn) - end = end_pfn; - if (start >= end) - break; - - free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT); - } - - /* Reserve the lowmem memblock reserved regions in bootmem. */ - for_each_memblock(reserved, reg) { - unsigned long start = memblock_region_reserved_base_pfn(reg); - unsigned long end = memblock_region_reserved_end_pfn(reg); - - if (end >= end_pfn) - end = end_pfn; - if (start >= end) - break; - - reserve_bootmem(__pfn_to_phys(start), - (end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT); - } -} - #ifdef CONFIG_ZONE_DMA phys_addr_t arm_dma_zone_size __read_mostly; @@ -236,7 +184,7 @@ void __init setup_dma_zone(const struct machine_desc *mdesc) #endif } -static void __init arm_bootmem_free(unsigned long min, unsigned long max_low, +static void __init zone_sizes_init(unsigned long min, unsigned long max_low, unsigned long max_high) { unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; @@ -396,8 +344,6 @@ void __init bootmem_init(void) find_limits(&min, &max_low, &max_high); - arm_bootmem_init(min, max_low); - /* * Sparsemem tries to allocate bootmem in memory_present(), * so must be done after the fixed reservations @@ -414,7 +360,7 @@ void __init bootmem_init(void) * the sparse mem_map arrays initialized by sparse_init() * for memmap_init_zone(), otherwise all PFNs are invalid. */ - arm_bootmem_free(min, max_low, max_high); + zone_sizes_init(min, max_low, max_high); /* * This doesn't seem to be used by the Linux memory manager any -- cgit v1.2.3-18-g5258 From 26825cfd90f94f47068519901b3670ae7da320fe Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 9 Dec 2013 10:38:20 +0100 Subject: ARM: 7914/1: amba: Drop legacy PM support and use the pm_generic functions All AMBA drivers have converted to use the modern PM ops thus we can safely drop the legacy PM support from the bus. While using the modern PM ops it also makes sense to convert to use the pm_generic callback functions. Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/amba/bus.c | 180 +++-------------------------------------------------- 1 file changed, 7 insertions(+), 173 deletions(-) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index c4876ac9151..b90dc1ec109 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -83,162 +83,6 @@ static struct device_attribute amba_dev_attrs[] = { __ATTR_NULL, }; -#ifdef CONFIG_PM_SLEEP - -static int amba_legacy_suspend(struct device *dev, pm_message_t mesg) -{ - struct amba_driver *adrv = to_amba_driver(dev->driver); - struct amba_device *adev = to_amba_device(dev); - int ret = 0; - - if (dev->driver && adrv->suspend) - ret = adrv->suspend(adev, mesg); - - return ret; -} - -static int amba_legacy_resume(struct device *dev) -{ - struct amba_driver *adrv = to_amba_driver(dev->driver); - struct amba_device *adev = to_amba_device(dev); - int ret = 0; - - if (dev->driver && adrv->resume) - ret = adrv->resume(adev); - - return ret; -} - -#endif /* CONFIG_PM_SLEEP */ - -#ifdef CONFIG_SUSPEND - -static int amba_pm_suspend(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->suspend) - ret = drv->pm->suspend(dev); - } else { - ret = amba_legacy_suspend(dev, PMSG_SUSPEND); - } - - return ret; -} - -static int amba_pm_resume(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->resume) - ret = drv->pm->resume(dev); - } else { - ret = amba_legacy_resume(dev); - } - - return ret; -} - -#else /* !CONFIG_SUSPEND */ - -#define amba_pm_suspend NULL -#define amba_pm_resume NULL - -#endif /* !CONFIG_SUSPEND */ - -#ifdef CONFIG_HIBERNATE_CALLBACKS - -static int amba_pm_freeze(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->freeze) - ret = drv->pm->freeze(dev); - } else { - ret = amba_legacy_suspend(dev, PMSG_FREEZE); - } - - return ret; -} - -static int amba_pm_thaw(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->thaw) - ret = drv->pm->thaw(dev); - } else { - ret = amba_legacy_resume(dev); - } - - return ret; -} - -static int amba_pm_poweroff(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->poweroff) - ret = drv->pm->poweroff(dev); - } else { - ret = amba_legacy_suspend(dev, PMSG_HIBERNATE); - } - - return ret; -} - -static int amba_pm_restore(struct device *dev) -{ - struct device_driver *drv = dev->driver; - int ret = 0; - - if (!drv) - return 0; - - if (drv->pm) { - if (drv->pm->restore) - ret = drv->pm->restore(dev); - } else { - ret = amba_legacy_resume(dev); - } - - return ret; -} - -#else /* !CONFIG_HIBERNATE_CALLBACKS */ - -#define amba_pm_freeze NULL -#define amba_pm_thaw NULL -#define amba_pm_poweroff NULL -#define amba_pm_restore NULL - -#endif /* !CONFIG_HIBERNATE_CALLBACKS */ - #ifdef CONFIG_PM_RUNTIME /* * Hooks to provide runtime PM of the pclk (bus clock). It is safe to @@ -272,15 +116,13 @@ static int amba_pm_runtime_resume(struct device *dev) } #endif -#ifdef CONFIG_PM - static const struct dev_pm_ops amba_pm = { - .suspend = amba_pm_suspend, - .resume = amba_pm_resume, - .freeze = amba_pm_freeze, - .thaw = amba_pm_thaw, - .poweroff = amba_pm_poweroff, - .restore = amba_pm_restore, + .suspend = pm_generic_suspend, + .resume = pm_generic_resume, + .freeze = pm_generic_freeze, + .thaw = pm_generic_thaw, + .poweroff = pm_generic_poweroff, + .restore = pm_generic_restore, SET_RUNTIME_PM_OPS( amba_pm_runtime_suspend, amba_pm_runtime_resume, @@ -288,14 +130,6 @@ static const struct dev_pm_ops amba_pm = { ) }; -#define AMBA_PM (&amba_pm) - -#else /* !CONFIG_PM */ - -#define AMBA_PM NULL - -#endif /* !CONFIG_PM */ - /* * Primecells are part of the Advanced Microcontroller Bus Architecture, * so we call the bus "amba". @@ -305,7 +139,7 @@ struct bus_type amba_bustype = { .dev_attrs = amba_dev_attrs, .match = amba_match, .uevent = amba_uevent, - .pm = AMBA_PM, + .pm = &amba_pm, }; static int __init amba_init(void) -- cgit v1.2.3-18-g5258 From 89a5c985f81a0b60f7522044938f76caf28075a6 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 9 Dec 2013 10:39:13 +0100 Subject: ARM: 7915/1: amba: Convert to clk_prepare_enable and clk_disable_unprepare To simplify code and error handling let's use clk_prepare_enable and clk_disable_unprepare. No functional change. Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/amba/bus.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index b90dc1ec109..ea1d8357f29 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -151,36 +151,23 @@ postcore_initcall(amba_init); static int amba_get_enable_pclk(struct amba_device *pcdev) { - struct clk *pclk = clk_get(&pcdev->dev, "apb_pclk"); int ret; - pcdev->pclk = pclk; + pcdev->pclk = clk_get(&pcdev->dev, "apb_pclk"); + if (IS_ERR(pcdev->pclk)) + return PTR_ERR(pcdev->pclk); - if (IS_ERR(pclk)) - return PTR_ERR(pclk); - - ret = clk_prepare(pclk); - if (ret) { - clk_put(pclk); - return ret; - } - - ret = clk_enable(pclk); - if (ret) { - clk_unprepare(pclk); - clk_put(pclk); - } + ret = clk_prepare_enable(pcdev->pclk); + if (ret) + clk_put(pcdev->pclk); return ret; } static void amba_put_disable_pclk(struct amba_device *pcdev) { - struct clk *pclk = pcdev->pclk; - - clk_disable(pclk); - clk_unprepare(pclk); - clk_put(pclk); + clk_disable_unprepare(pcdev->pclk); + clk_put(pcdev->pclk); } /* -- cgit v1.2.3-18-g5258 From 5303c0f46c8708fff4148ebcc491f78710356952 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 9 Dec 2013 10:40:22 +0100 Subject: ARM: 7916/1: amba: Add clk_prepare|unprepare in runtime PM callbacks To fully gate the clock and thus potentially also save more power in runtime suspend state, extend clock handling with clk_prepare|unprepare in the runtime PM callbacks. Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/amba/bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index ea1d8357f29..9e602910560 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -95,7 +95,7 @@ static int amba_pm_runtime_suspend(struct device *dev) int ret = pm_generic_runtime_suspend(dev); if (ret == 0 && dev->driver) - clk_disable(pcdev->pclk); + clk_disable_unprepare(pcdev->pclk); return ret; } @@ -106,7 +106,7 @@ static int amba_pm_runtime_resume(struct device *dev) int ret; if (dev->driver) { - ret = clk_enable(pcdev->pclk); + ret = clk_prepare_enable(pcdev->pclk); /* Failure is probably fatal to the system, but... */ if (ret) return ret; -- cgit v1.2.3-18-g5258 From 1fd15b879d0075c8916e52fb9e52522827433d1f Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 23 Oct 2013 16:13:02 +0100 Subject: ARM: add support to dump the kernel page tables This patch allows the kernel page tables to be dumped via a debugfs file, allowing kernel developers to check the layout of the kernel page tables and the verify the various permissions and type settings. Signed-off-by: Russell King --- arch/arm/Kconfig.debug | 12 ++ arch/arm/include/asm/pgtable-2level.h | 1 + arch/arm/include/asm/pgtable-3level.h | 1 + arch/arm/mm/Makefile | 1 + arch/arm/mm/dump.c | 345 ++++++++++++++++++++++++++++++++++ 5 files changed, 360 insertions(+) create mode 100644 arch/arm/mm/dump.c diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 5765abf5ce8..0603a6a5390 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -2,6 +2,18 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config ARM_PTDUMP + bool "Export kernel pagetable layout to userspace via debugfs" + depends on DEBUG_KERNEL + select DEBUG_FS + ---help--- + Say Y here if you want to show the kernel pagetable layout in a + debugfs file. This information is only useful for kernel developers + who are working in architecture specific areas of the kernel. + It is probably not a good idea to enable this feature in a production + kernel. + If in doubt, say "N" + config STRICT_DEVMEM bool "Filter access to /dev/mem" depends on MMU diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h index 86a659a1952..dfff709fda3 100644 --- a/arch/arm/include/asm/pgtable-2level.h +++ b/arch/arm/include/asm/pgtable-2level.h @@ -160,6 +160,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) return (pmd_t *)pud; } +#define pmd_large(pmd) (pmd_val(pmd) & 2) #define pmd_bad(pmd) (pmd_val(pmd) & 2) #define copy_pmd(pmdpd,pmdps) \ diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h index 4f9503908dc..03243f7eedd 100644 --- a/arch/arm/include/asm/pgtable-3level.h +++ b/arch/arm/include/asm/pgtable-3level.h @@ -142,6 +142,7 @@ PMD_TYPE_TABLE) #define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ PMD_TYPE_SECT) +#define pmd_large(pmd) pmd_sect(pmd) #define pud_clear(pudp) \ do { \ diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index ecfe6e53f6e..7f39ce2f841 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -12,6 +12,7 @@ ifneq ($(CONFIG_MMU),y) obj-y += nommu.o endif +obj-$(CONFIG_ARM_PTDUMP) += dump.o obj-$(CONFIG_MODULES) += proc-syms.o obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c new file mode 100644 index 00000000000..2b3a5641427 --- /dev/null +++ b/arch/arm/mm/dump.c @@ -0,0 +1,345 @@ +/* + * Debug helper to dump the current kernel pagetables of the system + * so that we can see what the various memory ranges are set to. + * + * Derived from x86 implementation: + * (C) Copyright 2008 Intel Corporation + * + * Author: Arjan van de Ven + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ +#include +#include +#include +#include + +#include +#include + +struct addr_marker { + unsigned long start_address; + const char *name; +}; + +static struct addr_marker address_markers[] = { + { MODULES_VADDR, "Modules" }, + { PAGE_OFFSET, "Kernel Mapping" }, + { 0, "vmalloc() Area" }, + { VMALLOC_END, "vmalloc() End" }, + { FIXADDR_START, "Fixmap Area" }, + { CONFIG_VECTORS_BASE, "Vectors" }, + { CONFIG_VECTORS_BASE + PAGE_SIZE * 2, "Vectors End" }, + { -1, NULL }, +}; + +struct pg_state { + struct seq_file *seq; + const struct addr_marker *marker; + unsigned long start_address; + unsigned level; + u64 current_prot; +}; + +struct prot_bits { + u64 mask; + u64 val; + const char *set; + const char *clear; +}; + +static const struct prot_bits pte_bits[] = { + { + .mask = L_PTE_USER, + .val = L_PTE_USER, + .set = "USR", + .clear = " ", + }, { + .mask = L_PTE_RDONLY, + .val = L_PTE_RDONLY, + .set = "ro", + .clear = "RW", + }, { + .mask = L_PTE_XN, + .val = L_PTE_XN, + .set = "NX", + .clear = "x ", + }, { + .mask = L_PTE_SHARED, + .val = L_PTE_SHARED, + .set = "SHD", + .clear = " ", + }, { + .mask = L_PTE_MT_MASK, + .val = L_PTE_MT_UNCACHED, + .set = "SO/UNCACHED", + }, { + .mask = L_PTE_MT_MASK, + .val = L_PTE_MT_BUFFERABLE, + .set = "MEM/BUFFERABLE/WC", + }, { + .mask = L_PTE_MT_MASK, + .val = L_PTE_MT_WRITETHROUGH, + .set = "MEM/CACHED/WT", + }, { + .mask = L_PTE_MT_MASK, + .val = L_PTE_MT_WRITEBACK, + .set = "MEM/CACHED/WBRA", +#ifndef CONFIG_ARM_LPAE + }, { + .mask = L_PTE_MT_MASK, + .val = L_PTE_MT_MINICACHE, + .set = "MEM/MINICACHE", +#endif + }, { + .mask = L_PTE_MT_MASK, + .val = L_PTE_MT_WRITEALLOC, + .set = "MEM/CACHED/WBWA", + }, { + .mask = L_PTE_MT_MASK, + .val = L_PTE_MT_DEV_SHARED, + .set = "DEV/SHARED", +#ifndef CONFIG_ARM_LPAE + }, { + .mask = L_PTE_MT_MASK, + .val = L_PTE_MT_DEV_NONSHARED, + .set = "DEV/NONSHARED", +#endif + }, { + .mask = L_PTE_MT_MASK, + .val = L_PTE_MT_DEV_WC, + .set = "DEV/WC", + }, { + .mask = L_PTE_MT_MASK, + .val = L_PTE_MT_DEV_CACHED, + .set = "DEV/CACHED", + }, +}; + +static const struct prot_bits section_bits[] = { +#ifndef CONFIG_ARM_LPAE + /* These are approximate */ + { + .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, + .val = 0, + .set = " ro", + }, { + .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, + .val = PMD_SECT_AP_WRITE, + .set = " RW", + }, { + .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, + .val = PMD_SECT_AP_READ, + .set = "USR ro", + }, { + .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, + .val = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, + .set = "USR RW", +#else + { + .mask = PMD_SECT_USER, + .val = PMD_SECT_USER, + .set = "USR", + }, { + .mask = PMD_SECT_RDONLY, + .val = PMD_SECT_RDONLY, + .set = "ro", + .clear = "RW", +#endif + }, { + .mask = PMD_SECT_XN, + .val = PMD_SECT_XN, + .set = "NX", + .clear = "x ", + }, { + .mask = PMD_SECT_S, + .val = PMD_SECT_S, + .set = "SHD", + .clear = " ", + }, +}; + +struct pg_level { + const struct prot_bits *bits; + size_t num; + u64 mask; +}; + +static struct pg_level pg_level[] = { + { + }, { /* pgd */ + }, { /* pud */ + }, { /* pmd */ + .bits = section_bits, + .num = ARRAY_SIZE(section_bits), + }, { /* pte */ + .bits = pte_bits, + .num = ARRAY_SIZE(pte_bits), + }, +}; + +static void dump_prot(struct pg_state *st, const struct prot_bits *bits, size_t num) +{ + unsigned i; + + for (i = 0; i < num; i++, bits++) { + const char *s; + + if ((st->current_prot & bits->mask) == bits->val) + s = bits->set; + else + s = bits->clear; + + if (s) + seq_printf(st->seq, " %s", s); + } +} + +static void note_page(struct pg_state *st, unsigned long addr, unsigned level, u64 val) +{ + static const char units[] = "KMGTPE"; + u64 prot = val & pg_level[level].mask; + + if (addr < USER_PGTABLES_CEILING) + return; + + if (!st->level) { + st->level = level; + st->current_prot = prot; + seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); + } else if (prot != st->current_prot || level != st->level || + addr >= st->marker[1].start_address) { + const char *unit = units; + unsigned long delta; + + if (st->current_prot) { + seq_printf(st->seq, "0x%08lx-0x%08lx ", + st->start_address, addr); + + delta = (addr - st->start_address) >> 10; + while (!(delta & 1023) && unit[1]) { + delta >>= 10; + unit++; + } + seq_printf(st->seq, "%9lu%c", delta, *unit); + if (pg_level[st->level].bits) + dump_prot(st, pg_level[st->level].bits, pg_level[st->level].num); + seq_printf(st->seq, "\n"); + } + + if (addr >= st->marker[1].start_address) { + st->marker++; + seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); + } + st->start_address = addr; + st->current_prot = prot; + st->level = level; + } +} + +static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start) +{ + pte_t *pte = pte_offset_kernel(pmd, 0); + unsigned long addr; + unsigned i; + + for (i = 0; i < PTRS_PER_PTE; i++, pte++) { + addr = start + i * PAGE_SIZE; + note_page(st, addr, 4, pte_val(*pte)); + } +} + +static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start) +{ + pmd_t *pmd = pmd_offset(pud, 0); + unsigned long addr; + unsigned i; + + for (i = 0; i < PTRS_PER_PMD; i++, pmd++) { + addr = start + i * PMD_SIZE; + if (pmd_none(*pmd) || pmd_large(*pmd) || !pmd_present(*pmd)) + note_page(st, addr, 3, pmd_val(*pmd)); + else + walk_pte(st, pmd, addr); + } +} + +static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start) +{ + pud_t *pud = pud_offset(pgd, 0); + unsigned long addr; + unsigned i; + + for (i = 0; i < PTRS_PER_PUD; i++, pud++) { + addr = start + i * PUD_SIZE; + if (!pud_none(*pud)) { + walk_pmd(st, pud, addr); + } else { + note_page(st, addr, 2, pud_val(*pud)); + } + } +} + +static void walk_pgd(struct seq_file *m) +{ + pgd_t *pgd = swapper_pg_dir; + struct pg_state st; + unsigned long addr; + unsigned i, pgdoff = USER_PGTABLES_CEILING / PGDIR_SIZE; + + memset(&st, 0, sizeof(st)); + st.seq = m; + st.marker = address_markers; + + pgd += pgdoff; + + for (i = pgdoff; i < PTRS_PER_PGD; i++, pgd++) { + addr = i * PGDIR_SIZE; + if (!pgd_none(*pgd)) { + walk_pud(&st, pgd, addr); + } else { + note_page(&st, addr, 1, pgd_val(*pgd)); + } + } + + note_page(&st, 0, 0, 0); +} + +static int ptdump_show(struct seq_file *m, void *v) +{ + walk_pgd(m); + return 0; +} + +static int ptdump_open(struct inode *inode, struct file *file) +{ + return single_open(file, ptdump_show, NULL); +} + +static const struct file_operations ptdump_fops = { + .open = ptdump_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int ptdump_init(void) +{ + struct dentry *pe; + unsigned i, j; + + for (i = 0; i < ARRAY_SIZE(pg_level); i++) + if (pg_level[i].bits) + for (j = 0; j < pg_level[i].num; j++) + pg_level[i].mask |= pg_level[i].bits[j].mask; + + address_markers[2].start_address = VMALLOC_START; + + pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, + &ptdump_fops); + return pe ? 0 : -ENOMEM; +} +__initcall(ptdump_init); -- cgit v1.2.3-18-g5258 From 2e2c9de207be043ee80161971c814d740759d3bc Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 24 Oct 2013 10:26:40 +0100 Subject: ARM: add permission annotations to MT_MEMORY* mapping types Document the permissions which the various MT_MEMORY* mapping types will provide. Signed-off-by: Russell King --- arch/arm/include/asm/mach/map.h | 26 ++++++++++++++------------ arch/arm/kernel/tcm.c | 4 ++-- arch/arm/mach-at91/setup.c | 2 +- arch/arm/mach-omap2/io.c | 4 ++-- arch/arm/mach-omap2/omap4-common.c | 2 +- arch/arm/mach-ux500/setup.h | 2 +- arch/arm/mm/ioremap.c | 4 ++-- arch/arm/mm/mmu.c | 30 +++++++++++++++--------------- 8 files changed, 38 insertions(+), 36 deletions(-) diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h index 2fe141fcc8d..447be0744a8 100644 --- a/arch/arm/include/asm/mach/map.h +++ b/arch/arm/include/asm/mach/map.h @@ -22,18 +22,20 @@ struct map_desc { }; /* types 0-3 are defined in asm/io.h */ -#define MT_UNCACHED 4 -#define MT_CACHECLEAN 5 -#define MT_MINICLEAN 6 -#define MT_LOW_VECTORS 7 -#define MT_HIGH_VECTORS 8 -#define MT_MEMORY 9 -#define MT_ROM 10 -#define MT_MEMORY_NONCACHED 11 -#define MT_MEMORY_DTCM 12 -#define MT_MEMORY_ITCM 13 -#define MT_MEMORY_SO 14 -#define MT_MEMORY_DMA_READY 15 +enum { + MT_UNCACHED = 4, + MT_CACHECLEAN, + MT_MINICLEAN, + MT_LOW_VECTORS, + MT_HIGH_VECTORS, + MT_MEMORY_RWX, + MT_ROM, + MT_MEMORY_RWX_NONCACHED, + MT_MEMORY_RW_DTCM, + MT_MEMORY_RWX_ITCM, + MT_MEMORY_RW_SO, + MT_MEMORY_DMA_READY, +}; #ifdef CONFIG_MMU extern void iotable_init(struct map_desc *, int); diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c index f50f19e5c13..7a3be1d4d0b 100644 --- a/arch/arm/kernel/tcm.c +++ b/arch/arm/kernel/tcm.c @@ -52,7 +52,7 @@ static struct map_desc dtcm_iomap[] __initdata = { .virtual = DTCM_OFFSET, .pfn = __phys_to_pfn(DTCM_OFFSET), .length = 0, - .type = MT_MEMORY_DTCM + .type = MT_MEMORY_RW_DTCM } }; @@ -61,7 +61,7 @@ static struct map_desc itcm_iomap[] __initdata = { .virtual = ITCM_OFFSET, .pfn = __phys_to_pfn(ITCM_OFFSET), .length = 0, - .type = MT_MEMORY_ITCM + .type = MT_MEMORY_RWX_ITCM, } }; diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 094b3459c28..2742e00ec5d 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -81,7 +81,7 @@ void __init at91_init_sram(int bank, unsigned long base, unsigned int length) desc->pfn = __phys_to_pfn(base); desc->length = length; - desc->type = MT_MEMORY_NONCACHED; + desc->type = MT_MEMORY_RWX_NONCACHED; pr_info("AT91: sram at 0x%lx of 0x%x mapped at 0x%lx\n", base, length, desc->virtual); diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index cd22262a2cc..07b68d5a794 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -244,7 +244,7 @@ static struct map_desc omap44xx_io_desc[] __initdata = { .virtual = OMAP4_SRAM_VA, .pfn = __phys_to_pfn(OMAP4_SRAM_PA), .length = PAGE_SIZE, - .type = MT_MEMORY_SO, + .type = MT_MEMORY_RW_SO, }, #endif @@ -282,7 +282,7 @@ static struct map_desc omap54xx_io_desc[] __initdata = { .virtual = OMAP4_SRAM_VA, .pfn = __phys_to_pfn(OMAP4_SRAM_PA), .length = PAGE_SIZE, - .type = MT_MEMORY_SO, + .type = MT_MEMORY_RW_SO, }, #endif }; diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 57911430324..08def5665e7 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -88,7 +88,7 @@ void __init omap_barriers_init(void) dram_io_desc[0].virtual = OMAP4_DRAM_BARRIER_VA; dram_io_desc[0].pfn = __phys_to_pfn(paddr); dram_io_desc[0].length = size; - dram_io_desc[0].type = MT_MEMORY_SO; + dram_io_desc[0].type = MT_MEMORY_RW_SO; iotable_init(dram_io_desc, ARRAY_SIZE(dram_io_desc)); dram_sync = (void __iomem *) dram_io_desc[0].virtual; sram_sync = (void __iomem *) OMAP4_SRAM_VA; diff --git a/arch/arm/mach-ux500/setup.h b/arch/arm/mach-ux500/setup.h index bdb356498a7..b1dd8584bed 100644 --- a/arch/arm/mach-ux500/setup.h +++ b/arch/arm/mach-ux500/setup.h @@ -43,7 +43,7 @@ extern void ux500_timer_init(void); .virtual = IO_ADDRESS(x), \ .pfn = __phys_to_pfn(x), \ .length = sz, \ - .type = MT_MEMORY, \ + .type = MT_MEMORY_RWX, \ } extern struct smp_operations ux500_smp_ops; diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index f123d6eb074..f9c32ba7354 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -392,9 +392,9 @@ __arm_ioremap_exec(phys_addr_t phys_addr, size_t size, bool cached) unsigned int mtype; if (cached) - mtype = MT_MEMORY; + mtype = MT_MEMORY_RWX; else - mtype = MT_MEMORY_NONCACHED; + mtype = MT_MEMORY_RWX_NONCACHED; return __arm_ioremap_caller(phys_addr, size, mtype, __builtin_return_address(0)); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 580ef2de82d..fce2e738809 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -287,7 +287,7 @@ static struct mem_type mem_types[] = { .prot_l1 = PMD_TYPE_TABLE, .domain = DOMAIN_USER, }, - [MT_MEMORY] = { + [MT_MEMORY_RWX] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY, .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, @@ -297,26 +297,26 @@ static struct mem_type mem_types[] = { .prot_sect = PMD_TYPE_SECT, .domain = DOMAIN_KERNEL, }, - [MT_MEMORY_NONCACHED] = { + [MT_MEMORY_RWX_NONCACHED] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_MT_BUFFERABLE, .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, .domain = DOMAIN_KERNEL, }, - [MT_MEMORY_DTCM] = { + [MT_MEMORY_RW_DTCM] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_XN, .prot_l1 = PMD_TYPE_TABLE, .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, .domain = DOMAIN_KERNEL, }, - [MT_MEMORY_ITCM] = { + [MT_MEMORY_RWX_ITCM] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY, .prot_l1 = PMD_TYPE_TABLE, .domain = DOMAIN_KERNEL, }, - [MT_MEMORY_SO] = { + [MT_MEMORY_RW_SO] = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_MT_UNCACHED | L_PTE_XN, .prot_l1 = PMD_TYPE_TABLE, @@ -487,11 +487,11 @@ static void __init build_mem_type_table(void) mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; - mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; - mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY_RWX].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_RWX].prot_pte |= L_PTE_SHARED; mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED; - mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; - mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_RWX_NONCACHED].prot_pte |= L_PTE_SHARED; } } @@ -502,15 +502,15 @@ static void __init build_mem_type_table(void) if (cpu_arch >= CPU_ARCH_ARMv6) { if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) { /* Non-cacheable Normal is XCB = 001 */ - mem_types[MT_MEMORY_NONCACHED].prot_sect |= + mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_BUFFERED; } else { /* For both ARMv6 and non-TEX-remapping ARMv7 */ - mem_types[MT_MEMORY_NONCACHED].prot_sect |= + mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_TEX(1); } } else { - mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE; + mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE; } #ifdef CONFIG_ARM_LPAE @@ -543,10 +543,10 @@ static void __init build_mem_type_table(void) mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; - mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd; - mem_types[MT_MEMORY].prot_pte |= kern_pgprot; + mem_types[MT_MEMORY_RWX].prot_sect |= ecc_mask | cp->pmd; + mem_types[MT_MEMORY_RWX].prot_pte |= kern_pgprot; mem_types[MT_MEMORY_DMA_READY].prot_pte |= kern_pgprot; - mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask; + mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= ecc_mask; mem_types[MT_ROM].prot_sect |= cp->pmd; switch (cp->pmd) { -- cgit v1.2.3-18-g5258 From ebd4922ecc38e31e662cd641dd04099a9652c9b3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 24 Oct 2013 08:12:39 +0100 Subject: ARM: implement basic NX support for kernel lowmem mappings Add basic NX support for kernel lowmem mappings. We mark any section which does not overlap kernel text as non-executable, preventing it from being used to write code and then execute directly from there. This does not change the alignment of the sections, so the kernel image doesn't grow significantly via this change, so we can do this without needing a config option. Signed-off-by: Russell King --- arch/arm/include/asm/mach/map.h | 1 + arch/arm/mm/mmu.c | 55 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h index 447be0744a8..f98c7f32c9c 100644 --- a/arch/arm/include/asm/mach/map.h +++ b/arch/arm/include/asm/mach/map.h @@ -29,6 +29,7 @@ enum { MT_LOW_VECTORS, MT_HIGH_VECTORS, MT_MEMORY_RWX, + MT_MEMORY_RW, MT_ROM, MT_MEMORY_RWX_NONCACHED, MT_MEMORY_RW_DTCM, diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index fce2e738809..9ec715f1222 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -293,6 +294,13 @@ static struct mem_type mem_types[] = { .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, .domain = DOMAIN_KERNEL, }, + [MT_MEMORY_RW] = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_XN, + .prot_l1 = PMD_TYPE_TABLE, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, + .domain = DOMAIN_KERNEL, + }, [MT_ROM] = { .prot_sect = PMD_TYPE_SECT, .domain = DOMAIN_KERNEL, @@ -410,6 +418,9 @@ static void __init build_mem_type_table(void) mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_XN; mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_XN; mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_XN; + + /* Also setup NX memory mapping */ + mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_XN; } if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) { /* @@ -489,6 +500,8 @@ static void __init build_mem_type_table(void) mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED; mem_types[MT_MEMORY_RWX].prot_sect |= PMD_SECT_S; mem_types[MT_MEMORY_RWX].prot_pte |= L_PTE_SHARED; + mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_S; + mem_types[MT_MEMORY_RW].prot_pte |= L_PTE_SHARED; mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED; mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_S; mem_types[MT_MEMORY_RWX_NONCACHED].prot_pte |= L_PTE_SHARED; @@ -545,6 +558,8 @@ static void __init build_mem_type_table(void) mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; mem_types[MT_MEMORY_RWX].prot_sect |= ecc_mask | cp->pmd; mem_types[MT_MEMORY_RWX].prot_pte |= kern_pgprot; + mem_types[MT_MEMORY_RW].prot_sect |= ecc_mask | cp->pmd; + mem_types[MT_MEMORY_RW].prot_pte |= kern_pgprot; mem_types[MT_MEMORY_DMA_READY].prot_pte |= kern_pgprot; mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= ecc_mask; mem_types[MT_ROM].prot_sect |= cp->pmd; @@ -1296,6 +1311,8 @@ static void __init kmap_init(void) static void __init map_lowmem(void) { struct memblock_region *reg; + unsigned long kernel_x_start = round_down(__pa(_stext), SECTION_SIZE); + unsigned long kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE); /* Map all the lowmem memory banks. */ for_each_memblock(memory, reg) { @@ -1308,12 +1325,40 @@ static void __init map_lowmem(void) if (start >= end) break; - map.pfn = __phys_to_pfn(start); - map.virtual = __phys_to_virt(start); - map.length = end - start; - map.type = MT_MEMORY; + if (end < kernel_x_start || start >= kernel_x_end) { + map.pfn = __phys_to_pfn(start); + map.virtual = __phys_to_virt(start); + map.length = end - start; + map.type = MT_MEMORY_RWX; - create_mapping(&map); + create_mapping(&map); + } else { + /* This better cover the entire kernel */ + if (start < kernel_x_start) { + map.pfn = __phys_to_pfn(start); + map.virtual = __phys_to_virt(start); + map.length = kernel_x_start - start; + map.type = MT_MEMORY_RW; + + create_mapping(&map); + } + + map.pfn = __phys_to_pfn(kernel_x_start); + map.virtual = __phys_to_virt(kernel_x_start); + map.length = kernel_x_end - kernel_x_start; + map.type = MT_MEMORY_RWX; + + create_mapping(&map); + + if (kernel_x_end < end) { + map.pfn = __phys_to_pfn(kernel_x_end); + map.virtual = __phys_to_virt(kernel_x_end); + map.length = end - kernel_x_end; + map.type = MT_MEMORY_RW; + + create_mapping(&map); + } + } } } -- cgit v1.2.3-18-g5258 From 27ec8da4ace46900a71b8462157aa2bc88ff5d2c Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 17 Jun 2013 10:29:12 -0700 Subject: ARM: add definitions for pte_mkexec/pte_mknexec Other architectures define pte_mkexec to mark a pte as executable. Add pte_mkexec for ARM to get the same functionality. Although no other architectures currently define it, also add pte_mknexec to explicitly allow a pte to be marked as non executable. Signed-off-by: Laura Abbott Signed-off-by: Russell King --- arch/arm/include/asm/pgtable.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index be956dbf6ba..910d2741c03 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -254,6 +254,8 @@ PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG); +PTE_BIT_FUNC(mkexec, &= ~L_PTE_XN); +PTE_BIT_FUNC(mknexec, |= L_PTE_XN); static inline pte_t pte_mkspecial(pte_t pte) { return pte; } -- cgit v1.2.3-18-g5258 From 75374ad47c6465de6c098d7b913fe02d6131195c Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 17 Jun 2013 10:29:13 -0700 Subject: ARM: mm: Define set_memory_* functions for ARM Other architectures define various set_memory functions to allow attributes to be changed (e.g. set_memory_x, set_memory_rw, etc.) Currently, these functions are missing on ARM. Define these in an appropriate manner for ARM. Signed-off-by: Laura Abbott Signed-off-by: Russell King --- arch/arm/include/asm/cacheflush.h | 5 +++++ arch/arm/mm/mmu.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index ee753f1749c..e9a49fe0284 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -481,4 +481,9 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size) : : : "r0","r1","r2","r3","r4","r5","r6","r7", \ "r9","r10","lr","memory" ) +int set_memory_ro(unsigned long addr, int numpages); +int set_memory_rw(unsigned long addr, int numpages); +int set_memory_x(unsigned long addr, int numpages); +int set_memory_nx(unsigned long addr, int numpages); + #endif diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9ec715f1222..09033890c8b 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -345,6 +345,44 @@ const struct mem_type *get_mem_type(unsigned int type) } EXPORT_SYMBOL(get_mem_type); +#define PTE_SET_FN(_name, pteop) \ +static int pte_set_##_name(pte_t *ptep, pgtable_t token, unsigned long addr, \ + void *data) \ +{ \ + pte_t pte = pteop(*ptep); \ +\ + set_pte_ext(ptep, pte, 0); \ + return 0; \ +} \ + +#define SET_MEMORY_FN(_name, callback) \ +int set_memory_##_name(unsigned long addr, int numpages) \ +{ \ + unsigned long start = addr; \ + unsigned long size = PAGE_SIZE*numpages; \ + unsigned end = start + size; \ +\ + if (start < MODULES_VADDR || start >= MODULES_END) \ + return -EINVAL;\ +\ + if (end < MODULES_VADDR || end >= MODULES_END) \ + return -EINVAL; \ +\ + apply_to_page_range(&init_mm, start, size, callback, NULL); \ + flush_tlb_kernel_range(start, end); \ + return 0;\ +} + +PTE_SET_FN(ro, pte_wrprotect) +PTE_SET_FN(rw, pte_mkwrite) +PTE_SET_FN(x, pte_mkexec) +PTE_SET_FN(nx, pte_mknexec) + +SET_MEMORY_FN(ro, pte_set_ro) +SET_MEMORY_FN(rw, pte_set_rw) +SET_MEMORY_FN(x, pte_set_x) +SET_MEMORY_FN(nx, pte_set_nx) + /* * Adjust the PMD section entries according to the CPU in use. */ -- cgit v1.2.3-18-g5258 From dca9aa92fc7caa3620b31ced1535968f4aeeb967 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 17 Jun 2013 10:29:14 -0700 Subject: ARM: add DEBUG_SET_MODULE_RONX option to Kconfig Now that all the page setting infrastructure is in place, Add the DEBUG_SET_MODULE_RONX to the ARM debugging Kconfig. When turned on, data sections for modules will be marked as NX and read only sections will be marked as such. Signed-off-by: Laura Abbott Signed-off-by: Russell King --- arch/arm/Kconfig.debug | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 0603a6a5390..1043cb80235 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -1162,4 +1162,15 @@ config PID_IN_CONTEXTIDR additional instructions during context switch. Say Y here only if you are planning to use hardware trace tools with this kernel. +config DEBUG_SET_MODULE_RONX + bool "Set loadable kernel module data as NX and text as RO" + depends on MODULES + ---help--- + This option helps catch unintended modifications to loadable + kernel module's text and read-only data. It also prevents execution + of module data. Such protection may interfere with run-time code + patching and dynamic kernel tracing - and they might also protect + against certain classes of kernel exploits. + If in doubt, say "N". + endmenu -- cgit v1.2.3-18-g5258 From 71b55663c5d0a6f8473045db1c8b376803780191 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 25 Nov 2013 12:01:03 +0000 Subject: ARM: fix executability of CMA mappings The CMA region was being marked executable: 0xdc04e000-0xdc050000 8K RW x MEM/CACHED/WBRA 0xdc060000-0xdc100000 640K RW x MEM/CACHED/WBRA 0xdc4f5000-0xdc500000 44K RW x MEM/CACHED/WBRA 0xdcce9000-0xe0000000 52316K RW x MEM/CACHED/WBRA This is mainly due to the badly worded MT_MEMORY_DMA_READY symbol, but there are also a few other places in dma-mapping which should be corrected to use the right constant. Fix all these places: 0xdc04e000-0xdc050000 8K RW NX MEM/CACHED/WBRA 0xdc060000-0xdc100000 640K RW NX MEM/CACHED/WBRA 0xdc280000-0xdc300000 512K RW NX MEM/CACHED/WBRA 0xdc6fc000-0xe0000000 58384K RW NX MEM/CACHED/WBRA Signed-off-by: Russell King --- arch/arm/mm/dma-mapping.c | 6 +++--- arch/arm/mm/mmu.c | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 79f8b39801a..f0ea0134e5a 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -361,7 +361,7 @@ void __init init_dma_coherent_pool_size(unsigned long size) static int __init atomic_pool_init(void) { struct dma_pool *pool = &atomic_pool; - pgprot_t prot = pgprot_dmacoherent(pgprot_kernel); + pgprot_t prot = pgprot_dmacoherent(PAGE_KERNEL); gfp_t gfp = GFP_KERNEL | GFP_DMA; unsigned long nr_pages = pool->size >> PAGE_SHIFT; unsigned long *bitmap; @@ -609,7 +609,7 @@ static void __free_from_contiguous(struct device *dev, struct page *page, if (PageHighMem(page)) __dma_free_remap(cpu_addr, size); else - __dma_remap(page, size, pgprot_kernel); + __dma_remap(page, size, PAGE_KERNEL); dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT); } @@ -1357,7 +1357,7 @@ static void __iommu_free_atomic(struct device *dev, void *cpu_addr, static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs) { - pgprot_t prot = __get_dma_pgprot(attrs, pgprot_kernel); + pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL); struct page **pages; void *addr = NULL; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 09033890c8b..4f08c133cc2 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -333,7 +333,8 @@ static struct mem_type mem_types[] = { .domain = DOMAIN_KERNEL, }, [MT_MEMORY_DMA_READY] = { - .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY, + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_XN, .prot_l1 = PMD_TYPE_TABLE, .domain = DOMAIN_KERNEL, }, -- cgit v1.2.3-18-g5258 From 7dde0c032869ea92206398ad5c538d01931e3947 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 9 Jul 2013 10:27:12 +0100 Subject: ARM: sa11x0: assabet: better reset handling The codec reset pin is connected to several peripherals. When the reset is released, unfortunately the ADV7171 powers itself up rather than remaining in power-down mode. As we don't have a driver for this device, we end up needlessly consuming an additional 330mW. Not only that but we should have a way to arbitrate the reset signal. This patch provides that facility: we program the ADV7171 to sleep mode whenever the reset is released, and we release the reset when any one of the three peripherals requests the reset to be released. Signed-off-by: Russell King --- arch/arm/mach-sa1100/assabet.c | 135 +++++++++++++++++++++++++++- arch/arm/mach-sa1100/include/mach/assabet.h | 6 +- 2 files changed, 137 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index c9808c68415..6a15354d43b 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -75,11 +75,142 @@ void ASSABET_BCR_frob(unsigned int mask, unsigned int val) EXPORT_SYMBOL(ASSABET_BCR_frob); +/* + * The codec reset goes to three devices, so we need to release + * the rest when any one of these requests it. However, that + * causes the ADV7171 to consume around 100mA - more than half + * the LCD-blanked power. + * + * With the ADV7171, LCD and backlight enabled, we go over + * budget on the MAX846 Li-Ion charger, and if no Li-Ion battery + * is connected, the Assabet crashes. + */ +#define RST_UCB1X00 (1 << 0) +#define RST_UDA1341 (1 << 1) +#define RST_ADV7171 (1 << 2) + +#define SDA GPIO_GPIO(15) +#define SCK GPIO_GPIO(18) +#define MOD GPIO_GPIO(17) + +static void adv7171_start(void) +{ + GPSR = SCK; + udelay(1); + GPSR = SDA; + udelay(2); + GPCR = SDA; +} + +static void adv7171_stop(void) +{ + GPSR = SCK; + udelay(2); + GPSR = SDA; + udelay(1); +} + +static void adv7171_send(unsigned byte) +{ + unsigned i; + + for (i = 0; i < 8; i++, byte <<= 1) { + GPCR = SCK; + udelay(1); + if (byte & 0x80) + GPSR = SDA; + else + GPCR = SDA; + udelay(1); + GPSR = SCK; + udelay(1); + } + GPCR = SCK; + udelay(1); + GPSR = SDA; + udelay(1); + GPDR &= ~SDA; + GPSR = SCK; + udelay(1); + if (GPLR & SDA) + printk(KERN_WARNING "No ACK from ADV7171\n"); + udelay(1); + GPCR = SCK | SDA; + udelay(1); + GPDR |= SDA; + udelay(1); +} + +static void adv7171_write(unsigned reg, unsigned val) +{ + unsigned gpdr = GPDR; + unsigned gplr = GPLR; + + ASSABET_BCR = BCR_value | ASSABET_BCR_AUDIO_ON; + udelay(100); + + GPCR = SDA | SCK | MOD; /* clear L3 mode to ensure UDA1341 doesn't respond */ + GPDR = (GPDR | SCK | MOD) & ~SDA; + udelay(10); + if (!(GPLR & SDA)) + printk(KERN_WARNING "Something dragging SDA down?\n"); + GPDR |= SDA; + + adv7171_start(); + adv7171_send(0x54); + adv7171_send(reg); + adv7171_send(val); + adv7171_stop(); + + /* Restore GPIO state for L3 bus */ + GPSR = gplr & (SDA | SCK | MOD); + GPCR = (~gplr) & (SDA | SCK | MOD); + GPDR = gpdr; +} + +static void adv7171_sleep(void) +{ + /* Put the ADV7171 into sleep mode */ + adv7171_write(0x04, 0x40); +} + +static unsigned codec_nreset; + +static void assabet_codec_reset(unsigned mask, int set) +{ + unsigned long flags; + bool old; + + local_irq_save(flags); + old = !codec_nreset; + if (set) + codec_nreset &= ~mask; + else + codec_nreset |= mask; + + if (old != !codec_nreset) { + if (codec_nreset) { + ASSABET_BCR_set(ASSABET_BCR_NCODEC_RST); + adv7171_sleep(); + } else { + ASSABET_BCR_clear(ASSABET_BCR_NCODEC_RST); + } + } + local_irq_restore(flags); +} + static void assabet_ucb1x00_reset(enum ucb1x00_reset state) { - if (state == UCB_RST_PROBE) - ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); + int set = state == UCB_RST_REMOVE || state == UCB_RST_SUSPEND || + state == UCB_RST_PROBE_FAIL; + assabet_codec_reset(RST_UCB1X00, set); +} + +void assabet_uda1341_reset(int set) +{ + assabet_codec_reset(RST_UDA1341, set); } +EXPORT_SYMBOL(assabet_uda1341_reset); /* diff --git a/arch/arm/mach-sa1100/include/mach/assabet.h b/arch/arm/mach-sa1100/include/mach/assabet.h index 307391488c2..c23fcdb047a 100644 --- a/arch/arm/mach-sa1100/include/mach/assabet.h +++ b/arch/arm/mach-sa1100/include/mach/assabet.h @@ -39,8 +39,8 @@ extern unsigned long SCR_value; #define ASSABET_BCR_CF_PWR (1<<0) /* Compact Flash Power (1 = 3.3v, 0 = off) */ #define ASSABET_BCR_CF_RST (1<<1) /* Compact Flash Reset (1 = power up reset) */ -#define ASSABET_BCR_GFX_RST (1<<1) /* Graphics Accelerator Reset (0 = hold reset) */ -#define ASSABET_BCR_CODEC_RST (1<<2) /* 0 = Holds UCB1300, ADI7171, and UDA1341 in reset */ +#define ASSABET_BCR_NGFX_RST (1<<1) /* Graphics Accelerator Reset (0 = hold reset) */ +#define ASSABET_BCR_NCODEC_RST (1<<2) /* 0 = Holds UCB1300, ADI7171, and UDA1341 in reset */ #define ASSABET_BCR_IRDA_FSEL (1<<3) /* IRDA Frequency select (0 = SIR, 1 = MIR/ FIR) */ #define ASSABET_BCR_IRDA_MD0 (1<<4) /* Range/Power select */ #define ASSABET_BCR_IRDA_MD1 (1<<5) /* Range/Power select */ @@ -69,6 +69,8 @@ extern void ASSABET_BCR_frob(unsigned int mask, unsigned int set); #define ASSABET_BCR_frob(x,y) do { } while (0) #endif +extern void assabet_uda1341_reset(int set); + #define ASSABET_BCR_set(x) ASSABET_BCR_frob((x), (x)) #define ASSABET_BCR_clear(x) ASSABET_BCR_frob((x), 0) -- cgit v1.2.3-18-g5258 From c8857758dbe18fb6cc6a5a2bed224a1846904f0e Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 9 Jul 2013 10:31:20 +0100 Subject: ARM: sa11x0: assabet: allow UCB1300 to wake up Assabet The UCB1300 is capable of waking up the Assabet. Indicate to the driver that wakeup from the UCB1300 is supported. Signed-off-by: Russell King --- arch/arm/mach-sa1100/assabet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index 6a15354d43b..fc840f62dfd 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -311,6 +311,7 @@ static struct irda_platform_data assabet_irda_data = { static struct ucb1x00_plat_data assabet_ucb1x00_data = { .reset = assabet_ucb1x00_reset, .gpio_base = -1, + .can_wakeup = 1, }; static struct mcp_plat_data assabet_mcp_data = { -- cgit v1.2.3-18-g5258 From 22564bde0bc4a0ec04d084d3a6c8c75eb2102d57 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 9 Jul 2013 10:32:30 +0100 Subject: ARM: sa11x0: assabet: clean up IrDA power setting Minor clean up to the IrDA power setting support. Signed-off-by: Russell King --- arch/arm/mach-sa1100/assabet.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index fc840f62dfd..8443a27bca2 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -286,12 +286,9 @@ static int assabet_irda_set_power(struct device *dev, unsigned int state) 0 }; - if (state < 4) { - state = bcr_state[state]; - ASSABET_BCR_clear(state ^ (ASSABET_BCR_IRDA_MD1| - ASSABET_BCR_IRDA_MD0)); - ASSABET_BCR_set(state); - } + if (state < 4) + ASSABET_BCR_frob(ASSABET_BCR_IRDA_MD1 | ASSABET_BCR_IRDA_MD0, + bcr_state[state]); return 0; } -- cgit v1.2.3-18-g5258 From 5f72d85e282e83db8eedb291aa89db9198470b38 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 26 Nov 2013 11:09:01 +0100 Subject: ARM: 7898/1: sa1100: h3100: refactor LCD GPIO handling As GPIOs are going to move to platform device, there is no guarantee that they will be available at init_machine time. Request all GPIOs directly in lcd_power callback and not at init_machine time. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-sa1100/h3100.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c index b8f2b151539..5b78c9f9a11 100644 --- a/arch/arm/mach-sa1100/h3100.c +++ b/arch/arm/mach-sa1100/h3100.c @@ -28,15 +28,35 @@ /* * helper for sa1100fb */ +static struct gpio h3100_lcd_gpio[] = { + { H3100_GPIO_LCD_3V_ON, GPIOF_OUT_INIT_LOW, "LCD 3V" }, + { H3XXX_EGPIO_LCD_ON, GPIOF_OUT_INIT_LOW, "LCD ON" }, +}; + +static bool h3100_lcd_request(void) +{ + static bool h3100_lcd_ok; + int rc; + + if (h3100_lcd_ok) + return true; + + rc = gpio_request_array(h3100_lcd_gpio, ARRAY_SIZE(h3100_lcd_gpio)); + if (rc) + pr_err("%s: can't request GPIOs\n", __func__); + else + h3100_lcd_ok = true; + + return h3100_lcd_ok; +} + static void h3100_lcd_power(int enable) { - if (!gpio_request(H3XXX_EGPIO_LCD_ON, "LCD ON")) { - gpio_set_value(H3100_GPIO_LCD_3V_ON, enable); - gpio_direction_output(H3XXX_EGPIO_LCD_ON, enable); - gpio_free(H3XXX_EGPIO_LCD_ON); - } else { - pr_err("%s: can't request H3XXX_EGPIO_LCD_ON\n", __func__); - } + if (!h3100_lcd_request()) + return; + + gpio_set_value(H3100_GPIO_LCD_3V_ON, enable); + gpio_set_value(H3XXX_EGPIO_LCD_ON, enable); } static struct sa1100fb_mach_info h3100_lcd_info = { @@ -91,7 +111,6 @@ static struct gpio_default_state h3100_default_gpio[] = { { H3XXX_GPIO_COM_DCD, GPIO_MODE_IN, "COM DCD" }, { H3XXX_GPIO_COM_CTS, GPIO_MODE_IN, "COM CTS" }, { H3XXX_GPIO_COM_RTS, GPIO_MODE_OUT0, "COM RTS" }, - { H3100_GPIO_LCD_3V_ON, GPIO_MODE_OUT0, "LCD 3v" }, }; static void __init h3100_mach_init(void) -- cgit v1.2.3-18-g5258 From 8bed576c1a81d620765ec96f7b4e80dedaef1bcf Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 26 Nov 2013 11:09:49 +0100 Subject: ARM: 7899/1: sa1100: h3600: refactor LCD GPIO handling Use gpio_request_array to request all GPIOs at once. Also don't call gpio_free. There is little point freeing LCD gpios once they are requested. Instead guard them with bool variable. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-sa1100/h3600.c | 48 ++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index b8dc5bd2262..559c2a0a40d 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -28,35 +28,39 @@ /* * helper for sa1100fb */ +static struct gpio h3600_lcd_gpio[] = { + { H3XXX_EGPIO_LCD_ON, GPIOF_OUT_INIT_LOW, "LCD power" }, + { H3600_EGPIO_LCD_PCI, GPIOF_OUT_INIT_LOW, "LCD control" }, + { H3600_EGPIO_LCD_5V_ON, GPIOF_OUT_INIT_LOW, "LCD 5v" }, + { H3600_EGPIO_LVDD_ON, GPIOF_OUT_INIT_LOW, "LCD 9v/-6.5v" }, +}; + +static bool h3600_lcd_request(void) +{ + static bool h3600_lcd_ok; + int rc; + + if (h3600_lcd_ok) + return true; + + rc = gpio_request_array(h3600_lcd_gpio, ARRAY_SIZE(h3600_lcd_gpio)); + if (rc) + pr_err("%s: can't request GPIOs\n", __func__); + else + h3600_lcd_ok = true; + + return h3600_lcd_ok; +} + static void h3600_lcd_power(int enable) { - if (gpio_request(H3XXX_EGPIO_LCD_ON, "LCD power")) { - pr_err("%s: can't request H3XXX_EGPIO_LCD_ON\n", __func__); - goto err1; - } - if (gpio_request(H3600_EGPIO_LCD_PCI, "LCD control")) { - pr_err("%s: can't request H3XXX_EGPIO_LCD_PCI\n", __func__); - goto err2; - } - if (gpio_request(H3600_EGPIO_LCD_5V_ON, "LCD 5v")) { - pr_err("%s: can't request H3XXX_EGPIO_LCD_5V_ON\n", __func__); - goto err3; - } - if (gpio_request(H3600_EGPIO_LVDD_ON, "LCD 9v/-6.5v")) { - pr_err("%s: can't request H3600_EGPIO_LVDD_ON\n", __func__); - goto err4; - } + if (!h3600_lcd_request()) + return; gpio_direction_output(H3XXX_EGPIO_LCD_ON, enable); gpio_direction_output(H3600_EGPIO_LCD_PCI, enable); gpio_direction_output(H3600_EGPIO_LCD_5V_ON, enable); gpio_direction_output(H3600_EGPIO_LVDD_ON, enable); - - gpio_free(H3600_EGPIO_LVDD_ON); -err4: gpio_free(H3600_EGPIO_LCD_5V_ON); -err3: gpio_free(H3600_EGPIO_LCD_PCI); -err2: gpio_free(H3XXX_EGPIO_LCD_ON); -err1: return; } static const struct sa1100fb_rgb h3600_rgb_16 = { -- cgit v1.2.3-18-g5258 From d8eec82c176a87aebc823ceed2b7656e43f88b49 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 26 Nov 2013 11:10:10 +0100 Subject: ARM: 7900/1: sa1100: h3100: refactor IrDA GPIO handling As GPIOs are going to move to platform device, there is no guarantee that they will be available at init_machine time. Request and free all GPIOs from IrDA startup/shutdown callbacks and not at init_machine time. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-sa1100/h3100.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c index 5b78c9f9a11..daa27c474c1 100644 --- a/arch/arm/mach-sa1100/h3100.c +++ b/arch/arm/mach-sa1100/h3100.c @@ -89,6 +89,11 @@ static void __init h3100_map_io(void) /* * This turns the IRDA power on or off on the Compaq H3100 */ +static struct gpio h3100_irda_gpio[] = { + { H3100_GPIO_IR_ON, GPIOF_OUT_INIT_LOW, "IrDA power" }, + { H3100_GPIO_IR_FSEL, GPIOF_OUT_INIT_LOW, "IrDA fsel" }, +}; + static int h3100_irda_set_power(struct device *dev, unsigned int state) { gpio_set_value(H3100_GPIO_IR_ON, state); @@ -100,14 +105,24 @@ static void h3100_irda_set_speed(struct device *dev, unsigned int speed) gpio_set_value(H3100_GPIO_IR_FSEL, !(speed < 4000000)); } +static int h3100_irda_startup(struct device *dev) +{ + return gpio_request_array(h3100_irda_gpio, sizeof(h3100_irda_gpio)); +} + +static void h3100_irda_shutdown(struct device *dev) +{ + return gpio_free_array(h3100_irda_gpio, sizeof(h3100_irda_gpio)); +} + static struct irda_platform_data h3100_irda_data = { .set_power = h3100_irda_set_power, .set_speed = h3100_irda_set_speed, + .startup = h3100_irda_startup, + .shutdown = h3100_irda_shutdown, }; static struct gpio_default_state h3100_default_gpio[] = { - { H3100_GPIO_IR_ON, GPIO_MODE_OUT0, "IrDA power" }, - { H3100_GPIO_IR_FSEL, GPIO_MODE_OUT0, "IrDA fsel" }, { H3XXX_GPIO_COM_DCD, GPIO_MODE_IN, "COM DCD" }, { H3XXX_GPIO_COM_CTS, GPIO_MODE_IN, "COM CTS" }, { H3XXX_GPIO_COM_RTS, GPIO_MODE_OUT0, "COM RTS" }, -- cgit v1.2.3-18-g5258 From 15cc324aca0a78e5882228e7e2eedf57e732d8f5 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 26 Nov 2013 11:10:40 +0100 Subject: ARM: 7901/1: sa1100: h3600: refactor IrDA GPIO handling Use gpio_request_array/gpio_free_array to request all GPIOs at once. Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-sa1100/h3600.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index 559c2a0a40d..a663e723014 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -97,6 +97,11 @@ static void __init h3600_map_io(void) /* * This turns the IRDA power on or off on the Compaq H3600 */ +static struct gpio h3600_irda_gpio[] = { + { H3600_EGPIO_IR_ON, GPIOF_OUT_INIT_LOW, "IrDA power" }, + { H3600_EGPIO_IR_FSEL, GPIOF_OUT_INIT_LOW, "IrDA fsel" }, +}; + static int h3600_irda_set_power(struct device *dev, unsigned int state) { gpio_set_value(H3600_EGPIO_IR_ON, state); @@ -110,29 +115,12 @@ static void h3600_irda_set_speed(struct device *dev, unsigned int speed) static int h3600_irda_startup(struct device *dev) { - int err = gpio_request(H3600_EGPIO_IR_ON, "IrDA power"); - if (err) - goto err1; - err = gpio_direction_output(H3600_EGPIO_IR_ON, 0); - if (err) - goto err2; - err = gpio_request(H3600_EGPIO_IR_FSEL, "IrDA fsel"); - if (err) - goto err2; - err = gpio_direction_output(H3600_EGPIO_IR_FSEL, 0); - if (err) - goto err3; - return 0; - -err3: gpio_free(H3600_EGPIO_IR_FSEL); -err2: gpio_free(H3600_EGPIO_IR_ON); -err1: return err; + return gpio_request_array(h3600_irda_gpio, sizeof(h3600_irda_gpio)); } static void h3600_irda_shutdown(struct device *dev) { - gpio_free(H3600_EGPIO_IR_ON); - gpio_free(H3600_EGPIO_IR_FSEL); + return gpio_free_array(h3600_irda_gpio, sizeof(h3600_irda_gpio)); } static struct irda_platform_data h3600_irda_data = { -- cgit v1.2.3-18-g5258 From 92341c83a904a23f9af52598cd97a8438b99eb00 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 22 Nov 2013 20:14:49 +0100 Subject: ARM: 7896/1: rename ioremap_cached to ioremap_cache ioremap_cache is more aligned with other architectures. There are only 2 users of this in the kernel: pxa2xx-flash and Xen. This fixes Xen build failures on arm64 caused by commit c04e8e2fe5 (arm64: allow ioremap_cache() to use existing RAM mappings) drivers/tty/hvc/hvc_xen.c:233:2: error: implicit declaration of function 'ioremap_cached' [-Werror=implicit-function-declaration] drivers/xen/grant-table.c:1174:3: error: implicit declaration of function 'ioremap_cached' [-Werror=implicit-function-declaration] drivers/xen/xenbus/xenbus_probe.c:778:4: error: implicit declaration of function 'ioremap_cached' [-Werror=implicit-function-declaration] Signed-off-by: Rob Herring Cc: Stefano Stabellini Acked-by: Catalin Marinas Cc: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/io.h | 2 +- arch/arm/include/asm/xen/page.h | 2 +- drivers/mtd/maps/pxa2xx-flash.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 3c597c222ef..fbeb39c869e 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -329,7 +329,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t); */ #define ioremap(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) #define ioremap_nocache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) -#define ioremap_cached(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_CACHED) +#define ioremap_cache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_CACHED) #define ioremap_wc(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_WC) #define iounmap __arm_iounmap diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h index 75579a9d6f7..3759cacdd7f 100644 --- a/arch/arm/include/asm/xen/page.h +++ b/arch/arm/include/asm/xen/page.h @@ -117,6 +117,6 @@ static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) return __set_phys_to_machine(pfn, mfn); } -#define xen_remap(cookie, size) ioremap_cached((cookie), (size)); +#define xen_remap(cookie, size) ioremap_cache((cookie), (size)); #endif /* _ASM_ARM_XEN_PAGE_H */ diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index d210d131fef..0f55589a56b 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c @@ -73,7 +73,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev) return -ENOMEM; } info->map.cached = - ioremap_cached(info->map.phys, info->map.size); + ioremap_cache(info->map.phys, info->map.size); if (!info->map.cached) printk(KERN_WARNING "Failed to ioremap cached %s\n", info->map.name); -- cgit v1.2.3-18-g5258 From ef41b5c924984b34d9c2830185295b2a9ae78e13 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 20 Oct 2013 15:34:10 +0100 Subject: ARM: make kernel oops easier to read We don't need the offset for the first function name in each backtrace entry; this needlessly consumes screen space. This is virtually always the first or second instruction in the called function. Also, recognise stmfd instructions which include r10 as a valid stack saving instruction, and when dumping the registers, dump six registers per line rather than five, and fix the wrapping. Signed-off-by: Russell King --- arch/arm/kernel/traps.c | 2 +- arch/arm/lib/backtrace.S | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 7940241f057..a55a1426787 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -56,7 +56,7 @@ static void dump_mem(const char *, const char *, unsigned long, unsigned long); void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) { #ifdef CONFIG_KALLSYMS - printk("[<%08lx>] (%pS) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from); + printk("[<%08lx>] (%ps) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from); #else printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); #endif diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S index cd07b5814c2..4102be617fc 100644 --- a/arch/arm/lib/backtrace.S +++ b/arch/arm/lib/backtrace.S @@ -80,14 +80,14 @@ for_each_frame: tst frame, mask @ Check for address exceptions ldr r1, [sv_pc, #-4] @ if stmfd sp!, {args} exists, ldr r3, .Ldsi+4 - teq r3, r1, lsr #10 + teq r3, r1, lsr #11 ldreq r0, [frame, #-8] @ get sp subeq r0, r0, #4 @ point at the last arg bleq .Ldumpstm @ dump saved registers 1004: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, ip, lr, pc} ldr r3, .Ldsi @ instruction exists, - teq r3, r1, lsr #10 + teq r3, r1, lsr #11 subeq r0, frame, #16 bleq .Ldumpstm @ dump saved registers @@ -128,11 +128,11 @@ ENDPROC(c_backtrace) beq 2f add r7, r7, #1 teq r7, #6 - moveq r7, #1 - moveq r1, #'\n' - movne r1, #' ' - ldr r3, [stack], #-4 - mov r2, reg + moveq r7, #0 + adr r3, .Lcr + addne r3, r3, #1 @ skip newline + ldr r2, [stack], #-4 + mov r1, reg adr r0, .Lfp bl printk 2: subs reg, reg, #1 @@ -142,11 +142,11 @@ ENDPROC(c_backtrace) blne printk ldmfd sp!, {instr, reg, stack, r7, pc} -.Lfp: .asciz "%cr%d:%08x" +.Lfp: .asciz " r%d:%08x%s" .Lcr: .asciz "\n" .Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n" .align -.Ldsi: .word 0xe92dd800 >> 10 @ stmfd sp!, {... fp, ip, lr, pc} - .word 0xe92d0000 >> 10 @ stmfd sp!, {} +.Ldsi: .word 0xe92dd800 >> 11 @ stmfd sp!, {... fp, ip, lr, pc} + .word 0xe92d0000 >> 11 @ stmfd sp!, {} #endif -- cgit v1.2.3-18-g5258 From e6d159cdf9f79edd1738bd1f3b430226fe3924ae Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 14 Nov 2013 11:45:59 +0100 Subject: ARM: 7890/1: v7-M: drop using mach/entry-macro.S MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only v7-M platform only has some unused stubs in its mach/entry-macro.S file. So don't include it which allows efm32 to drop the file. Acked-by: Olof Johansson Signed-off-by: Uwe Kleine-König Signed-off-by: Russell King --- arch/arm/kernel/entry-v7m.S | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S index 52b26432c9a..2260f185582 100644 --- a/arch/arm/kernel/entry-v7m.S +++ b/arch/arm/kernel/entry-v7m.S @@ -14,8 +14,6 @@ #include #include -#include - #include "entry-header.S" #ifdef CONFIG_TRACE_IRQFLAGS -- cgit v1.2.3-18-g5258 From 90a8471232797b96ed9af3a31fbb21b2df245ed1 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 26 Nov 2013 11:38:18 +0100 Subject: ARM: 7904/1: input: ambakmi: Remove unnecessary amba_set_drvdata() Driver core clears the driver data to NULL after device_release or on probe failure, so just remove it from here. Driver core change: "device-core: Ensure drvdata = NULL when no driver is bound" (sha1: 0998d0631001288a5974afc0b2a5f568bcdecb4d) Signed-off-by: Michal Simek Signed-off-by: Russell King --- drivers/input/serio/ambakmi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 4e2fd44865e..b7c206db0df 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -167,8 +167,6 @@ static int amba_kmi_remove(struct amba_device *dev) { struct amba_kmi_port *kmi = amba_get_drvdata(dev); - amba_set_drvdata(dev, NULL); - serio_unregister_port(kmi->io); clk_put(kmi->clk); iounmap(kmi->base); -- cgit v1.2.3-18-g5258 From de77d1e5b412b31aa2f382bc6fe048d84e28d48e Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 26 Nov 2013 11:38:19 +0100 Subject: ARM: 7905/1: etm: Remove unnecessary amba_set_drvdata() Driver core clears the driver data to NULL after device_release or on probe failure, so just remove it from here. Driver core change: "device-core: Ensure drvdata = NULL when no driver is bound" (sha1: 0998d0631001288a5974afc0b2a5f568bcdecb4d) Signed-off-by: Michal Simek Signed-off-by: Russell King --- arch/arm/kernel/etm.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c index 8ff0ecdc637..131a6ab5f35 100644 --- a/arch/arm/kernel/etm.c +++ b/arch/arm/kernel/etm.c @@ -385,7 +385,6 @@ out: return ret; out_unmap: - amba_set_drvdata(dev, NULL); iounmap(t->etb_regs); out_release: @@ -398,8 +397,6 @@ static int etb_remove(struct amba_device *dev) { struct tracectx *t = amba_get_drvdata(dev); - amba_set_drvdata(dev, NULL); - iounmap(t->etb_regs); t->etb_regs = NULL; @@ -588,7 +585,6 @@ out: return ret; out_unmap: - amba_set_drvdata(dev, NULL); iounmap(t->etm_regs); out_release: @@ -601,8 +597,6 @@ static int etm_remove(struct amba_device *dev) { struct tracectx *t = amba_get_drvdata(dev); - amba_set_drvdata(dev, NULL); - iounmap(t->etm_regs); t->etm_regs = NULL; -- cgit v1.2.3-18-g5258 From 23c34527a45885cd8f9dd58294de3cbaa32b10be Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 26 Nov 2013 11:38:20 +0100 Subject: ARM: 7906/1: mmc: mmci: Remove unnecessary amba_set_drvdata() Driver core clears the driver data to NULL after device_release or on probe failure, so just remove it from here. Driver core change: "device-core: Ensure drvdata = NULL when no driver is bound" (sha1: 0998d0631001288a5974afc0b2a5f568bcdecb4d) Signed-off-by: Michal Simek Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index f32057972dd..b9312263653 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -1683,8 +1683,6 @@ static int mmci_remove(struct amba_device *dev) { struct mmc_host *mmc = amba_get_drvdata(dev); - amba_set_drvdata(dev, NULL); - if (mmc) { struct mmci_host *host = mmc_priv(mmc); -- cgit v1.2.3-18-g5258 From 1b0f6681fcbc0e6365f42ef11beb882c9f73c945 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Thu, 5 Dec 2013 18:29:35 +0100 Subject: ARM: 7911/2: Clean up setup printks a bit Clean up the setup ARM printks a bit. Add printk level to a few that were missing (CPU: <...> ones, in particular), and switch from printk(KERN_* ..) to pr_*(). Finally, un-wrap some long lines since it makes it harder to grep the sources from where an error came from and tweak some cases of indentation. Signed-off-by: Olof Johansson Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 987a7f5bce5..7a2dd4689a7 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -334,7 +334,7 @@ static void __init cacheid_init(void) cacheid = CACHEID_VIVT; } - printk("CPU: %s data cache, %s instruction cache\n", + pr_info("CPU: %s data cache, %s instruction cache\n", cache_is_vivt() ? "VIVT" : cache_is_vipt_aliasing() ? "VIPT aliasing" : cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown", @@ -416,7 +416,7 @@ void notrace cpu_init(void) struct stack *stk = &stacks[cpu]; if (cpu >= NR_CPUS) { - printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu); + pr_crit("CPU%u: bad primary CPU number\n", cpu); BUG(); } @@ -484,7 +484,7 @@ void __init smp_setup_processor_id(void) */ set_my_cpu_offset(0); - printk(KERN_INFO "Booting Linux on physical CPU 0x%x\n", mpidr); + pr_info("Booting Linux on physical CPU 0x%x\n", mpidr); } struct mpidr_hash mpidr_hash; @@ -564,8 +564,8 @@ static void __init setup_processor(void) */ list = lookup_processor_type(read_cpuid_id()); if (!list) { - printk("CPU configuration botched (ID %08x), unable " - "to continue.\n", read_cpuid_id()); + pr_err("CPU configuration botched (ID %08x), unable to continue.\n", + read_cpuid_id()); while (1); } @@ -585,9 +585,9 @@ static void __init setup_processor(void) cpu_cache = *list->cache; #endif - printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n", - cpu_name, read_cpuid_id(), read_cpuid_id() & 15, - proc_arch[cpu_architecture()], cr_alignment); + pr_info("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n", + cpu_name, read_cpuid_id(), read_cpuid_id() & 15, + proc_arch[cpu_architecture()], cr_alignment); snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c", list->arch_name, ENDIANNESS); @@ -629,8 +629,8 @@ int __init arm_add_memory(u64 start, u64 size) u64 aligned_start; if (meminfo.nr_banks >= NR_BANKS) { - printk(KERN_CRIT "NR_BANKS too low, " - "ignoring memory at 0x%08llx\n", (long long)start); + pr_crit("NR_BANKS too low, ignoring memory at 0x%08llx\n", + (long long)start); return -EINVAL; } @@ -643,14 +643,14 @@ int __init arm_add_memory(u64 start, u64 size) #ifndef CONFIG_ARCH_PHYS_ADDR_T_64BIT if (aligned_start > ULONG_MAX) { - printk(KERN_CRIT "Ignoring memory at 0x%08llx outside " - "32-bit physical address space\n", (long long)start); + pr_crit("Ignoring memory at 0x%08llx outside 32-bit physical address space\n", + (long long)start); return -EINVAL; } if (aligned_start + size > ULONG_MAX) { - printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in " - "32-bit physical address space\n", (long long)start); + pr_crit("Truncating memory at 0x%08llx to fit in 32-bit physical address space\n", + (long long)start); /* * To ensure bank->start + bank->size is representable in * 32 bits, we use ULONG_MAX as the upper limit rather than 4GB. @@ -819,16 +819,15 @@ static void __init reserve_crashkernel(void) ret = reserve_bootmem(crash_base, crash_size, BOOTMEM_EXCLUSIVE); if (ret < 0) { - printk(KERN_WARNING "crashkernel reservation failed - " - "memory is in use (0x%lx)\n", (unsigned long)crash_base); + pr_warn("crashkernel reservation failed - memory is in use (0x%lx)\n", + (unsigned long)crash_base); return; } - printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " - "for crashkernel (System RAM: %ldMB)\n", - (unsigned long)(crash_size >> 20), - (unsigned long)(crash_base >> 20), - (unsigned long)(total_mem >> 20)); + pr_info("Reserving %ldMB of memory at %ldMB for crashkernel (System RAM: %ldMB)\n", + (unsigned long)(crash_size >> 20), + (unsigned long)(crash_base >> 20), + (unsigned long)(total_mem >> 20)); crashk_res.start = crash_base; crashk_res.end = crash_base + crash_size - 1; -- cgit v1.2.3-18-g5258 From efcfc46e8a654c3dddb51a6c4f46cd818dd926cc Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 9 Dec 2013 16:10:18 +0100 Subject: ARM: 7918/1: clean up cache handling in core code We have a handy macro to replace open coded __cpuc_flush_dcache_area(() and outer_clean_range() sequences. Let's use it. No functional change. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/common/mcpm_entry.c | 3 +-- arch/arm/kernel/smp.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c index 26020a03f65..87c5f1b595b 100644 --- a/arch/arm/common/mcpm_entry.c +++ b/arch/arm/common/mcpm_entry.c @@ -35,8 +35,7 @@ void mcpm_set_early_poke(unsigned cpu, unsigned cluster, unsigned long *poke = &mcpm_entry_early_pokes[cluster][cpu][0]; poke[0] = poke_phys_addr; poke[1] = poke_val; - __cpuc_flush_dcache_area((void *)poke, 8); - outer_clean_range(__pa(poke), __pa(poke + 2)); + __sync_cache_range_w(poke, 2 * sizeof(*poke)); } static const struct mcpm_platform_ops *platform_ops; diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index dc894ab3622..8c61325b8bf 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -105,8 +105,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) secondary_data.pgdir = get_arch_pgd(idmap_pgd); secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir); #endif - __cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data)); - outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1)); + sync_cache_w(&secondary_data); /* * Now bring the CPU into our world. -- cgit v1.2.3-18-g5258 From 70f665fe77c54740d0fa8aaad5de2181d75af15e Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 9 Dec 2013 18:06:53 +0100 Subject: ARM: 7919/1: mm: refactor v7 cache cleaning ops to use way/index sequence Set-associative caches on all v7 implementations map the index bits to physical addresses LSBs and tag bits to MSBs. As the last level of cache on current and upcoming ARM systems grows in size, this means that under normal DRAM controller configurations, the current v7 cache flush routine using set/way operations triggers a DRAM memory controller precharge/activate for every cache line writeback since the cache routine cleans lines by first fixing the index and then looping through ways (index bits are mapped to lower physical addresses on all v7 cache implementations; this means that, with last level cache sizes in the order of MBytes, lines belonging to the same set but different ways map to different DRAM pages). Given the random content of cache tags, swapping the order between indexes and ways loops do not prevent DRAM pages precharge and activate cycles but at least, on average, improves the chances that either multiple lines hit the same page or multiple lines belong to different DRAM banks, improving throughput significantly. This patch swaps the inner loops in the v7 cache flushing routine to carry out the clean operations first on all sets belonging to a given way (looping through sets) and then decrementing the way. Benchmarks showed that by swapping the ordering in which sets and ways are decremented in the v7 cache flushing routine, that uses set/way operations, time required to flush caches is reduced significantly, owing to improved writebacks throughput to the DRAM controller. Benchmarks results vary and depend heavily on the last level of cache tag RAM content when cache is cleaned and invalidated, ranging from 2x throughput when all tag RAM entries contain dirty lines mapping to sequential pages of RAM to 1x (ie no improvement) when all tag RAM accesses trigger a DRAM precharge/activate cycle, as the current code implies on most DRAM controller configurations. Acked-by: Catalin Marinas Acked-by: Nicolas Pitre Acked-by: Santosh Shilimkar Reviewed-by: Dave Martin Signed-off-by: Lorenzo Pieralisi Signed-off-by: Russell King --- arch/arm/mm/cache-v7.S | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index b5c467a65c2..778bcf88ee7 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -146,18 +146,18 @@ flush_levels: ldr r7, =0x7fff ands r7, r7, r1, lsr #13 @ extract max number of the index size loop1: - mov r9, r4 @ create working copy of max way size + mov r9, r7 @ create working copy of max index loop2: - ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 - THUMB( lsl r6, r9, r5 ) + ARM( orr r11, r10, r4, lsl r5 ) @ factor way and cache number into r11 + THUMB( lsl r6, r4, r5 ) THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 - ARM( orr r11, r11, r7, lsl r2 ) @ factor index number into r11 - THUMB( lsl r6, r7, r2 ) + ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11 + THUMB( lsl r6, r9, r2 ) THUMB( orr r11, r11, r6 ) @ factor index number into r11 mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way - subs r9, r9, #1 @ decrement the way + subs r9, r9, #1 @ decrement the index bge loop2 - subs r7, r7, #1 @ decrement the index + subs r4, r4, #1 @ decrement the way bge loop1 skip: add r10, r10, #2 @ increment cache number -- cgit v1.2.3-18-g5258 From d46cda12e8b0fa5082cb40eb4bbfcba66b603bb2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 Dec 2013 22:49:14 +0000 Subject: ARM: fix csum_tcpudp_magic() miscompilation There is a miscompilation of csum_tcpudp_magic() due to the way we pass the asm() operands in. Fortunately, this doesn't affect the IP code, but can affect anyone who passes ntohs(udp->len) as the length argument, or protocols with more than 8 bits. The problem stems from passing 16-bit operands into an asm() - GCC makes no guarantees about what may be in the high 16-bits of such a register passed into assembly which is in the "HI" machine mode. Address this by changing the way we handle the 16-bit arguments - since accumulating the protocol and length can never overflow, we can delegate this to the compiler to perform, and then accumulate it into the checksum inside the asm(), taking account of the endian-ness via an appropriate 32-bit rotation. While we are here, also realise that there's a chance to optimise this a little: several callers from IP code pass a constant zero as the initial sum. This is wasteful - if we detect this condition, we can optimise away one instruction. Tested-by: Maxime Bizon Signed-off-by: Russell King --- arch/arm/include/asm/checksum.h | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/arch/arm/include/asm/checksum.h b/arch/arm/include/asm/checksum.h index 6dcc1643086..52331511547 100644 --- a/arch/arm/include/asm/checksum.h +++ b/arch/arm/include/asm/checksum.h @@ -87,19 +87,33 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum) { - __asm__( - "adds %0, %1, %2 @ csum_tcpudp_nofold \n\ - adcs %0, %0, %3 \n" + u32 lenprot = len | proto << 16; + if (__builtin_constant_p(sum) && sum == 0) { + __asm__( + "adds %0, %1, %2 @ csum_tcpudp_nofold0 \n\t" #ifdef __ARMEB__ - "adcs %0, %0, %4 \n" + "adcs %0, %0, %3 \n\t" #else - "adcs %0, %0, %4, lsl #8 \n" + "adcs %0, %0, %3, ror #8 \n\t" #endif - "adcs %0, %0, %5 \n\ - adc %0, %0, #0" - : "=&r"(sum) - : "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto)) - : "cc"); + "adc %0, %0, #0" + : "=&r" (sum) + : "r" (daddr), "r" (saddr), "r" (lenprot) + : "cc"); + } else { + __asm__( + "adds %0, %1, %2 @ csum_tcpudp_nofold \n\t" + "adcs %0, %0, %3 \n\t" +#ifdef __ARMEB__ + "adcs %0, %0, %4 \n\t" +#else + "adcs %0, %0, %4, ror #8 \n\t" +#endif + "adc %0, %0, #0" + : "=&r"(sum) + : "r" (sum), "r" (daddr), "r" (saddr), "r" (lenprot) + : "cc"); + } return sum; } /* -- cgit v1.2.3-18-g5258 From 145bc292dce9dbdface2acf1e7e1f175729fb5fb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 10 Dec 2013 12:10:17 +0100 Subject: ARM: 7920/1: topology: Staticise non-exported symbols These symbols are only referenced in this source file so can be made static, and the efficiency table is constant data so can be declared as such. This avoids polluting the global namespace and fixes warnings from sparse. The function arch_scale_freq_power() is still not prototyped or static, this is a separate issue as this is overriding a weak symbol from the scheduler which neglects to provide a prototype. Signed-off-by: Mark Brown Signed-off-by: Russell King --- arch/arm/kernel/topology.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 85a87370f14..0bc94b1fd1a 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -68,16 +68,16 @@ struct cpu_efficiency { * Processors that are not defined in the table, * use the default SCHED_POWER_SCALE value for cpu_scale. */ -struct cpu_efficiency table_efficiency[] = { +static const struct cpu_efficiency table_efficiency[] = { {"arm,cortex-a15", 3891}, {"arm,cortex-a7", 2048}, {NULL, }, }; -unsigned long *__cpu_capacity; +static unsigned long *__cpu_capacity; #define cpu_capacity(cpu) __cpu_capacity[cpu] -unsigned long middle_capacity = 1; +static unsigned long middle_capacity = 1; /* * Iterate all CPUs' descriptor in DT and compute the efficiency @@ -89,7 +89,7 @@ unsigned long middle_capacity = 1; */ static void __init parse_dt_topology(void) { - struct cpu_efficiency *cpu_eff; + const struct cpu_efficiency *cpu_eff; struct device_node *cn = NULL; unsigned long min_capacity = (unsigned long)(-1); unsigned long max_capacity = 0; @@ -158,7 +158,7 @@ static void __init parse_dt_topology(void) * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the * function returns directly for SMP system. */ -void update_cpu_power(unsigned int cpu) +static void update_cpu_power(unsigned int cpu) { if (!cpu_capacity(cpu)) return; @@ -185,7 +185,7 @@ const struct cpumask *cpu_coregroup_mask(int cpu) return &cpu_topology[cpu].core_sibling; } -void update_siblings_masks(unsigned int cpuid) +static void update_siblings_masks(unsigned int cpuid) { struct cputopo_arm *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; int cpu; -- cgit v1.2.3-18-g5258 From 03aa6580e336c19e923372a3b6b72a300f24880c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 10 Dec 2013 20:12:27 +0100 Subject: ARM: 7921/1: mcpm: remove redundant dsb instructions prior to sev sync_cache_w already includes a dsb, so we can just use sev() directly then following a cache-sync. Acked-by: Dave Martin Acked-by: Nicolas Pitre Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/common/mcpm_entry.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c index 87c5f1b595b..1e361abc29e 100644 --- a/arch/arm/common/mcpm_entry.c +++ b/arch/arm/common/mcpm_entry.c @@ -166,7 +166,7 @@ void __mcpm_cpu_down(unsigned int cpu, unsigned int cluster) dmb(); mcpm_sync.clusters[cluster].cpus[cpu].cpu = CPU_DOWN; sync_cache_w(&mcpm_sync.clusters[cluster].cpus[cpu].cpu); - dsb_sev(); + sev(); } /* @@ -182,7 +182,7 @@ void __mcpm_outbound_leave_critical(unsigned int cluster, int state) dmb(); mcpm_sync.clusters[cluster].cluster = state; sync_cache_w(&mcpm_sync.clusters[cluster].cluster); - dsb_sev(); + sev(); } /* -- cgit v1.2.3-18-g5258 From 017f161a55b48807a73fc9dff0b69f081bf43ee3 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Wed, 6 Nov 2013 05:15:24 +0100 Subject: ARM: 7877/1: use built-in byte swap function Enable the compiler intrinsic for byte swapping on arch ARM. This allows the compiler to detect and be able to optimize out byte swappings, and has a very modest benefit on vmlinux size (Linaro gcc 4.8): text data bss dec hex filename 2840310 123932 61960 3026202 2e2d1a vmlinux-lart #orig 2840152 123932 61960 3026044 2e2c7c vmlinux-lart #builtin-bswap 6473120 314840 5616016 12403976 bd4508 vmlinux-mxs #orig 6472586 314848 5616016 12403450 bd42fa vmlinux-mxs #builtin-bswap 7419872 318372 379556 8117800 7bde28 vmlinux-imx_v6_v7 #orig 7419170 318364 379556 8117090 7bdb62 vmlinux-imx_v6_v7 #builtin-bswap Signed-off-by: Kim Phillips Reviewed-by: Nicolas Pitre Acked-by: David Woodhouse Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/boot/compressed/Makefile | 15 +++++++++++---- arch/arm/kernel/armksyms.c | 4 ++++ arch/arm/lib/Makefile | 2 +- arch/arm/lib/bswapsdi2.S | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 arch/arm/lib/bswapsdi2.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c1f1a7eee95..75597213c5b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -6,6 +6,7 @@ config ARM select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAVE_CUSTOM_GPIO_H select ARCH_MIGHT_HAVE_PC_PARPORT + select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF select ARCH_WANT_IPC_PARSE_VERSION select BUILDTIME_EXTABLE_SORT if MMU diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index e7190bb5998..4bb86d9a749 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -108,12 +108,12 @@ endif targets := vmlinux vmlinux.lds \ piggy.$(suffix_y) piggy.$(suffix_y).o \ - lib1funcs.o lib1funcs.S ashldi3.o ashldi3.S \ - font.o font.c head.o misc.o $(OBJS) + lib1funcs.o lib1funcs.S ashldi3.o ashldi3.S bswapsdi2.o \ + bswapsdi2.S font.o font.c head.o misc.o $(OBJS) # Make sure files are removed during clean extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern piggy.lz4 \ - lib1funcs.S ashldi3.S $(libfdt) $(libfdt_hdrs) \ + lib1funcs.S ashldi3.S bswapsdi2.S $(libfdt) $(libfdt_hdrs) \ hyp-stub.S ifeq ($(CONFIG_FUNCTION_TRACER),y) @@ -156,6 +156,12 @@ ashldi3 = $(obj)/ashldi3.o $(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S $(call cmd,shipped) +# For __bswapsi2, __bswapdi2 +bswapsdi2 = $(obj)/bswapsdi2.o + +$(obj)/bswapsdi2.S: $(srctree)/arch/$(SRCARCH)/lib/bswapsdi2.S + $(call cmd,shipped) + # We need to prevent any GOTOFF relocs being used with references # to symbols in the .bss section since we cannot relocate them # independently from the rest at run time. This can be achieved by @@ -177,7 +183,8 @@ if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \ fi $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ - $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE + $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \ + $(bswapsdi2) FORCE @$(check_for_multiple_zreladdr) $(call if_changed,ld) @$(check_for_bad_syms) diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 1f031ddd066..85e664b6a5f 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -35,6 +35,8 @@ extern void __ucmpdi2(void); extern void __udivsi3(void); extern void __umodsi3(void); extern void __do_div64(void); +extern void __bswapsi2(void); +extern void __bswapdi2(void); extern void __aeabi_idiv(void); extern void __aeabi_idivmod(void); @@ -114,6 +116,8 @@ EXPORT_SYMBOL(__ucmpdi2); EXPORT_SYMBOL(__udivsi3); EXPORT_SYMBOL(__umodsi3); EXPORT_SYMBOL(__do_div64); +EXPORT_SYMBOL(__bswapsi2); +EXPORT_SYMBOL(__bswapdi2); #ifdef CONFIG_AEABI EXPORT_SYMBOL(__aeabi_idiv); diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 47d7338561d..0573faab96a 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -13,7 +13,7 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ ucmpdi2.o lib1funcs.o div64.o \ io-readsb.o io-writesb.o io-readsl.o io-writesl.o \ - call_with_stack.o + call_with_stack.o bswapsdi2.o mmu-y := clear_user.o copy_page.o getuser.o putuser.o diff --git a/arch/arm/lib/bswapsdi2.S b/arch/arm/lib/bswapsdi2.S new file mode 100644 index 00000000000..9fcdd154eff --- /dev/null +++ b/arch/arm/lib/bswapsdi2.S @@ -0,0 +1,36 @@ +#include + +#if __LINUX_ARM_ARCH__ >= 6 +ENTRY(__bswapsi2) + rev r0, r0 + bx lr +ENDPROC(__bswapsi2) + +ENTRY(__bswapdi2) + rev r3, r0 + rev r0, r1 + mov r1, r3 + bx lr +ENDPROC(__bswapdi2) +#else +ENTRY(__bswapsi2) + eor r3, r0, r0, ror #16 + mov r3, r3, lsr #8 + bic r3, r3, #0xff00 + eor r0, r3, r0, ror #8 + mov pc, lr +ENDPROC(__bswapsi2) + +ENTRY(__bswapdi2) + mov ip, r1 + eor r3, ip, ip, ror #16 + eor r1, r0, r0, ror #16 + mov r1, r1, lsr #8 + mov r3, r3, lsr #8 + bic r3, r3, #0xff00 + bic r1, r1, #0xff00 + eor r1, r1, r0, ror #8 + eor r0, r3, ip, ror #8 + mov pc, lr +ENDPROC(__bswapdi2) +#endif -- cgit v1.2.3-18-g5258 From e68f31f4520ea5d1ddbcaddb320ef0b4201eef3c Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Fri, 13 Dec 2013 16:42:19 +0100 Subject: ARM: 7922/1: l2x0: add Marvell Tauros3 support This adds support for the Marvell Tauros3 cache controller which is compatible with pl310 cache controller but broadcasts L1 cache operations to L2 cache. While updating the binding documentation, clean up the list of possible compatibles. Also reorder driver compatibles to allow non-ARM derivated to be compatible to ARM cache controller compatibles. Signed-off-by: Sebastian Hesselbarth Reviewed-by: Mark Rutland Signed-off-by: Russell King --- Documentation/devicetree/bindings/arm/l2cc.txt | 23 ++++++------ arch/arm/include/asm/hardware/cache-l2x0.h | 1 + arch/arm/mm/cache-l2x0.c | 48 +++++++++++++++++++++----- arch/arm/mm/cache-tauros3.h | 41 ++++++++++++++++++++++ 4 files changed, 94 insertions(+), 19 deletions(-) create mode 100644 arch/arm/mm/cache-tauros3.h diff --git a/Documentation/devicetree/bindings/arm/l2cc.txt b/Documentation/devicetree/bindings/arm/l2cc.txt index c0c7626fd0f..b513cb8196f 100644 --- a/Documentation/devicetree/bindings/arm/l2cc.txt +++ b/Documentation/devicetree/bindings/arm/l2cc.txt @@ -7,20 +7,21 @@ The ARM L2 cache representation in the device tree should be done as follows: Required properties: - compatible : should be one of: - "arm,pl310-cache" - "arm,l220-cache" - "arm,l210-cache" - "marvell,aurora-system-cache": Marvell Controller designed to be + "arm,pl310-cache" + "arm,l220-cache" + "arm,l210-cache" + "bcm,bcm11351-a2-pl310-cache": DEPRECATED by "brcm,bcm11351-a2-pl310-cache" + "brcm,bcm11351-a2-pl310-cache": For Broadcom bcm11351 chipset where an + offset needs to be added to the address before passing down to the L2 + cache controller + "marvell,aurora-system-cache": Marvell Controller designed to be compatible with the ARM one, with system cache mode (meaning maintenance operations on L1 are broadcasted to the L2 and L2 performs the same operation). - "marvell,"aurora-outer-cache: Marvell Controller designed to be - compatible with the ARM one with outer cache mode. - "brcm,bcm11351-a2-pl310-cache": For Broadcom bcm11351 chipset where an - offset needs to be added to the address before passing down to the L2 - cache controller - "bcm,bcm11351-a2-pl310-cache": DEPRECATED by - "brcm,bcm11351-a2-pl310-cache" + "marvell,aurora-outer-cache": Marvell Controller designed to be + compatible with the ARM one with outer cache mode. + "marvell,tauros3-cache": Marvell Tauros3 cache controller, compatible + with arm,pl310-cache controller. - cache-unified : Specifies the cache is a unified cache. - cache-level : Should be set to 2 for a level 2 cache. - reg : Physical base address and size of cache controller's memory mapped diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 3b2c40b5bfa..6795ff743b3 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -131,6 +131,7 @@ struct l2x0_regs { unsigned long prefetch_ctrl; unsigned long pwr_ctrl; unsigned long ctrl; + unsigned long aux2_ctrl; }; extern struct l2x0_regs l2x0_saved_regs; diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 447da6ffadd..7abde2ce897 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -25,6 +25,7 @@ #include #include +#include "cache-tauros3.h" #include "cache-aurora-l2.h" #define CACHE_LINE_SIZE 32 @@ -767,6 +768,14 @@ static void aurora_save(void) l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); } +static void __init tauros3_save(void) +{ + l2x0_saved_regs.aux2_ctrl = + readl_relaxed(l2x0_base + TAUROS3_AUX2_CTRL); + l2x0_saved_regs.prefetch_ctrl = + readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); +} + static void l2x0_resume(void) { if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { @@ -821,6 +830,18 @@ static void aurora_resume(void) } } +static void tauros3_resume(void) +{ + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { + writel_relaxed(l2x0_saved_regs.aux2_ctrl, + l2x0_base + TAUROS3_AUX2_CTRL); + writel_relaxed(l2x0_saved_regs.prefetch_ctrl, + l2x0_base + L2X0_PREFETCH_CTRL); + } + + l2x0_resume(); +} + static void __init aurora_broadcast_l2_commands(void) { __u32 u; @@ -906,6 +927,15 @@ static const struct l2x0_of_data aurora_no_outer_data = { }, }; +static const struct l2x0_of_data tauros3_data = { + .setup = NULL, + .save = tauros3_save, + /* Tauros3 broadcasts L1 cache operations to L2 */ + .outer_cache = { + .resume = tauros3_resume, + }, +}; + static const struct l2x0_of_data bcm_l2x0_data = { .setup = pl310_of_setup, .save = pl310_save, @@ -922,17 +952,19 @@ static const struct l2x0_of_data bcm_l2x0_data = { }; static const struct of_device_id l2x0_ids[] __initconst = { - { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data }, - { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data }, { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data }, - { .compatible = "marvell,aurora-system-cache", - .data = (void *)&aurora_no_outer_data}, - { .compatible = "marvell,aurora-outer-cache", - .data = (void *)&aurora_with_outer_data}, - { .compatible = "brcm,bcm11351-a2-pl310-cache", - .data = (void *)&bcm_l2x0_data}, + { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data }, + { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data }, { .compatible = "bcm,bcm11351-a2-pl310-cache", /* deprecated name */ .data = (void *)&bcm_l2x0_data}, + { .compatible = "brcm,bcm11351-a2-pl310-cache", + .data = (void *)&bcm_l2x0_data}, + { .compatible = "marvell,aurora-outer-cache", + .data = (void *)&aurora_with_outer_data}, + { .compatible = "marvell,aurora-system-cache", + .data = (void *)&aurora_no_outer_data}, + { .compatible = "marvell,tauros3-cache", + .data = (void *)&tauros3_data }, {} }; diff --git a/arch/arm/mm/cache-tauros3.h b/arch/arm/mm/cache-tauros3.h new file mode 100644 index 00000000000..02c0a97cbc0 --- /dev/null +++ b/arch/arm/mm/cache-tauros3.h @@ -0,0 +1,41 @@ +/* + * Marvell Tauros3 cache controller includes + * + * Sebastian Hesselbarth + * + * based on GPL'ed 2.6 kernel sources + * (c) Marvell International Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARM_HARDWARE_TAUROS3_H +#define __ASM_ARM_HARDWARE_TAUROS3_H + +/* + * Marvell Tauros3 L2CC is compatible with PL310 r0p0 + * but with PREFETCH_CTRL (r2p0) and an additional event counter. + * Also, there is AUX2_CTRL for some Marvell specific control. + */ + +#define TAUROS3_EVENT_CNT2_CFG 0x224 +#define TAUROS3_EVENT_CNT2_VAL 0x228 +#define TAUROS3_INV_ALL 0x780 +#define TAUROS3_CLEAN_ALL 0x784 +#define TAUROS3_AUX2_CTRL 0x820 + +/* Registers shifts and masks */ +#define TAUROS3_AUX2_CTRL_LINEFILL_BURST8_EN (1 << 2) + +#endif -- cgit v1.2.3-18-g5258 From 6cefe92f2991c2bcd8f3a16faa9f4e3c91be48f2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 29 Nov 2013 01:03:35 +0000 Subject: ARM: footbridge: add sched_clock implementation Signed-off-by: Russell King --- arch/arm/mach-footbridge/common.h | 2 ++ arch/arm/mach-footbridge/dc21285-timer.c | 17 +++++++++++++++++ arch/arm/mach-footbridge/ebsa285.c | 1 + 3 files changed, 20 insertions(+) diff --git a/arch/arm/mach-footbridge/common.h b/arch/arm/mach-footbridge/common.h index 56607b3a773..b911e5587ec 100644 --- a/arch/arm/mach-footbridge/common.h +++ b/arch/arm/mach-footbridge/common.h @@ -10,3 +10,5 @@ extern void footbridge_init_irq(void); extern void isa_init_irq(unsigned int irq); extern void footbridge_restart(enum reboot_mode, const char *); + +extern void footbridge_sched_clock(void); diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 9ee78f7b499..785e4199f9c 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -104,3 +105,19 @@ void __init footbridge_timer_init(void) ce->cpumask = cpumask_of(smp_processor_id()); clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff); } + +static u32 notrace footbridge_read_sched_clock(void) +{ + return ~*CSR_TIMER3_VALUE; +} + +void __init footbridge_sched_clock(void) +{ + unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16); + + *CSR_TIMER3_LOAD = 0; + *CSR_TIMER3_CLR = 0; + *CSR_TIMER3_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16; + + setup_sched_clock(footbridge_read_sched_clock, 24, rate); +} diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c index 1a7235fb52a..3ff7a0c30a0 100644 --- a/arch/arm/mach-footbridge/ebsa285.c +++ b/arch/arm/mach-footbridge/ebsa285.c @@ -104,6 +104,7 @@ MACHINE_START(EBSA285, "EBSA285") .video_start = 0x000a0000, .video_end = 0x000bffff, .map_io = footbridge_map_io, + .init_early = footbridge_sched_clock, .init_irq = footbridge_init_irq, .init_time = footbridge_timer_init, .restart = footbridge_restart, -- cgit v1.2.3-18-g5258 From 4808972a1cac08f8e8d65419ab56d27a9da3a922 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 30 Nov 2013 12:21:21 +0000 Subject: ARM: footbridge: add one-shot mode for DC21285 timer Add a one-shot mode for the DC21285 timer. This allows us to use the NO_HZ modes on this platform. Signed-off-by: Russell King --- arch/arm/mach-footbridge/dc21285-timer.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 785e4199f9c..2babdbcaa69 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -47,6 +47,16 @@ static struct clocksource cksrc_dc21285 = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static int ckevt_dc21285_set_next_event(unsigned long delta, + struct clock_event_device *c) +{ + *CSR_TIMER1_CLR = 0; + *CSR_TIMER1_LOAD = delta; + *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16; + + return 0; +} + static void ckevt_dc21285_set_mode(enum clock_event_mode mode, struct clock_event_device *c) { @@ -59,7 +69,9 @@ static void ckevt_dc21285_set_mode(enum clock_event_mode mode, TIMER_CNTL_DIV16; break; - default: + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: *CSR_TIMER1_CNTL = 0; break; } @@ -67,9 +79,11 @@ static void ckevt_dc21285_set_mode(enum clock_event_mode mode, static struct clock_event_device ckevt_dc21285 = { .name = "dc21285_timer1", - .features = CLOCK_EVT_FEAT_PERIODIC, + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, .rating = 200, .irq = IRQ_TIMER1, + .set_next_event = ckevt_dc21285_set_next_event, .set_mode = ckevt_dc21285_set_mode, }; @@ -79,6 +93,10 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id) *CSR_TIMER1_CLR = 0; + /* Stop the timer if in one-shot mode */ + if (ce->mode == CLOCK_EVT_MODE_ONESHOT) + *CSR_TIMER1_CNTL = 0; + ce->event_handler(ce); return IRQ_HANDLED; -- cgit v1.2.3-18-g5258 From 8c65da6dc89ccb605d73773b1dd617e72982d971 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 30 Nov 2013 12:52:31 +0000 Subject: ARM: pgd allocation: retry on failure Make pgd allocation retry on failure; we really need this to succeed otherwise fork() can trigger OOMs. Signed-off-by: Russell King --- arch/arm/mm/pgd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c index 1046b373d1a..249379535be 100644 --- a/arch/arm/mm/pgd.c +++ b/arch/arm/mm/pgd.c @@ -23,7 +23,7 @@ #define __pgd_alloc() kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL) #define __pgd_free(pgd) kfree(pgd) #else -#define __pgd_alloc() (pgd_t *)__get_free_pages(GFP_KERNEL, 2) +#define __pgd_alloc() (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_REPEAT, 2) #define __pgd_free(pgd) free_pages((unsigned long)pgd, 2) #endif -- cgit v1.2.3-18-g5258 From 43024ed6fa831094b1e0eca7f18de372842ac9a1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 30 Nov 2013 13:41:26 +0000 Subject: ARM: footbridge: cleanup LEDs code Cleanup the LEDs code to use ioremap()/writeb() to access the register. This allows us to move the definitions out of a header file directly into the ebsa285 support code. Signed-off-by: Russell King --- arch/arm/mach-footbridge/common.c | 5 ----- arch/arm/mach-footbridge/ebsa285.c | 17 ++++++++++++++--- arch/arm/mach-footbridge/include/mach/hardware.h | 6 +----- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c index e0091685fd4..9e8220e3839 100644 --- a/arch/arm/mach-footbridge/common.c +++ b/arch/arm/mach-footbridge/common.c @@ -143,11 +143,6 @@ static struct map_desc fb_common_io_desc[] __initdata = { .pfn = __phys_to_pfn(DC21285_ARMCSR_BASE), .length = ARMCSR_SIZE, .type = MT_DEVICE, - }, { - .virtual = XBUS_BASE, - .pfn = __phys_to_pfn(0x40000000), - .length = XBUS_SIZE, - .type = MT_DEVICE, } }; diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c index 3ff7a0c30a0..aee8300f349 100644 --- a/arch/arm/mach-footbridge/ebsa285.c +++ b/arch/arm/mach-footbridge/ebsa285.c @@ -4,6 +4,7 @@ * EBSA285 machine fixup */ #include +#include #include #include #include @@ -17,6 +18,11 @@ /* LEDs */ #if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) +#define XBUS_AMBER_L BIT(0) +#define XBUS_GREEN_L BIT(1) +#define XBUS_RED_L BIT(2) +#define XBUS_TOGGLE BIT(7) + struct ebsa285_led { struct led_classdev cdev; u8 mask; @@ -36,6 +42,7 @@ static const struct { }; static unsigned char hw_led_state; +static void __iomem *xbus; static void ebsa285_led_set(struct led_classdev *cdev, enum led_brightness b) @@ -47,7 +54,7 @@ static void ebsa285_led_set(struct led_classdev *cdev, hw_led_state |= led->mask; else hw_led_state &= ~led->mask; - *XBUS_LEDS = hw_led_state; + writeb(hw_led_state, xbus); } static enum led_brightness ebsa285_led_get(struct led_classdev *cdev) @@ -65,9 +72,13 @@ static int __init ebsa285_leds_init(void) if (!machine_is_ebsa285()) return -ENODEV; + xbus = ioremap(XBUS_CS2, SZ_4K); + if (!xbus) + return -ENOMEM; + /* 3 LEDS all off */ - hw_led_state = XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED; - *XBUS_LEDS = hw_led_state; + hw_led_state = XBUS_AMBER_L | XBUS_GREEN_L | XBUS_RED_L; + writeb(hw_led_state, xbus); for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) { struct ebsa285_led *led; diff --git a/arch/arm/mach-footbridge/include/mach/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h index e3d6ccac216..02f6d7a706b 100644 --- a/arch/arm/mach-footbridge/include/mach/hardware.h +++ b/arch/arm/mach-footbridge/include/mach/hardware.h @@ -51,11 +51,7 @@ #define PCIMEM_SIZE 0x01000000 #define PCIMEM_BASE MMU_IO(0xf0000000, 0x80000000) -#define XBUS_LEDS ((volatile unsigned char *)(XBUS_BASE + 0x12000)) -#define XBUS_LED_AMBER (1 << 0) -#define XBUS_LED_GREEN (1 << 1) -#define XBUS_LED_RED (1 << 2) -#define XBUS_LED_TOGGLE (1 << 8) +#define XBUS_CS2 0x40012000 #define XBUS_SWITCH ((volatile unsigned char *)(XBUS_BASE + 0x12000)) #define XBUS_SWITCH_SWITCH ((*XBUS_SWITCH) & 15) -- cgit v1.2.3-18-g5258 From a472b09dd5bb00f7da3087f2a324eb963e8eaa9f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 29 Dec 2013 12:42:25 +0000 Subject: ARM: PCI: add legacy IDE IRQ implementation The IDE code used to specify the IDE IRQs for chipsets operating in legacy mode. This appears to no longer work, and this information must be provided by the arch. Do so. This partially fixes CY82C693 (and probably others) on Footbridge platforms. Signed-off-by: Russell King --- arch/arm/include/asm/pci.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h index a98a2e112fa..680a83e9446 100644 --- a/arch/arm/include/asm/pci.h +++ b/arch/arm/include/asm/pci.h @@ -57,12 +57,9 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine); -/* - * Dummy implementation; always return 0. - */ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) { - return 0; + return channel ? 15 : 14; } #endif /* __KERNEL__ */ -- cgit v1.2.3-18-g5258 From e1a5848e3398dca135f3ae77fe2e01145f9d8826 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 17 Dec 2013 19:17:11 +0100 Subject: ARM: 7924/1: mm: don't bother with reserved ttbr0 when running with LPAE With the new ASID allocation algorithm, active ASIDs at the time of a rollover event will be marked as reserved, so active mm_structs can continue to operate with the same ASID as before. This in turn means that we don't need to worry about allocating a new ASID to an mm that is currently active (installed in TTBR0). Since updating the pgd and ASID is atomic on LPAE systems (by virtue of the two being fields in the same hardware register), we can dispose of the reserved TTBR0 and rely on whatever tables we currently have live. Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/context.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 84e6f772e20..3ad0fdaa5cc 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -78,20 +78,21 @@ void a15_erratum_get_cpumask(int this_cpu, struct mm_struct *mm, #endif #ifdef CONFIG_ARM_LPAE -static void cpu_set_reserved_ttbr0(void) -{ - /* - * Set TTBR0 to swapper_pg_dir which contains only global entries. The - * ASID is set to 0. - */ - cpu_set_ttbr(0, __pa(swapper_pg_dir)); - isb(); -} +/* + * With LPAE, the ASID and page tables are updated atomicly, so there is + * no need for a reserved set of tables (the active ASID tracking prevents + * any issues across a rollover). + */ +#define cpu_set_reserved_ttbr0() #else static void cpu_set_reserved_ttbr0(void) { u32 ttb; - /* Copy TTBR1 into TTBR0 */ + /* + * Copy TTBR1 into TTBR0. + * This points at swapper_pg_dir, which contains only global + * entries so any speculative walks are perfectly safe. + */ asm volatile( " mrc p15, 0, %0, c2, c0, 1 @ read TTBR1\n" " mcr p15, 0, %0, c2, c0, 0 @ set TTBR0\n" -- cgit v1.2.3-18-g5258 From a7a04105068e9bb4cba43d97613c4f19b9e90b0c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 17 Dec 2013 19:17:31 +0100 Subject: ARM: 7925/1: mm: keep track of last ASID allocation to improve bitmap searching Since we only clear entries in the ASID bitmap on a rollover event, the bitmap tends to consist of a block of consecutive set bits followed by a block of consecutive clear bits. The exception to this rule is for ASIDs which have been carried over from a previous generation, but these are bound by the number of CPUs. This patch optimises our bitmap searching strategy, so that we search from the last successful allocation, rather than search from index 1 each time we allocate a new ASID. Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 3ad0fdaa5cc..52e6f13ac9c 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -180,6 +180,7 @@ static int is_reserved_asid(u64 asid) static u64 new_context(struct mm_struct *mm, unsigned int cpu) { + static u32 cur_idx = 1; u64 asid = atomic64_read(&mm->context.id); u64 generation = atomic64_read(&asid_generation); @@ -197,7 +198,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) * as we reserve ASID #0 to switch via TTBR0 and indicate * rollover events. */ - asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); + asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx); if (asid == NUM_USER_ASIDS) { generation = atomic64_add_return(ASID_FIRST_VERSION, &asid_generation); @@ -205,6 +206,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1); } __set_bit(asid, asid_map); + cur_idx = asid; asid |= generation; cpumask_clear(mm_cpumask(mm)); } -- cgit v1.2.3-18-g5258 From 5d49750933210457ec2d5e8507823e365b2604fb Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 17 Dec 2013 19:17:54 +0100 Subject: ARM: 7926/1: mm: flesh out and fix the comments in the ASID allocator The ASID allocator has to deal with some pretty horrible behaviours by the CPU, so expand on some of the comments in there so I remember why we can never allocate ASID zero to a userspace task. Reviewed-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/context.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 52e6f13ac9c..6eb97b3a748 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -36,8 +36,8 @@ * The context ID is used by debuggers and trace logic, and * should be unique within all running processes. * - * In big endian operation, the two 32 bit words are swapped if accesed by - * non 64-bit operations. + * In big endian operation, the two 32 bit words are swapped if accessed + * by non-64-bit operations. */ #define ASID_FIRST_VERSION (1ULL << ASID_BITS) #define NUM_USER_ASIDS ASID_FIRST_VERSION @@ -195,8 +195,11 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) * Allocate a free ASID. If we can't find one, take a * note of the currently active ASIDs and mark the TLBs * as requiring flushes. We always count from ASID #1, - * as we reserve ASID #0 to switch via TTBR0 and indicate - * rollover events. + * as we reserve ASID #0 to switch via TTBR0 and to + * avoid speculative page table walks from hitting in + * any partial walk caches, which could be populated + * from overlapping level-1 descriptors used to map both + * the module area and the userspace stack. */ asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx); if (asid == NUM_USER_ASIDS) { @@ -224,8 +227,9 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk) __check_vmalloc_seq(mm); /* - * Required during context switch to avoid speculative page table - * walking with the wrong TTBR. + * We cannot update the pgd and the ASID atomicly with classic + * MMU, so switch exclusively to global mappings to avoid + * speculative page table walking with the wrong TTBR. */ cpu_set_reserved_ttbr0(); -- cgit v1.2.3-18-g5258 From cb601185da996656e0bcef46a89a5a2d9619b071 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 17 Dec 2013 19:50:11 +0100 Subject: ARM: 7927/1: dcache: select DCACHE_WORD_ACCESS for big-endian CPUs With commit 11ec50caedb5 ("word-at-a-time: provide generic big-endian zero_bytemask implementation"), the asm-generic word-at-a-time code now provides a zero_bytemask implementation, allowing us to make use of DCACHE_WORD_ACCESS on big-endian CPUs, providing our load_unaligned_zeropad function is endianness-clean. This patch reworks the load_unaligned_zeropad fixup code to work for both big- and little-endian CPUs, then removes the !CPU_BIG_ENDIAN check when selecting DCACHE_WORD_ACCESS. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 2 +- arch/arm/include/asm/word-at-a-time.h | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 75597213c5b..810a0c4b03b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -12,7 +12,7 @@ config ARM select BUILDTIME_EXTABLE_SORT if MMU select CLONE_BACKWARDS select CPU_PM if (SUSPEND || CPU_IDLE) - select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN && MMU + select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI) select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_IDLE_POLL_SETUP diff --git a/arch/arm/include/asm/word-at-a-time.h b/arch/arm/include/asm/word-at-a-time.h index 4d52f92967a..a6d0a29861e 100644 --- a/arch/arm/include/asm/word-at-a-time.h +++ b/arch/arm/include/asm/word-at-a-time.h @@ -48,10 +48,14 @@ static inline unsigned long find_zero(unsigned long mask) return ret; } -#ifdef CONFIG_DCACHE_WORD_ACCESS - #define zero_bytemask(mask) (mask) +#else /* __ARMEB__ */ +#include +#endif + +#ifdef CONFIG_DCACHE_WORD_ACCESS + /* * Load an unaligned word from kernel space. * @@ -73,7 +77,11 @@ static inline unsigned long load_unaligned_zeropad(const void *addr) " bic %2, %2, #0x3\n" " ldr %0, [%2]\n" " lsl %1, %1, #0x3\n" +#ifndef __ARMEB__ " lsr %0, %0, %1\n" +#else + " lsl %0, %0, %1\n" +#endif " b 2b\n" " .popsection\n" " .pushsection __ex_table,\"a\"\n" @@ -86,11 +94,5 @@ static inline unsigned long load_unaligned_zeropad(const void *addr) return ret; } - #endif /* DCACHE_WORD_ACCESS */ - -#else /* __ARMEB__ */ -#include -#endif - #endif /* __ASM_ARM_WORD_AT_A_TIME_H */ -- cgit v1.2.3-18-g5258 From dce5c9e35bc4085bd33eccdb8c9ec5a643507a14 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 17 Dec 2013 19:50:16 +0100 Subject: ARM: 7928/1: kconfig: select HAVE_EFFICIENT_UNALIGNED_ACCESS for CPUv6+ && MMU Modern ARM CPUs can perform efficient unaligned memory accesses in hardware and this feature is relied up on by code such as the dcache word-at-a-time name hashing. This patch selects HAVE_EFFICIENT_UNALIGNED_ACCESS for these cores and reworks the kconfig select logic for DCACHE_WORD_ACCESS to use the new symbol. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 810a0c4b03b..929915e177a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -12,7 +12,7 @@ config ARM select BUILDTIME_EXTABLE_SORT if MMU select CLONE_BACKWARDS select CPU_PM if (SUSPEND || CPU_IDLE) - select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU + select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI) select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_IDLE_POLL_SETUP @@ -36,6 +36,7 @@ config ARM select HAVE_DMA_ATTRS select HAVE_DMA_CONTIGUOUS if MMU select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) + select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL) select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL) select HAVE_FUNCTION_TRACER if (!XIP_KERNEL) -- cgit v1.2.3-18-g5258 From 3077202eb95ad5bb6abd1e6dcb28d852c1fa48b3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 18 Dec 2013 04:26:52 +0100 Subject: ARM: 7929/1: Remove duplicate SCHED_HRTICK config option There are two SCHED_HRTICK config entries in Kconfig. This looks like a merge mistake. Fix it. Signed-off-by: Axel Lin Signed-off-by: Russell King --- arch/arm/Kconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 929915e177a..8c064a3e43d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1653,9 +1653,6 @@ config HZ config SCHED_HRTICK def_bool HIGH_RES_TIMERS -config SCHED_HRTICK - def_bool HIGH_RES_TIMERS - config THUMB2_KERNEL bool "Compile the kernel in Thumb-2 mode" if !CPU_THUMBONLY depends on (CPU_V7 || CPU_V7M) && !CPU_V6 && !CPU_V6K -- cgit v1.2.3-18-g5258 From 753d12434da3e9adae73c8fbe2b5eae84f4cfff8 Mon Sep 17 00:00:00 2001 From: Christian Daudt Date: Mon, 23 Dec 2013 09:00:01 +0100 Subject: ARM: 7932/1: bcm: Add DEBUG_LL console support This patch adds low level debug uart support to Broadcom mobile based SOCs. Signed-off-by: Christian Daudt Tested-by: Markus Mayer Acked-by: Olof Johansson Tested-by: Matt Porter Signed-off-by: Russell King --- arch/arm/Kconfig.debug | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 5765abf5ce8..7f0708c238e 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -94,6 +94,17 @@ choice depends on ARCH_BCM2835 select DEBUG_UART_PL01X + config DEBUG_BCM_KONA_UART + bool "Kernel low-level debugging messages via BCM KONA UART" + depends on ARCH_BCM + select DEBUG_UART_8250 + help + Say Y here if you want kernel low-level debugging support + on Broadcom SoC platforms. + This low level debug works for Broadcom + mobile SoCs in the Kona family of chips (e.g. bcm28155, + bcm11351, etc...) + config DEBUG_CLPS711X_UART1 bool "Kernel low-level debugging messages via UART1" depends on ARCH_CLPS711X @@ -988,6 +999,7 @@ config DEBUG_UART_PHYS default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2 default 0x20068000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3 default 0x20201000 if DEBUG_BCM2835 + default 0x3e000000 if DEBUG_BCM_KONA_UART default 0x4000e400 if DEBUG_LL_UART_EFM32 default 0x40090000 if ARCH_LPC32XX default 0x40100000 if DEBUG_PXA_UART1 @@ -1049,6 +1061,7 @@ config DEBUG_UART_VIRT default 0xfe018000 if DEBUG_MMP_UART3 default 0xfe100000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART default 0xfe230000 if DEBUG_PICOXCELL_UART + default 0xfe300000 if DEBUG_BCM_KONA_UART default 0xfe800000 if ARCH_IOP32X default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HI3716_UART default 0xfeb24000 if DEBUG_RK3X_UART0 @@ -1091,7 +1104,8 @@ config DEBUG_UART_8250_WORD default y if DEBUG_PICOXCELL_UART || DEBUG_SOCFPGA_UART || \ ARCH_KEYSTONE || \ DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \ - DEBUG_DAVINCI_DA8XX_UART2 || DEBUG_DAVINCI_TNETV107X_UART1 + DEBUG_DAVINCI_DA8XX_UART2 || DEBUG_DAVINCI_TNETV107X_UART1 || \ + DEBUG_BCM_KONA_UART config DEBUG_UART_8250_FLOW_CONTROL bool "Enable flow control for 8250 UART" -- cgit v1.2.3-18-g5258 From 162e68c08c916d0b701331a85291537fed2ad537 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 9 Jan 2014 13:31:48 +0100 Subject: ARM: 7935/1: sa1100: collie: add gpio-keys configuration collie has several GPIO lines that act like keys - Sync/Wakeup button on dock station is connected to GPIO line. Another one is connected to on/off button. Add corresponding gpio-keys configuration. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Russell King --- arch/arm/mach-sa1100/collie.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 7fb96ebdc0f..831a15824ec 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -242,10 +244,43 @@ struct platform_device collie_locomo_device = { .resource = locomo_resources, }; +static struct gpio_keys_button collie_gpio_keys[] = { + { + .type = EV_PWR, + .code = KEY_RESERVED, + .gpio = COLLIE_GPIO_ON_KEY, + .desc = "On key", + .wakeup = 1, + .active_low = 1, + }, + { + .type = EV_PWR, + .code = KEY_WAKEUP, + .gpio = COLLIE_GPIO_WAKEUP, + .desc = "Sync", + .wakeup = 1, + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data collie_gpio_keys_data = { + .buttons = collie_gpio_keys, + .nbuttons = ARRAY_SIZE(collie_gpio_keys), +}; + +static struct platform_device collie_gpio_keys_device = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &collie_gpio_keys_data, + }, +}; + static struct platform_device *devices[] __initdata = { &collie_locomo_device, &colliescoop_device, &collie_power_device, + &collie_gpio_keys_device, }; static struct mtd_partition collie_partitions[] = { -- cgit v1.2.3-18-g5258 From 23f6620a360dfd17ac9abbf28e944a9677504819 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 13 Jan 2014 23:34:56 +0000 Subject: ARM: fix ffs/fls implementations to match x86 ARMs ffs/fls implementations are not type compatible with x86, so when they're used in combination with min()/max(), they provoke warnings. Change these to be inline functions with the correct types, providing the clz as a separate documentation, and document their individual behaviours. Signed-off-by: Russell King --- arch/arm/include/asm/bitops.h | 54 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h index e691ec91e4d..b2e298a90d7 100644 --- a/arch/arm/include/asm/bitops.h +++ b/arch/arm/include/asm/bitops.h @@ -254,25 +254,59 @@ static inline int constant_fls(int x) } /* - * On ARMv5 and above those functions can be implemented around - * the clz instruction for much better code efficiency. + * On ARMv5 and above those functions can be implemented around the + * clz instruction for much better code efficiency. __clz returns + * the number of leading zeros, zero input will return 32, and + * 0x80000000 will return 0. */ +static inline unsigned int __clz(unsigned int x) +{ + unsigned int ret; + + asm("clz\t%0, %1" : "=r" (ret) : "r" (x)); + return ret; +} + +/* + * fls() returns zero if the input is zero, otherwise returns the bit + * position of the last set bit, where the LSB is 1 and MSB is 32. + */ static inline int fls(int x) { - int ret; - if (__builtin_constant_p(x)) return constant_fls(x); - asm("clz\t%0, %1" : "=r" (ret) : "r" (x)); - ret = 32 - ret; - return ret; + return 32 - __clz(x); +} + +/* + * __fls() returns the bit position of the last bit set, where the + * LSB is 0 and MSB is 31. Zero input is undefined. + */ +static inline unsigned long __fls(unsigned long x) +{ + return fls(x) - 1; +} + +/* + * ffs() returns zero if the input was zero, otherwise returns the bit + * position of the first set bit, where the LSB is 1 and MSB is 32. + */ +static inline int ffs(int x) +{ + return fls(x & -x); +} + +/* + * __ffs() returns the bit position of the first bit set, where the + * LSB is 0 and MSB is 31. Zero input is undefined. + */ +static inline unsigned long __ffs(unsigned long x) +{ + return ffs(x) - 1; } -#define __fls(x) (fls(x) - 1) -#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); }) -#define __ffs(x) (ffs(x) - 1) #define ffz(x) __ffs( ~(x) ) #endif -- cgit v1.2.3-18-g5258 From 1096813131dcfd7d86f156c14b43eb0fdbc090b6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 1 Jan 2014 11:59:44 +0000 Subject: Fix select-induced Kconfig warning for ZBOOT_ROM warning: (ARCH_MULTIPLATFORM && ARCH_CLPS711X && ARCH_PXA && SOC_EXYNOS5440 && ARCH_EMEV2) selects AUTO_ZRELADDR which has unmet direct dependencies (!ZBOOT_ROM) This is because it's possible to have ZBOOT_ROM enabled, but at the same time have another option enabled which selects AUTO_ZRELADDR overriding the !ZBOOT_ROM dependency. Fix this by reversing the dependencies between ZBOOT_ROM and the options which depend on !ZBOOT_ROM. Signed-off-by: Russell King --- arch/arm/Kconfig | 6 +++--- arch/arm/mach-imx/Kconfig | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 8c064a3e43d..f219c30eb4e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1945,6 +1945,7 @@ config ZBOOT_ROM_BSS config ZBOOT_ROM bool "Compressed boot loader in ROM/flash" depends on ZBOOT_ROM_TEXT != ZBOOT_ROM_BSS + depends on !ARM_APPENDED_DTB && !XIP_KERNEL && !AUTO_ZRELADDR help Say Y here if you intend to execute your compressed kernel image (zImage) directly from ROM or flash. If unsure, say N. @@ -1980,7 +1981,7 @@ endchoice config ARM_APPENDED_DTB bool "Use appended device tree blob to zImage (EXPERIMENTAL)" - depends on OF && !ZBOOT_ROM + depends on OF help With this option, the boot code will look for a device tree binary (DTB) appended to zImage @@ -2068,7 +2069,7 @@ endchoice config XIP_KERNEL bool "Kernel Execute-In-Place from ROM" - depends on !ZBOOT_ROM && !ARM_LPAE && !ARCH_MULTIPLATFORM + depends on !ARM_LPAE && !ARCH_MULTIPLATFORM help Execute-In-Place allows the kernel to run from non-volatile storage directly addressable by the CPU, such as NOR flash. This saves RAM @@ -2131,7 +2132,6 @@ config CRASH_DUMP config AUTO_ZRELADDR bool "Auto calculation of the decompressed kernel image address" - depends on !ZBOOT_ROM help ZRELADDR is the physical address where the decompressed kernel image will be placed. If AUTO_ZRELADDR is selected, the address diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 7a6e6f71006..fae0578fec7 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -3,7 +3,6 @@ config ARCH_MXC select ARCH_REQUIRE_GPIOLIB select ARM_CPU_SUSPEND if PM select ARM_PATCH_PHYS_VIRT - select AUTO_ZRELADDR if !ZBOOT_ROM select CLKSRC_MMIO select COMMON_CLK select GENERIC_ALLOCATOR -- cgit v1.2.3-18-g5258 From 571b14375019c3a66ef70d4d4a7083f4238aca30 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Jan 2014 11:22:18 +0000 Subject: ARM: ignore memory below PHYS_OFFSET If the kernel is loaded higher in physical memory than normal, and we calculate PHYS_OFFSET higher than the start of RAM, this leads to boot problems as we attempt to map part of this RAM into userspace. Rather than struggle with this, just truncate the mapping. Signed-off-by: Russell King --- arch/arm/kernel/setup.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 7a2dd4689a7..061cea820e3 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -660,6 +660,20 @@ int __init arm_add_memory(u64 start, u64 size) } #endif + if (aligned_start < PHYS_OFFSET) { + if (aligned_start + size <= PHYS_OFFSET) { + pr_info("Ignoring memory below PHYS_OFFSET: 0x%08llx-0x%08llx\n", + aligned_start, aligned_start + size); + return -EINVAL; + } + + pr_info("Ignoring memory below PHYS_OFFSET: 0x%08llx-0x%08llx\n", + aligned_start, (u64)PHYS_OFFSET); + + size -= PHYS_OFFSET - aligned_start; + aligned_start = PHYS_OFFSET; + } + bank->start = aligned_start; bank->size = size & ~(phys_addr_t)(PAGE_SIZE - 1); -- cgit v1.2.3-18-g5258 From 668bc38669f9a6d5e91846e9435b22b196cee9d1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 11 Jan 2014 11:25:37 +0000 Subject: ARM: SMP implementations are not supposed to return from smp_ops.cpu_die() Although we allow recovery in this case, this is not supposed to be the normal path for hotplugging a CPU back in. This path only exists to serve those rare platforms where it's not possible to power down the CPU or reset the CPU. This patch causes the kernel to print a message when a platform uses this path. Signed-off-by: Russell King --- arch/arm/kernel/smp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8c61325b8bf..b7b4c86e338 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -293,6 +293,9 @@ void __ref cpu_die(void) if (smp_ops.cpu_die) smp_ops.cpu_die(cpu); + pr_warn("CPU%u: smp_ops.cpu_die() returned, trying to resuscitate\n", + cpu); + /* * Do not return to the idle loop - jump back to the secondary * cpu initialisation. There's some initialisation which needs -- cgit v1.2.3-18-g5258