|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.