Annotation of sys/arch/amd64/amd64/sys_machdep.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: sys_machdep.c,v 1.5 2007/01/15 23:19:05 jsg Exp $ */
2: /* $NetBSD: sys_machdep.c,v 1.1 2003/04/26 18:39:32 fvdl Exp $ */
3:
4: /*-
5: * Copyright (c) 1998 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Charles M. Hannum.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: /*
41: * XXXfvdl check USER_LDT
42: */
43:
44: #include <sys/param.h>
45: #include <sys/systm.h>
46: #include <sys/ioctl.h>
47: #include <sys/file.h>
48: #include <sys/time.h>
49: #include <sys/proc.h>
50: #include <sys/user.h>
51: #include <sys/uio.h>
52: #include <sys/kernel.h>
53: #include <sys/buf.h>
54: #include <sys/signal.h>
55:
56: #include <sys/mount.h>
57: #include <sys/syscallargs.h>
58:
59: #include <uvm/uvm_extern.h>
60:
61: #include <machine/cpu.h>
62: #include <machine/cpufunc.h>
63: #include <machine/gdt.h>
64: #include <machine/psl.h>
65: #include <machine/reg.h>
66: #include <machine/sysarch.h>
67: #include <machine/mtrr.h>
68:
69: #if defined(PERFCTRS) && 0
70: #include <machine/pmc.h>
71: #endif
72:
73: extern struct vm_map *kernel_map;
74:
75: #if 0
76: int amd64_get_ioperm(struct proc *, void *, register_t *);
77: int amd64_set_ioperm(struct proc *, void *, register_t *);
78: #endif
79: int amd64_iopl(struct proc *, void *, register_t *);
80: int amd64_get_mtrr(struct proc *, void *, register_t *);
81: int amd64_set_mtrr(struct proc *, void *, register_t *);
82:
83: /* XXXfvdl disabled USER_LDT stuff until I check this stuff */
84:
85: #if defined(USER_LDT) && 0
86: int
87: amd64_get_ldt(struct proc *p, void *args, register_t *retval)
88: {
89: int error;
90: pmap_t pmap = p->p_vmspace->vm_map.pmap;
91: int nldt, num;
92: union descriptor *lp;
93: struct amd64_get_ldt_args ua;
94:
95: if ((error = copyin(args, &ua, sizeof(ua))) != 0)
96: return (error);
97:
98: #ifdef LDT_DEBUG
99: printf("amd64_get_ldt: start=%d num=%d descs=%p\n", ua.start,
100: ua.num, ua.desc);
101: #endif
102:
103: if (ua.start < 0 || ua.num < 0)
104: return (EINVAL);
105:
106: /*
107: * XXX LOCKING.
108: */
109:
110: if (pmap->pm_flags & PMF_USER_LDT) {
111: nldt = pmap->pm_ldt_len;
112: lp = pmap->pm_ldt;
113: } else {
114: nldt = NLDT;
115: lp = ldt;
116: }
117:
118: if (ua.start > nldt)
119: return (EINVAL);
120:
121: lp += ua.start;
122: num = min(ua.num, nldt - ua.start);
123:
124: error = copyout(lp, ua.desc, num * sizeof(union descriptor));
125: if (error)
126: return (error);
127:
128: *retval = num;
129: return (0);
130: }
131:
132: int
133: amd64_set_ldt(struct proc *p, void *args, register_t *retval)
134: {
135: int error, i, n;
136: struct pcb *pcb = &p->p_addr->u_pcb;
137: pmap_t pmap = p->p_vmspace->vm_map.pmap;
138: struct amd64_set_ldt_args ua;
139: union descriptor desc;
140:
141: if ((error = copyin(args, &ua, sizeof(ua))) != 0)
142: return (error);
143:
144: #ifdef LDT_DEBUG
145: printf("amd64_set_ldt: start=%d num=%d descs=%p\n", ua.start,
146: ua.num, ua.desc);
147: #endif
148:
149: if (ua.start < 0 || ua.num < 0)
150: return (EINVAL);
151: if (ua.start > 8192 || (ua.start + ua.num) > 8192)
152: return (EINVAL);
153:
154: /*
155: * XXX LOCKING
156: */
157:
158: /* allocate user ldt */
159: if (pmap->pm_ldt == 0 || (ua.start + ua.num) > pmap->pm_ldt_len) {
160: size_t old_len, new_len;
161: union descriptor *old_ldt, *new_ldt;
162:
163: if (pmap->pm_flags & PMF_USER_LDT) {
164: old_len = pmap->pm_ldt_len * sizeof(union descriptor);
165: old_ldt = pmap->pm_ldt;
166: } else {
167: old_len = NLDT * sizeof(union descriptor);
168: old_ldt = ldt;
169: pmap->pm_ldt_len = 512;
170: }
171: while ((ua.start + ua.num) > pmap->pm_ldt_len)
172: pmap->pm_ldt_len *= 2;
173: new_len = pmap->pm_ldt_len * sizeof(union descriptor);
174: new_ldt = (union descriptor *)uvm_km_alloc(kernel_map, new_len);
175: memcpy(new_ldt, old_ldt, old_len);
176: memset((caddr_t)new_ldt + old_len, 0, new_len - old_len);
177: pmap->pm_ldt = new_ldt;
178:
179: if (pmap->pm_flags & PCB_USER_LDT)
180: ldt_free(pmap);
181: else
182: pmap->pm_flags |= PCB_USER_LDT;
183: ldt_alloc(pmap, new_ldt, new_len);
184: pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
185: if (pcb == curpcb)
186: lldt(pcb->pcb_ldt_sel);
187:
188: /*
189: * XXX Need to notify other processors which may be
190: * XXX currently using this pmap that they need to
191: * XXX re-load the LDT.
192: */
193:
194: if (old_ldt != ldt)
195: uvm_km_free(kernel_map, (vaddr_t)old_ldt, old_len);
196: #ifdef LDT_DEBUG
197: printf("amd64_set_ldt(%d): new_ldt=%p\n", p->p_pid, new_ldt);
198: #endif
199: }
200:
201: if (pcb == curpcb)
202: savectx(curpcb);
203: error = 0;
204:
205: /* Check descriptors for access violations. */
206: for (i = 0, n = ua.start; i < ua.num; i++, n++) {
207: if ((error = copyin(&ua.desc[i], &desc, sizeof(desc))) != 0)
208: return (error);
209:
210: switch (desc.sd.sd_type) {
211: case SDT_SYSNULL:
212: desc.sd.sd_p = 0;
213: break;
214: case SDT_SYS286CGT:
215: case SDT_SYS386CGT:
216: /*
217: * Only allow call gates targeting a segment
218: * in the LDT or a user segment in the fixed
219: * part of the gdt. Segments in the LDT are
220: * constrained (below) to be user segments.
221: */
222: if (desc.gd.gd_p != 0 && !ISLDT(desc.gd.gd_selector) &&
223: ((IDXSEL(desc.gd.gd_selector) >= NGDT) ||
224: (gdt[IDXSEL(desc.gd.gd_selector)].sd.sd_dpl !=
225: SEL_UPL)))
226: return (EACCES);
227: break;
228: case SDT_MEMEC:
229: case SDT_MEMEAC:
230: case SDT_MEMERC:
231: case SDT_MEMERAC:
232: /* Must be "present" if executable and conforming. */
233: if (desc.sd.sd_p == 0)
234: return (EACCES);
235: break;
236: case SDT_MEMRO:
237: case SDT_MEMROA:
238: case SDT_MEMRW:
239: case SDT_MEMRWA:
240: case SDT_MEMROD:
241: case SDT_MEMRODA:
242: case SDT_MEMRWD:
243: case SDT_MEMRWDA:
244: case SDT_MEME:
245: case SDT_MEMEA:
246: case SDT_MEMER:
247: case SDT_MEMERA:
248: break;
249: default:
250: /* Only care if it's present. */
251: if (desc.sd.sd_p != 0)
252: return (EACCES);
253: break;
254: }
255:
256: if (desc.sd.sd_p != 0) {
257: /* Only user (ring-3) descriptors may be present. */
258: if (desc.sd.sd_dpl != SEL_UPL)
259: return (EACCES);
260: }
261: }
262:
263: /* Now actually replace the descriptors. */
264: for (i = 0, n = ua.start; i < ua.num; i++, n++) {
265: if ((error = copyin(&ua.desc[i], &desc, sizeof(desc))) != 0)
266: goto out;
267:
268: pmap->pm_ldt[n] = desc;
269: }
270:
271: *retval = ua.start;
272:
273: out:
274: return (error);
275: }
276: #endif /* USER_LDT */
277:
278: #ifdef APERTURE
279: extern int allowaperture;
280: #endif
281:
282: int
283: amd64_iopl(struct proc *p, void *args, register_t *retval)
284: {
285: int error;
286: struct trapframe *tf = p->p_md.md_regs;
287: struct amd64_iopl_args ua;
288:
289: if ((error = suser(p, 0)) != 0)
290: return error;
291:
292: #ifdef APERTURE
293: if (!allowaperture && securelevel > 0)
294: return EPERM;
295: #else
296: if (securelevel > 0)
297: return EPERM;
298: #endif
299:
300: if ((error = copyin(args, &ua, sizeof(ua))) != 0)
301: return error;
302:
303: if (ua.iopl)
304: tf->tf_rflags |= PSL_IOPL;
305: else
306: tf->tf_rflags &= ~PSL_IOPL;
307:
308: return 0;
309: }
310:
311: #if 0
312:
313: int
314: amd64_get_ioperm(struct proc *p, void *args, register_t *retval)
315: {
316: int error;
317: struct pcb *pcb = &p->p_addr->u_pcb;
318: struct amd64_get_ioperm_args ua;
319:
320: if ((error = copyin(args, &ua, sizeof(ua))) != 0)
321: return (error);
322:
323: return copyout(pcb->pcb_iomap, ua.iomap, sizeof(pcb->pcb_iomap));
324: }
325:
326: int
327: amd64_set_ioperm(struct proc *p, void *args, register_t *retval)
328: {
329: int error;
330: struct pcb *pcb = &p->p_addr->u_pcb;
331: struct amd64_set_ioperm_args ua;
332:
333: if (securelevel > 1)
334: return EPERM;
335:
336: if ((error = suser(p, 0)) != 0)
337: return error;
338:
339: if ((error = copyin(args, &ua, sizeof(ua))) != 0)
340: return (error);
341:
342: return copyin(ua.iomap, pcb->pcb_iomap, sizeof(pcb->pcb_iomap));
343: }
344:
345: #endif
346:
347: #ifdef MTRR
348:
349: int
350: amd64_get_mtrr(struct proc *p, void *args, register_t *retval)
351: {
352: struct amd64_get_mtrr_args ua;
353: int error, n;
354:
355: if (mtrr_funcs == NULL)
356: return ENOSYS;
357:
358: error = copyin(args, &ua, sizeof ua);
359: if (error != 0)
360: return error;
361:
362: error = copyin(ua.n, &n, sizeof n);
363: if (error != 0)
364: return error;
365:
366: error = mtrr_get(ua.mtrrp, &n, p, MTRR_GETSET_USER);
367:
368: copyout(&n, ua.n, sizeof (int));
369:
370: return error;
371: }
372:
373: int
374: amd64_set_mtrr(struct proc *p, void *args, register_t *retval)
375: {
376: int error, n;
377: struct amd64_set_mtrr_args ua;
378:
379: if (mtrr_funcs == NULL)
380: return ENOSYS;
381:
382: error = suser(p, 0);
383: if (error != 0)
384: return error;
385:
386: error = copyin(args, &ua, sizeof ua);
387: if (error != 0)
388: return error;
389:
390: error = copyin(ua.n, &n, sizeof n);
391: if (error != 0)
392: return error;
393:
394: error = mtrr_set(ua.mtrrp, &n, p, MTRR_GETSET_USER);
395: if (n != 0)
396: mtrr_commit();
397:
398: copyout(&n, ua.n, sizeof n);
399:
400: return error;
401: }
402: #endif
403:
404: int
405: sys_sysarch(struct proc *p, void *v, register_t *retval)
406: {
407: struct sys_sysarch_args /* {
408: syscallarg(int) op;
409: syscallarg(void *) parms;
410: } */ *uap = v;
411: int error = 0;
412:
413: switch(SCARG(uap, op)) {
414: #if defined(USER_LDT) && 0
415: case AMD64_GET_LDT:
416: error = amd64_get_ldt(p, SCARG(uap, parms), retval);
417: break;
418:
419: case AMD64_SET_LDT:
420: error = amd64_set_ldt(p, SCARG(uap, parms), retval);
421: break;
422: #endif
423: case AMD64_IOPL:
424: error = amd64_iopl(p, SCARG(uap, parms), retval);
425: break;
426:
427: #if 0
428: case AMD64_GET_IOPERM:
429: error = amd64_get_ioperm(p, SCARG(uap, parms), retval);
430: break;
431:
432: case AMD64_SET_IOPERM:
433: error = amd64_set_ioperm(p, SCARG(uap, parms), retval);
434: break;
435: #endif
436: #ifdef MTRR
437: case AMD64_GET_MTRR:
438: error = amd64_get_mtrr(p, SCARG(uap, parms), retval);
439: break;
440: case AMD64_SET_MTRR:
441: error = amd64_set_mtrr(p, SCARG(uap, parms), retval);
442: break;
443: #endif
444:
445: #if defined(PERFCTRS) && 0
446: case AMD64_PMC_INFO:
447: error = pmc_info(p, SCARG(uap, parms), retval);
448: break;
449:
450: case AMD64_PMC_STARTSTOP:
451: error = pmc_startstop(p, SCARG(uap, parms), retval);
452: break;
453:
454: case AMD64_PMC_READ:
455: error = pmc_read(p, SCARG(uap, parms), retval);
456: break;
457: #endif
458: default:
459: error = EINVAL;
460: break;
461: }
462: return (error);
463: }
CVSweb