diff options
author | Maxime Ripard <maxime@cerno.tech> | 2023-05-09 16:03:40 +0300 |
---|---|---|
committer | Maxime Ripard <maxime@cerno.tech> | 2023-05-09 16:03:40 +0300 |
commit | ff32fcca64437f679a2bf1c0a19d5def389a18e2 (patch) | |
tree | 122863d5d6159b30fd6834cbe599f8ce1b9e8144 /arch/parisc | |
parent | 79c87edd18ec49f5b6fb40175bd1b1fea9398fdb (diff) | |
parent | ac9a78681b921877518763ba0e89202254349d1b (diff) | |
download | linux-ff32fcca64437f679a2bf1c0a19d5def389a18e2.tar.xz |
Merge drm/drm-next into drm-misc-next
Start the 6.5 release cycle.
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Diffstat (limited to 'arch/parisc')
-rw-r--r-- | arch/parisc/Kconfig | 1 | ||||
-rw-r--r-- | arch/parisc/include/asm/cmpxchg.h | 4 | ||||
-rw-r--r-- | arch/parisc/include/asm/grfioctl.h | 38 | ||||
-rw-r--r-- | arch/parisc/include/asm/kgdb.h | 2 | ||||
-rw-r--r-- | arch/parisc/include/asm/pdc.h | 1 | ||||
-rw-r--r-- | arch/parisc/kernel/firmware.c | 27 | ||||
-rw-r--r-- | arch/parisc/kernel/module.c | 51 | ||||
-rw-r--r-- | arch/parisc/kernel/pacache.S | 2 | ||||
-rw-r--r-- | arch/parisc/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/parisc/kernel/real2.S | 5 | ||||
-rw-r--r-- | arch/parisc/kernel/smp.c | 4 | ||||
-rw-r--r-- | arch/parisc/kernel/sys_parisc.c | 166 |
12 files changed, 116 insertions, 187 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index a98940e64243..466a25525364 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -47,6 +47,7 @@ config PARISC select MODULES_USE_ELF_RELA select CLONE_BACKWARDS select TTY # Needed for pdc_cons.c + select HAS_IOPORT if PCI || EISA select HAVE_DEBUG_STACKOVERFLOW select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_HASH diff --git a/arch/parisc/include/asm/cmpxchg.h b/arch/parisc/include/asm/cmpxchg.h index 5f274be10567..c1d776bb16b4 100644 --- a/arch/parisc/include/asm/cmpxchg.h +++ b/arch/parisc/include/asm/cmpxchg.h @@ -22,7 +22,7 @@ extern unsigned long __xchg64(unsigned long, volatile unsigned long *); /* optimizer better get rid of switch since size is a constant */ static inline unsigned long -__xchg(unsigned long x, volatile void *ptr, int size) +__arch_xchg(unsigned long x, volatile void *ptr, int size) { switch (size) { #ifdef CONFIG_64BIT @@ -49,7 +49,7 @@ __xchg(unsigned long x, volatile void *ptr, int size) __typeof__(*(ptr)) __ret; \ __typeof__(*(ptr)) _x_ = (x); \ __ret = (__typeof__(*(ptr))) \ - __xchg((unsigned long)_x_, (ptr), sizeof(*(ptr))); \ + __arch_xchg((unsigned long)_x_, (ptr), sizeof(*(ptr))); \ __ret; \ }) diff --git a/arch/parisc/include/asm/grfioctl.h b/arch/parisc/include/asm/grfioctl.h index a740844a1581..597201530d20 100644 --- a/arch/parisc/include/asm/grfioctl.h +++ b/arch/parisc/include/asm/grfioctl.h @@ -59,42 +59,4 @@ #define CRT_ID_LEGO 0x35ACDA30 /* Lego FX5, FX10 ... */ #define CRT_ID_PINNACLE 0x35ACDA16 /* Pinnacle FXe */ -/* structure for ioctl(GCDESCRIBE) */ - -#define gaddr_t unsigned long /* FIXME: PA2.0 (64bit) portable ? */ - -struct grf_fbinfo { - unsigned int id; /* upper 32 bits of graphics id */ - unsigned int mapsize; /* mapped size of framebuffer */ - unsigned int dwidth, dlength;/* x and y sizes */ - unsigned int width, length; /* total x and total y size */ - unsigned int xlen; /* x pitch size */ - unsigned int bpp, bppu; /* bits per pixel and used bpp */ - unsigned int npl, nplbytes; /* # of planes and bytes per plane */ - char name[32]; /* name of the device (from ROM) */ - unsigned int attr; /* attributes */ - gaddr_t fbbase, regbase;/* framebuffer and register base addr */ - gaddr_t regions[6]; /* region bases */ -}; - -#define GCID _IOR('G', 0, int) -#define GCON _IO('G', 1) -#define GCOFF _IO('G', 2) -#define GCAON _IO('G', 3) -#define GCAOFF _IO('G', 4) -#define GCMAP _IOWR('G', 5, int) -#define GCUNMAP _IOWR('G', 6, int) -#define GCMAP_HPUX _IO('G', 5) -#define GCUNMAP_HPUX _IO('G', 6) -#define GCLOCK _IO('G', 7) -#define GCUNLOCK _IO('G', 8) -#define GCLOCK_MINIMUM _IO('G', 9) -#define GCUNLOCK_MINIMUM _IO('G', 10) -#define GCSTATIC_CMAP _IO('G', 11) -#define GCVARIABLE_CMAP _IO('G', 12) -#define GCTERM _IOWR('G',20,int) /* multi-headed Tomcat */ -#define GCDESCRIBE _IOR('G', 21, struct grf_fbinfo) -#define GCFASTLOCK _IO('G', 26) - #endif /* __ASM_PARISC_GRFIOCTL_H */ - diff --git a/arch/parisc/include/asm/kgdb.h b/arch/parisc/include/asm/kgdb.h index f23e7f8f13a5..317cd434bee3 100644 --- a/arch/parisc/include/asm/kgdb.h +++ b/arch/parisc/include/asm/kgdb.h @@ -17,6 +17,8 @@ #define NUMREGBYTES sizeof(struct parisc_gdb_regs) #define BUFMAX 4096 +#define KGDB_MAX_BREAKPOINTS 40 + #define CACHE_FLUSH_IS_SAFE 1 #ifndef __ASSEMBLY__ diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h index 40793bef8429..2b4fad8328e8 100644 --- a/arch/parisc/include/asm/pdc.h +++ b/arch/parisc/include/asm/pdc.h @@ -80,6 +80,7 @@ int pdc_do_firm_test_reset(unsigned long ftc_bitmap); int pdc_do_reset(void); int pdc_soft_power_info(unsigned long *power_reg); int pdc_soft_power_button(int sw_control); +int pdc_soft_power_button_panic(int sw_control); void pdc_io_reset(void); void pdc_io_reset_devices(void); int pdc_iodc_getc(void); diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index 6817892a2c58..cc124d9f1f7f 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -1232,15 +1232,18 @@ int __init pdc_soft_power_info(unsigned long *power_reg) } /* - * pdc_soft_power_button - Control the soft power button behaviour - * @sw_control: 0 for hardware control, 1 for software control + * pdc_soft_power_button{_panic} - Control the soft power button behaviour + * @sw_control: 0 for hardware control, 1 for software control * * * This PDC function places the soft power button under software or * hardware control. - * Under software control the OS may control to when to allow to shut - * down the system. Under hardware control pressing the power button + * Under software control the OS may control to when to allow to shut + * down the system. Under hardware control pressing the power button * powers off the system immediately. + * + * The _panic version relies on spin_trylock to prevent deadlock + * on panic path. */ int pdc_soft_power_button(int sw_control) { @@ -1254,6 +1257,22 @@ int pdc_soft_power_button(int sw_control) return retval; } +int pdc_soft_power_button_panic(int sw_control) +{ + int retval; + unsigned long flags; + + if (!spin_trylock_irqsave(&pdc_lock, flags)) { + pr_emerg("Couldn't enable soft power button\n"); + return -EBUSY; /* ignored by the panic notifier */ + } + + retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, __pa(pdc_result), sw_control); + spin_unlock_irqrestore(&pdc_lock, flags); + + return retval; +} + /* * pdc_io_reset - Hack to avoid overlapping range registers of Bridges devices. * Primarily a problem on T600 (which parisc-linux doesn't support) but diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 7df140545b22..f6e38c4d3904 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -27,9 +27,9 @@ * We are not doing SEGREL32 handling correctly. According to the ABI, we * should do a value offset, like this: * if (in_init(me, (void *)val)) - * val -= (uint32_t)me->init_layout.base; + * val -= (uint32_t)me->mem[MOD_INIT_TEXT].base; * else - * val -= (uint32_t)me->core_layout.base; + * val -= (uint32_t)me->mem[MOD_TEXT].base; * However, SEGREL32 is used only for PARISC unwind entries, and we want * those entries to have an absolute address, and not just an offset. * @@ -76,25 +76,6 @@ * allows us to allocate up to 4095 GOT entries. */ #define MAX_GOTS 4095 -/* three functions to determine where in the module core - * or init pieces the location is */ -static inline int in_init(struct module *me, void *loc) -{ - return (loc >= me->init_layout.base && - loc <= (me->init_layout.base + me->init_layout.size)); -} - -static inline int in_core(struct module *me, void *loc) -{ - return (loc >= me->core_layout.base && - loc <= (me->core_layout.base + me->core_layout.size)); -} - -static inline int in_local(struct module *me, void *loc) -{ - return in_init(me, loc) || in_core(me, loc); -} - #ifndef CONFIG_64BIT struct got_entry { Elf32_Addr addr; @@ -302,6 +283,7 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr, { unsigned long gots = 0, fdescs = 0, len; unsigned int i; + struct module_memory *mod_mem; len = hdr->e_shnum * sizeof(me->arch.section[0]); me->arch.section = kzalloc(len, GFP_KERNEL); @@ -346,14 +328,15 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr, me->arch.section[s].stub_entries += count; } + mod_mem = &me->mem[MOD_TEXT]; /* align things a bit */ - me->core_layout.size = ALIGN(me->core_layout.size, 16); - me->arch.got_offset = me->core_layout.size; - me->core_layout.size += gots * sizeof(struct got_entry); + mod_mem->size = ALIGN(mod_mem->size, 16); + me->arch.got_offset = mod_mem->size; + mod_mem->size += gots * sizeof(struct got_entry); - me->core_layout.size = ALIGN(me->core_layout.size, 16); - me->arch.fdesc_offset = me->core_layout.size; - me->core_layout.size += fdescs * sizeof(Elf_Fdesc); + mod_mem->size = ALIGN(mod_mem->size, 16); + me->arch.fdesc_offset = mod_mem->size; + mod_mem->size += fdescs * sizeof(Elf_Fdesc); me->arch.got_max = gots; me->arch.fdesc_max = fdescs; @@ -371,7 +354,7 @@ static Elf64_Word get_got(struct module *me, unsigned long value, long addend) BUG_ON(value == 0); - got = me->core_layout.base + me->arch.got_offset; + got = me->mem[MOD_TEXT].base + me->arch.got_offset; for (i = 0; got[i].addr; i++) if (got[i].addr == value) goto out; @@ -389,7 +372,7 @@ static Elf64_Word get_got(struct module *me, unsigned long value, long addend) #ifdef CONFIG_64BIT static Elf_Addr get_fdesc(struct module *me, unsigned long value) { - Elf_Fdesc *fdesc = me->core_layout.base + me->arch.fdesc_offset; + Elf_Fdesc *fdesc = me->mem[MOD_TEXT].base + me->arch.fdesc_offset; if (!value) { printk(KERN_ERR "%s: zero OPD requested!\n", me->name); @@ -407,7 +390,7 @@ static Elf_Addr get_fdesc(struct module *me, unsigned long value) /* Create new one */ fdesc->addr = value; - fdesc->gp = (Elf_Addr)me->core_layout.base + me->arch.got_offset; + fdesc->gp = (Elf_Addr)me->mem[MOD_TEXT].base + me->arch.got_offset; return (Elf_Addr)fdesc; } #endif /* CONFIG_64BIT */ @@ -742,7 +725,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, loc, val); val += addend; /* can we reach it locally? */ - if (in_local(me, (void *)val)) { + if (within_module(val, me)) { /* this is the case where the symbol is local * to the module, but in a different section, * so stub the jump in case it's more than 22 @@ -801,7 +784,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, break; case R_PARISC_FPTR64: /* 64-bit function address */ - if(in_local(me, (void *)(val + addend))) { + if (within_module(val + addend, me)) { *loc64 = get_fdesc(me, val+addend); pr_debug("FDESC for %s at %llx points to %llx\n", strtab + sym->st_name, *loc64, @@ -839,7 +822,7 @@ register_unwind_table(struct module *me, table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr; end = table + sechdrs[me->arch.unwind_section].sh_size; - gp = (Elf_Addr)me->core_layout.base + me->arch.got_offset; + gp = (Elf_Addr)me->mem[MOD_TEXT].base + me->arch.got_offset; pr_debug("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n", me->arch.unwind_section, table, end, gp); @@ -977,7 +960,7 @@ void module_arch_cleanup(struct module *mod) #ifdef CONFIG_64BIT void *dereference_module_function_descriptor(struct module *mod, void *ptr) { - unsigned long start_opd = (Elf64_Addr)mod->core_layout.base + + unsigned long start_opd = (Elf64_Addr)mod->mem[MOD_TEXT].base + mod->arch.fdesc_offset; unsigned long end_opd = start_opd + mod->arch.fdesc_count * sizeof(Elf64_Fdesc); diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 9a0018f1f42c..541370d14559 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -889,6 +889,7 @@ ENDPROC_CFI(flush_icache_page_asm) ENTRY_CFI(flush_kernel_dcache_page_asm) 88: ldil L%dcache_stride, %r1 ldw R%dcache_stride(%r1), %r23 + depi_safe 0, 31,PAGE_SHIFT, %r26 /* Clear any offset bits */ #ifdef CONFIG_64BIT depdi,z 1, 63-PAGE_SHIFT,1, %r25 @@ -925,6 +926,7 @@ ENDPROC_CFI(flush_kernel_dcache_page_asm) ENTRY_CFI(purge_kernel_dcache_page_asm) 88: ldil L%dcache_stride, %r1 ldw R%dcache_stride(%r1), %r23 + depi_safe 0, 31,PAGE_SHIFT, %r26 /* Clear any offset bits */ #ifdef CONFIG_64BIT depdi,z 1, 63-PAGE_SHIFT,1, %r25 diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index c064719b49b0..97c6f875bd0e 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -159,7 +159,7 @@ EXPORT_SYMBOL(running_on_qemu); /* * Called from the idle thread for the CPU which has been shutdown. */ -void arch_cpu_idle_dead(void) +void __noreturn arch_cpu_idle_dead(void) { #ifdef CONFIG_HOTPLUG_CPU idle_task_exit(); diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S index 4dc12c4c0980..509d18b8e0e6 100644 --- a/arch/parisc/kernel/real2.S +++ b/arch/parisc/kernel/real2.S @@ -235,9 +235,6 @@ ENTRY_CFI(real64_call_asm) /* save fn */ copy %arg2, %r31 - /* set up the new ap */ - ldo 64(%arg1), %r29 - /* load up the arg registers from the saved arg area */ /* 32-bit calling convention passes first 4 args in registers */ ldd 0*REG_SZ(%arg1), %arg0 /* note overwriting arg0 */ @@ -249,7 +246,9 @@ ENTRY_CFI(real64_call_asm) ldd 7*REG_SZ(%arg1), %r19 ldd 1*REG_SZ(%arg1), %arg1 /* do this one last! */ + /* set up real-mode stack and real-mode ap */ tophys_r1 %sp + ldo -16(%sp), %r29 /* Reference param save area */ b,l rfi_virt2real,%r2 nop diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 7dbd92cafae3..b7fc859fa87d 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -246,8 +246,8 @@ void kgdb_roundup_cpus(void) inline void smp_send_stop(void) { send_IPI_allbutself(IPI_CPU_STOP); } -void -smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); } +void +arch_smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); } void smp_send_all_nop(void) diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 09a34b07f02e..39acccabf2ed 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -25,31 +25,26 @@ #include <linux/random.h> #include <linux/compat.h> -/* we construct an artificial offset for the mapping based on the physical - * address of the kernel mapping variable */ -#define GET_LAST_MMAP(filp) \ - (filp ? ((unsigned long) filp->f_mapping) >> 8 : 0UL) -#define SET_LAST_MMAP(filp, val) \ - { /* nothing */ } - -static int get_offset(unsigned int last_mmap) -{ - return (last_mmap & (SHM_COLOUR-1)) >> PAGE_SHIFT; -} +/* + * Construct an artificial page offset for the mapping based on the physical + * address of the kernel file mapping variable. + */ +#define GET_FILP_PGOFF(filp) \ + (filp ? (((unsigned long) filp->f_mapping) >> 8) \ + & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL) -static unsigned long shared_align_offset(unsigned int last_mmap, +static unsigned long shared_align_offset(unsigned long filp_pgoff, unsigned long pgoff) { - return (get_offset(last_mmap) + pgoff) << PAGE_SHIFT; + return (filp_pgoff + pgoff) << PAGE_SHIFT; } static inline unsigned long COLOR_ALIGN(unsigned long addr, - unsigned int last_mmap, unsigned long pgoff) + unsigned long filp_pgoff, unsigned long pgoff) { unsigned long base = (addr+SHM_COLOUR-1) & ~(SHM_COLOUR-1); unsigned long off = (SHM_COLOUR-1) & - (shared_align_offset(last_mmap, pgoff) << PAGE_SHIFT); - + shared_align_offset(filp_pgoff, pgoff); return base + off; } @@ -98,126 +93,91 @@ static unsigned long mmap_upper_limit(struct rlimit *rlim_stack) return PAGE_ALIGN(STACK_TOP - stack_base); } +enum mmap_allocation_direction {UP, DOWN}; -unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) +static unsigned long arch_get_unmapped_area_common(struct file *filp, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags, enum mmap_allocation_direction dir) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma, *prev; - unsigned long task_size = TASK_SIZE; - int do_color_align, last_mmap; + unsigned long filp_pgoff; + int do_color_align; struct vm_unmapped_area_info info; - if (len > task_size) + if (unlikely(len > TASK_SIZE)) return -ENOMEM; do_color_align = 0; if (filp || (flags & MAP_SHARED)) do_color_align = 1; - last_mmap = GET_LAST_MMAP(filp); + filp_pgoff = GET_FILP_PGOFF(filp); if (flags & MAP_FIXED) { - if ((flags & MAP_SHARED) && last_mmap && - (addr - shared_align_offset(last_mmap, pgoff)) + /* Even MAP_FIXED mappings must reside within TASK_SIZE */ + if (TASK_SIZE - len < addr) + return -EINVAL; + + if ((flags & MAP_SHARED) && filp && + (addr - shared_align_offset(filp_pgoff, pgoff)) & (SHM_COLOUR - 1)) return -EINVAL; - goto found_addr; + return addr; } if (addr) { - if (do_color_align && last_mmap) - addr = COLOR_ALIGN(addr, last_mmap, pgoff); + if (do_color_align) + addr = COLOR_ALIGN(addr, filp_pgoff, pgoff); else addr = PAGE_ALIGN(addr); vma = find_vma_prev(mm, addr, &prev); - if (task_size - len >= addr && + if (TASK_SIZE - len >= addr && (!vma || addr + len <= vm_start_gap(vma)) && (!prev || addr >= vm_end_gap(prev))) - goto found_addr; + return addr; } - info.flags = 0; info.length = len; + info.align_mask = do_color_align ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0; + info.align_offset = shared_align_offset(filp_pgoff, pgoff); + + if (dir == DOWN) { + info.flags = VM_UNMAPPED_AREA_TOPDOWN; + info.low_limit = PAGE_SIZE; + info.high_limit = mm->mmap_base; + addr = vm_unmapped_area(&info); + if (!(addr & ~PAGE_MASK)) + return addr; + VM_BUG_ON(addr != -ENOMEM); + + /* + * A failed mmap() very likely causes application failure, + * so fall back to the bottom-up function here. This scenario + * can happen with large stack limits and large mmap() + * allocations. + */ + } + + info.flags = 0; info.low_limit = mm->mmap_legacy_base; info.high_limit = mmap_upper_limit(NULL); - info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0; - info.align_offset = shared_align_offset(last_mmap, pgoff); - addr = vm_unmapped_area(&info); - -found_addr: - if (do_color_align && !last_mmap && !(addr & ~PAGE_MASK)) - SET_LAST_MMAP(filp, addr - (pgoff << PAGE_SHIFT)); - - return addr; + return vm_unmapped_area(&info); } -unsigned long -arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - const unsigned long len, const unsigned long pgoff, - const unsigned long flags) +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) { - struct vm_area_struct *vma, *prev; - struct mm_struct *mm = current->mm; - unsigned long addr = addr0; - int do_color_align, last_mmap; - struct vm_unmapped_area_info info; - - /* requested length too big for entire address space */ - if (len > TASK_SIZE) - return -ENOMEM; - - do_color_align = 0; - if (filp || (flags & MAP_SHARED)) - do_color_align = 1; - last_mmap = GET_LAST_MMAP(filp); - - if (flags & MAP_FIXED) { - if ((flags & MAP_SHARED) && last_mmap && - (addr - shared_align_offset(last_mmap, pgoff)) - & (SHM_COLOUR - 1)) - return -EINVAL; - goto found_addr; - } - - /* requesting a specific address */ - if (addr) { - if (do_color_align && last_mmap) - addr = COLOR_ALIGN(addr, last_mmap, pgoff); - else - addr = PAGE_ALIGN(addr); - - vma = find_vma_prev(mm, addr, &prev); - if (TASK_SIZE - len >= addr && - (!vma || addr + len <= vm_start_gap(vma)) && - (!prev || addr >= vm_end_gap(prev))) - goto found_addr; - } - - info.flags = VM_UNMAPPED_AREA_TOPDOWN; - info.length = len; - info.low_limit = PAGE_SIZE; - info.high_limit = mm->mmap_base; - info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0; - info.align_offset = shared_align_offset(last_mmap, pgoff); - addr = vm_unmapped_area(&info); - if (!(addr & ~PAGE_MASK)) - goto found_addr; - VM_BUG_ON(addr != -ENOMEM); - - /* - * A failed mmap() very likely causes application failure, - * so fall back to the bottom-up function here. This scenario - * can happen with large stack limits and large mmap() - * allocations. - */ - return arch_get_unmapped_area(filp, addr0, len, pgoff, flags); - -found_addr: - if (do_color_align && !last_mmap && !(addr & ~PAGE_MASK)) - SET_LAST_MMAP(filp, addr - (pgoff << PAGE_SHIFT)); + return arch_get_unmapped_area_common(filp, + addr, len, pgoff, flags, UP); +} - return addr; +unsigned long arch_get_unmapped_area_topdown(struct file *filp, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + return arch_get_unmapped_area_common(filp, + addr, len, pgoff, flags, DOWN); } static int mmap_is_legacy(void) |