xref: /openbsd/sys/arch/i386/i386/sys_machdep.c (revision f4e70637)
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