[BACK]Return to sys_machdep.c CVS log [TXT][DIR] Up to [local] / sys / arch / amd64 / amd64

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