/* $Id: sys_sunos32.c,v 1.64 2002/02/09 19:49:31 davem Exp $
* sys_sunos32.c: SunOS binary compatibility layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
*
* Based upon preliminary work which is:
*
* Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/capability.h>
#include <linux/compat.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/resource.h>
#include <linux/ipc.h>
#include <linux/shm.h>
#include <linux/msg.h>
#include <linux/sem.h>
#include <linux/signal.h>
#include <linux/uio.h>
#include <linux/utsname.h>
#include <linux/major.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/pconf.h>
#include <asm/idprom.h> /* for gethostid() */
#include <asm/unistd.h>
#include <asm/system.h>
/* For the nfs mount emulation */
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/nfs.h>
#include <linux/nfs2.h>
#include <linux/nfs_mount.h>
/* for sunos_select */
#include <linux/time.h>
#include <linux/personality.h>
/* For SOCKET_I */
#include <linux/socket.h>
#include <net/sock.h>
#include <net/compat.h>
#define SUNOS_NR_OPEN 256
asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
{
struct file *file = NULL;
unsigned long retval, ret_type;
if (flags & MAP_NORESERVE) {
static int cnt;
if (cnt++ < 10)
printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
current->comm);
flags &= ~MAP_NORESERVE;
}
retval = -EBADF;
if (!(flags & MAP_ANONYMOUS)) {
struct inode * inode;
if (fd >= SUNOS_NR_OPEN)
goto out;
file = fget(fd);
if (!file)
goto out;
inode = file->f_dentry->d_inode;
if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) {
flags |= MAP_ANONYMOUS;
fput(file);
file = NULL;
}
}
retval = -EINVAL;
if (!(flags & MAP_FIXED))
addr = 0;
else if (len > 0xf0000000 || addr > 0xf0000000 - len)
goto out_putf;
ret_type = flags & _MAP_NEW;
flags &= ~_MAP_NEW;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
down_write(¤t->mm->mmap_sem);
retval = do_mmap(file,
(unsigned long) addr, (unsigned long) len,
(unsigned long) prot, (unsigned long) flags,
(unsigned long) off);
up_write(¤t->mm->mmap_sem);
if (!ret_type)
retval = ((retval < 0xf0000000) ? 0 : retval);
out_putf:
if (file)
fput(file);
out:
return (u32) retval;
}
asmlinkage int sunos_mctl(u32 addr, u32 len, int function, u32 arg)
{
return 0;
}
asmlinkage int sunos_brk(u32 baddr)
{
int freepages, retval = -ENOMEM;
unsigned long rlim;
unsigned long newbrk, oldbrk, brk = (unsigned long) baddr;
down_write(¤t->mm->mmap_sem);
if (brk < current->mm->end_code)
goto out;
newbrk = PAGE_ALIGN(brk);
oldbrk = PAGE_ALIGN(current->mm->brk);
retval = 0;
if (oldbrk == newbrk) {
current->mm->brk = brk;
goto out;
}
/* Always allow shrinking brk. */
if (brk <= current->mm->brk) {
current->mm->brk = brk;
do_munmap(current->mm, newbrk, oldbrk-newbrk);
goto out;
}
/* Check against rlimit and stack.. */
retval = -ENOMEM;
rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
if (rlim >= RLIM_INFINITY)
rlim = ~0;
if (brk - current->mm->end_code > rlim)
goto out;
/* Check against existing mmap mappings. */
if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))
goto out;
/* stupid algorithm to decide if we have enough memory: while
* simple, it hopefully works in most obvious cases.. Easy to
* fool it, but this should catch most mistakes.
*/
freepages = get_page_cache_size();
freepages >>= 1;
freepages += nr_free_pages();
freepages
|