📄 osf_sys.c
字号:
down_read(&uts_sem); error = -EFAULT; if (copy_to_user(name + 0, system_utsname.sysname, 32)) goto out; if (copy_to_user(name + 32, system_utsname.nodename, 32)) goto out; if (copy_to_user(name + 64, system_utsname.release, 32)) goto out; if (copy_to_user(name + 96, system_utsname.version, 32)) goto out; if (copy_to_user(name + 128, system_utsname.machine, 32)) goto out; error = 0;out: up_read(&uts_sem); return error;}asmlinkage int osf_swapon(const char *path, int flags, int lowat, int hiwat){ int ret; /* for now, simply ignore lowat and hiwat... */ lock_kernel(); ret = sys_swapon(path, flags); unlock_kernel(); return ret;}asmlinkage unsigned long sys_getpagesize(void){ return PAGE_SIZE;}asmlinkage unsigned long sys_getdtablesize(void){ return NR_OPEN;}asmlinkage int sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5, struct pt_regs regs){ int fd[2]; int error; error = do_pipe(fd); if (error) goto out; (®s)->r20 = fd[1]; error = fd[0];out: return error;}/* * For compatibility with OSF/1 only. Use utsname(2) instead. */asmlinkage int osf_getdomainname(char *name, int namelen){ unsigned len; int i, error; error = verify_area(VERIFY_WRITE, name, namelen); if (error) goto out; len = namelen; if (namelen > 32) len = 32; down_read(&uts_sem); for (i = 0; i < len; ++i) { __put_user(system_utsname.domainname[i], name + i); if (system_utsname.domainname[i] == '\0') break; } up_read(&uts_sem);out: return error;}asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg){ unsigned long raddr; long err; lock_kernel(); err = sys_shmat(shmid, shmaddr, shmflg, &raddr); if (err) goto out; /* * This works because all user-level addresses are * non-negative longs! */ err = raddr;out: unlock_kernel(); return err;}/* * The following stuff should move into a header file should it ever * be labeled "officially supported." Right now, there is just enough * support to avoid applications (such as tar) printing error * messages. The attributes are not really implemented. *//* * Values for Property list entry flag */#define PLE_PROPAGATE_ON_COPY 0x1 /* cp(1) will copy entry by default */#define PLE_FLAG_MASK 0x1 /* Valid flag values */#define PLE_FLAG_ALL -1 /* All flag value */struct proplistname_args { unsigned int pl_mask; unsigned int pl_numnames; char **pl_names;};union pl_args { struct setargs { char *path; long follow; long nbytes; char *buf; } set; struct fsetargs { long fd; long nbytes; char *buf; } fset; struct getargs { char *path; long follow; struct proplistname_args *name_args; long nbytes; char *buf; int *min_buf_size; } get; struct fgetargs { long fd; struct proplistname_args *name_args; long nbytes; char *buf; int *min_buf_size; } fget; struct delargs { char *path; long follow; struct proplistname_args *name_args; } del; struct fdelargs { long fd; struct proplistname_args *name_args; } fdel;};enum pl_code { PL_SET = 1, PL_FSET = 2, PL_GET = 3, PL_FGET = 4, PL_DEL = 5, PL_FDEL = 6};asmlinkage long osf_proplist_syscall(enum pl_code code, union pl_args *args){ long error; int *min_buf_size_ptr; lock_kernel(); switch (code) { case PL_SET: error = verify_area(VERIFY_READ, &args->set.nbytes, sizeof(args->set.nbytes)); if (!error) error = args->set.nbytes; break; case PL_FSET: error = verify_area(VERIFY_READ, &args->fset.nbytes, sizeof(args->fset.nbytes)); if (!error) error = args->fset.nbytes; break; case PL_GET: get_user(min_buf_size_ptr, &args->get.min_buf_size); error = verify_area(VERIFY_WRITE, min_buf_size_ptr, sizeof(*min_buf_size_ptr)); if (!error) put_user(0, min_buf_size_ptr); break; case PL_FGET: get_user(min_buf_size_ptr, &args->fget.min_buf_size); error = verify_area(VERIFY_WRITE, min_buf_size_ptr, sizeof(*min_buf_size_ptr)); if (!error) put_user(0, min_buf_size_ptr); break; case PL_DEL: case PL_FDEL: error = 0; break; default: error = -EOPNOTSUPP; break; }; unlock_kernel(); return error;}asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss){ unsigned long usp = rdusp(); unsigned long oss_sp = current->sas_ss_sp + current->sas_ss_size; unsigned long oss_os = on_sig_stack(usp); int error; if (uss) { void *ss_sp; error = -EFAULT; if (get_user(ss_sp, &uss->ss_sp)) goto out; /* If the current stack was set with sigaltstack, don't swap stacks while we are on it. */ error = -EPERM; if (current->sas_ss_sp && on_sig_stack(usp)) goto out; /* Since we don't know the extent of the stack, and we don't track onstack-ness, but rather calculate it, we must presume a size. Ho hum this interface is lossy. */ current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ; current->sas_ss_size = SIGSTKSZ; } if (uoss) { error = -EFAULT; if (! access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)) || __put_user(oss_sp, &uoss->ss_sp) || __put_user(oss_os, &uoss->ss_onstack)) goto out; } error = 0;out: return error;}/* * The Linux kernel isn't good at returning values that look * like negative longs (they are mistaken as error values). * Until that is fixed, we need this little workaround for * create_module() because it's one of the few system calls * that return kernel addresses (which are negative). */asmlinkage unsigned long alpha_create_module(char *module_name, unsigned long size, int a3, int a4, int a5, int a6, struct pt_regs regs){ asmlinkage unsigned long sys_create_module(char *, unsigned long); long retval; lock_kernel(); retval = sys_create_module(module_name, size); /* * we get either a module address or an error number, * and we know the error number is a small negative * number, while the address is always negative but * much larger. */ if (retval + 1000 > 0) goto out; /* tell entry.S:syscall_error that this is NOT an error: */ regs.r0 = 0;out: unlock_kernel(); return retval;}asmlinkage long osf_sysinfo(int command, char *buf, long count){ static char * sysinfo_table[] = { system_utsname.sysname, system_utsname.nodename, system_utsname.release, system_utsname.version, system_utsname.machine, "alpha", /* instruction set architecture */ "dummy", /* hardware serial number */ "dummy", /* hardware manufacturer */ "dummy", /* secure RPC domain */ }; unsigned long offset; char *res; long len, err = -EINVAL; offset = command-1; if (offset >= sizeof(sysinfo_table)/sizeof(char *)) { /* Digital UNIX has a few unpublished interfaces here */ printk("sysinfo(%d)", command); goto out; } down_read(&uts_sem); res = sysinfo_table[offset]; len = strlen(res)+1; if (len > count) len = count; if (copy_to_user(buf, res, len)) err = -EFAULT; else err = 0; up_read(&uts_sem);out: return err;}asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, unsigned long nbytes, int *start, void *arg){ unsigned long w; struct percpu_struct *cpu; switch (op) { case GSI_IEEE_FP_CONTROL: /* Return current software fp control & status bits. */ /* Note that DU doesn't verify available space here. */ w = current->thread.flags & IEEE_SW_MASK; w = swcr_update_status(w, rdfpcr()); if (put_user(w, (unsigned long *) buffer)) return -EFAULT; return 0; case GSI_IEEE_STATE_AT_SIGNAL: /* * Not sure anybody will ever use this weird stuff. These * ops can be used (under OSF/1) to set the fpcr that should * be used when a signal handler starts executing. */ break; case GSI_UACPROC: if (nbytes < sizeof(unsigned int)) return -EINVAL; w = (current->thread.flags >> UAC_SHIFT) & UAC_BITMASK; if (put_user(w, (unsigned int *)buffer)) return -EFAULT; return 1; case GSI_PROC_TYPE: if (nbytes < sizeof(unsigned long)) return -EINVAL; cpu = (struct percpu_struct*) ((char*)hwrpb + hwrpb->processor_offset); w = cpu->type; if (put_user(w, (unsigned long *)buffer)) return -EFAULT; return 1; case GSI_GET_HWRPB: if (nbytes < sizeof(*hwrpb)) return -EINVAL; if (copy_to_user(buffer, hwrpb, nbytes) != 0) return -EFAULT; return 1; default: break; } return -EOPNOTSUPP;}asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, unsigned long nbytes, int *start, void *arg){ switch (op) { case SSI_IEEE_FP_CONTROL: { unsigned long swcr, fpcr; /* * Alpha Architecture Handbook 4.7.7.3: * To be fully IEEE compiant, we must track the current IEEE * exception state in software, because spurrious bits can be * set in the trap shadow of a software-complete insn. */ /* Update softare trap enable bits. */ if (get_user(swcr, (unsigned long *)buffer)) return -EFAULT; current->thread.flags &= ~IEEE_SW_MASK; current->thread.flags |= swcr & IEEE_SW_MASK; /* Update the real fpcr. */ fpcr = rdfpcr(); fpcr &= FPCR_DYN_MASK; fpcr |= ieee_swcr_to_fpcr(swcr); wrfpcr(fpcr); /* If any exceptions are now unmasked, send a signal. */ if (((swcr & IEEE_STATUS_MASK) >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr) { send_sig(SIGFPE, current, 1); } return 0; } case SSI_IEEE_STATE_AT_SIGNAL: case SSI_IEEE_IGNORE_STATE_AT_SIGNAL: /* * Not sure anybody will ever use this weird stuff. These * ops can be used (under OSF/1) to set the fpcr that should * be used when a signal handler starts executing. */ break; case SSI_NVPAIRS: { unsigned long v, w, i; for (i = 0; i < nbytes; ++i) { if (get_user(v, 2*i + (unsigned int *)buffer)) return -EFAULT; if (get_user(w, 2*i + 1 + (unsigned int *)buffer)) return -EFAULT; switch (v) { case SSIN_UACPROC: current->thread.flags &= ~(UAC_BITMASK << UAC_SHIFT); current->thread.flags |= (w & UAC_BITMASK) << UAC_SHIFT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -