1 /* $OpenBSD: sys_machdep.c,v 1.41 2023/01/30 10:49:05 jsg Exp $ */
2 /* $NetBSD: sys_machdep.c,v 1.28 1996/05/03 19:42:29 christos Exp $ */
3
4 /*-
5 * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
6 * Copyright (c) 1990 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * William Jolitz.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91
37 */
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/proc.h>
42 #include <sys/user.h>
43
44 #include <sys/mount.h>
45 #include <sys/syscallargs.h>
46
47 #include <machine/psl.h>
48 #include <machine/sysarch.h>
49
50 extern struct vm_map *kernel_map;
51
52 int i386_iopl(struct proc *, void *, register_t *);
53
54 #ifdef APERTURE
55 extern int allowaperture;
56 #endif
57
58 int
i386_iopl(struct proc * p,void * args,register_t * retval)59 i386_iopl(struct proc *p, void *args, register_t *retval)
60 {
61 int error;
62 struct trapframe *tf = p->p_md.md_regs;
63 struct i386_iopl_args ua;
64
65 if ((error = suser(p)) != 0)
66 return error;
67 #ifdef APERTURE
68 if (!allowaperture && securelevel > 0)
69 return EPERM;
70 #else
71 if (securelevel > 0)
72 return EPERM;
73 #endif
74
75 if ((error = copyin(args, &ua, sizeof(ua))) != 0)
76 return error;
77
78 if (ua.iopl)
79 tf->tf_eflags |= PSL_IOPL;
80 else
81 tf->tf_eflags &= ~PSL_IOPL;
82
83 return 0;
84 }
85
86 uint32_t
i386_get_threadbase(struct proc * p,int which)87 i386_get_threadbase(struct proc *p, int which)
88 {
89 struct segment_descriptor *sdp =
90 &p->p_addr->u_pcb.pcb_threadsegs[which];
91 return sdp->sd_hibase << 24 | sdp->sd_lobase;
92 }
93
94 int
i386_set_threadbase(struct proc * p,uint32_t base,int which)95 i386_set_threadbase(struct proc *p, uint32_t base, int which)
96 {
97 struct segment_descriptor *sdp;
98
99 /*
100 * We can't place a limit on the segment used by the library
101 * thread register (%gs) because the ELF ABI for i386 places
102 * data structures both before and after base pointer, using
103 * negative offsets for some bits (the static (load-time)
104 * TLS slots) and non-negative for others (the TCB block,
105 * including the pointer to the TLS dynamic thread vector).
106 * Protection must be provided by the paging subsystem.
107 */
108 sdp = &p->p_addr->u_pcb.pcb_threadsegs[which];
109 setsegment(sdp, (void *)base, 0xfffff, SDT_MEMRWA, SEL_UPL, 1, 1);
110
111 if (p == curproc) {
112 curcpu()->ci_gdt[which == TSEG_FS ? GUFS_SEL : GUGS_SEL].sd
113 = *sdp;
114 }
115 return 0;
116 }
117
118 int
sys_sysarch(struct proc * p,void * v,register_t * retval)119 sys_sysarch(struct proc *p, void *v, register_t *retval)
120 {
121 struct sys_sysarch_args /* {
122 syscallarg(int) op;
123 syscallarg(void *) parms;
124 } */ *uap = v;
125 int error = 0;
126
127 switch(SCARG(uap, op)) {
128 case I386_IOPL:
129 error = i386_iopl(p, SCARG(uap, parms), retval);
130 break;
131
132 case I386_GET_FSBASE:
133 {
134 uint32_t base = i386_get_threadbase(p, TSEG_FS);
135
136 error = copyout(&base, SCARG(uap, parms), sizeof(base));
137 break;
138 }
139
140 case I386_SET_FSBASE:
141 {
142 uint32_t base;
143
144 if ((error = copyin(SCARG(uap, parms), &base, sizeof(base))))
145 break;
146 error = i386_set_threadbase(p, base, TSEG_FS);
147 break;
148 }
149
150 case I386_GET_GSBASE:
151 {
152 uint32_t base = i386_get_threadbase(p, TSEG_GS);
153
154 error = copyout(&base, SCARG(uap, parms), sizeof(base));
155 break;
156 }
157
158 case I386_SET_GSBASE:
159 {
160 uint32_t base;
161
162 if ((error = copyin(SCARG(uap, parms), &base, sizeof(base))))
163 break;
164 error = i386_set_threadbase(p, base, TSEG_GS);
165 break;
166 }
167
168 default:
169 error = EINVAL;
170 break;
171 }
172 return (error);
173 }
174