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

📄 sys_ia32.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		child_regs->r13 = value;		break;	case PT_EAX:	case PT_ORIG_EAX:		child_regs->r8 = value;		break;	case PT_EIP:		child_regs->cr_iip = value;		break;	case PT_UESP:		child_regs->r12 = value;		break;	case PT_EFL:		child->thread.eflag = value;		break;	case PT_DS:	case PT_ES:	case PT_FS:	case PT_GS:	case PT_SS:		if (value != __USER_DS)			printk("setregs:try to set invalid segment register %d = %x\n", regno, value);		break;	case PT_CS:		if (value != __USER_CS)			printk("setregs:try to set invalid segment register %d = %x\n", regno, value);		break;	default:		printk("getregs:unknown register %d\n", regno);		break;	}}static inline voidia32f2ia64f(void *dst, void *src){	__asm__ ("ldfe f6=[%1] ;;\n\t"		 "stf.spill [%0]=f6"		:		: "r"(dst), "r"(src));	return;}static inline voidia64f2ia32f(void *dst, void *src){	__asm__ ("ldf.fill f6=[%1] ;;\n\t"		 "stfe [%0]=f6"		:		: "r"(dst),  "r"(src));	return;}voidput_fpreg(int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos){	struct _fpreg_ia32 *f;	char buf[32];	f = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15);	if ((regno += tos) >= 8)		regno -= 8;	switch (regno) {	case 0:		ia64f2ia32f(f, &ptp->f8);		break;	case 1:		ia64f2ia32f(f, &ptp->f9);		break;	case 2:	case 3:	case 4:	case 5:	case 6:	case 7:		ia64f2ia32f(f, &swp->f10 + (regno - 2));		break;	}	__copy_to_user(reg, f, sizeof(*reg));	return;}voidget_fpreg(int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos){	if ((regno += tos) >= 8)		regno -= 8;	switch (regno) {	case 0:		__copy_from_user(&ptp->f8, reg, sizeof(*reg));		break;	case 1:		__copy_from_user(&ptp->f9, reg, sizeof(*reg));		break;	case 2:	case 3:	case 4:	case 5:	case 6:	case 7:		__copy_from_user(&swp->f10 + (regno - 2), reg, sizeof(*reg));		break;	}	return;}intsave_ia32_fpstate(struct task_struct *tsk, struct _fpstate_ia32 *save){	struct switch_stack *swp;	struct pt_regs *ptp;	int i, tos;	if (!access_ok(VERIFY_WRITE, save, sizeof(*save)))		return(-EIO);	__put_user(tsk->thread.fcr, &save->cw);	__put_user(tsk->thread.fsr, &save->sw);	__put_user(tsk->thread.fsr >> 32, &save->tag);	__put_user(tsk->thread.fir, &save->ipoff);	__put_user(__USER_CS, &save->cssel);	__put_user(tsk->thread.fdr, &save->dataoff);	__put_user(__USER_DS, &save->datasel);	/*	 *  Stack frames start with 16-bytes of temp space	 */	swp = (struct switch_stack *)(tsk->thread.ksp + 16);	ptp = ia64_task_regs(tsk);	tos = (tsk->thread.fsr >> 11) & 3;	for (i = 0; i < 8; i++)		put_fpreg(i, &save->_st[i], ptp, swp, tos);	return(0);}intrestore_ia32_fpstate(struct task_struct *tsk, struct _fpstate_ia32 *save){	struct switch_stack *swp;	struct pt_regs *ptp;	int i, tos, ret;	int fsrlo, fsrhi;	if (!access_ok(VERIFY_READ, save, sizeof(*save)))		return(-EIO);	ret = __get_user(tsk->thread.fcr, (unsigned int *)&save->cw);	ret |= __get_user(fsrlo, (unsigned int *)&save->sw);	ret |= __get_user(fsrhi, (unsigned int *)&save->tag);	tsk->thread.fsr = ((long)fsrhi << 32) | (long)fsrlo;	ret |= __get_user(tsk->thread.fir, (unsigned int *)&save->ipoff);	ret |= __get_user(tsk->thread.fdr, (unsigned int *)&save->dataoff);	/*	 *  Stack frames start with 16-bytes of temp space	 */	swp = (struct switch_stack *)(tsk->thread.ksp + 16);	ptp = ia64_task_regs(tsk);	tos = (tsk->thread.fsr >> 11) & 3;	for (i = 0; i < 8; i++)		get_fpreg(i, &save->_st[i], ptp, swp, tos);	return(ret ? -EFAULT : 0);}asmlinkage long sys_ptrace(long, pid_t, unsigned long, unsigned long, long, long, long, long, long);/* *  Note that the IA32 version of `ptrace' calls the IA64 routine for *    many of the requests.  This will only work for requests that do *    not need access to the calling processes `pt_regs' which is located *    at the address of `stack'.  Once we call the IA64 `sys_ptrace' then *    the address of `stack' will not be the address of the `pt_regs'. */asmlinkage longsys32_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,	    long arg4, long arg5, long arg6, long arg7, long stack){	struct pt_regs *regs = (struct pt_regs *) &stack;	struct task_struct *child;	long i, ret;	unsigned int value;	lock_kernel();	if (request == PTRACE_TRACEME) {		ret = sys_ptrace(request, pid, addr, data,				arg4, arg5, arg6, arg7, stack);		goto out;	}	ret = -ESRCH;	read_lock(&tasklist_lock);	child = find_task_by_pid(pid);	read_unlock(&tasklist_lock);	if (!child)		goto out;	ret = -EPERM;	if (pid == 1)		/* no messing around with init! */		goto out;	if (request == PTRACE_ATTACH) {		ret = sys_ptrace(request, pid, addr, data,				arg4, arg5, arg6, arg7, stack);		goto out;	}	ret = -ESRCH;	if (!(child->ptrace & PT_PTRACED))		goto out;	if (child->state != TASK_STOPPED) {		if (request != PTRACE_KILL)			goto out;	}	if (child->p_pptr != current)		goto out;	switch (request) {	      case PTRACE_PEEKTEXT:	      case PTRACE_PEEKDATA:	/* read word at location addr */		ret = ia32_peek(regs, child, addr, &value);		if (ret == 0)			ret = put_user(value, (unsigned int *)data);		else			ret = -EIO;		goto out;	      case PTRACE_POKETEXT:	      case PTRACE_POKEDATA:	/* write the word at location addr */		ret = ia32_poke(regs, child, addr, (unsigned int)data);		goto out;	      case PTRACE_PEEKUSR:	/* read word at addr in USER area */		ret = 0;		break;	      case PTRACE_POKEUSR:	/* write word at addr in USER area */		ret = 0;		break;	      case IA32_PTRACE_GETREGS:	  	if (!access_ok(VERIFY_WRITE, (int *)data, 17*sizeof(int))) {			ret = -EIO;			break;		}		for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) {			__put_user(getreg(child, i),(unsigned int *) data);			data += sizeof(int);		}		ret = 0;		break;	      case IA32_PTRACE_SETREGS:	      {		unsigned int tmp;	  	if (!access_ok(VERIFY_READ, (int *)data, 17*sizeof(int))) {			ret = -EIO;			break;		}		for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) {			__get_user(tmp, (unsigned int *) data);			putreg(child, i, tmp);			data += sizeof(int);		}		ret = 0;		break;	      }	      case IA32_PTRACE_GETFPREGS:		ret = save_ia32_fpstate(child, (struct _fpstate_ia32 *)data);		break;	      case IA32_PTRACE_SETFPREGS:		ret = restore_ia32_fpstate(child, (struct _fpstate_ia32 *)data);		break;	      case PTRACE_SYSCALL:	/* continue, stop after next syscall */	      case PTRACE_CONT:		/* restart after signal. */	      case PTRACE_KILL:	      case PTRACE_SINGLESTEP:	/* execute chile for one instruction */	      case PTRACE_DETACH:	/* detach a process */		unlock_kernel();		ret = sys_ptrace(request, pid, addr, data,				arg4, arg5, arg6, arg7, stack);		return(ret);	      default:		ret = -EIO;		break;	}  out:	unlock_kernel();	return ret;}static inline intget_flock32(struct flock *kfl, struct flock32 *ufl){	int err;		err = get_user(kfl->l_type, &ufl->l_type);	err |= __get_user(kfl->l_whence, &ufl->l_whence);	err |= __get_user(kfl->l_start, &ufl->l_start);	err |= __get_user(kfl->l_len, &ufl->l_len);	err |= __get_user(kfl->l_pid, &ufl->l_pid);	return err;}static inline intput_flock32(struct flock *kfl, struct flock32 *ufl){	int err;		err = __put_user(kfl->l_type, &ufl->l_type);	err |= __put_user(kfl->l_whence, &ufl->l_whence);	err |= __put_user(kfl->l_start, &ufl->l_start);	err |= __put_user(kfl->l_len, &ufl->l_len);	err |= __put_user(kfl->l_pid, &ufl->l_pid);	return err;}extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd,				 unsigned long arg);asmlinkage longsys32_fcntl(unsigned int fd, unsigned int cmd, int arg){	struct flock f;	mm_segment_t old_fs;	long ret;	switch (cmd) {	case F_GETLK:	case F_SETLK:	case F_SETLKW:		if(cmd != F_GETLK && get_flock32(&f, (struct flock32 *)((long)arg)))			return -EFAULT;		old_fs = get_fs();		set_fs(KERNEL_DS);		ret = sys_fcntl(fd, cmd, (unsigned long)&f);		set_fs(old_fs);		if(cmd == F_GETLK && put_flock32(&f, (struct flock32 *)((long)arg)))			return -EFAULT;		return ret;	default:		/*		 *  `sys_fcntl' lies about arg, for the F_SETOWN		 *  sub-function arg can have a negative value.		 */		return sys_fcntl(fd, cmd, (unsigned long)((long)arg));	}}asmlinkage longsys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact){        struct k_sigaction new_ka, old_ka;        int ret;        if (act) {		old_sigset32_t mask;				ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);		ret |= __get_user(mask, &act->sa_mask);		if (ret)			return ret;		siginitset(&new_ka.sa.sa_mask, mask);        }        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);		ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);        }	return ret;}asmlinkage long sys_ni_syscall(void);asmlinkage longsys32_ni_syscall(int dummy0, int dummy1, int dummy2, int dummy3,	int dummy4, int dummy5, int dummy6, int dummy7, int stack){	struct pt_regs *regs = (struct pt_regs *)&stack;	printk("IA32 syscall #%d issued, maybe we should implement it\n",		(int)regs->r1);	return(sys_ni_syscall());}/* *  The IA64 maps 4 I/O ports for each 4K page */#define IOLEN	((65536 / 4) * 4096)asmlinkage longsys_iopl (int level, long arg1, long arg2, long arg3){	extern unsigned long ia64_iobase;	int fd;	struct file * file;	unsigned int old;	unsigned long addr;	mm_segment_t old_fs = get_fs ();	if (level != 3)		return(-EINVAL);	/* Trying to gain more privileges? */	__asm__ __volatile__("mov %0=ar.eflag ;;" : "=r"(old));	if (level > ((old >> 12) & 3)) {		if (!capable(CAP_SYS_RAWIO))			return -EPERM;	}	set_fs(KERNEL_DS);	fd = sys_open("/dev/mem", O_SYNC | O_RDWR, 0);	set_fs(old_fs);	if (fd < 0)		return fd;	file = fget(fd);	if (file == NULL) {		sys_close(fd);		return(-EFAULT);	}	down(&current->mm->mmap_sem);	lock_kernel();	addr = do_mmap_pgoff(file, IA32_IOBASE,			IOLEN, PROT_READ|PROT_WRITE, MAP_SHARED,			(ia64_iobase & ~PAGE_OFFSET) >> PAGE_SHIFT);	unlock_kernel();	up(&current->mm->mmap_sem);	if (addr >= 0) {		__asm__ __volatile__("mov ar.k0=%0 ;;" :: "r"(addr));		old = (old & ~0x3000) | (level << 12);		__asm__ __volatile__("mov ar.eflag=%0 ;;" :: "r"(old));	}	fput(file);	sys_close(fd);	return 0;}asmlinkage longsys_ioperm (unsigned long from, unsigned long num, int on){	/*	 *  Since IA64 doesn't have permission bits we'd have to go to	 *    a lot of trouble to simulate them in software.  There's	 *    no point, only trusted programs can make this call so we'll	 *    just turn it into an iopl call and let the process have	 *    access to all I/O ports.	 *	 * XXX proper ioperm() support should be emulated by	 *	manipulating the page protections...	 */	return(sys_iopl(3, 0, 0, 0));}typedef struct {	unsigned int	ss_sp;	unsigned int	ss_flags;	unsigned int	ss_size;} ia32_stack_t;asmlinkage longsys32_sigaltstack (const ia32_stack_t *uss32, ia32_stack_t *uoss32,long arg2, long arg3, long arg4,long arg5, long arg6, long arg7,long stack){	struct pt_regs *pt = (struct pt_regs *) &stack;	stack_t uss, uoss;	ia32_stack_t buf32;	int ret;	mm_segment_t old_fs = get_fs();	if (uss32)		if (copy_from_user(&buf32, (void *)A(uss32), sizeof(ia32_stack_t)))			return(-EFAULT);	uss.ss_sp = (void *) (long) buf32.ss_sp;	uss.ss_flags = buf32.ss_flags;	uss.ss_size = buf32.ss_size;	set_fs(KERNEL_DS);	ret = do_sigaltstack(uss32 ? &uss : NULL, &uoss, pt->r12);	set_fs(old_fs);	if (ret < 0)		return(ret);	if (uoss32) {		buf32.ss_sp = (long) uoss.ss_sp;		buf32.ss_flags = uoss.ss_flags;		buf32.ss_size = uoss.ss_size;		if (copy_to_user((void*)A(uoss32), &buf32, sizeof(ia32_stack_t)))			return(-EFAULT);	}	return(ret);}asmlinkage intsys_pause (void){	current->state = TASK_INTERRUPTIBLE;	schedule();	return -ERESTARTNOHAND;}#ifdef	NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN *//* In order to reduce some races, while at the same time doing additional * checking and hopefully speeding things up, we copy filenames to the * kernel data space before using them.. * * POSIX.1 2.4: an empty pathname is invalid (ENOENT). */static inline intdo_getname32(const char *filename, char *page){	int retval;	/* 32bit pointer will be always far below TASK_SIZE :)) */	retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE);	if (retval > 0) {		if (retval < PAGE_SIZE)

⌨️ 快捷键说明

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