Annotation of XNU/osfmk/ppc/PseudoKernel.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:        File:           PseudoKernel.c
        !            24: 
        !            25:        Contains:       BlueBox PseudoKernel calls
        !            26: 
        !            27:        Copyright:      1997 by Apple Computer, Inc., all rights reserved
        !            28: 
        !            29: */
        !            30: 
        !            31: #include <mach/mach_types.h>
        !            32: #include <mach/kern_return.h>
        !            33: #include <kern/host.h>
        !            34: #include <kern/task.h>
        !            35: #include <kern/thread.h>
        !            36: #include <ppc/PseudoKernel.h>
        !            37: #include <ppc/exception.h>
        !            38: #include <vm/vm_kern.h>
        !            39: 
        !            40: void bbSetRupt(ReturnHandler *rh, thread_act_t ct);
        !            41: void DumpTheSave(struct savearea *save);                       /* (TEST/DEBUG) */
        !            42: 
        !            43: /*
        !            44: ** Function:   NotifyInterruption
        !            45: **
        !            46: ** Inputs:
        !            47: **             ppcInterrupHandler      - interrupt handler to execute
        !            48: **             interruptStatePtr       - current interrupt state
        !            49: **
        !            50: ** Outputs:
        !            51: **
        !            52: ** Notes:
        !            53: **
        !            54: */
        !            55: kern_return_t syscall_notify_interrupt (UInt32 ppcInterruptHandler) {
        !            56:   
        !            57:     UInt32             interruptState; 
        !            58:     task_t             task;
        !            59:     spl_t              s;
        !            60:        thread_act_t    act, fact;
        !            61:        thread_t        thread;
        !            62:        bbRupt          *bbr;
        !            63:        int                     i;
        !            64: 
        !            65:        task = current_task();                                  /* Figure out who our task is */
        !            66: 
        !            67:        task_lock(task);                                                /* Lock our task */
        !            68:        mutex_lock(&task->act_list_lock);               /* Lock the list so it can't change on us */
        !            69:        
        !            70:        fact = (thread_act_t)task->thr_acts.next;       /* Get the first activation on task */
        !            71:        act = 0;                                                                /* Pretend we didn't find it yet */
        !            72:        
        !            73:        for(i = 0; i < task->thr_act_count; i++) {      /* Scan the whole list */
        !            74:                if(fact->mact.bbDescAddr) {                     /* Is this the Blue thread? */
        !            75:                        act = fact;                                             /* Yeah... */
        !            76:                        break;                                                  /* Bail the loop... */
        !            77:                }
        !            78:                fact = (thread_act_t)fact->thr_acts.next;       /* Go to the next one */
        !            79:        }
        !            80:        
        !            81:        mutex_unlock(&task->act_list_lock);
        !            82: 
        !            83:        if(!act) {                                                              /* Couldn't find a bluebox */
        !            84:                task_unlock(task);                                      /* Release task lock */
        !            85:                return KERN_FAILURE;                            /* No tickie, no shirtee... */
        !            86:        }
        !            87:        
        !            88:        act_lock_thread(act);                                   /* Make sure this stays 'round */
        !            89:        task_unlock(task);                                              /* Safe to release now */
        !            90:        
        !            91:        if(act->mact.bbPendRupt >= 16) {                /* Have we hit the arbitrary maximum? */
        !            92:                act_unlock_thread(act);                         /* Unlock the activation */
        !            93:                return KERN_RESOURCE_SHORTAGE;          /* Too many pending right now */
        !            94:        }
        !            95:        
        !            96:        if(!(bbr = (bbRupt *)kalloc(sizeof(bbRupt)))) { /* Get a return handler control block */
        !            97:                act_unlock_thread(act);                         /* Unlock the activation */
        !            98:                return KERN_RESOURCE_SHORTAGE;          /* No storage... */
        !            99:        }
        !           100:        
        !           101:        act->mact.bbPendRupt++;                                 /* Count this 'rupt */
        !           102:        bbr->rh.handler = bbSetRupt;                    /* Set interruption routine */
        !           103:        bbr->ruptRtn = ppcInterruptHandler;             /* Set address to vector to */
        !           104: 
        !           105:        bbr->rh.next = act->handlers;                   /* Put our interrupt at the start of the list */
        !           106:        act->handlers = &bbr->rh;
        !           107: 
        !           108:        s = splsched();                                                 /* No talking in class */
        !           109:        act_set_apc(act);                                               /* Set an APC AST */
        !           110:        splx(s);                                                                /* Ok, you can talk now */
        !           111: 
        !           112:        act_unlock_thread(act);                                 /* Unlock the activation */
        !           113:        return KERN_SUCCESS;                                    /* We're done... */
        !           114: }
        !           115: 
        !           116: /* 
        !           117:  *     This guy is fired off asynchronously to actually do the 'rupt.
        !           118:  *     We will find the user state savearea and modify it.  If we can't,
        !           119:  *     we just leave after releasing our work area
        !           120:  */
        !           121: 
        !           122: void bbSetRupt(ReturnHandler *rh, thread_act_t act) {
        !           123: 
        !           124:        savearea        *sv;
        !           125:        BDA_t           *bda;
        !           126:        bbRupt          *bbr;
        !           127:        UInt32          interruptState;
        !           128:        
        !           129:        bbr = (bbRupt *)rh;                                             /* Make our area convenient */
        !           130: 
        !           131:        if(!(bda = (BDA_t *)act->mact.bbDescAddr)) {    /* Is BlueBox still enabled? */
        !           132:                kfree((vm_offset_t)bbr, sizeof(bbRupt));        /* No, release the control block */
        !           133:                return;
        !           134:        }
        !           135:        
        !           136:        act->mact.bbPendRupt--;                                 /* Uncount this 'rupt */
        !           137: 
        !           138:        if(!(sv = (savearea *)find_user_regs(act))) {   /* Find the user state registers */
        !           139:                kfree((vm_offset_t)bbr, sizeof(bbRupt));        /* Couldn't find 'em, release the control block */
        !           140:                return;
        !           141:        }
        !           142:                
        !           143:     interruptState = (bda->InterruptControlWord & kInterruptStateMask) >> kInterruptStateShift; 
        !           144: 
        !           145:     switch (interruptState) {
        !           146:                
        !           147:                case kInUninitialized:
        !           148:                        break;
        !           149:                                
        !           150:                case kInPseudoKernel:
        !           151:                case kOutsideBlue:
        !           152:                        bda->InterruptControlWord = bda->InterruptControlWord | 
        !           153:                                ((bda->postIntMask >> kCR2ToBackupShift) & kBackupCR2Mask);
        !           154:                        break;
        !           155:                        
        !           156:                case kInSystemContext:
        !           157:                        sv->save_cr |= bda->postIntMask;
        !           158:                        break;
        !           159:                        
        !           160:                case kInAlternateContext:
        !           161:                        bda->InterruptControlWord = bda->InterruptControlWord |
        !           162:                                ((bda->postIntMask >> kCR2ToBackupShift) & kBackupCR2Mask);
        !           163:                        bda->InterruptControlWord = (bda->InterruptControlWord & ~kInterruptStateMask) | 
        !           164:                                (kInPseudoKernel << kInterruptStateShift);
        !           165:                                
        !           166:                        bda->ihs_pc = sv->save_srr0;            /* Save the current PC */
        !           167:                        sv->save_srr0 = bbr->ruptRtn;           /* Set the new one */
        !           168:                        bda->ihs_gpr2 = sv->save_r2;            /* Save the original R2 */
        !           169:                        break;
        !           170:                        
        !           171:                case kInExceptionHandler:
        !           172:                        bda->InterruptControlWord = bda->InterruptControlWord |
        !           173:                                ((bda->postIntMask >> kCR2ToBackupShift) & kBackupCR2Mask);
        !           174:                        break;
        !           175:                        
        !           176:                default:
        !           177:                        break;
        !           178:        }
        !           179: 
        !           180:        kfree((vm_offset_t)bbr, sizeof(bbRupt));        /* Release the control block */
        !           181:        return;
        !           182: 
        !           183: }
        !           184: 
        !           185: kern_return_t enable_bluebox(
        !           186:       host_t host,
        !           187:          void *TWI_TableStart,                                                                 /* Start of TWI table */
        !           188:          char *Desc_TableStart                                                                 /* Start of descriptor table */
        !           189:         ) {
        !           190:        
        !           191:        thread_t                th;
        !           192:        vm_offset_t             kerndescaddr, physdescaddr;
        !           193:        kern_return_t   ret;
        !           194:        int                     i;
        !           195:        
        !           196:        th = current_thread();                                                                  /* Get our thread */                                    
        !           197: 
        !           198:        if (host == HOST_NULL) return KERN_INVALID_HOST;
        !           199:        
        !           200:        if(!is_suser()) return KERN_FAILURE;                                    /* We will only do this for the superuser */
        !           201:        if(th->top_act->mact.bbDescAddr) return KERN_FAILURE;   /* Bail if already authorized... */
        !           202:        if((unsigned int) Desc_TableStart & (PAGE_SIZE - 1))    /* Is the descriptor page aligned? */ 
        !           203:                return KERN_FAILURE;                                                            /* No, kick 'em out... */
        !           204: 
        !           205:        ret = vm_map_wire(th->top_act->map,                                     /* Kernel wire the descriptor in the user's map */
        !           206:                (vm_offset_t)Desc_TableStart,
        !           207:                (vm_offset_t)Desc_TableStart + PAGE_SIZE,
        !           208:                VM_PROT_READ | VM_PROT_WRITE,
        !           209:                FALSE);                                                                                                                 
        !           210:                
        !           211:        if(ret != KERN_SUCCESS) {                                                               /* Couldn't wire it, spit on 'em... */
        !           212:                return KERN_FAILURE;    
        !           213:        }
        !           214:                
        !           215:        physdescaddr =                                                                                  /* Get the physical address of the page */
        !           216:                pmap_extract(th->top_act->map->pmap, (vm_offset_t) Desc_TableStart);
        !           217: 
        !           218:        ret =  kmem_alloc_pageable(kernel_map, &kerndescaddr, PAGE_SIZE);       /* Find a virtual address to use */
        !           219:        if(ret != KERN_SUCCESS) {                                                               /* Could we get an address? */
        !           220:                (void) vm_map_unwire(th->top_act->map,                          /* No, unwire the descriptor */
        !           221:                        (vm_offset_t)Desc_TableStart,
        !           222:                        (vm_offset_t)Desc_TableStart + PAGE_SIZE,
        !           223:                        TRUE);
        !           224:                return KERN_FAILURE;                                                            /* Split... */
        !           225:        }
        !           226:        
        !           227:        (void) pmap_enter(kernel_pmap,                                                  /* Map this into the kernel */
        !           228:                kerndescaddr, physdescaddr, VM_PROT_READ|VM_PROT_WRITE, 
        !           229:                TRUE);
        !           230:                
        !           231:        th->top_act->mact.bbDescAddr = (unsigned int)kerndescaddr;      /* Set kernel address of the table */
        !           232:        th->top_act->mact.bbUserDA = (unsigned int)Desc_TableStart;     /* Set user address of the table */
        !           233:        th->top_act->mact.bbTableStart = (unsigned int)TWI_TableStart;  /* Set address of the trap table */
        !           234:        th->top_act->mact.bbPendRupt = 0;                                               /* Clean pending 'rupt count */
        !           235:                
        !           236:        return KERN_SUCCESS;
        !           237: 
        !           238: }
        !           239: 
        !           240: kern_return_t disable_bluebox( host_t host ) {
        !           241:        
        !           242:        thread_act_t    act;
        !           243:        
        !           244:        act = current_act();                                                                    /* Get our thread */                                    
        !           245: 
        !           246:        if (host == HOST_NULL) return KERN_INVALID_HOST;
        !           247:        
        !           248:        if(!is_suser()) return KERN_FAILURE;                                    /* We will only do this for the superuser */
        !           249:        if(!act->mact.bbDescAddr) return KERN_FAILURE;                  /* Bail if not authorized... */
        !           250: 
        !           251:        (void) vm_map_unwire(act->map,                                                  /* Unwire the descriptor in user's address space */
        !           252:                (vm_offset_t)act->mact.bbUserDA,
        !           253:                (vm_offset_t)act->mact.bbUserDA + PAGE_SIZE,
        !           254:                FALSE);
        !           255:                
        !           256:        kmem_free(kernel_map, (vm_offset_t)act->mact.bbDescAddr, PAGE_SIZE);    /* Release the page */
        !           257:        
        !           258:        act->mact.bbDescAddr = 0;                                                               /* Clear kernel pointer to it */
        !           259:        act->mact.bbUserDA = 0;                                                                 /* Clear user pointer to it */
        !           260:        act->mact.bbTableStart = 0;                                                             /* Clear start of table address */
        !           261:        act->mact.bbPendRupt = 0;                                                               /* Clean pending 'rupt count */
        !           262:        return KERN_SUCCESS;
        !           263: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.