patch-2.3.46 linux/arch/sparc/kernel/sys_sparc.c
Next file: linux/arch/sparc/kernel/sys_sunos.c
Previous file: linux/arch/sparc/kernel/sparc_ksyms.c
Back to the patch index
Back to the overall index
- Lines: 124
- Date:
Mon Feb 14 15:31:14 2000
- Orig file:
v2.3.45/linux/arch/sparc/kernel/sys_sparc.c
- Orig date:
Thu Feb 10 17:11:05 2000
diff -u --recursive --new-file v2.3.45/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
@@ -34,12 +34,39 @@
return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
}
+unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
+{
+ struct vm_area_struct * vmm;
+
+ /* See asm-sparc/uaccess.h */
+ if (len > TASK_SIZE - PAGE_SIZE)
+ return 0;
+ if (ARCH_SUN4C_SUN4 && len > 0x20000000)
+ return 0;
+ if (!addr)
+ addr = TASK_UNMAPPED_BASE;
+ addr = PAGE_ALIGN(addr);
+
+ for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
+ /* At this point: (!vmm || addr < vmm->vm_end). */
+ if (ARCH_SUN4C_SUN4 && addr < 0xe0000000 && 0x20000000 - len < addr) {
+ addr = PAGE_OFFSET;
+ vmm = find_vma(current->mm, PAGE_OFFSET);
+ }
+ if (TASK_SIZE - PAGE_SIZE - len < addr)
+ return 0;
+ if (!vmm || addr + len <= vmm->vm_start)
+ return addr;
+ addr = vmm->vm_end;
+ }
+}
+
extern asmlinkage unsigned long sys_brk(unsigned long brk);
asmlinkage unsigned long sparc_brk(unsigned long brk)
{
if(ARCH_SUN4C_SUN4) {
- if(brk >= 0x20000000 && brk < 0xe0000000)
+ if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000))
return current->mm->brk;
}
return sys_brk(brk);
@@ -190,24 +217,16 @@
down(¤t->mm->mmap_sem);
lock_kernel();
- retval = -ENOMEM;
+ retval = -EINVAL;
len = PAGE_ALIGN(len);
- if(!(flags & MAP_FIXED) &&
- (!addr || (ARCH_SUN4C_SUN4 &&
- (addr >= 0x20000000 && addr < 0xe0000000)))) {
- addr = get_unmapped_area(0, len);
- if(!addr)
- goto out_putf;
- if (ARCH_SUN4C_SUN4 &&
- (addr >= 0x20000000 && addr < 0xe0000000)) {
- retval = -EINVAL;
- goto out_putf;
- }
- }
+ if (ARCH_SUN4C_SUN4 &&
+ (len > 0x20000000 ||
+ ((flags & MAP_FIXED) &&
+ addr < 0xe0000000 && addr + len > 0x20000000)))
+ goto out_putf;
/* See asm-sparc/uaccess.h */
- retval = -EINVAL;
- if((len > (TASK_SIZE - PAGE_SIZE)) || (addr > (TASK_SIZE-len-PAGE_SIZE)))
+ if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
goto out_putf;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
@@ -236,6 +255,50 @@
unsigned long off)
{
return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+}
+
+extern unsigned long do_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr);
+
+asmlinkage unsigned long sparc_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr)
+{
+ unsigned long ret = -EINVAL;
+ if (ARCH_SUN4C_SUN4) {
+ if (old_len > 0x20000000 || new_len > 0x20000000)
+ goto out;
+ if (addr < 0xe0000000 && addr + old_len > 0x20000000)
+ goto out;
+ }
+ if (old_len > TASK_SIZE - PAGE_SIZE ||
+ new_len > TASK_SIZE - PAGE_SIZE)
+ goto out;
+ down(¤t->mm->mmap_sem);
+ if (flags & MREMAP_FIXED) {
+ if (ARCH_SUN4C_SUN4 &&
+ new_addr < 0xe0000000 &&
+ new_addr + new_len > 0x20000000)
+ goto out_sem;
+ if (new_addr + new_len > TASK_SIZE - PAGE_SIZE)
+ goto out_sem;
+ } else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 &&
+ addr + new_len > 0x20000000) ||
+ addr + new_len > TASK_SIZE - PAGE_SIZE) {
+ ret = -ENOMEM;
+ if (!(flags & MREMAP_MAYMOVE))
+ goto out_sem;
+ new_addr = get_unmapped_area (addr, new_len);
+ if (!new_addr)
+ goto out_sem;
+ flags |= MREMAP_FIXED;
+ }
+ ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+out_sem:
+ up(¤t->mm->mmap_sem);
+out:
+ return ret;
}
/* we come to here via sys_nis_syscall so it can setup the regs argument */
FUNET's LINUX-ADM group, [email protected]
TCL-scripts by Sam Shen (who was at: [email protected])