1*41aa5859Sriastradh /* $NetBSD: linux_machdep.c,v 1.44 2021/09/07 11:43:04 riastradh Exp $ */
263d1ca84Smanu
363d1ca84Smanu /*-
463d1ca84Smanu * Copyright (c) 1995, 2000, 2001 The NetBSD Foundation, Inc.
563d1ca84Smanu * All rights reserved.
663d1ca84Smanu *
763d1ca84Smanu * This code is derived from software contributed to The NetBSD Foundation
863d1ca84Smanu * by Frank van der Linden and Emmanuel Dreyfus.
963d1ca84Smanu *
1063d1ca84Smanu * Redistribution and use in source and binary forms, with or without
1163d1ca84Smanu * modification, are permitted provided that the following conditions
1263d1ca84Smanu * are met:
1363d1ca84Smanu * 1. Redistributions of source code must retain the above copyright
1463d1ca84Smanu * notice, this list of conditions and the following disclaimer.
1563d1ca84Smanu * 2. Redistributions in binary form must reproduce the above copyright
1663d1ca84Smanu * notice, this list of conditions and the following disclaimer in the
1763d1ca84Smanu * documentation and/or other materials provided with the distribution.
1863d1ca84Smanu *
1963d1ca84Smanu * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2063d1ca84Smanu * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2163d1ca84Smanu * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2263d1ca84Smanu * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2363d1ca84Smanu * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2463d1ca84Smanu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2563d1ca84Smanu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2663d1ca84Smanu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2763d1ca84Smanu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2863d1ca84Smanu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2963d1ca84Smanu * POSSIBILITY OF SUCH DAMAGE.
3063d1ca84Smanu */
3163d1ca84Smanu
32dab6ef8bSlukem #include <sys/cdefs.h>
33*41aa5859Sriastradh __KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.44 2021/09/07 11:43:04 riastradh Exp $");
34dab6ef8bSlukem
3563d1ca84Smanu #include <sys/param.h>
3663d1ca84Smanu #include <sys/systm.h>
3763d1ca84Smanu #include <sys/signalvar.h>
3863d1ca84Smanu #include <sys/kernel.h>
3963d1ca84Smanu #include <sys/proc.h>
4063d1ca84Smanu #include <sys/buf.h>
4163d1ca84Smanu #include <sys/reboot.h>
4263d1ca84Smanu #include <sys/conf.h>
4363d1ca84Smanu #include <sys/exec.h>
4463d1ca84Smanu #include <sys/file.h>
4563d1ca84Smanu #include <sys/callout.h>
4663d1ca84Smanu #include <sys/mbuf.h>
4763d1ca84Smanu #include <sys/msgbuf.h>
4863d1ca84Smanu #include <sys/mount.h>
4963d1ca84Smanu #include <sys/vnode.h>
5063d1ca84Smanu #include <sys/device.h>
5163d1ca84Smanu #include <sys/syscallargs.h>
5263d1ca84Smanu #include <sys/filedesc.h>
5363d1ca84Smanu #include <sys/exec_elf.h>
5463d1ca84Smanu #include <sys/disklabel.h>
5563d1ca84Smanu #include <sys/ioctl.h>
56801da946Smanu #include <sys/sysctl.h>
5788f8ec6cSyamt #include <sys/kauth.h>
5863d1ca84Smanu #include <miscfs/specfs/specdev.h>
5963d1ca84Smanu
6063d1ca84Smanu #include <compat/linux/common/linux_types.h>
6163d1ca84Smanu #include <compat/linux/common/linux_signal.h>
6263d1ca84Smanu #include <compat/linux/common/linux_util.h>
6363d1ca84Smanu #include <compat/linux/common/linux_ioctl.h>
6463d1ca84Smanu #include <compat/linux/common/linux_hdio.h>
6563d1ca84Smanu #include <compat/linux/common/linux_exec.h>
6663d1ca84Smanu #include <compat/linux/common/linux_machdep.h>
6763d1ca84Smanu
6863d1ca84Smanu #include <compat/linux/linux_syscallargs.h>
6963d1ca84Smanu
70a2a38285Sad #include <sys/cpu.h>
7163d1ca84Smanu #include <machine/psl.h>
7263d1ca84Smanu #include <machine/reg.h>
7363d1ca84Smanu #include <machine/regnum.h>
7463d1ca84Smanu #include <machine/vmparam.h>
7563d1ca84Smanu #include <machine/locore.h>
7663d1ca84Smanu
7786349adcSmanu #include <mips/cache.h>
7886349adcSmanu
79aa306c70Smatt union linux_ksigframe {
80aa306c70Smatt struct linux_sigframe sf;
81aa306c70Smatt #if !defined(__mips_o32)
82aa306c70Smatt struct linux_sigframe32 sf32;
83aa306c70Smatt #endif
84aa306c70Smatt };
85aa306c70Smatt
8663d1ca84Smanu /*
8763d1ca84Smanu * To see whether wscons is configured (for virtual console ioctl calls).
8863d1ca84Smanu */
8963d1ca84Smanu #if defined(_KERNEL_OPT)
9063d1ca84Smanu #include "wsdisplay.h"
9163d1ca84Smanu #endif
9263d1ca84Smanu #if (NWSDISPLAY > 0)
9363d1ca84Smanu #include <dev/wscons/wsconsio.h>
9463d1ca84Smanu #include <dev/wscons/wsdisplay_usl_io.h>
9563d1ca84Smanu #endif
9663d1ca84Smanu
9763d1ca84Smanu /*
9863d1ca84Smanu * Set set up registers on exec.
9963d1ca84Smanu */
10063d1ca84Smanu void
linux_setregs(struct lwp * l,struct exec_package * pack,vaddr_t stack)10133fa5ccbSchs linux_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
10263d1ca84Smanu {
10346141a31Sthorpej setregs(l, pack, stack);
10463d1ca84Smanu return;
10563d1ca84Smanu }
10663d1ca84Smanu
107aa306c70Smatt #if !defined(__mips_o32)
108aa306c70Smatt static void
linux_setup_sigcontext32(struct linux_sigcontext32 * sc,const struct trapframe * tf)109aa306c70Smatt linux_setup_sigcontext32(struct linux_sigcontext32 *sc,
110aa306c70Smatt const struct trapframe *tf)
111aa306c70Smatt {
112aa306c70Smatt for (u_int i = 0; i < 32; i++) {
113aa306c70Smatt sc->lsc_regs[i] = tf->tf_regs[i];
114aa306c70Smatt }
115aa306c70Smatt sc->lsc_mdhi = tf->tf_regs[_R_MULHI];
116aa306c70Smatt sc->lsc_mdlo = tf->tf_regs[_R_MULLO];
117aa306c70Smatt sc->lsc_pc = tf->tf_regs[_R_PC];
118aa306c70Smatt }
119aa306c70Smatt #endif
120aa306c70Smatt
121aa306c70Smatt static void
linux_setup_sigcontext(struct linux_sigcontext * sc,const struct trapframe * tf)122aa306c70Smatt linux_setup_sigcontext(struct linux_sigcontext *sc,
123aa306c70Smatt const struct trapframe *tf)
124aa306c70Smatt {
125aa306c70Smatt for (u_int i = 0; i < 32; i++) {
126aa306c70Smatt sc->lsc_regs[i] = tf->tf_regs[i];
127aa306c70Smatt }
128aa306c70Smatt sc->lsc_mdhi = tf->tf_regs[_R_MULHI];
129aa306c70Smatt sc->lsc_mdlo = tf->tf_regs[_R_MULLO];
130aa306c70Smatt sc->lsc_pc = tf->tf_regs[_R_PC];
131aa306c70Smatt }
132aa306c70Smatt
13363d1ca84Smanu /*
13463d1ca84Smanu * Send an interrupt to process.
13563d1ca84Smanu *
13663d1ca84Smanu * Adapted from sys/arch/mips/mips/mips_machdep.c
13763d1ca84Smanu *
13863d1ca84Smanu * XXX Does not work well yet with RT signals
13963d1ca84Smanu *
14063d1ca84Smanu */
14163d1ca84Smanu
14263d1ca84Smanu void
linux_sendsig(const ksiginfo_t * ksi,const sigset_t * mask)14328bae79bSdsl linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
14463d1ca84Smanu {
145b2563527Smanu const int sig = ksi->ksi_signo;
146aa306c70Smatt struct lwp * const l = curlwp;
147aa306c70Smatt struct proc * const p = l->l_proc;
148aa306c70Smatt struct trapframe * const tf = l->l_md.md_utf;
149aa306c70Smatt #ifdef __mips_o32
150aa306c70Smatt const int abi = _MIPS_BSD_API_O32;
151aa306c70Smatt #else
152aa306c70Smatt const int abi = p->p_md.md_abi;
153aa306c70Smatt #endif
154aa306c70Smatt union linux_ksigframe ksf, *sf;
155aa306c70Smatt bool onstack;
156aa306c70Smatt int error;
157011d4d5fSthorpej sig_t catcher = SIGACTION(p, sig).sa_handler;
15863d1ca84Smanu
159948a7fa8Smanu #ifdef DEBUG_LINUX
16063d1ca84Smanu printf("linux_sendsig()\n");
161948a7fa8Smanu #endif /* DEBUG_LINUX */
16263d1ca84Smanu
16363d1ca84Smanu /*
16463d1ca84Smanu * Do we need to jump onto the signal stack?
16563d1ca84Smanu */
166aa306c70Smatt onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0
167aa306c70Smatt && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
16863d1ca84Smanu
16963d1ca84Smanu /*
170cb5cba1cSmanu * Signal stack is broken (see at the end of linux_sigreturn), so we do
17163d1ca84Smanu * not use it yet. XXX fix this.
17263d1ca84Smanu */
173aa306c70Smatt onstack = false;
17463d1ca84Smanu
17563d1ca84Smanu /*
17663d1ca84Smanu * Allocate space for the signal handler context.
17763d1ca84Smanu */
178aa306c70Smatt sf = (void *)(onstack
179aa306c70Smatt ? (uintptr_t) l->l_sigstk.ss_sp + l->l_sigstk.ss_size
180aa306c70Smatt : (uintptr_t) tf->tf_regs[_R_SP]);
18163d1ca84Smanu
182948a7fa8Smanu /*
183948a7fa8Smanu * Build stack frame for signal trampoline.
184948a7fa8Smanu */
185aa306c70Smatt memset(&ksf, 0, sizeof ksf);
186948a7fa8Smanu
187948a7fa8Smanu /*
188948a7fa8Smanu * This is the signal trampoline used by Linux, we don't use it,
189cb5cba1cSmanu * but we set it up in case an application expects it to be there
190948a7fa8Smanu */
191aa306c70Smatt ksf.sf.lsf_code[0] = 0x24020000; /* li v0, __NR_sigreturn */
192aa306c70Smatt ksf.sf.lsf_code[1] = 0x0000000c; /* syscall */
193948a7fa8Smanu
194aa306c70Smatt switch (abi) {
195aa306c70Smatt default:
196aa306c70Smatt native_to_linux_sigset(&ksf.sf.lsf_mask, mask);
197aa306c70Smatt linux_setup_sigcontext(&ksf.sf.lsf_sc, tf);
198aa306c70Smatt break;
199aa306c70Smatt #if !defined(__mips_o32)
200aa306c70Smatt case _MIPS_BSD_API_O32:
201aa306c70Smatt native_to_linux_sigset(&ksf.sf32.lsf_mask, mask);
202aa306c70Smatt linux_setup_sigcontext32(&ksf.sf32.lsf_sc, tf);
203aa306c70Smatt break;
204aa306c70Smatt #endif
205675946fdSmanu }
206b07ec3fcSad sendsig_reset(l, sig);
20763d1ca84Smanu
20863d1ca84Smanu /*
20963d1ca84Smanu * Save signal stack. XXX broken
21063d1ca84Smanu */
211b07ec3fcSad /* kregs.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; */
21263d1ca84Smanu
21363d1ca84Smanu /*
21463d1ca84Smanu * Install the sigframe onto the stack
21563d1ca84Smanu */
216aa306c70Smatt sf -= sizeof(*sf);
217284c2b9aSad mutex_exit(p->p_lock);
218aa306c70Smatt error = copyout(&ksf, sf, sizeof(ksf));
219284c2b9aSad mutex_enter(p->p_lock);
220b07ec3fcSad
221b07ec3fcSad if (error != 0) {
22263d1ca84Smanu /*
22363d1ca84Smanu * Process has trashed its stack; give it an illegal
22463d1ca84Smanu * instruction to halt it in its tracks.
22563d1ca84Smanu */
226948a7fa8Smanu #ifdef DEBUG_LINUX
227948a7fa8Smanu printf("linux_sendsig: stack trashed\n");
228948a7fa8Smanu #endif /* DEBUG_LINUX */
22946141a31Sthorpej sigexit(l, SIGILL);
23063d1ca84Smanu /* NOTREACHED */
23163d1ca84Smanu }
23263d1ca84Smanu
23363d1ca84Smanu /* Set up the registers to return to sigcode. */
234aa306c70Smatt tf->tf_regs[_R_A0] = native_to_linux_signo[sig];
235aa306c70Smatt tf->tf_regs[_R_A1] = 0;
236aa306c70Smatt tf->tf_regs[_R_A2] = (intptr_t)&sf->sf.lsf_sc;
23763d1ca84Smanu
238948a7fa8Smanu #ifdef DEBUG_LINUX
239aa306c70Smatt printf("sigcontext is at %p\n", &sf->sf.lsf_sc);
240948a7fa8Smanu #endif /* DEBUG_LINUX */
24163d1ca84Smanu
242aa306c70Smatt tf->tf_regs[_R_SP] = (intptr_t)sf;
24363d1ca84Smanu /* Signal trampoline code is at base of user stack. */
244aa306c70Smatt tf->tf_regs[_R_RA] = (intptr_t)p->p_sigctx.ps_sigcode;
245aa306c70Smatt tf->tf_regs[_R_T9] = (intptr_t)catcher;
246aa306c70Smatt tf->tf_regs[_R_PC] = (intptr_t)catcher;
24763d1ca84Smanu
24863d1ca84Smanu /* Remember that we're now on the signal stack. */
24963d1ca84Smanu if (onstack)
250b07ec3fcSad l->l_sigstk.ss_flags |= SS_ONSTACK;
25163d1ca84Smanu
25263d1ca84Smanu return;
25363d1ca84Smanu }
25463d1ca84Smanu
255aa306c70Smatt static void
linux_putaway_sigcontext(struct trapframe * tf,const struct linux_sigcontext * sc)256aa306c70Smatt linux_putaway_sigcontext(struct trapframe *tf,
257aa306c70Smatt const struct linux_sigcontext *sc)
258aa306c70Smatt {
259aa306c70Smatt for (u_int i = 0; i < 32; i++) {
260aa306c70Smatt tf->tf_regs[i] = sc->lsc_regs[i];
261aa306c70Smatt }
262aa306c70Smatt tf->tf_regs[_R_MULLO] = sc->lsc_mdlo;
263aa306c70Smatt tf->tf_regs[_R_MULHI] = sc->lsc_mdhi;
264aa306c70Smatt tf->tf_regs[_R_PC] = sc->lsc_pc;
265aa306c70Smatt }
266aa306c70Smatt
267aa306c70Smatt #ifndef __mips_o32
268aa306c70Smatt static void
linux_putaway_sigcontext32(struct trapframe * tf,const struct linux_sigcontext32 * sc)269aa306c70Smatt linux_putaway_sigcontext32(struct trapframe *tf,
270aa306c70Smatt const struct linux_sigcontext32 *sc)
271aa306c70Smatt {
272aa306c70Smatt for (u_int i = 0; i < 32; i++) {
273aa306c70Smatt tf->tf_regs[i] = sc->lsc_regs[i];
274aa306c70Smatt }
275aa306c70Smatt tf->tf_regs[_R_MULLO] = sc->lsc_mdlo;
276aa306c70Smatt tf->tf_regs[_R_MULHI] = sc->lsc_mdhi;
277aa306c70Smatt tf->tf_regs[_R_PC] = sc->lsc_pc;
278aa306c70Smatt }
279aa306c70Smatt #endif
280aa306c70Smatt
28163d1ca84Smanu /*
28263d1ca84Smanu * System call to cleanup state after a signal
28363d1ca84Smanu * has been taken. Reset signal mask and
28463d1ca84Smanu * stack state from context left by sendsig (above).
28563d1ca84Smanu */
28663d1ca84Smanu int
linux_sys_sigreturn(struct lwp * l,const struct linux_sys_sigreturn_args * uap,register_t * retval)2877e2790cfSdsl linux_sys_sigreturn(struct lwp *l, const struct linux_sys_sigreturn_args *uap, register_t *retval)
28863d1ca84Smanu {
2897e2790cfSdsl /* {
290675946fdSmanu syscallarg(struct linux_sigframe *) sf;
2917e2790cfSdsl } */
29246141a31Sthorpej struct proc *p = l->l_proc;
293aa306c70Smatt union linux_ksigframe ksf, *sf;
294aa306c70Smatt #ifdef __mips_o32
295aa306c70Smatt const int abi = _MIPS_BSD_API_O32;
296aa306c70Smatt #else
297aa306c70Smatt const int abi = p->p_md.md_abi;
298aa306c70Smatt #endif
299aa306c70Smatt linux_sigset_t *lmask;
30063d1ca84Smanu sigset_t mask;
301aa306c70Smatt int error;
30263d1ca84Smanu
303948a7fa8Smanu #ifdef DEBUG_LINUX
30463d1ca84Smanu printf("linux_sys_sigreturn()\n");
305948a7fa8Smanu #endif /* DEBUG_LINUX */
306948a7fa8Smanu
30763d1ca84Smanu /*
30863d1ca84Smanu * The trampoline code hands us the context.
30963d1ca84Smanu * It is unsafe to keep track of it ourselves, in the event that a
31063d1ca84Smanu * program jumps out of a signal handler.
31163d1ca84Smanu */
312aa306c70Smatt sf = (void *)SCARG(uap, sf);
31363d1ca84Smanu
31463d1ca84Smanu if ((error = copyin(sf, &ksf, sizeof(ksf))) != 0)
31563d1ca84Smanu return (error);
31663d1ca84Smanu
31763d1ca84Smanu /* Restore the register context. */
318aa306c70Smatt switch (abi) {
319aa306c70Smatt default:
320aa306c70Smatt lmask = &ksf.sf.lsf_mask;
321aa306c70Smatt linux_putaway_sigcontext(l->l_md.md_utf, &ksf.sf.lsf_sc);
322aa306c70Smatt break;
323aa306c70Smatt #if !defined(__mips_o32)
324aa306c70Smatt case _MIPS_BSD_API_O32:
325aa306c70Smatt lmask = &ksf.sf32.lsf_mask;
326aa306c70Smatt linux_putaway_sigcontext32(l->l_md.md_utf, &ksf.sf32.lsf_sc);
327aa306c70Smatt break;
328aa306c70Smatt #endif
329aa306c70Smatt }
33063d1ca84Smanu
331284c2b9aSad mutex_enter(p->p_lock);
332b07ec3fcSad
33363d1ca84Smanu /* Restore signal stack. */
334b07ec3fcSad l->l_sigstk.ss_flags &= ~SS_ONSTACK;
33563d1ca84Smanu
33663d1ca84Smanu /* Restore signal mask. */
337aa306c70Smatt linux_to_native_sigset(&mask, lmask);
338b07ec3fcSad (void)sigprocmask1(l, SIG_SETMASK, &mask, 0);
339b07ec3fcSad
340284c2b9aSad mutex_exit(p->p_lock);
34163d1ca84Smanu
34263d1ca84Smanu return (EJUSTRETURN);
34363d1ca84Smanu }
34463d1ca84Smanu
34563d1ca84Smanu
34663d1ca84Smanu int
linux_sys_rt_sigreturn(struct lwp * l,const struct linux_sys_rt_sigreturn_args * v,register_t * retval)34733fa5ccbSchs linux_sys_rt_sigreturn(struct lwp *l, const struct linux_sys_rt_sigreturn_args *v, register_t *retval)
34863d1ca84Smanu {
34946141a31Sthorpej return (ENOSYS);
35063d1ca84Smanu }
35163d1ca84Smanu
35263d1ca84Smanu
35363d1ca84Smanu /*
35463d1ca84Smanu * major device numbers remapping
35563d1ca84Smanu */
35663d1ca84Smanu dev_t
linux_fakedev(dev_t dev,int raw)35728bae79bSdsl linux_fakedev(dev_t dev, int raw)
35863d1ca84Smanu {
35963d1ca84Smanu /* XXX write me */
36063d1ca84Smanu return dev;
36163d1ca84Smanu }
36263d1ca84Smanu
36363d1ca84Smanu /*
36463d1ca84Smanu * We come here in a last attempt to satisfy a Linux ioctl() call
36563d1ca84Smanu */
36663d1ca84Smanu int
linux_machdepioctl(struct lwp * l,const struct linux_sys_ioctl_args * uap,register_t * retval)3677e2790cfSdsl linux_machdepioctl(struct lwp *l, const struct linux_sys_ioctl_args *uap, register_t *retval)
36863d1ca84Smanu {
36963d1ca84Smanu return 0;
37063d1ca84Smanu }
37163d1ca84Smanu
37263d1ca84Smanu /*
37363d1ca84Smanu * See above. If a root process tries to set access to an I/O port,
37463d1ca84Smanu * just let it have the whole range.
37563d1ca84Smanu */
37663d1ca84Smanu int
linux_sys_ioperm(struct lwp * l,const struct linux_sys_ioperm_args * uap,register_t * retval)3777e2790cfSdsl linux_sys_ioperm(struct lwp *l, const struct linux_sys_ioperm_args *uap, register_t *retval)
37863d1ca84Smanu {
37963d1ca84Smanu /*
38063d1ca84Smanu * This syscall is not implemented in Linux/Mips: we should not be here
38163d1ca84Smanu */
38263d1ca84Smanu #ifdef DEBUG_LINUX
38363d1ca84Smanu printf("linux_sys_ioperm: should not be here.\n");
384948a7fa8Smanu #endif /* DEBUG_LINUX */
38563d1ca84Smanu return 0;
38663d1ca84Smanu }
38763d1ca84Smanu
38863d1ca84Smanu /*
38963d1ca84Smanu * wrapper linux_sys_new_uname() -> linux_sys_uname()
39063d1ca84Smanu */
39163d1ca84Smanu int
linux_sys_new_uname(struct lwp * l,const struct linux_sys_new_uname_args * uap,register_t * retval)3927e2790cfSdsl linux_sys_new_uname(struct lwp *l, const struct linux_sys_new_uname_args *uap, register_t *retval)
39363d1ca84Smanu {
394948a7fa8Smanu /*
395948a7fa8Smanu * Use this if you want to try Linux emulation with a glibc-2.2
396948a7fa8Smanu * or higher. Note that signals will not work
397948a7fa8Smanu */
398948a7fa8Smanu #if 0
399948a7fa8Smanu struct linux_sys_uname_args /* {
400948a7fa8Smanu syscallarg(struct linux_utsname *) up;
401948a7fa8Smanu } */ *uap = v;
402948a7fa8Smanu struct linux_utsname luts;
403948a7fa8Smanu
404*41aa5859Sriastradh memset(&luts, 0, sizeof(luts));
40523e9f9faSnjoly strlcpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname));
40623e9f9faSnjoly strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
40723e9f9faSnjoly strlcpy(luts.l_release, "2.4.0", sizeof(luts.l_release));
40823e9f9faSnjoly strlcpy(luts.l_version, linux_version, sizeof(luts.l_version));
40923e9f9faSnjoly strlcpy(luts.l_machine, machine, sizeof(luts.l_machine));
41023e9f9faSnjoly strlcpy(luts.l_domainname, domainname, sizeof(luts.l_domainname));
411948a7fa8Smanu
412948a7fa8Smanu return copyout(&luts, SCARG(uap, up), sizeof(luts));
413948a7fa8Smanu #else
4147e2790cfSdsl return linux_sys_uname(l, (const void *)uap, retval);
415948a7fa8Smanu #endif
41663d1ca84Smanu }
41763d1ca84Smanu
41863d1ca84Smanu /*
41946141a31Sthorpej * In Linux, cacheflush is currently implemented
42063d1ca84Smanu * as a whole cache flush (arguments are ignored)
42163d1ca84Smanu * we emulate this broken beahior.
42263d1ca84Smanu */
42363d1ca84Smanu int
linux_sys_cacheflush(struct lwp * l,const struct linux_sys_cacheflush_args * uap,register_t * retval)4247e2790cfSdsl linux_sys_cacheflush(struct lwp *l, const struct linux_sys_cacheflush_args *uap, register_t *retval)
42563d1ca84Smanu {
42686349adcSmanu mips_icache_sync_all();
42786349adcSmanu mips_dcache_wbinv_all();
42863d1ca84Smanu return 0;
42963d1ca84Smanu }
43063d1ca84Smanu
431801da946Smanu /*
432801da946Smanu * This system call is depecated in Linux, but
433801da946Smanu * some binaries and some libraries use it.
434801da946Smanu */
435801da946Smanu int
linux_sys_sysmips(struct lwp * l,const struct linux_sys_sysmips_args * uap,register_t * retval)4367e2790cfSdsl linux_sys_sysmips(struct lwp *l, const struct linux_sys_sysmips_args *uap, register_t *retval)
437801da946Smanu {
43833fa5ccbSchs /* {
439aa306c70Smatt syscallarg(long) cmd;
440aa306c70Smatt syscallarg(long) arg1;
441aa306c70Smatt syscallarg(long) arg2;
442aa306c70Smatt syscallarg(long) arg3;
44333fa5ccbSchs } */
444801da946Smanu int error;
445801da946Smanu
446801da946Smanu switch (SCARG(uap, cmd)) {
447801da946Smanu case LINUX_SETNAME: {
448801da946Smanu char nodename [LINUX___NEW_UTS_LEN + 1];
44913f8d2ceSatatat int name[2];
450801da946Smanu size_t len;
451801da946Smanu
452801da946Smanu if ((error = copyinstr((char *)SCARG(uap, arg1), nodename,
453801da946Smanu LINUX___NEW_UTS_LEN, &len)) != 0)
454801da946Smanu return error;
455801da946Smanu
45613f8d2ceSatatat name[0] = CTL_KERN;
45713f8d2ceSatatat name[1] = KERN_HOSTNAME;
45813f8d2ceSatatat return (old_sysctl(&name[0], 2, 0, 0, nodename, len, NULL));
459801da946Smanu
460801da946Smanu break;
461801da946Smanu }
4622d38e850Smanu case LINUX_MIPS_ATOMIC_SET: {
4632d38e850Smanu void *addr;
4642d38e850Smanu int s;
465e0fe4268Sjdolecek u_int8_t value = 0;
4662d38e850Smanu
4672d38e850Smanu addr = (void *)SCARG(uap, arg1);
4682d38e850Smanu
4692d38e850Smanu s = splhigh();
4702d38e850Smanu /*
4712d38e850Smanu * No error testing here. This is bad, but Linux does
4722d38e850Smanu * it like this. The source aknowledge "This is broken"
4732d38e850Smanu * in a comment...
4742d38e850Smanu */
475e0fe4268Sjdolecek (void) copyin(addr, &value, 1);
476e0fe4268Sjdolecek *retval = value;
477e0fe4268Sjdolecek value = (u_int8_t) SCARG(uap, arg2);
478e0fe4268Sjdolecek error = copyout(&value, addr, 1);
4792d38e850Smanu splx(s);
4802d38e850Smanu
4812d38e850Smanu return 0;
482801da946Smanu break;
4832d38e850Smanu }
484801da946Smanu case LINUX_MIPS_FIXADE: /* XXX not implemented */
485801da946Smanu break;
486801da946Smanu case LINUX_FLUSH_CACHE:
48786349adcSmanu mips_icache_sync_all();
48886349adcSmanu mips_dcache_wbinv_all();
489801da946Smanu break;
490801da946Smanu case LINUX_MIPS_RDNVRAM:
491801da946Smanu return EIO;
492801da946Smanu break;
493801da946Smanu default:
494801da946Smanu return EINVAL;
495801da946Smanu break;
496801da946Smanu }
4972d38e850Smanu #ifdef DEBUG_LINUX
498801da946Smanu printf("linux_sys_sysmips(): unimplemented command %d\n",
499801da946Smanu SCARG(uap,cmd));
500801da946Smanu #endif /* DEBUG_LINUX */
501801da946Smanu return 0;
502801da946Smanu }
50333e2d79fSfvdl
50433e2d79fSfvdl int
linux_usertrap(struct lwp * l,vaddr_t trapaddr,void * arg)50533e2d79fSfvdl linux_usertrap(struct lwp *l, vaddr_t trapaddr, void *arg)
50633e2d79fSfvdl {
50733e2d79fSfvdl return 0;
50833e2d79fSfvdl }
50933fa5ccbSchs
51033fa5ccbSchs int
linux_sys_set_thread_area(struct lwp * l,const struct linux_sys_set_thread_area_args * uap,register_t * retval)51133fa5ccbSchs linux_sys_set_thread_area(struct lwp *l, const struct linux_sys_set_thread_area_args *uap, register_t *retval)
51233fa5ccbSchs {
51333fa5ccbSchs /* {
51433fa5ccbSchs syscallarg(void *) tls;
51533fa5ccbSchs } */
51633fa5ccbSchs
51733fa5ccbSchs return lwp_setprivate(l, SCARG(uap, tls));
51833fa5ccbSchs }
519