linux_osf1.c revision 1.3.4.2 1 /* $NetBSD: linux_osf1.c,v 1.3.4.2 2019/06/10 22:06:59 christos Exp $ */
2
3 /*
4 * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Christopher G. Demetriou
17 * for the NetBSD Project.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: linux_osf1.c,v 1.3.4.2 2019/06/10 22:06:59 christos Exp $");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/namei.h>
39 #include <sys/proc.h>
40 #include <sys/file.h>
41 #include <sys/filedesc.h>
42 #include <sys/kernel.h>
43 #include <sys/mount.h>
44 #include <sys/vnode.h>
45 #include <sys/wait.h>
46 #include <sys/select.h>
47 #include <sys/syscallargs.h>
48 #include <sys/vfs_syscalls.h>
49
50 #include <machine/alpha.h>
51 #include <machine/cpuconf.h>
52 #include <machine/rpb.h>
53 #include <machine/fpu.h>
54
55 #include <compat/common/compat_util.h>
56 #include <compat/linux/common/linux_types.h>
57 #include <compat/linux/common/linux_signal.h>
58 #include <compat/linux/arch/alpha/linux_signal.h>
59 #include <compat/linux/arch/alpha/linux_osf1.h>
60 #include <compat/linux/linux_syscallargs.h>
61
62 #include <net/if.h>
63 #include <netinet/in.h>
64
65 #include <nfs/rpcv2.h>
66 #include <nfs/nfsproto.h>
67 #include <nfs/nfs.h>
68 #include <nfs/nfsmount.h>
69
70 #include <ufs/ufs/quota.h>
71 #include <ufs/ufs/ufsmount.h>
72
73 #include <machine/vmparam.h>
74
75 const struct emul_flags_xtab osf1_wait_options_xtab[] = {
76 { OSF1_WNOHANG, OSF1_WNOHANG, WNOHANG },
77 { OSF1_WUNTRACED, OSF1_WUNTRACED, WUNTRACED },
78 { 0 }
79 };
80
81 const struct emul_flags_xtab osf1_nfs_mount_flags_xtab[] = {
82 { OSF1_NFSMNT_SOFT, OSF1_NFSMNT_SOFT, NFSMNT_SOFT, },
83 { OSF1_NFSMNT_WSIZE, OSF1_NFSMNT_WSIZE, NFSMNT_WSIZE, },
84 { OSF1_NFSMNT_RSIZE, OSF1_NFSMNT_RSIZE, NFSMNT_RSIZE, },
85 { OSF1_NFSMNT_TIMEO, OSF1_NFSMNT_TIMEO, NFSMNT_TIMEO, },
86 { OSF1_NFSMNT_RETRANS, OSF1_NFSMNT_RETRANS, NFSMNT_RETRANS, },
87 #if 0 /* no equivalent; needs special handling, see below */
88 { OSF1_NFSMNT_HOSTNAME, OSF1_NFSMNT_HOSTNAME, ???, },
89 #endif
90 { OSF1_NFSMNT_INT, OSF1_NFSMNT_INT, NFSMNT_INT, },
91 { OSF1_NFSMNT_NOCONN, OSF1_NFSMNT_NOCONN, NFSMNT_NOCONN, },
92 #if 0 /* no equivalents */
93 { OSF1_NFSMNT_NOAC, OSF1_NFSMNT_NOAC, ???, },
94 { OSF1_NFSMNT_ACREGMIN, OSF1_NFSMNT_ACREGMIN, ???, },
95 { OSF1_NFSMNT_ACREGMAX, OSF1_NFSMNT_ACREGMAX, ???, },
96 { OSF1_NFSMNT_ACDIRMIN, OSF1_NFSMNT_ACDIRMIN, ???, },
97 { OSF1_NFSMNT_ACDIRMAX, OSF1_NFSMNT_ACDIRMAX, ???, },
98 { OSF1_NFSMNT_NOCTO, OSF1_NFSMNT_NOCTO, ???, },
99 { OSF1_NFSMNT_POSIX, OSF1_NFSMNT_POSIX, ???, },
100 { OSF1_NFSMNT_AUTO, OSF1_NFSMNT_AUTO, ???, },
101 { OSF1_NFSMNT_SEC, OSF1_NFSMNT_SEC, ???, },
102 { OSF1_NFSMNT_TCP, OSF1_NFSMNT_TCP, ???, },
103 { OSF1_NFSMNT_PROPLIST, OSF1_NFSMNT_PROPLIST, ???, },
104 #endif
105 { 0 }
106 };
107
108 static void
109 osf1_cvt_rusage_from_native(const struct rusage *ru, struct osf1_rusage *oru)
110 {
111
112 oru->ru_utime.tv_sec = ru->ru_utime.tv_sec;
113 oru->ru_utime.tv_usec = ru->ru_utime.tv_usec;
114
115 oru->ru_stime.tv_sec = ru->ru_stime.tv_sec;
116 oru->ru_stime.tv_usec = ru->ru_stime.tv_usec;
117
118 oru->ru_maxrss = ru->ru_maxrss;
119 oru->ru_ixrss = ru->ru_ixrss;
120 oru->ru_idrss = ru->ru_idrss;
121 oru->ru_isrss = ru->ru_isrss;
122 oru->ru_minflt = ru->ru_minflt;
123 oru->ru_majflt = ru->ru_majflt;
124 oru->ru_nswap = ru->ru_nswap;
125 oru->ru_inblock = ru->ru_inblock;
126 oru->ru_oublock = ru->ru_oublock;
127 oru->ru_msgsnd = ru->ru_msgsnd;
128 oru->ru_msgrcv = ru->ru_msgrcv;
129 oru->ru_nsignals = ru->ru_nsignals;
130 oru->ru_nvcsw = ru->ru_nvcsw;
131 oru->ru_nivcsw = ru->ru_nivcsw;
132 }
133
134 static void
135 osf1_cvt_statfs_from_native(const struct statvfs *bsfs, struct osf1_statfs *osfs)
136 {
137
138 memset(osfs, 0, sizeof (struct osf1_statfs));
139 if (!strncmp(MOUNT_FFS, bsfs->f_fstypename, sizeof(bsfs->f_fstypename)))
140 osfs->f_type = OSF1_MOUNT_UFS;
141 else if (!strncmp(MOUNT_NFS, bsfs->f_fstypename, sizeof(bsfs->f_fstypename)))
142 osfs->f_type = OSF1_MOUNT_NFS;
143 else if (!strncmp(MOUNT_MFS, bsfs->f_fstypename, sizeof(bsfs->f_fstypename)))
144 osfs->f_type = OSF1_MOUNT_MFS;
145 else
146 /* uh oh... XXX = PC, CDFS, PROCFS, etc. */
147 osfs->f_type = OSF1_MOUNT_ADDON;
148 osfs->f_flags = bsfs->f_flag; /* XXX translate */
149 osfs->f_fsize = bsfs->f_frsize;
150 osfs->f_bsize = bsfs->f_bsize;
151 osfs->f_blocks = bsfs->f_blocks;
152 osfs->f_bfree = bsfs->f_bfree;
153 osfs->f_bavail = bsfs->f_bavail;
154 osfs->f_files = bsfs->f_files;
155 osfs->f_ffree = bsfs->f_ffree;
156 memcpy(&osfs->f_fsid, &bsfs->f_fsidx, sizeof osfs->f_fsid);
157 /* osfs->f_spare zeroed above */
158 memcpy(osfs->f_mntonname, bsfs->f_mntonname, sizeof osfs->f_mntonname);
159 memcpy(osfs->f_mntfromname, bsfs->f_mntfromname,
160 sizeof osfs->f_mntfromname);
161 /* XXX osfs->f_xxx should be filled in... */
162 }
163
164 /* --------------------------------------------------------------------- */
165
166 int
167 linux_sys_osf1_wait4(struct lwp *l, const struct linux_sys_osf1_wait4_args *uap, register_t *retval)
168 {
169 struct osf1_rusage osf1_rusage;
170 struct rusage netbsd_rusage;
171 unsigned long leftovers;
172 int error, status;
173 int options = SCARG(uap, options);
174 int pid = SCARG(uap, pid);
175
176 /* translate options */
177 options = emul_flags_translate(osf1_wait_options_xtab,
178 options, &leftovers);
179 if (leftovers != 0)
180 return (EINVAL);
181
182 error = do_sys_wait(&pid, &status, options,
183 SCARG(uap, rusage) != NULL ? &netbsd_rusage : NULL);
184
185 retval[0] = pid;
186 if (pid == 0)
187 return error;
188
189 if (SCARG(uap, rusage)) {
190 osf1_cvt_rusage_from_native(&netbsd_rusage, &osf1_rusage);
191 error = copyout(&osf1_rusage, SCARG(uap, rusage),
192 sizeof osf1_rusage);
193 }
194
195 if (error == 0 && SCARG(uap, status))
196 error = copyout(&status, SCARG(uap, status), sizeof(status));
197
198 return error;
199 }
200
201 #define OSF1_MNT_WAIT 0x1
202 #define OSF1_MNT_NOWAIT 0x2
203
204 #define OSF1_MNT_FORCE 0x1
205 #define OSF1_MNT_NOFORCE 0x2
206
207 /* acceptable flags for various calls */
208 #define OSF1_GETFSSTAT_FLAGS (OSF1_MNT_WAIT|OSF1_MNT_NOWAIT)
209 #define OSF1_MOUNT_FLAGS 0xffffffff /* XXX */
210 #define OSF1_UNMOUNT_FLAGS (OSF1_MNT_FORCE|OSF1_MNT_NOFORCE)
211
212 static int
213 osf1_mount_mfs(struct lwp *l, const struct linux_sys_osf1_mount_args *uap)
214 {
215 struct osf1_mfs_args osf_ma;
216 struct mfs_args bsd_ma;
217 int error;
218 register_t dummy;
219
220 if ((error = copyin(SCARG(uap, data), &osf_ma, sizeof osf_ma)))
221 return error;
222
223 memset(&bsd_ma, 0, sizeof bsd_ma);
224 bsd_ma.fspec = osf_ma.name;
225 /* XXX export args */
226 bsd_ma.base = osf_ma.base;
227 bsd_ma.size = osf_ma.size;
228
229 return do_sys_mount(l, "mfs", UIO_SYSSPACE, SCARG(uap, path),
230 SCARG(uap, flags), &bsd_ma, UIO_SYSSPACE, sizeof bsd_ma, &dummy);
231 }
232
233 static int
234 osf1_mount_nfs(struct lwp *l, const struct linux_sys_osf1_mount_args *uap)
235 {
236 struct osf1_nfs_args osf_na;
237 struct nfs_args bsd_na;
238 int error;
239 unsigned long leftovers;
240 register_t dummy;
241
242 if ((error = copyin(SCARG(uap, data), &osf_na, sizeof osf_na)))
243 return error;
244
245 memset(&bsd_na, 0, sizeof bsd_na);
246 bsd_na.addr = (struct sockaddr *)osf_na.addr;
247 bsd_na.addrlen = sizeof (struct sockaddr_in);
248 bsd_na.fh = osf_na.fh;
249
250 /* translate flags */
251 bsd_na.flags = emul_flags_translate(osf1_nfs_mount_flags_xtab,
252 osf_na.flags, &leftovers);
253 if (leftovers & OSF1_NFSMNT_HOSTNAME) {
254 leftovers &= ~OSF1_NFSMNT_HOSTNAME;
255 bsd_na.hostname = osf_na.hostname;
256 } else {
257 /* XXX FILL IN HOST NAME WITH IPADDR? */
258 }
259 if (leftovers & OSF1_NFSMNT_TCP) {
260 leftovers &= ~OSF1_NFSMNT_TCP;
261 bsd_na.sotype = SOCK_DGRAM;
262 bsd_na.proto = 0;
263 } else {
264 bsd_na.sotype = SOCK_STREAM;
265 bsd_na.proto = 0;
266 }
267 if (leftovers != 0)
268 return (EINVAL);
269
270 /* copy structure elements based on flags */
271 if (bsd_na.flags & NFSMNT_WSIZE)
272 bsd_na.wsize = osf_na.wsize;
273 if (bsd_na.flags & NFSMNT_RSIZE)
274 bsd_na.rsize = osf_na.rsize;
275 if (bsd_na.flags & NFSMNT_TIMEO)
276 bsd_na.timeo = osf_na.timeo;
277 if (bsd_na.flags & NFSMNT_RETRANS)
278 bsd_na.retrans = osf_na.retrans;
279
280 return do_sys_mount(l, "nfs", UIO_SYSSPACE, SCARG(uap, path),
281 SCARG(uap, flags), &bsd_na, UIO_SYSSPACE, sizeof bsd_na, &dummy);
282 }
283
284 int
285 linux_sys_osf1_mount(struct lwp *l, const struct linux_sys_osf1_mount_args *uap, register_t *retval)
286 {
287
288 if (SCARG(uap, flags) & ~OSF1_MOUNT_FLAGS)
289 return (EINVAL);
290
291 /* XXX - xlate flags */
292
293 switch (SCARG(uap, type)) {
294 case OSF1_MOUNT_NFS:
295 return osf1_mount_nfs(l, uap);
296 break;
297
298 case OSF1_MOUNT_MFS:
299 return osf1_mount_mfs(l, uap);
300
301 default:
302 return (EINVAL);
303 }
304 }
305
306 int
307 linux_sys_osf1_set_program_attributes(struct lwp *l, const struct linux_sys_osf1_set_program_attributes_args *uap, register_t *retval)
308 {
309 struct proc *p = l->l_proc;
310 segsz_t tsize, dsize;
311
312 tsize = btoc(SCARG(uap, tsize));
313 dsize = btoc(SCARG(uap, dsize));
314
315 if (dsize > p->p_rlimit[RLIMIT_DATA].rlim_cur)
316 return (ENOMEM);
317 if (tsize > MAXTSIZ)
318 return (ENOMEM);
319
320 /* XXXSMP unlocked */
321 p->p_vmspace->vm_taddr = SCARG(uap, taddr);
322 p->p_vmspace->vm_tsize = tsize;
323 p->p_vmspace->vm_daddr = SCARG(uap, daddr);
324 p->p_vmspace->vm_dsize = dsize;
325
326 return (0);
327 }
328
329 int
330 linux_sys_osf1_setitimer(struct lwp *l, const struct linux_sys_osf1_setitimer_args *uap, register_t *retval)
331 {
332 struct osf1_itimerval o_itv, o_oitv;
333 struct itimerval b_itv, b_oitv;
334 int which;
335 int error;
336
337 switch (SCARG(uap, which)) {
338 case OSF1_ITIMER_REAL:
339 which = ITIMER_REAL;
340 break;
341
342 case OSF1_ITIMER_VIRTUAL:
343 which = ITIMER_VIRTUAL;
344 break;
345
346 case OSF1_ITIMER_PROF:
347 which = ITIMER_PROF;
348 break;
349
350 default:
351 return (EINVAL);
352 }
353
354 /* get the OSF/1 itimerval argument */
355 error = copyin(SCARG(uap, itv), &o_itv, sizeof o_itv);
356 if (error != 0)
357 return error;
358
359 /* fill in and the NetBSD timeval */
360 memset(&b_itv, 0, sizeof b_itv);
361 b_itv.it_interval.tv_sec = o_itv.it_interval.tv_sec;
362 b_itv.it_interval.tv_usec = o_itv.it_interval.tv_usec;
363 b_itv.it_value.tv_sec = o_itv.it_value.tv_sec;
364 b_itv.it_value.tv_usec = o_itv.it_value.tv_usec;
365
366 if (SCARG(uap, oitv) != NULL) {
367 dogetitimer(l->l_proc, which, &b_oitv);
368 if (error)
369 return error;
370 }
371
372 error = dosetitimer(l->l_proc, which, &b_itv);
373
374 if (error == 0 || SCARG(uap, oitv) == NULL)
375 return error;
376
377 /* fill in and copy out the old timeval */
378 memset(&o_oitv, 0, sizeof o_oitv);
379 o_oitv.it_interval.tv_sec = b_oitv.it_interval.tv_sec;
380 o_oitv.it_interval.tv_usec = b_oitv.it_interval.tv_usec;
381 o_oitv.it_value.tv_sec = b_oitv.it_value.tv_sec;
382 o_oitv.it_value.tv_usec = b_oitv.it_value.tv_usec;
383
384 return copyout(&o_oitv, SCARG(uap, oitv), sizeof o_oitv);
385 }
386
387 int
388 linux_sys_osf1_select(struct lwp *l, const struct linux_sys_osf1_select_args *uap,
389 register_t *retval)
390 {
391 struct osf1_timeval otv;
392 struct timespec ats, *ts = NULL;
393 int error;
394
395 if (SCARG(uap, tv)) {
396 /* get the OSF/1 timeval argument */
397 error = copyin(SCARG(uap, tv), &otv, sizeof otv);
398 if (error != 0)
399 return error;
400
401 ats.tv_sec = otv.tv_sec;
402 ats.tv_nsec = otv.tv_usec * 1000;
403 ts = &ats;
404 }
405
406 return selcommon(retval, SCARG(uap, nd), SCARG(uap, in),
407 SCARG(uap, ou), SCARG(uap, ex), ts, NULL);
408 }
409
410 int
411 linux_sys_osf1_gettimeofday(struct lwp *l, const struct linux_sys_osf1_gettimeofday_args *uap, register_t *retval)
412 {
413 struct osf1_timeval otv;
414 struct osf1_timezone otz;
415 struct timeval tv;
416 int error;
417
418 microtime(&tv);
419 memset(&otv, 0, sizeof otv);
420 otv.tv_sec = tv.tv_sec;
421 otv.tv_usec = tv.tv_usec;
422 error = copyout(&otv, SCARG(uap, tv), sizeof otv);
423
424 if (error == 0 && SCARG(uap, tzp) != NULL) {
425 memset(&otz, 0, sizeof otz);
426 error = copyout(&otz, SCARG(uap, tzp), sizeof otz);
427 }
428 return (error);
429 }
430
431 int
432 linux_sys_osf1_getrusage(struct lwp *l, const struct linux_sys_osf1_getrusage_args *uap, register_t *retval)
433 {
434 int error, who;
435 struct osf1_rusage osf1_rusage;
436 struct rusage ru;
437 struct proc *p = l->l_proc;
438
439
440 switch (SCARG(uap, who)) {
441 case OSF1_RUSAGE_SELF:
442 who = RUSAGE_SELF;
443 break;
444
445 case OSF1_RUSAGE_CHILDREN:
446 who = RUSAGE_CHILDREN;
447 break;
448
449 case OSF1_RUSAGE_THREAD: /* XXX not supported */
450 default:
451 return EINVAL;
452 }
453
454 error = getrusage1(p, who, &ru);
455 if (error != 0)
456 return error;
457
458 osf1_cvt_rusage_from_native(&ru, &osf1_rusage);
459
460 return copyout(&osf1_rusage, SCARG(uap, rusage), sizeof osf1_rusage);
461 }
462
463 int
464 linux_sys_osf1_settimeofday(struct lwp *l, const struct linux_sys_osf1_settimeofday_args *uap, register_t *retval)
465 {
466 struct osf1_timeval otv;
467 struct timeval tv, *tvp;
468 int error = 0;
469
470 if (SCARG(uap, tv) == NULL)
471 tvp = NULL;
472 else {
473 /* get the OSF/1 timeval argument */
474 error = copyin(SCARG(uap, tv), &otv, sizeof otv);
475 if (error != 0)
476 return error;
477
478 tv.tv_sec = otv.tv_sec;
479 tv.tv_usec = otv.tv_usec;
480 tvp = &tv;
481 }
482
483 /* NetBSD ignores the timezone field */
484
485 return settimeofday1(tvp, false, (const void *)SCARG(uap, tzp), l, true);
486 }
487
488 int
489 linux_sys_osf1_utimes(struct lwp *l, const struct linux_sys_osf1_utimes_args *uap, register_t *retval)
490 {
491 struct osf1_timeval otv;
492 struct timeval tv[2], *tvp;
493 int error;
494
495 if (SCARG(uap, tptr) == NULL)
496 tvp = NULL;
497 else {
498 /* get the OSF/1 timeval argument */
499 error = copyin(SCARG(uap, tptr), &otv, sizeof otv);
500 if (error != 0)
501 return error;
502
503 /* fill in and copy out the NetBSD timeval */
504 tv[0].tv_sec = otv.tv_sec;
505 tv[0].tv_usec = otv.tv_usec;
506 /* Set access and modified to the same time */
507 tv[1].tv_sec = otv.tv_sec;
508 tv[1].tv_usec = otv.tv_usec;
509 tvp = tv;
510 }
511
512 return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW,
513 tvp, UIO_SYSSPACE);
514 }
515
516 int
517 linux_sys_osf1_statfs(struct lwp *l, const struct linux_sys_osf1_statfs_args *uap, register_t *retval)
518 {
519 struct mount *mp;
520 struct statvfs *sp;
521 struct osf1_statfs osfs;
522 int error;
523 struct vnode *vp;
524
525 error = namei_simple_user(SCARG(uap, path),
526 NSM_FOLLOW_TRYEMULROOT, &vp);
527 if (error != 0)
528 return (error);
529 mp = vp->v_mount;
530 sp = &mp->mnt_stat;
531 vrele(vp);
532 if ((error = VFS_STATVFS(mp, sp)))
533 return (error);
534 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
535 osf1_cvt_statfs_from_native(sp, &osfs);
536 return copyout(&osfs, SCARG(uap, buf), uimin(sizeof osfs,
537 SCARG(uap, len)));
538 }
539
540 int
541 linux_sys_osf1_fstatfs(struct lwp *l, const struct linux_sys_osf1_fstatfs_args *uap, register_t *retval)
542 {
543 file_t *fp;
544 struct mount *mp;
545 struct statvfs *sp;
546 struct osf1_statfs osfs;
547 int error;
548
549 /* fd_getvnode() will use the descriptor for us */
550 if ((error = fd_getvnode(SCARG(uap, fd), &fp)))
551 return (error);
552 mp = fp->f_vnode->v_mount;
553 sp = &mp->mnt_stat;
554 if ((error = VFS_STATVFS(mp, sp)))
555 goto out;
556 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
557 osf1_cvt_statfs_from_native(sp, &osfs);
558 error = copyout(&osfs, SCARG(uap, buf), uimin(sizeof osfs,
559 SCARG(uap, len)));
560 out:
561 fd_putfile(SCARG(uap, fd));
562 return (error);
563 }
564
565 int
566 linux_sys_osf1_sysinfo(struct lwp *l, const struct linux_sys_osf1_sysinfo_args *uap, register_t *retval)
567 {
568 const char *string;
569 size_t slen;
570 int error;
571
572 error = 0;
573 switch (SCARG(uap, cmd)) {
574 case OSF1_SI_SYSNAME:
575 string = ostype;
576 break;
577
578 case OSF1_SI_HOSTNAME:
579 string = hostname;
580 break;
581
582 case OSF1_SI_RELEASE:
583 string = osrelease;
584 break;
585
586 case OSF1_SI_VERSION:
587 goto should_handle;
588
589 case OSF1_SI_MACHINE:
590 string = MACHINE;
591 break;
592
593 case OSF1_SI_ARCHITECTURE:
594 string = MACHINE_ARCH;
595 break;
596
597 case OSF1_SI_HW_SERIAL:
598 string = "666"; /* OSF/1 emulation? YES! */
599 break;
600
601 case OSF1_SI_HW_PROVIDER:
602 string = "unknown";
603 break;
604
605 case OSF1_SI_SRPC_DOMAIN:
606 goto dont_care;
607
608 case OSF1_SI_SET_HOSTNAME:
609 goto should_handle;
610
611 case OSF1_SI_SET_SYSNAME:
612 goto should_handle;
613
614 case OSF1_SI_SET_SRPC_DOMAIN:
615 goto dont_care;
616
617 default:
618 should_handle:
619 printf("osf1_sys_sysinfo(%d, %p, 0x%lx)\n", SCARG(uap, cmd),
620 SCARG(uap, buf), SCARG(uap,len));
621 dont_care:
622 return (EINVAL);
623 };
624
625 slen = strlen(string) + 1;
626 if (SCARG(uap, buf)) {
627 error = copyout(string, SCARG(uap, buf),
628 uimin(slen, SCARG(uap, len)));
629 if (!error && (SCARG(uap, len) > 0) && (SCARG(uap, len) < slen))
630 error = ustore_char(SCARG(uap, buf)
631 + SCARG(uap, len) - 1, 0);
632 }
633 if (!error)
634 retval[0] = slen;
635
636 return (error);
637 }
638
639 int
640 linux_sys_osf1_usleep_thread(struct lwp *l, const struct linux_sys_osf1_usleep_thread_args *uap, register_t *retval)
641 {
642 struct osf1_timeval otv, endotv;
643 struct timeval tv, ntv, endtv;
644 u_long ticks;
645 int error;
646
647 if ((error = copyin(SCARG(uap, sleep), &otv, sizeof otv)))
648 return (error);
649 tv.tv_sec = otv.tv_sec;
650 tv.tv_usec = otv.tv_usec;
651
652 ticks = howmany((u_long)tv.tv_sec * 1000000 + tv.tv_usec, tick);
653 if (ticks == 0)
654 ticks = 1;
655
656 getmicrotime(&tv);
657
658 tsleep(l, PUSER|PCATCH, "uslpthrd", ticks); /* XXX */
659
660 if (SCARG(uap, slept) != NULL) {
661 getmicrotime(&ntv);
662 timersub(&ntv, &tv, &endtv);
663 if (endtv.tv_sec < 0 || endtv.tv_usec < 0)
664 endtv.tv_sec = endtv.tv_usec = 0;
665
666 endotv.tv_sec = endtv.tv_sec;
667 endotv.tv_usec = endtv.tv_usec;
668 error = copyout(&endotv, SCARG(uap, slept), sizeof endotv);
669 }
670 return (error);
671 }
672
673 int
674 linux_sys_osf1_getsysinfo(struct lwp *l, const struct linux_sys_osf1_getsysinfo_args *uap, register_t *retval)
675 {
676 extern int ncpus;
677 int error;
678 int unit;
679 long percpu;
680 long proctype;
681 u_int64_t fpflags;
682 struct osf1_cpu_info cpuinfo;
683 const void *data;
684 size_t datalen;
685
686 error = 0;
687
688 switch(SCARG(uap, op))
689 {
690 case OSF_GET_MAX_UPROCS:
691 data = &maxproc;
692 datalen = sizeof(maxproc);
693 break;
694 case OSF_GET_PHYSMEM:
695 data = &physmem;
696 datalen = sizeof(physmem);
697 break;
698 case OSF_GET_MAX_CPU:
699 case OSF_GET_CPUS_IN_BOX:
700 data = &ncpus;
701 datalen = sizeof(ncpus);
702 break;
703 case OSF_GET_IEEE_FP_CONTROL:
704 if (((fpflags = alpha_read_fp_c(l)) & IEEE_INHERIT) != 0) {
705 fpflags |= 1ULL << 63;
706 fpflags &= ~IEEE_INHERIT;
707 }
708 data = &fpflags;
709 datalen = sizeof(fpflags);
710 break;
711 case OSF_GET_CPU_INFO:
712 memset(&cpuinfo, 0, sizeof(cpuinfo));
713 #ifdef __alpha__
714 unit = alpha_pal_whami();
715 #else
716 unit = 0; /* XXX */
717 #endif
718 cpuinfo.current_cpu = unit;
719 cpuinfo.cpus_in_box = ncpus;
720 cpuinfo.cpu_type = LOCATE_PCS(hwrpb, unit)->pcs_proc_type;
721 cpuinfo.ncpus = ncpus;
722 cpuinfo.cpus_present = ncpus;
723 cpuinfo.cpus_running = ncpus;
724 cpuinfo.cpu_binding = 1;
725 cpuinfo.cpu_ex_binding = 0;
726 cpuinfo.mhz = hwrpb->rpb_cc_freq / 1000000;
727 data = &cpuinfo;
728 datalen = sizeof(cpuinfo);
729 break;
730 case OSF_GET_PROC_TYPE:
731 #ifdef __alpha__
732 unit = alpha_pal_whami();
733 proctype = LOCATE_PCS(hwrpb, unit)->pcs_proc_type;
734 #else
735 proctype = 0; /* XXX */
736 #endif
737 data = &proctype;
738 datalen = sizeof(percpu);
739 break;
740 case OSF_GET_HWRPB: /* note -- osf/1 doesn't have rpb_tbhint[8] */
741 data = hwrpb;
742 datalen = hwrpb->rpb_size;
743 break;
744 case OSF_GET_PLATFORM_NAME:
745 data = platform.model;
746 datalen = strlen(platform.model) + 1;
747 break;
748 default:
749 printf("osf1_getsysinfo called with unknown op=%ld\n",
750 SCARG(uap, op));
751 /* return EINVAL; */
752 return 0;
753 }
754
755 if (SCARG(uap, nbytes) < datalen)
756 return (EINVAL);
757 error = copyout(data, SCARG(uap, buffer), datalen);
758 if (!error)
759 retval[0] = 1;
760 return (error);
761 }
762
763 int
764 linux_sys_osf1_setsysinfo(struct lwp *l, const struct linux_sys_osf1_setsysinfo_args *uap, register_t *retval)
765 {
766 u_int64_t temp;
767 int error;
768
769 error = 0;
770
771 switch(SCARG(uap, op)) {
772 case OSF_SET_IEEE_FP_CONTROL:
773
774 if ((error = copyin(SCARG(uap, buffer), &temp, sizeof(temp))))
775 break;
776 if (temp >> 63 != 0)
777 temp |= IEEE_INHERIT;
778 alpha_write_fp_c(l, temp);
779 break;
780 default:
781 uprintf("osf1_setsysinfo called with op=%ld\n", SCARG(uap, op));
782 //error = EINVAL;
783 }
784 retval[0] = 0;
785 return (error);
786 }
787