Annotation of XNU/osfmk/ppc/PseudoKernel.c, revision 1.1.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.