ARM updates for 7.4-rc1

- remove supersection support
 - set "current" earlier to avoid KASAN issues
 - fix a couple of corner cases in the alignment handler
 - fix wrong free function in iommu allocation path
 - cacheinfo updates
 - properly align hugetlb mappings
 - always set endianness on xscale
 - fix clang backtracer
 - avoid replacing active_asids if already 0
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEuNNh8scc2k/wOAE+9OeQG+StrGQFAmrZ0I8ACgkQ9OeQG+St
 rGSolA//VJVHLDLnM5UGhlmazwNnJVJPElYCLRNLJroLgaY5XznBJObeiMU9/xvS
 wFW/PBgqKZiFDtkvqVNp8fFgNCivKhJZhY7oH2a86y61YEO1rHNJb5pA7DQGcxaG
 pzeMjs4Ot0eLhqsJAUCr1ZxGM5OwbxoHgnABZhE0jlcNFMrJirrKwIQlrcyHFimp
 3O/1G73UvHZVFCeXUmEUZYwJCQ9f11WgEM4DFu7SSYQBhoKRkaYI4/MljueqEiZr
 /jsK14nZFbZCB0Kf9mBM7W10E5KQycIlsuDidB+FmIfIfPIL2UZUdACLEztPA6hP
 QfCDITJQaAnyf4B6Mk0QzqQij5DKjmU6qk/2FnOM5pYOSlmg2H900gxv62NXzTLz
 HIOWYwvDv+hA9acHRtSCgAmBF6oT6/HzDCHwZG5T8DmADn1wvvY4PkFg+q2Qh2pc
 9WQhVm5xkXsqBVnjhMgPTpjT4lWmPjFeZmeHL+KuQndmfc9kQR26UJNV3TqH/qGy
 mJVMjKYNxQQs7/kU8pqImOTcDYoKgNPi1XgQKG7kUi2vTUeko3mI/kNCv77tZZMZ
 U88wiljFRnae9xTa8NxqFmZka+ASxpOoyOLhRV4/VcSvKwY9L5DpNa7sq7MIhy8j
 XM3cLDz7PeIJOwBJviz4vOZnD9BhK9n7bHqO2e0LcaIPdlietAc=
 =S0pM
 -----END PGP SIGNATURE-----

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux

Pull ARM updates from Russell King:

 - remove supersection support

 - set "current" earlier to avoid KASAN issues

 - fix a couple of corner cases in the alignment handler

 - fix wrong free function in iommu allocation path

 - cacheinfo updates

 - properly align hugetlb mappings

 - always set endianness on xscale

 - fix clang backtracer

 - avoid replacing active_asids if already 0

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux:
  ARM: 9493/1: asid: Do not replace active_asids if already 0
  ARM: 9490/1: backtrace-clang: fix wrong sp usage for unwinding
  ARM: 9482/5: decompressor: always set endianess on xscale
  ARM: 9524/1: mm: align hugetlb mappings to the huge page size
  ARM: 9523/1: topology: allocate the cacheinfo early on the boot CPU
  ARM: 9522/1: cacheinfo: guard the CLIDR read in populate_cache_leaves()
  ARM: 9521/1: cacheinfo: count external caches in early_cache_level()
  ARM: 9520/1: cacheinfo: avoid out-of-bounds write in populate_cache_leaves()
  ARM: 9519/1: dma-mapping: Fix wrong free function in __iommu_alloc_simple() error path
  ARM: 9492/1: alignment: fix LSR #32 and ASR #32 offset decoding
  ARM: 9491/1: alignment: restore uaccess state on emulation fault
  ARM: 9488/1: smp: set current pointer in assembly before jumping into C
  ARM: 9486/1: set !LPAE MAX_PHYSMEM_BITS to 32 and remove supersection mappings
This commit is contained in:
Linus Torvalds 2026-10-22 07:58:09 -10:00
commit 5b6eaf4aeb
23 changed files with 162 additions and 239 deletions

View File

@ -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

View File

@ -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

View File

@ -7,6 +7,7 @@
*/
#include <linux/linkage.h>
#include <asm/cp15.h>
.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.

View File

@ -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
/*

View File

@ -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)

View File

@ -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))

View File

@ -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)
/*

View File

@ -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);
/*

View File

@ -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

View File

@ -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);
}
}

View File

@ -6,6 +6,7 @@
#include <linux/efi.h>
#include <linux/memblock.h>
#include <linux/screen_info.h>
#include <linux/sizes.h>
#include <asm/efi.h>
#include <asm/mach/map.h>
@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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();
/*

View File

@ -12,6 +12,7 @@
*/
#include <linux/arch_topology.h>
#include <linux/cacheinfo.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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);

View File

@ -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;
}

View File

@ -30,8 +30,6 @@
#include <linux/sizes.h>
#include <linux/memblock.h>
#include <asm/cp15.h>
#include <asm/cputype.h>
#include <asm/cacheflush.h>
#include <asm/early_ioremap.h>
#include <asm/mmu_context.h>
@ -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

View File

@ -11,6 +11,7 @@
#include <linux/io.h>
#include <linux/personality.h>
#include <linux/random.h>
#include <linux/hugetlb.h>
#include <asm/cachetype.h>
#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);

View File

@ -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)
{