/* * This file handles some of the stranger OSF/1 system call interfaces. * Some of the system calls expect a non-C calling standard, others have * special parameter blocks..
*/
/* * Brk needs to return an error. Still support Linux's brk(0) query idiom, * which OSF programs just shouldn't be doing. We're still not quite * identical to OSF as we don't return 0 on success, but doing otherwise * would require changes to libc. Hopefully this is good enough.
*/
SYSCALL_DEFINE1(osf_brk, unsignedlong, brk)
{ unsignedlong retval = sys_brk(brk); if (brk && brk != retval)
retval = -ENOMEM; return retval;
}
/* * This is pure guess-work..
*/
SYSCALL_DEFINE4(osf_set_program_attributes, unsignedlong, text_start, unsignedlong, text_len, unsignedlong, bss_start, unsignedlong, bss_len)
{ struct mm_struct *mm;
/* * OSF/1 directory handling functions... * * The "getdents()" interface is much more sane: the "basep" stuff is * braindamage (it can't really handle filesystems where the directory * offset differences aren't the same as "d_reclen").
*/ #define NAME_OFFSET offsetof (struct osf_dirent, d_name)
#if 0 if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
printk("%s: unimplemented OSF mmap flags %04lx\n",
current->comm, flags); #endif if ((off + PAGE_ALIGN(len)) < off) goto out; if (off & ~PAGE_MASK) goto out;
ret = ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
out: return ret;
}
struct osf_stat { int st_dev; int st_pad1; unsigned st_mode; unsignedshort st_nlink; short st_nlink_reserved; unsigned st_uid; unsigned st_gid; int st_rdev; int st_ldev; long st_size; int st_pad2; int st_uatime; int st_pad3; int st_umtime; int st_pad4; int st_uctime; int st_pad5; int st_pad6; unsigned st_flags; unsigned st_gen; long st_spare[4]; unsigned st_ino; int st_ino_reserved; int st_atime; int st_atime_reserved; int st_mtime; int st_mtime_reserved; int st_ctime; int st_ctime_reserved; long st_blksize; long st_blocks;
};
/* * The OSF/1 statfs structure is much larger, but this should * match the beginning, at least.
*/ struct osf_statfs { short f_type; short f_flags; int f_fsize; int f_bsize; int f_blocks; int f_bfree; int f_bavail; int f_files; int f_ffree;
__kernel_fsid_t f_fsid;
};
struct osf_statfs64 { short f_type; short f_flags; int f_pad1; int f_pad2; int f_pad3; int f_pad4; int f_pad5; int f_pad6; int f_pad7;
__kernel_fsid_t f_fsid;
u_short f_namemax; short f_reserved1; int f_spare[8]; char f_pad8[90]; char f_pad9[90]; long mount_info[10];
u_long f_flags2; long f_spare2[14]; long f_fsize; long f_bsize; long f_blocks; long f_bfree; long f_bavail; long f_files; long f_ffree;
};
/* * Uhh.. OSF/1 mount parameters aren't exactly obvious.. * * Although to be frank, neither are the native Linux/i386 ones..
*/ struct ufs_args { char __user *devname; int flags;
uid_t exroot;
};
struct cdfs_args { char __user *devname; int flags;
uid_t exroot;
/* This has lots more here, which Linux handles with the option block
but I'm too lazy to do the translation into ASCII. */
};
/* * We can't actually handle ufs yet, so we translate UFS mounts to * ext2fs mounts. I wouldn't mind a UFS filesystem, but the UFS * layout is so braindead it's a major headache doing it. * * Just how long ago was it written? OTOH our UFS driver may be still * unhappy with OSF UFS. [CHECKME]
*/ staticint
osf_ufs_mount(constchar __user *dirname, struct ufs_args __user *args, int flags)
{ int retval; struct cdfs_args tmp; struct filename *devname;
/* * For compatibility with OSF/1 only. Use utsname(2) instead.
*/
SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen)
{ int len; char *kname; char tmp[32];
if (namelen < 0 || namelen > 32)
namelen = 32;
down_read(&uts_sem);
kname = utsname()->domainname;
len = strnlen(kname, namelen);
len = min(len + 1, namelen);
memcpy(tmp, kname, len);
up_read(&uts_sem);
if (copy_to_user(name, tmp, len)) return -EFAULT; return 0;
}
/* * 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 */
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 = (unsignedlong)ss_sp - SIGSTKSZ;
current->sas_ss_size = SIGSTKSZ;
}
if (uoss) {
error = -EFAULT; if (put_user(oss_sp, &uoss->ss_sp) ||
put_user(oss_os, &uoss->ss_onstack)) goto out;
}
offset = command-1; if (offset >= ARRAY_SIZE(sysinfo_table)) { /* Digital UNIX has a few unpublished interfaces here */
printk("sysinfo(%d)", command); return -EINVAL;
}
down_read(&uts_sem);
res = sysinfo_table[offset];
len = strlen(res)+1; if ((unsignedlong)len > (unsignedlong)count)
len = count;
memcpy(tmp, res, len);
up_read(&uts_sem); if (copy_to_user(buf, tmp, len)) return -EFAULT; return 0;
}
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_info()->ieee_state & IEEE_SW_MASK;
w = swcr_update_status(w, rdfpcr()); if (put_user(w, (unsignedlong __user *) 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(unsignedint)) return -EINVAL;
w = current_thread_info()->status & UAC_BITMASK; if (put_user(w, (unsignedint __user *)buffer)) return -EFAULT; return 1;
case GSI_PROC_TYPE: if (nbytes < sizeof(unsignedlong)) return -EINVAL;
cpu = (struct percpu_struct*)
((char*)hwrpb + hwrpb->processor_offset);
w = cpu->type; if (put_user(w, (unsignedlong __user*)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;
/* * Alpha Architecture Handbook 4.7.7.3: * To be fully IEEE compiant, we must track the current IEEE * exception state in software, because spurious bits can be * set in the trap shadow of a software-complete insn.
*/
if (get_user(swcr, (unsignedlong __user *)buffer)) return -EFAULT;
state = ¤t_thread_info()->ieee_state;
/* Update the real fpcr. */
fpcr = rdfpcr();
fpcr |= ieee_swcr_to_fpcr(swcr);
wrfpcr(fpcr);
/* If any exceptions set by this call, and are unmasked,
send a signal. Old exceptions are not signaled. */
fex = (exc >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr; if (fex) { int si_code = FPE_FLTUNK;
if (fex & IEEE_TRAP_ENABLE_DNO) si_code = FPE_FLTUND; if (fex & IEEE_TRAP_ENABLE_INE) si_code = FPE_FLTRES; if (fex & IEEE_TRAP_ENABLE_UNF) si_code = FPE_FLTUND; if (fex & IEEE_TRAP_ENABLE_OVF) si_code = FPE_FLTOVF; if (fex & IEEE_TRAP_ENABLE_DZE) si_code = FPE_FLTDIV; if (fex & IEEE_TRAP_ENABLE_INV) si_code = FPE_FLTINV;
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 __user *p = buffer; unsigned i;
for (i = 0, p = buffer; i < nbytes; ++i, p += 2) { unsigned v, w, status;
if (get_user(v, p) || get_user(w, p + 1)) return -EFAULT; switch (v) { case SSIN_UACPROC:
w &= UAC_BITMASK;
status = current_thread_info()->status;
status = (status & ~UAC_BITMASK) | w;
current_thread_info()->status = status; break;
default: return -EOPNOTSUPP;
}
} return 0;
}
case SSI_LMF: return 0;
default: break;
}
return -EOPNOTSUPP;
}
/* Translations due to the fact that OSF's time_t is an int. Which
affects all sorts of things, like timeval and itimerval. */
if (tv.tv_sec < 0 || tv.tv_nsec < 0) return -EINVAL;
if (poll_select_set_timeout(to, tv.tv_sec, tv.tv_nsec)) return -EINVAL;
}
/* OSF does not copy back the remaining time. */ return core_sys_select(n, inp, outp, exp, to);
}
struct rusage32 { struct timeval32 ru_utime; /* user time used */ struct timeval32 ru_stime; /* system time used */ long ru_maxrss; /* maximum resident set size */ long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data size */ long ru_isrss; /* integral unshared stack size */ long ru_minflt; /* page reclaims */ long ru_majflt; /* page faults */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* messages sent */ long ru_msgrcv; /* messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary " */
};
SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, struct rusage32 __user *, ur)
{ struct rusage r; long err = kernel_wait4(pid, ustatus, options, &r); if (err <= 0) return err; if (!ur) return err; if (put_tv_to_tv32(&ur->ru_utime, &r.ru_utime)) return -EFAULT; if (put_tv_to_tv32(&ur->ru_stime, &r.ru_stime)) return -EFAULT; if (copy_to_user(&ur->ru_maxrss, &r.ru_maxrss, sizeof(struct rusage32) - offsetof(struct rusage32, ru_maxrss))) return -EFAULT; return err;
}
/* * I don't know what the parameters are: the first one * seems to be a timeval pointer, and I suspect the second * one is the time remaining.. Ho humm.. No documentation.
*/
SYSCALL_DEFINE2(osf_usleep_thread, struct timeval32 __user *, sleep, struct timeval32 __user *, remain)
{ struct timespec64 tmp; unsignedlong ticks;
if (get_tv32(&tmp, sleep)) goto fault;
ticks = timespec64_to_jiffies(&tmp);
ticks = schedule_timeout_interruptible(ticks);
if (remain) {
jiffies_to_timespec64(ticks, &tmp); if (put_tv32(remain, &tmp)) goto fault;
}
return 0;
fault: return -EFAULT;
}
struct timex32 { unsignedint modes; /* mode selector */ long offset; /* time offset (usec) */ long freq; /* frequency offset (scaled ppm) */ long maxerror; /* maximum error (usec) */ long esterror; /* estimated error (usec) */ int status; /* clock command/status */ long constant; /* pll time constant */ long precision; /* clock precision (usec) (read only) */ long tolerance; /* clock frequency tolerance (ppm) * (read only)
*/ struct timeval32 time; /* (read only) */ long tick; /* (modified) usecs between clock ticks */
long ppsfreq; /* pps frequency (scaled ppm) (ro) */ long jitter; /* pps jitter (us) (ro) */ int shift; /* interval duration (s) (shift) (ro) */ long stabil; /* pps stability (scaled ppm) (ro) */ long jitcnt; /* jitter limit exceeded (ro) */ long calcnt; /* calibration intervals (ro) */ long errcnt; /* calibration errors (ro) */ long stbcnt; /* stability limit exceeded (ro) */
int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32;
};
The OSF/1 loader (/sbin/loader) relies on us returning an address larger than the requested if one exists, which is a terribly broken way to program.
That said, I can see the use in being able to suggest not merely specific addresses, but regions of memory -- perhaps
this feature should be incorporated into all ports? */
if (addr) {
addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit); if (addr != (unsignedlong) -ENOMEM) return addr;
}
/* Next, try allocating at TASK_UNMAPPED_BASE. */
addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE),
len, limit); if (addr != (unsignedlong) -ENOMEM) return addr;
SYSCALL_DEFINE2(osf_getpriority, int, which, int, who)
{ int prio = sys_getpriority(which, who); if (prio >= 0) { /* Return value is the unbiased priority, i.e. 20 - prio. This does result in negative return values, so signal
no error */
force_successful_syscall_return();
prio = 20 - prio;
} return prio;
}
SYSCALL_DEFINE0(alpha_pipe)
{ int fd[2]; int res = do_pipe_flags(fd, 0); if (!res) { /* The return values are in $0 and $20. */
current_pt_regs()->r20 = fd[1];
res = fd[0];
} return res;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.