Annotation of sys/arch/i386/i386/sys_machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: sys_machdep.c,v 1.26 2006/09/19 11:06:33 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/ioctl.h>
42: #include <sys/file.h>
43: #include <sys/time.h>
44: #include <sys/proc.h>
45: #include <sys/signalvar.h>
46: #include <sys/user.h>
47: #include <sys/uio.h>
48: #include <sys/kernel.h>
49: #include <sys/mtio.h>
50: #include <sys/buf.h>
51: #include <sys/signal.h>
52: #include <sys/malloc.h>
53:
54: #include <sys/mount.h>
55: #include <sys/syscallargs.h>
56:
57: #include <uvm/uvm_extern.h>
58:
59: #include <machine/cpu.h>
60: #include <machine/cpufunc.h>
61: #include <machine/gdt.h>
62: #include <machine/psl.h>
63: #include <machine/reg.h>
64: #include <machine/sysarch.h>
65:
66: #ifdef VM86
67: #include <machine/vm86.h>
68: #endif
69:
70: extern struct vm_map *kernel_map;
71:
72: int i386_iopl(struct proc *, void *, register_t *);
73: int i386_get_ioperm(struct proc *, void *, register_t *);
74: int i386_set_ioperm(struct proc *, void *, register_t *);
75:
76: #ifdef USER_LDT
77:
78: #ifdef LDT_DEBUG
79: static void i386_print_ldt(int, const struct segment_descriptor *);
80:
81: static void
82: i386_print_ldt(int i, const struct segment_descriptor *d)
83: {
84: printf("[%d] lolimit=0x%x, lobase=0x%x, type=%u, dpl=%u, p=%u, "
85: "hilimit=0x%x, xx=%x, def32=%u, gran=%u, hibase=0x%x\n",
86: i, d->sd_lolimit, d->sd_lobase, d->sd_type, d->sd_dpl, d->sd_p,
87: d->sd_hilimit, d->sd_xx, d->sd_def32, d->sd_gran, d->sd_hibase);
88: }
89: #endif
90:
91: int
92: i386_get_ldt(struct proc *p, void *args, register_t *retval)
93: {
94: int error;
95: pmap_t pmap = p->p_vmspace->vm_map.pmap;
96: int nldt, num;
97: union descriptor *lp, *cp;
98: struct i386_get_ldt_args ua;
99:
100: if (user_ldt_enable == 0)
101: return (ENOSYS);
102:
103: if ((error = copyin(args, &ua, sizeof(ua))) != 0)
104: return (error);
105:
106: #ifdef LDT_DEBUG
107: printf("i386_get_ldt: start=%d num=%d descs=%p\n", ua.start,
108: ua.num, ua.desc);
109: #endif
110:
111: if (ua.start < 0 || ua.num < 0 || ua.start > 8192 || ua.num > 8192 ||
112: ua.start + ua.num > 8192)
113: return (EINVAL);
114:
115: cp = malloc(ua.num * sizeof(union descriptor), M_TEMP, M_WAITOK);
116: if (cp == NULL)
117: return ENOMEM;
118:
119: simple_lock(&pmap->pm_lock);
120:
121: if (pmap->pm_flags & PMF_USER_LDT) {
122: nldt = pmap->pm_ldt_len;
123: lp = pmap->pm_ldt;
124: } else {
125: nldt = NLDT;
126: lp = ldt;
127: }
128:
129: if (ua.start > nldt) {
130: simple_unlock(&pmap->pm_lock);
131: free(cp, M_TEMP);
132: return (EINVAL);
133: }
134:
135: lp += ua.start;
136: num = min(ua.num, nldt - ua.start);
137: #ifdef LDT_DEBUG
138: {
139: int i;
140: for (i = 0; i < num; i++)
141: i386_print_ldt(i, &lp[i].sd);
142: }
143: #endif
144:
145: memcpy(cp, lp, num * sizeof(union descriptor));
146: simple_unlock(&pmap->pm_lock);
147:
148: error = copyout(cp, ua.desc, num * sizeof(union descriptor));
149: if (error == 0)
150: *retval = num;
151:
152: free(cp, M_TEMP);
153: return (error);
154: }
155:
156: int
157: i386_set_ldt(struct proc *p, void *args, register_t *retval)
158: {
159: int error, i, n;
160: struct pcb *pcb = &p->p_addr->u_pcb;
161: pmap_t pmap = p->p_vmspace->vm_map.pmap;
162: struct i386_set_ldt_args ua;
163: union descriptor *descv;
164: size_t old_len, new_len, ldt_len;
165: union descriptor *old_ldt, *new_ldt;
166:
167: if (user_ldt_enable == 0)
168: return (ENOSYS);
169:
170: if ((error = copyin(args, &ua, sizeof(ua))) != 0)
171: return (error);
172:
173: if (ua.start < 0 || ua.num < 0 || ua.start > 8192 || ua.num > 8192 ||
174: ua.start + ua.num > 8192)
175: return (EINVAL);
176:
177: descv = malloc(sizeof (*descv) * ua.num, M_TEMP, M_NOWAIT);
178: if (descv == NULL)
179: return (ENOMEM);
180:
181: if ((error = copyin(ua.desc, descv, sizeof (*descv) * ua.num)) != 0)
182: goto out;
183:
184: /* Check descriptors for access violations. */
185: for (i = 0; i < ua.num; i++) {
186: union descriptor *desc = &descv[i];
187:
188: switch (desc->sd.sd_type) {
189: case SDT_SYSNULL:
190: desc->sd.sd_p = 0;
191: break;
192: case SDT_SYS286CGT:
193: case SDT_SYS386CGT:
194: /*
195: * Only allow call gates targeting a segment
196: * in the LDT or a user segment in the fixed
197: * part of the gdt. Segments in the LDT are
198: * constrained (below) to be user segments.
199: */
200: if (desc->gd.gd_p != 0 &&
201: !ISLDT(desc->gd.gd_selector) &&
202: ((IDXSEL(desc->gd.gd_selector) >= NGDT) ||
203: (gdt[IDXSEL(desc->gd.gd_selector)].sd.sd_dpl !=
204: SEL_UPL))) {
205: error = EACCES;
206: goto out;
207: }
208: break;
209: case SDT_MEMEC:
210: case SDT_MEMEAC:
211: case SDT_MEMERC:
212: case SDT_MEMERAC:
213: /* Must be "present" if executable and conforming. */
214: if (desc->sd.sd_p == 0) {
215: error = EACCES;
216: goto out;
217: }
218: break;
219: case SDT_MEMRO:
220: case SDT_MEMROA:
221: case SDT_MEMRW:
222: case SDT_MEMRWA:
223: case SDT_MEMROD:
224: case SDT_MEMRODA:
225: case SDT_MEMRWD:
226: case SDT_MEMRWDA:
227: case SDT_MEME:
228: case SDT_MEMEA:
229: case SDT_MEMER:
230: case SDT_MEMERA:
231: break;
232: default:
233: /*
234: * Make sure that unknown descriptor types are
235: * not marked present.
236: */
237: if (desc->sd.sd_p != 0) {
238: error = EACCES;
239: goto out;
240: }
241: break;
242: }
243:
244: if (desc->sd.sd_p != 0) {
245: /* Only user (ring-3) descriptors may be present. */
246: if (desc->sd.sd_dpl != SEL_UPL) {
247: error = EACCES;
248: goto out;
249: }
250: }
251: }
252:
253: /* allocate user ldt */
254: simple_lock(&pmap->pm_lock);
255: if (pmap->pm_ldt == 0 || (ua.start + ua.num) > pmap->pm_ldt_len) {
256: if (pmap->pm_flags & PMF_USER_LDT)
257: ldt_len = pmap->pm_ldt_len;
258: else
259: ldt_len = 512;
260: while ((ua.start + ua.num) > ldt_len)
261: ldt_len *= 2;
262: new_len = ldt_len * sizeof(union descriptor);
263:
264: simple_unlock(&pmap->pm_lock);
265: new_ldt = (union descriptor *)uvm_km_alloc(kernel_map,
266: new_len);
267: simple_lock(&pmap->pm_lock);
268:
269: if (pmap->pm_ldt != NULL && ldt_len <= pmap->pm_ldt_len) {
270: /*
271: * Another thread (re)allocated the LDT to
272: * sufficient size while we were blocked in
273: * uvm_km_alloc. Oh well. The new entries
274: * will quite probably not be right, but
275: * hey.. not our problem if user applications
276: * have race conditions like that.
277: */
278: uvm_km_free(kernel_map, (vaddr_t)new_ldt, new_len);
279: goto copy;
280: }
281:
282: old_ldt = pmap->pm_ldt;
283:
284: if (old_ldt != NULL) {
285: old_len = pmap->pm_ldt_len * sizeof(union descriptor);
286: } else {
287: old_len = NLDT * sizeof(union descriptor);
288: old_ldt = ldt;
289: }
290:
291: memcpy(new_ldt, old_ldt, old_len);
292: memset((caddr_t)new_ldt + old_len, 0, new_len - old_len);
293:
294: if (old_ldt != ldt)
295: uvm_km_free(kernel_map, (vaddr_t)old_ldt, old_len);
296:
297: pmap->pm_ldt = new_ldt;
298: pmap->pm_ldt_len = ldt_len;
299:
300: if (pmap->pm_flags & PMF_USER_LDT)
301: ldt_free(pmap);
302: else
303: pmap->pm_flags |= PMF_USER_LDT;
304: ldt_alloc(pmap, new_ldt, new_len);
305: pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
306: if (pcb == curpcb)
307: lldt(pcb->pcb_ldt_sel);
308:
309: }
310: copy:
311: /* Now actually replace the descriptors. */
312: for (i = 0, n = ua.start; i < ua.num; i++, n++)
313: pmap->pm_ldt[n] = descv[i];
314:
315: simple_unlock(&pmap->pm_lock);
316:
317: *retval = ua.start;
318:
319: out:
320: free(descv, M_TEMP);
321: return (error);
322: }
323: #endif /* USER_LDT */
324:
325: #ifdef APERTURE
326: extern int allowaperture;
327: #endif
328:
329: int
330: i386_iopl(struct proc *p, void *args, register_t *retval)
331: {
332: int error;
333: struct trapframe *tf = p->p_md.md_regs;
334: struct i386_iopl_args ua;
335:
336: if ((error = suser(p, 0)) != 0)
337: return error;
338: #ifdef APERTURE
339: if (!allowaperture && securelevel > 0)
340: return EPERM;
341: #else
342: if (securelevel > 0)
343: return EPERM;
344: #endif
345:
346: if ((error = copyin(args, &ua, sizeof(ua))) != 0)
347: return error;
348:
349: if (ua.iopl)
350: tf->tf_eflags |= PSL_IOPL;
351: else
352: tf->tf_eflags &= ~PSL_IOPL;
353:
354: return 0;
355: }
356:
357: int
358: i386_get_ioperm(struct proc *p, void *args, register_t *retval)
359: {
360: int error;
361: struct pcb *pcb = &p->p_addr->u_pcb;
362: struct i386_get_ioperm_args ua;
363:
364: if ((error = copyin(args, &ua, sizeof(ua))) != 0)
365: return (error);
366:
367: return copyout(pcb->pcb_iomap, ua.iomap, sizeof(pcb->pcb_iomap));
368: }
369:
370: int
371: i386_set_ioperm(struct proc *p, void *args, register_t *retval)
372: {
373: int error;
374: struct pcb *pcb = &p->p_addr->u_pcb;
375: struct i386_set_ioperm_args ua;
376:
377: if ((error = suser(p, 0)) != 0)
378: return error;
379:
380: #ifdef APERTURE
381: if (!allowaperture && securelevel > 0)
382: return EPERM;
383: #else
384: if (securelevel > 0)
385: return EPERM;
386: #endif
387: if ((error = copyin(args, &ua, sizeof(ua))) != 0)
388: return (error);
389:
390: return copyin(ua.iomap, pcb->pcb_iomap, sizeof(pcb->pcb_iomap));
391: }
392:
393: int
394: sys_sysarch(struct proc *p, void *v, register_t *retval)
395: {
396: struct sys_sysarch_args /* {
397: syscallarg(int) op;
398: syscallarg(void *) parms;
399: } */ *uap = v;
400: int error = 0;
401:
402: switch(SCARG(uap, op)) {
403: #ifdef USER_LDT
404: case I386_GET_LDT:
405: error = i386_get_ldt(p, SCARG(uap, parms), retval);
406: break;
407:
408: case I386_SET_LDT:
409: error = i386_set_ldt(p, SCARG(uap, parms), retval);
410: break;
411: #endif
412:
413: case I386_IOPL:
414: error = i386_iopl(p, SCARG(uap, parms), retval);
415: break;
416:
417: case I386_GET_IOPERM:
418: error = i386_get_ioperm(p, SCARG(uap, parms), retval);
419: break;
420:
421: case I386_SET_IOPERM:
422: error = i386_set_ioperm(p, SCARG(uap, parms), retval);
423: break;
424:
425: #ifdef VM86
426: case I386_VM86:
427: error = i386_vm86(p, SCARG(uap, parms), retval);
428: break;
429: #endif
430:
431: default:
432: error = EINVAL;
433: break;
434: }
435: return (error);
436: }
CVSweb