diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 5f0a1a2e915a..777b035f1d74 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -41,14 +41,6 @@ ifeq ($(CONFIG_PXA_SHARPSL_DETECT_MACH_ID),y) OBJS += head-sharpsl.o endif -ifeq ($(CONFIG_CPU_ENDIAN_BE32),y) -ifeq ($(CONFIG_CPU_CP15),y) -OBJS += big-endian.o -else -# The endian should be set by h/w design. -endif -endif - # # We now have a PIC decompressor implementation. Decompressors running # from RAM should not define ZTEXTADDR. Decompressors running directly diff --git a/arch/arm/boot/compressed/big-endian.S b/arch/arm/boot/compressed/big-endian.S deleted file mode 100644 index 0e092c36da2f..000000000000 --- a/arch/arm/boot/compressed/big-endian.S +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * linux/arch/arm/boot/compressed/big-endian.S - * - * Switch CPU into big endian mode. - * Author: Nicolas Pitre - */ - - .section ".start", "ax" - - mrc p15, 0, r0, c1, c0, 0 @ read control reg - orr r0, r0, #(1 << 7) @ enable big endian mode - mcr p15, 0, r0, c1, c0, 0 @ write control reg - diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S index 20fa44d59f82..d6c3d0a76550 100644 --- a/arch/arm/boot/compressed/head-xscale.S +++ b/arch/arm/boot/compressed/head-xscale.S @@ -7,6 +7,7 @@ */ #include +#include .section ".start", "ax" @@ -14,6 +15,23 @@ __XScale_start: @ Preserve r8/r7 i.e. kernel entry values + @ set correct endianness for ixp4xx regardless of bootloader + mrc p15, 0, r0, c1, c0, 0 +#ifdef CONFIG_CPU_BIG_ENDIAN + orr r0, r0, #CR_B @ enable big endian mode +#else + bic r0, r0, #CR_B +#endif + mcr p15, 0, r0, c1, c0, 0 +0: mrc p15, 0, r0, c1, c0, 0 + tst r0, #0x80 +#ifdef CONFIG_CPU_BIG_ENDIAN + beq 0b +#else + bne 0b +#endif + sub pc, pc, #4 @ flush instruction pipeline + @ Data cache might be active. @ Be sure to flush kernel binary out of the cache, @ whatever state it is, before it is turned off. diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h index d48859fdf32c..f91c2a72b9dc 100644 --- a/arch/arm/include/asm/domain.h +++ b/arch/arm/include/asm/domain.h @@ -18,27 +18,10 @@ * DOMAIN_IO - domain 2 includes all IO only * DOMAIN_USER - domain 1 includes all user memory only * DOMAIN_KERNEL - domain 0 includes all kernel memory only - * - * The domain numbering depends on whether we support 36 physical - * address for I/O or not. Addresses above the 32 bit boundary can - * only be mapped using supersections and supersections can only - * be set for domain 0. We could just default to DOMAIN_IO as zero, - * but there may be systems with supersection support and no 36-bit - * addressing. In such cases, we want to map system memory with - * supersections to reduce TLB misses and footprint. - * - * 36-bit addressing and supersections are only available on - * CPUs based on ARMv6+ or the Intel XSC3 core. */ -#ifndef CONFIG_IO_36 #define DOMAIN_KERNEL 0 #define DOMAIN_USER 1 #define DOMAIN_IO 2 -#else -#define DOMAIN_KERNEL 2 -#define DOMAIN_USER 1 -#define DOMAIN_IO 0 -#endif #define DOMAIN_VECTORS 3 /* diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 7c2fa7dcec6d..e25749bfbf90 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -89,9 +89,9 @@ #if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE) /* - * Allow 16MB-aligned ioremap pages + * Allow 2MB-aligned ioremap pages */ -#define IOREMAP_MAX_ORDER 24 +#define IOREMAP_MAX_ORDER 21 #endif #define VECTORS_BASE UL(0xffff0000) diff --git a/arch/arm/include/asm/pgtable-2level-hwdef.h b/arch/arm/include/asm/pgtable-2level-hwdef.h index 556937e1790e..3fa254ac8a26 100644 --- a/arch/arm/include/asm/pgtable-2level-hwdef.h +++ b/arch/arm/include/asm/pgtable-2level-hwdef.h @@ -35,7 +35,6 @@ #define PMD_SECT_APX (_AT(pmdval_t, 1) << 15) /* v6 */ #define PMD_SECT_S (_AT(pmdval_t, 1) << 16) /* v6 */ #define PMD_SECT_nG (_AT(pmdval_t, 1) << 17) /* v6 */ -#define PMD_SECT_SUPER (_AT(pmdval_t, 1) << 18) /* v6 */ #define PMD_SECT_AF (_AT(pmdval_t, 0)) #define PMD_SECT_UNCACHED (_AT(pmdval_t, 0)) diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h index 6b5392e20f41..7e1c08fdd029 100644 --- a/arch/arm/include/asm/pgtable-2level.h +++ b/arch/arm/include/asm/pgtable-2level.h @@ -96,13 +96,6 @@ #define SECTION_SIZE (1UL << SECTION_SHIFT) #define SECTION_MASK (~(SECTION_SIZE-1)) -/* - * ARMv6 supersection address mask and size definitions. - */ -#define SUPERSECTION_SHIFT 24 -#define SUPERSECTION_SIZE (1UL << SUPERSECTION_SHIFT) -#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1)) - #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) /* diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 8c05a7f374d8..84aa6a663e81 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -43,7 +43,7 @@ extern void set_smp_ipi_range(int ipi_base, int nr_ipi); * Called from platform specific assembly code, this is the * secondary CPU entry point. */ -asmlinkage void secondary_start_kernel(struct task_struct *task); +asmlinkage void secondary_start_kernel(void); /* diff --git a/arch/arm/include/asm/sparsemem.h b/arch/arm/include/asm/sparsemem.h index 421e3415338a..6b512be3a34a 100644 --- a/arch/arm/include/asm/sparsemem.h +++ b/arch/arm/include/asm/sparsemem.h @@ -19,7 +19,11 @@ * These can be overridden in your mach/memory.h. */ #if !defined(MAX_PHYSMEM_BITS) || !defined(SECTION_SIZE_BITS) +#ifdef CONFIG_ARM_LPAE #define MAX_PHYSMEM_BITS 36 +#else +#define MAX_PHYSMEM_BITS 32 +#endif #define SECTION_SIZE_BITS 28 #endif diff --git a/arch/arm/kernel/cacheinfo.c b/arch/arm/kernel/cacheinfo.c index e1469b641780..993c8a134786 100644 --- a/arch/arm/kernel/cacheinfo.c +++ b/arch/arm/kernel/cacheinfo.c @@ -80,19 +80,21 @@ static void ci_leaf_init(struct cacheinfo *this_leaf, this_leaf->type = type; } +static bool clidr_present(void) +{ + /* CLIDR is not present before ARMv7/v7m */ + if (cpu_architecture() < CPU_ARCH_ARMv7) + return false; + + /* Don't try reading CLIDR if CTR declares old format */ + return FIELD_GET(CTR_FORMAT_MASK, read_cpuid_cachetype()) == CTR_FORMAT_ARMV7; +} + static int detect_cache_level(unsigned int *level_p, unsigned int *leaves_p) { unsigned int ctype, level, leaves; - u32 ctr, format; - /* CLIDR is not present before ARMv7/v7m */ - if (cpu_architecture() < CPU_ARCH_ARMv7) - return -EOPNOTSUPP; - - /* Don't try reading CLIDR if CTR declares old format */ - ctr = read_cpuid_cachetype(); - format = FIELD_GET(CTR_FORMAT_MASK, ctr); - if (format != CTR_FORMAT_ARMV7) + if (!clidr_present()) return -EOPNOTSUPP; for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) { @@ -111,13 +113,6 @@ static int detect_cache_level(unsigned int *level_p, unsigned int *leaves_p) return 0; } -int early_cache_level(unsigned int cpu) -{ - struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); - - return detect_cache_level(&this_cpu_ci->num_levels, &this_cpu_ci->num_leaves); -} - int init_cache_level(unsigned int cpu) { unsigned int level, leaves; @@ -146,26 +141,32 @@ int init_cache_level(unsigned int cpu) return 0; } +int early_cache_level(unsigned int cpu) +{ + return init_cache_level(cpu); +} + int populate_cache_leaves(unsigned int cpu) { unsigned int level, idx; enum cache_type type; struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); - struct cacheinfo *this_leaf = this_cpu_ci->info_list; - unsigned int arch = cpu_architecture(); + struct cacheinfo *infos = this_cpu_ci->info_list; - /* CLIDR is not present before ARMv7/v7m */ - if (arch < CPU_ARCH_ARMv7) - return -EOPNOTSUPP; + /* The device tree can describe caches CLIDR cannot fill in. */ + if (!clidr_present()) + return -ENOENT; for (idx = 0, level = 1; level <= this_cpu_ci->num_levels && - idx < this_cpu_ci->num_leaves; idx++, level++) { + idx < this_cpu_ci->num_leaves; level++) { type = get_cache_type(level); if (type == CACHE_TYPE_SEPARATE) { - ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level); - ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level); + if (idx + 1 >= this_cpu_ci->num_leaves) + break; + ci_leaf_init(&infos[idx++], CACHE_TYPE_DATA, level); + ci_leaf_init(&infos[idx++], CACHE_TYPE_INST, level); } else { - ci_leaf_init(this_leaf++, type, level); + ci_leaf_init(&infos[idx++], type, level); } } diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c index 6f9ec7d28a71..c14275257a8a 100644 --- a/arch/arm/kernel/efi.c +++ b/arch/arm/kernel/efi.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,18 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) .length = md->num_pages * EFI_PAGE_SIZE, }; + /* + * Non-LPAE page tables cannot map EFI runtime regions extending + * beyond the 32-bit physical address space. + */ + if (!IS_ENABLED(CONFIG_ARM_LPAE) && + (md->phys_addr >= SZ_4G || + md->num_pages > (SZ_4G - md->phys_addr) / EFI_PAGE_SIZE)) { + pr_warn("EFI runtime region at 0x%llx exceeds 32-bit physical address space\n", + md->phys_addr); + return -ERANGE; + } + /* * Order is important here: memory regions may have all of the * bits below set (and usually do), so we check them in order of diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index b9d6818f1ee1..f80bbfbd3a6f 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -116,6 +116,7 @@ ENTRY(secondary_startup) ldr r7, __secondary_data @ reload r7 ldr sp, [r7, #12] @ set up the stack pointer ldr r0, [r7, #16] @ set up task pointer + set_current r0, r1 mov fp, #0 b secondary_start_kernel ENDPROC(secondary_startup) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index f22c50d4bd41..a22403a629ef 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -442,6 +442,7 @@ ENTRY(__secondary_switched) adr_l r7, secondary_data + 12 @ get secondary_data.stack ldr sp, [r7] ldr r0, [r7, #4] @ get secondary_data.task + set_current r0, r1 mov fp, #0 b secondary_start_kernel ENDPROC(__secondary_switched) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index b5fb4697bc3f..a9f4600fe4d0 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -371,12 +371,9 @@ void __noreturn arch_cpu_idle_dead(void) */ __asm__("mov sp, %0\n" " mov fp, #0\n" - " mov r0, %1\n" " b secondary_start_kernel" : - : "r" (task_stack_page(current) + THREAD_SIZE - 8), - "r" (current) - : "r0"); + : "r" (task_stack_page(current) + THREAD_SIZE - 8)); unreachable(); } @@ -397,23 +394,15 @@ static void smp_store_cpu_info(unsigned int cpuid) check_cpu_icache_size(cpuid); } -static void set_current(struct task_struct *cur) -{ - /* Set TPIDRURO */ - asm("mcr p15, 0, %0, c13, c0, 3" :: "r"(cur) : "memory"); -} - /* * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ -asmlinkage void secondary_start_kernel(struct task_struct *task) +asmlinkage void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu; - set_current(task); - secondary_biglittle_init(); /* diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 2336ee2aa44a..e6b50cd43ce5 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include @@ -238,8 +239,20 @@ void store_cpu_topology(unsigned int cpuid) */ void __init init_cpu_topology(void) { + int cpu, ret; + reset_cpu_topology(); smp_wmb(); parse_dt_topology(); + + for_each_possible_cpu(cpu) { + ret = fetch_cache_info(cpu); + if (!ret) + continue; + /* CPUs without a usable CLIDR return -EOPNOTSUPP. */ + if (ret != -ENOENT && ret != -EOPNOTSUPP) + pr_err("Early cacheinfo failed, ret = %d\n", ret); + return; + } } diff --git a/arch/arm/lib/backtrace-clang.S b/arch/arm/lib/backtrace-clang.S index 290c52a60fc6..9a10828992af 100644 --- a/arch/arm/lib/backtrace-clang.S +++ b/arch/arm/lib/backtrace-clang.S @@ -107,8 +107,10 @@ ENDPROC(c_backtrace) /* * Switches the current frame to be the frame for dump_stack. + * (Only in case of current task using current registers) */ - add frame, sp, #24 @ switch to false frame + cmp frame, fp + addeq frame, sp, #24 @ switch to false frame for_each_frame: tst frame, mask @ Check for address exceptions bne no_frame diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 6574659dfb61..41d7b495ec45 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -328,7 +328,6 @@ config CPU_XSC3 select CPU_PABRT_LEGACY select CPU_THUMB_CAPABLE select CPU_TLB_V4WBI if MMU - select IO_36 # Marvell PJ1 (Mohawk) config CPU_MOHAWK @@ -676,12 +675,6 @@ config CPU_V7M_NUM_IRQ If unsure, keep default value. -# -# CPU supports 36-bit I/O -# -config IO_36 - bool - comment "Processor Features" config ARM_LPAE diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 812380f30ae3..f6c1e6b61179 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -341,6 +341,8 @@ static int do_alignment_ldrhstrh(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); + unsigned int ua_flags; + bool ua_saved = false; ai_half += 1; @@ -364,10 +366,11 @@ do_alignment_ldrhstrh(unsigned long addr, u32 instr, struct pt_regs *regs) user: if (LDST_L_BIT(instr)) { unsigned long val; - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; get16t_unaligned_check(val, addr); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); /* signed half-word? */ if (instr & 0x40) @@ -375,14 +378,17 @@ do_alignment_ldrhstrh(unsigned long addr, u32 instr, struct pt_regs *regs) regs->uregs[rd] = val; } else { - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; put16t_unaligned_check(regs->uregs[rd], addr); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); } return TYPE_LDST; fault: + if (ua_saved) + uaccess_restore(ua_flags); return TYPE_FAULT; } @@ -391,6 +397,8 @@ do_alignment_ldrdstrd(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); unsigned int rd2; + unsigned int ua_flags; + bool ua_saved = false; int load; if ((instr & 0xfe000000) == 0xe8000000) { @@ -425,26 +433,30 @@ do_alignment_ldrdstrd(unsigned long addr, u32 instr, struct pt_regs *regs) user: if (load) { unsigned long val, val2; - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; get32t_unaligned_check(val, addr); get32t_unaligned_check(val2, addr + 4); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); regs->uregs[rd] = val; regs->uregs[rd2] = val2; } else { - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; put32t_unaligned_check(regs->uregs[rd], addr); put32t_unaligned_check(regs->uregs[rd2], addr + 4); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); } return TYPE_LDST; bad: return TYPE_ERROR; fault: + if (ua_saved) + uaccess_restore(ua_flags); return TYPE_FAULT; } @@ -452,6 +464,8 @@ static int do_alignment_ldrstr(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); + unsigned int ua_flags; + bool ua_saved = false; ai_word += 1; @@ -469,18 +483,22 @@ do_alignment_ldrstr(unsigned long addr, u32 instr, struct pt_regs *regs) trans: if (LDST_L_BIT(instr)) { unsigned int val; - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; get32t_unaligned_check(val, addr); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); regs->uregs[rd] = val; } else { - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; put32t_unaligned_check(regs->uregs[rd], addr); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); } return TYPE_LDST; fault: + if (ua_saved) + uaccess_restore(ua_flags); return TYPE_FAULT; } @@ -502,6 +520,8 @@ do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd, rn, correction, nr_regs, regbits; unsigned long eaddr, newaddr; + unsigned int ua_flags; + bool ua_saved = false; if (LDM_S_BIT(instr)) goto bad; @@ -547,7 +567,8 @@ do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) #endif if (user_mode(regs)) { - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1) if (regbits & 1) { @@ -559,7 +580,7 @@ do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) put32t_unaligned_check(regs->uregs[rd], eaddr); eaddr += 4; } - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); } else { for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1) @@ -581,6 +602,8 @@ do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) return TYPE_DONE; fault: + if (ua_saved) + uaccess_restore(ua_flags); regs->ARM_pc -= correction; return TYPE_FAULT; @@ -892,11 +915,17 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) break; case SHIFT_LSR: - offset.un >>= shiftval; + if (shiftval == 0) + offset.un = 0; + else + offset.un >>= shiftval; break; case SHIFT_ASR: - offset.sn >>= shiftval; + if (shiftval == 0) + offset.sn >>= 31; + else + offset.sn >>= shiftval; break; case SHIFT_RORRRX: diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 4204ffa2d104..7c4e1e4ba77b 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c @@ -238,7 +238,7 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk) { unsigned long flags; unsigned int cpu = smp_processor_id(); - u64 asid; + u64 asid, old_active_asid; check_vmalloc_seq(mm); @@ -250,8 +250,17 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk) cpu_set_reserved_ttbr0(); asid = atomic64_read(&mm->context.id); - if (!((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS) - && atomic64_xchg(&per_cpu(active_asids, cpu), asid)) + + /* + * If our active_asids is zero, we are racing with an ASID roll-over + * on a different CPU, so skip the update (using cmpxchg if non-zero) + * and take the slow path. + */ + old_active_asid = atomic64_read(&per_cpu(active_asids, cpu)); + if (old_active_asid && + !((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS) && + atomic64_cmpxchg(&per_cpu(active_asids, cpu), + old_active_asid, asid)) goto switch_mm_fastpath; raw_spin_lock_irqsave(&cpu_asid_lock, flags); diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 7761099dde9e..fb2eb0ed7bb8 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1056,7 +1056,10 @@ static void *__iommu_alloc_simple(struct device *dev, size_t size, gfp_t gfp, return addr; err_mapping: - __free_from_pool(addr, size); + if (coherent_flag == COHERENT) + __dma_free_buffer(virt_to_page(addr), size); + else + __free_from_pool(addr, size); return NULL; } diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 27e64f782cb3..539b6c2995af 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -30,8 +30,6 @@ #include #include -#include -#include #include #include #include @@ -236,39 +234,6 @@ remap_area_sections(unsigned long virt, unsigned long pfn, return 0; } -static int -remap_area_supersections(unsigned long virt, unsigned long pfn, - size_t size, const struct mem_type *type) -{ - unsigned long addr = virt, end = virt + size; - pmd_t *pmd = pmd_off_k(addr); - - /* - * Remove and free any PTE-based mapping, and - * sync the current kernel mapping. - */ - unmap_area_sections(virt, size); - do { - unsigned long super_pmd_val, i; - - super_pmd_val = __pfn_to_phys(pfn) | type->prot_sect | - PMD_SECT_SUPER; - super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20; - - for (i = 0; i < 8; i++) { - pmd[0] = __pmd(super_pmd_val); - pmd[1] = __pmd(super_pmd_val); - flush_pmd_entry(pmd); - - addr += PMD_SIZE; - pmd += 2; - } - - pfn += SUPERSECTION_SIZE >> PAGE_SHIFT; - } while (addr < end); - - return 0; -} #endif static void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, @@ -278,15 +243,17 @@ static void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, int err; unsigned long addr; struct vm_struct *area; - phys_addr_t paddr = __pfn_to_phys(pfn); + phys_addr_t paddr; #ifndef CONFIG_ARM_LPAE /* - * High mappings must be supersection aligned + * The physical range must not extend beyond the 32-bit + * phys_addr_t */ - if (pfn >= 0x100000 && (paddr & ~SUPERSECTION_MASK)) + if (((u64)pfn << PAGE_SHIFT) + offset + size > SZ_4G) return NULL; #endif + paddr = __pfn_to_phys(pfn); type = get_mem_type(mtype); if (!type) @@ -300,7 +267,7 @@ static void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, /* * Try to reuse one of the static mapping whenever possible. */ - if (size && !(sizeof(phys_addr_t) == 4 && pfn >= 0x100000)) { + if (size) { struct static_vm *svm; svm = find_static_vm_paddr(paddr, size, mtype); @@ -326,13 +293,7 @@ static void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, area->phys_addr = paddr; #if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE) - if (DOMAIN_IO == 0 && - (((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) || - cpu_is_xsc3()) && pfn >= 0x100000 && - !((paddr | size | addr) & ~SUPERSECTION_MASK)) { - area->flags |= VM_ARM_SECTION_MAPPING; - err = remap_area_supersections(addr, pfn, size, type); - } else if (!((paddr | size | addr) & ~PMD_MASK)) { + if (!((paddr | size | addr) & ~PMD_MASK)) { area->flags |= VM_ARM_SECTION_MAPPING; err = remap_area_sections(addr, pfn, size, type); } else diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index 3dbb383c26d5..dbb3f07a7785 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #define COLOUR_ALIGN(addr,pgoff) \ @@ -72,7 +73,10 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, info.length = len; info.low_limit = mm->mmap_base; info.high_limit = TASK_SIZE; - info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; + if (filp && is_file_hugepages(filp)) + info.align_mask = huge_page_mask_align(filp); + else + info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; info.align_offset = pgoff << PAGE_SHIFT; return vm_unmapped_area(&info); } @@ -123,7 +127,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, info.length = len; info.low_limit = FIRST_USER_ADDRESS; info.high_limit = mm->mmap_base; - info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; + if (filp && is_file_hugepages(filp)) + info.align_mask = huge_page_mask_align(filp); + else + info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; info.align_offset = pgoff << PAGE_SHIFT; addr = vm_unmapped_area(&info); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 23b87b5ef7f1..5d0ae2529872 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -854,69 +854,6 @@ static void __init alloc_init_p4d(pgd_t *pgd, unsigned long addr, } while (p4d++, addr = next, addr != end); } -#ifndef CONFIG_ARM_LPAE -static void __init create_36bit_mapping(struct mm_struct *mm, - struct map_desc *md, - const struct mem_type *type, - bool ng) -{ - unsigned long addr, length, end; - phys_addr_t phys; - pgd_t *pgd; - - addr = md->virtual; - phys = __pfn_to_phys(md->pfn); - length = PAGE_ALIGN(md->length); - - if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) { - pr_err("MM: CPU does not support supersection mapping for 0x%08llx at 0x%08lx\n", - (long long)__pfn_to_phys((u64)md->pfn), addr); - return; - } - - /* N.B. ARMv6 supersections are only defined to work with domain 0. - * Since domain assignments can in fact be arbitrary, the - * 'domain == 0' check below is required to insure that ARMv6 - * supersections are only allocated for domain 0 regardless - * of the actual domain assignments in use. - */ - if (type->domain) { - pr_err("MM: invalid domain in supersection mapping for 0x%08llx at 0x%08lx\n", - (long long)__pfn_to_phys((u64)md->pfn), addr); - return; - } - - if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) { - pr_err("MM: cannot create mapping for 0x%08llx at 0x%08lx invalid alignment\n", - (long long)__pfn_to_phys((u64)md->pfn), addr); - return; - } - - /* - * Shift bits [35:32] of address into bits [23:20] of PMD - * (See ARMv6 spec). - */ - phys |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20); - - pgd = pgd_offset(mm, addr); - end = addr + length; - do { - p4d_t *p4d = p4d_offset(pgd, addr); - pud_t *pud = pud_offset(p4d, addr); - pmd_t *pmd = pmd_offset(pud, addr); - int i; - - for (i = 0; i < 16; i++) - *pmd++ = __pmd(phys | type->prot_sect | PMD_SECT_SUPER | - (ng ? PMD_SECT_nG : 0)); - - addr += SUPERSECTION_SIZE; - phys += SUPERSECTION_SIZE; - pgd += SUPERSECTION_SIZE >> PGDIR_SHIFT; - } while (addr != end); -} -#endif /* !CONFIG_ARM_LPAE */ - static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md, void *(*alloc)(unsigned long sz), bool ng) @@ -928,16 +865,6 @@ static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md, type = &mem_types[md->type]; -#ifndef CONFIG_ARM_LPAE - /* - * Catch 36-bit addresses - */ - if (md->pfn >= 0x100000) { - create_36bit_mapping(mm, md, type, ng); - return; - } -#endif - addr = md->virtual & PAGE_MASK; phys = __pfn_to_phys(md->pfn); length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); @@ -964,8 +891,7 @@ static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md, * Create the page directory entries and any necessary * page tables for the mapping specified by `md'. We * are able to cope here with varying sizes and address - * offsets, and we take full advantage of sections and - * supersections. + * offsets, and we take full advantage of sections. */ static void __init create_mapping(struct map_desc *md) {