⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysirix.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * sysirix.c: IRIX system call emulation. * * Copyright (C) 1996 David S. Miller * Copyright (C) 1997 Miguel de Icaza * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/pagemap.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/slab.h>#include <linux/swap.h>#include <linux/errno.h>#include <linux/timex.h>#include <linux/times.h>#include <linux/elf.h>#include <linux/msg.h>#include <linux/shm.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/utsname.h>#include <linux/file.h>#include <asm/ptrace.h>#include <asm/page.h>#include <asm/pgalloc.h>#include <asm/uaccess.h>#include <asm/inventory.h>/* 2,191 lines of complete and utter shit coming up... */extern int max_threads;/* The sysmp commands supported thus far. */#define MP_NPROCS       	1 /* # processor in complex */#define MP_NAPROCS      	2 /* # active processors in complex */#define MP_PGSIZE           	14 /* Return system page size in v1. */asmlinkage int irix_sysmp(struct pt_regs *regs){	unsigned long cmd;	int base = 0;	int error = 0;	if(regs->regs[2] == 1000)		base = 1;	cmd = regs->regs[base + 4];	switch(cmd) {	case MP_PGSIZE:		error = PAGE_SIZE;		break;	case MP_NPROCS:	case MP_NAPROCS:		error = smp_num_cpus;		break;	default:		printk("SYSMP[%s:%d]: Unsupported opcode %d\n",		       current->comm, current->pid, (int)cmd);		error = -EINVAL;		break;	}	return error;}/* The prctl commands. */#define PR_MAXPROCS          1 /* Tasks/user. */#define PR_ISBLOCKED         2 /* If blocked, return 1. */#define PR_SETSTACKSIZE      3 /* Set largest task stack size. */#define PR_GETSTACKSIZE      4 /* Get largest task stack size. */#define PR_MAXPPROCS         5 /* Num parallel tasks. */#define PR_UNBLKONEXEC       6 /* When task exec/exit's, unblock. */#define PR_SETEXITSIG        8 /* When task exit's, set signal. */#define PR_RESIDENT          9 /* Make task unswappable. */#define PR_ATTACHADDR       10 /* (Re-)Connect a vma to a task. */#define PR_DETACHADDR       11 /* Disconnect a vma from a task. */#define PR_TERMCHILD        12 /* When parent sleeps with fishes, kill child. */#define PR_GETSHMASK        13 /* Get the sproc() share mask. */#define PR_GETNSHARE        14 /* Number of share group members. */#define PR_COREPID          15 /* Add task pid to name when it core. */#define	PR_ATTACHADDRPERM   16 /* (Re-)Connect vma, with specified prot. */#define PR_PTHREADEXIT      17 /* Kill a pthread without prejudice. */asmlinkage int irix_prctl(struct pt_regs *regs){	unsigned long cmd;	int error = 0, base = 0;	if (regs->regs[2] == 1000)		base = 1;	cmd = regs->regs[base + 4];	switch (cmd) {	case PR_MAXPROCS:		printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",		       current->comm, current->pid);		error = max_threads;		break;	case PR_ISBLOCKED: {		struct task_struct *task;		printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n",		       current->comm, current->pid);		read_lock(&tasklist_lock);		task = find_task_by_pid(regs->regs[base + 5]);		error = -ESRCH;		if (error)			error = (task->run_list.next != NULL);		read_unlock(&tasklist_lock);		/* Can _your_ OS find this out that fast? */ 		break;	}	case PR_SETSTACKSIZE: {		long value = regs->regs[base + 5];		printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n",		       current->comm, current->pid, (unsigned long) value);		if (value > RLIM_INFINITY)			value = RLIM_INFINITY;		if (capable(CAP_SYS_ADMIN)) {			current->rlim[RLIMIT_STACK].rlim_max =				current->rlim[RLIMIT_STACK].rlim_cur = value;			error = value;			break;		}		if (value > current->rlim[RLIMIT_STACK].rlim_max) {			error = -EINVAL;			break;		}		current->rlim[RLIMIT_STACK].rlim_cur = value;		error = value;		break;	}	case PR_GETSTACKSIZE:		printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n",		       current->comm, current->pid);		error = current->rlim[RLIMIT_STACK].rlim_cur;		break;	case PR_MAXPPROCS:		printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",		       current->comm, current->pid);		error = 1;		break;	case PR_UNBLKONEXEC:		printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_SETEXITSIG:		printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n",		       current->comm, current->pid);		/* We can probably play some game where we set the task		 * exit_code to some non-zero value when this is requested,		 * and check whether exit_code is already set in do_exit().		 */		error = -EINVAL;		break;	case PR_RESIDENT:		printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n",		       current->comm, current->pid);		error = 0; /* Compatibility indeed. */		break;	case PR_ATTACHADDR:		printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_DETACHADDR:		printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_TERMCHILD:		printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_GETSHMASK:		printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n",		       current->comm, current->pid);		error = -EINVAL; /* Until I have the sproc() stuff in. */		break;	case PR_GETNSHARE:		error = 0;       /* Until I have the sproc() stuff in. */		break;	case PR_COREPID:		printk("irix_prctl[%s:%d]: Wants PR_COREPID\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_ATTACHADDRPERM:		printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n",		       current->comm, current->pid);		error = -EINVAL;		break;	case PR_PTHREADEXIT:		printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n",		       current->comm, current->pid);		do_exit(regs->regs[base + 5]);	default:		printk("irix_prctl[%s:%d]: Non-existant opcode %d\n",		       current->comm, current->pid, (int)cmd);		error = -EINVAL;		break;	}	return error;}#undef DEBUG_PROCGRPSextern unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt);extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid);extern void sys_sync(void);extern asmlinkage int sys_getsid(pid_t pid);extern asmlinkage long sys_write (unsigned int fd, const char *buf, unsigned long count);extern asmlinkage long sys_lseek (unsigned int fd, off_t offset, unsigned int origin);extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);extern int getrusage(struct task_struct *p, int who, struct rusage *ru);extern char *prom_getenv(char *name);extern long prom_setenv(char *name, char *value);/* The syssgi commands supported thus far. */#define SGI_SYSID         1       /* Return unique per-machine identifier. */#define SGI_INVENT        5       /* Fetch inventory  */#   define SGI_INV_SIZEOF 1#   define SGI_INV_READ   2#define SGI_RDNAME        6       /* Return string name of a process. */#define SGI_SETNVRAM	  8	  /* Set PROM variable. */#define SGI_GETNVRAM	  9	  /* Get PROM variable. */#define SGI_SETPGID      21       /* Set process group id. */#define SGI_SYSCONF      22       /* POSIX sysconf garbage. */#define SGI_PATHCONF     24       /* POSIX sysconf garbage. */#define SGI_SETGROUPS    40       /* POSIX sysconf garbage. */#define SGI_GETGROUPS    41       /* POSIX sysconf garbage. */#define SGI_RUSAGE       56       /* BSD style rusage(). */#define SGI_SSYNC        62       /* Synchronous fs sync. */#define SGI_GETSID       65       /* SysVr4 get session id. */#define SGI_ELFMAP       68       /* Map an elf image. */#define SGI_TOSSTSAVE   108       /* Toss saved vma's. */#define SGI_FP_BCOPY    129       /* Should FPU bcopy be used on this machine? */#define SGI_PHYSP      1011       /* Translate virtual into physical page. */asmlinkage int irix_syssgi(struct pt_regs *regs){	unsigned long cmd;	int retval, base = 0;	if (regs->regs[2] == 1000)		base = 1;	cmd = regs->regs[base + 4];	switch(cmd) {	case SGI_SYSID: {		char *buf = (char *) regs->regs[base + 5];		/* XXX Use ethernet addr.... */		retval = clear_user(buf, 64);		break;	}#if 0	case SGI_RDNAME: {		int pid = (int) regs->regs[base + 5];		char *buf = (char *) regs->regs[base + 6];		struct task_struct *p;		char comm[16];		retval = verify_area(VERIFY_WRITE, buf, 16);		if (retval)			break;		read_lock(&tasklist_lock);		p = find_task_by_pid(pid);		if (!p) {			read_unlock(&tasklist_lock);			retval = -ESRCH;			break;		}		memcpy(comm, p->comm, 16);		read_unlock(&tasklist_lock);		/* XXX Need to check sizes. */		copy_to_user(buf, p->comm, 16);		retval = 0;		break;	}	case SGI_GETNVRAM: {		char *name = (char *) regs->regs[base+5];		char *buf = (char *) regs->regs[base+6];		char *value;		return -EINVAL;	/* til I fix it */		retval = verify_area(VERIFY_WRITE, buf, 128);		if (retval)			break;		value = prom_getenv(name);	/* PROM lock?  */		if (!value) {			retval = -EINVAL;			break;		}		/* Do I strlen() for the length? */		copy_to_user(buf, value, 128);		retval = 0;		break;	}	case SGI_SETNVRAM: {		char *name = (char *) regs->regs[base+5];		char *value = (char *) regs->regs[base+6];		return -EINVAL;	/* til I fix it */		retval = prom_setenv(name, value);		/* XXX make sure retval conforms to syssgi(2) */		printk("[%s:%d] setnvram(\"%s\", \"%s\"): retval %d",		       current->comm, current->pid, name, value, retval);/*		if (retval == PROM_ENOENT)		  	retval = -ENOENT; */		break;				   	}#endif	case SGI_SETPGID: {#ifdef DEBUG_PROCGRPS		printk("[%s:%d] setpgid(%d, %d) ",		       current->comm, current->pid,		       (int) regs->regs[base + 5], (int)regs->regs[base + 6]);#endif		retval = sys_setpgid(regs->regs[base + 5], regs->regs[base + 6]);#ifdef DEBUG_PROCGRPS		printk("retval=%d\n", retval);#endif	}	case SGI_SYSCONF: {		switch(regs->regs[base + 5]) {		case 1:			retval = (MAX_ARG_PAGES >> 4); /* XXX estimate... */			goto out;		case 2:			retval = max_threads;			goto out;		case 3:			retval = HZ;			goto out;		case 4:			retval = NGROUPS;			goto out;		case 5:			retval = NR_OPEN;			goto out;		case 6:			retval = 1;			goto out;		case 7:			retval = 1;			goto out;		case 8:			retval = 199009;			goto out;		case 11:			retval = PAGE_SIZE;			goto out;		case 12:			retval = 4;			goto out;		case 25:		case 26:		case 27:		case 28:		case 29:		case 30:			retval = 0;			goto out;		case 31:			retval = 32;			goto out;		default:			retval = -EINVAL;			goto out;		};	}	case SGI_SETGROUPS:		retval = sys_setgroups((int) regs->regs[base + 5],		                       (gid_t *) regs->regs[base + 6]);		break;	case SGI_GETGROUPS:		retval = sys_getgroups((int) regs->regs[base + 5],		                       (gid_t *) regs->regs[base + 6]);		break;	case SGI_RUSAGE: {		struct rusage *ru = (struct rusage *) regs->regs[base + 6];		switch((int) regs->regs[base + 5]) {		case 0:			/* rusage self */			retval = getrusage(current, RUSAGE_SELF, ru);			goto out;		case -1:			/* rusage children */			retval = getrusage(current, RUSAGE_CHILDREN, ru);			goto out;		default:			retval = -EINVAL;			goto out;		};	}	case SGI_SSYNC:		sys_sync();		retval = 0;		break;	case SGI_GETSID:#ifdef DEBUG_PROCGRPS		printk("[%s:%d] getsid(%d) ", current->comm, current->pid,		       (int) regs->regs[base + 5]);#endif		retval = sys_getsid(regs->regs[base + 5]);#ifdef DEBUG_PROCGRPS		printk("retval=%d\n", retval);#endif		break;	case SGI_ELFMAP:		retval = irix_mapelf((int) regs->regs[base + 5],				     (struct elf_phdr *) regs->regs[base + 6],				     (int) regs->regs[base + 7]);		break;	case SGI_TOSSTSAVE:		/* XXX We don't need to do anything? */		retval = 0;		break;	case SGI_FP_BCOPY:		retval = 0;		break;	case SGI_PHYSP: {		unsigned long addr = regs->regs[base + 5];		int *pageno = (int *) (regs->regs[base + 6]);		struct mm_struct *mm = current->mm;		pgd_t *pgdp;		pmd_t *pmdp;		pte_t *ptep;		retval = verify_area(VERIFY_WRITE, pageno, sizeof(int));		if (retval)			return retval;		down_read(&mm->mmap_sem);		pgdp = pgd_offset(mm, addr);		pmdp = pmd_offset(pgdp, addr);		ptep = pte_offset(pmdp, addr);		retval = -EINVAL;		if (ptep) {			pte_t pte = *ptep;			if (pte_val(pte) & (_PAGE_VALID | _PAGE_PRESENT)) {				retval =  put_user((pte_val(pte) & PAGE_MASK) >>				                   PAGE_SHIFT, pageno);			}		}		up_read(&mm->mmap_sem);		break;	}	case SGI_INVENT: {		int  arg1    = (int)    regs->regs [base + 5];		void *buffer = (void *) regs->regs [base + 6];		int  count   = (int)    regs->regs [base + 7];		switch (arg1) {		case SGI_INV_SIZEOF:			retval = sizeof (inventory_t);			break;		case SGI_INV_READ:			retval = dump_inventory_to_user (buffer, count);			break;		default:			retval = -EINVAL;		}		break;	}		default:		printk("irix_syssgi: Unsupported command %d\n", (int)cmd);		retval = -EINVAL;		break;	};out:	return retval;}asmlinkage int irix_gtime(struct pt_regs *regs){	return CURRENT_TIME;}int vm_enough_memory(long pages);/* * IRIX is completely broken... it returns 0 on success, otherwise * ENOMEM. */asmlinkage int irix_brk(unsigned long brk){	unsigned long rlim;	unsigned long newbrk, oldbrk;	struct mm_struct *mm = current->mm;	int ret;	down_write(&mm->mmap_sem);	if (brk < mm->end_code) {		ret = -ENOMEM;		goto out;	}	newbrk = PAGE_ALIGN(brk);	oldbrk = PAGE_ALIGN(mm->brk);	if (oldbrk == newbrk) {		mm->brk = brk;		ret = 0;		goto out;	}	/*	 * Always allow shrinking brk	 */	if (brk <= mm->brk) {		mm->brk = brk;		do_munmap(mm, newbrk, oldbrk-newbrk);		ret = 0;		goto out;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -