1/* 2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_COPYRIGHT@ 30 */ 31/* 32 * Mach Operating System 33 * Copyright (c) 1991,1990 Carnegie Mellon University 34 * All Rights Reserved. 35 * 36 * Permission to use, copy, modify and distribute this software and its 37 * documentation is hereby granted, provided that both the copyright 38 * notice and this permission notice appear in all copies of the 39 * software, derivative works or modified versions, and any portions 40 * thereof, and that both notices appear in supporting documentation. 41 * 42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 45 * 46 * Carnegie Mellon requests users of this software to return to 47 * 48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie Mellon 54 * the rights to redistribute these changes. 55 */ 56 57#include <kern/task.h> 58#include <kern/thread.h> 59#include <i386/misc_protos.h> 60 61#if HYPERVISOR 62#include <kern/hv_support.h> 63#endif 64 65extern zone_t ids_zone; 66 67kern_return_t 68machine_task_set_state( 69 task_t task, 70 int flavor, 71 thread_state_t state, 72 mach_msg_type_number_t state_count) 73{ 74 switch (flavor) { 75 case x86_DEBUG_STATE32: 76 { 77 x86_debug_state32_t *tstate = (x86_debug_state32_t*) state; 78 if ((task_has_64BitAddr(task)) || 79 (state_count != x86_DEBUG_STATE32_COUNT) || 80 (!debug_state_is_valid32(tstate))) { 81 return KERN_INVALID_ARGUMENT; 82 } 83 84 if (task->task_debug == NULL) { 85 task->task_debug = zalloc(ids_zone); 86 } 87 88 copy_debug_state32(tstate, (x86_debug_state32_t*) task->task_debug, FALSE); 89 90 return KERN_SUCCESS; 91 break; 92 } 93 case x86_DEBUG_STATE64: 94 { 95 x86_debug_state64_t *tstate = (x86_debug_state64_t*) state; 96 97 if ((!task_has_64BitAddr(task)) || 98 (state_count != x86_DEBUG_STATE64_COUNT) || 99 (!debug_state_is_valid64(tstate))) { 100 return KERN_INVALID_ARGUMENT; 101 } 102 103 if (task->task_debug == NULL) { 104 task->task_debug = zalloc(ids_zone); 105 } 106 107 copy_debug_state64(tstate, (x86_debug_state64_t*) task->task_debug, FALSE); 108 109 return KERN_SUCCESS; 110 break; 111 } 112 case x86_DEBUG_STATE: 113 { 114 x86_debug_state_t *tstate = (x86_debug_state_t*) state; 115 116 if (state_count != x86_DEBUG_STATE_COUNT) { 117 return KERN_INVALID_ARGUMENT; 118 } 119 120 if ((tstate->dsh.flavor == x86_DEBUG_STATE32) && 121 (tstate->dsh.count == x86_DEBUG_STATE32_COUNT) && 122 (!task_has_64BitAddr(task)) && 123 debug_state_is_valid32(&tstate->uds.ds32)) { 124 125 if (task->task_debug == NULL) { 126 task->task_debug = zalloc(ids_zone); 127 } 128 129 copy_debug_state32(&tstate->uds.ds32, (x86_debug_state32_t*) task->task_debug, FALSE); 130 return KERN_SUCCESS; 131 132 } else if ((tstate->dsh.flavor == x86_DEBUG_STATE64) && 133 (tstate->dsh.count == x86_DEBUG_STATE64_COUNT) && 134 task_has_64BitAddr(task) && 135 debug_state_is_valid64(&tstate->uds.ds64)) { 136 137 if (task->task_debug == NULL) { 138 task->task_debug = zalloc(ids_zone); 139 } 140 141 copy_debug_state64(&tstate->uds.ds64, (x86_debug_state64_t*) task->task_debug, FALSE); 142 return KERN_SUCCESS; 143 } else { 144 return KERN_INVALID_ARGUMENT; 145 } 146 147 break; 148 } 149 default: 150 { 151 return KERN_INVALID_ARGUMENT; 152 break; 153 } 154 } 155} 156 157kern_return_t 158machine_task_get_state(task_t task, 159 int flavor, 160 thread_state_t state, 161 mach_msg_type_number_t *state_count) 162{ 163 switch (flavor) { 164 case x86_DEBUG_STATE32: 165 { 166 x86_debug_state32_t *tstate = (x86_debug_state32_t*) state; 167 168 if ((task_has_64BitAddr(task)) || (*state_count != x86_DEBUG_STATE32_COUNT)) { 169 return KERN_INVALID_ARGUMENT; 170 } 171 172 if (task->task_debug == NULL) { 173 bzero(state, sizeof(*tstate)); 174 } else { 175 copy_debug_state32((x86_debug_state32_t*) task->task_debug, tstate, TRUE); 176 } 177 178 return KERN_SUCCESS; 179 break; 180 } 181 case x86_DEBUG_STATE64: 182 { 183 x86_debug_state64_t *tstate = (x86_debug_state64_t*) state; 184 185 if ((!task_has_64BitAddr(task)) || (*state_count != x86_DEBUG_STATE64_COUNT)) { 186 return KERN_INVALID_ARGUMENT; 187 } 188 189 if (task->task_debug == NULL) { 190 bzero(state, sizeof(*tstate)); 191 } else { 192 copy_debug_state64((x86_debug_state64_t*) task->task_debug, tstate, TRUE); 193 } 194 195 return KERN_SUCCESS; 196 break; 197 } 198 case x86_DEBUG_STATE: 199 { 200 x86_debug_state_t *tstate = (x86_debug_state_t*)state; 201 202 if (*state_count != x86_DEBUG_STATE_COUNT) 203 return(KERN_INVALID_ARGUMENT); 204 205 if (task_has_64BitAddr(task)) { 206 tstate->dsh.flavor = x86_DEBUG_STATE64; 207 tstate->dsh.count = x86_DEBUG_STATE64_COUNT; 208 209 if (task->task_debug == NULL) { 210 bzero(&tstate->uds.ds64, sizeof(tstate->uds.ds64)); 211 } else { 212 copy_debug_state64((x86_debug_state64_t*)task->task_debug, &tstate->uds.ds64, TRUE); 213 } 214 } else { 215 tstate->dsh.flavor = x86_DEBUG_STATE32; 216 tstate->dsh.count = x86_DEBUG_STATE32_COUNT; 217 218 if (task->task_debug == NULL) { 219 bzero(&tstate->uds.ds32, sizeof(tstate->uds.ds32)); 220 } else { 221 copy_debug_state32((x86_debug_state32_t*)task->task_debug, &tstate->uds.ds32, TRUE); 222 } 223 } 224 225 return KERN_SUCCESS; 226 break; 227 } 228 default: 229 { 230 return KERN_INVALID_ARGUMENT; 231 break; 232 } 233 } 234} 235 236/* 237 * This is called when a task is terminated, and also on exec(). 238 * Clear machine-dependent state that is stored on the task. 239 */ 240void 241machine_task_terminate(task_t task) 242{ 243 if (task) { 244 user_ldt_t user_ldt; 245 void *task_debug; 246 247#if HYPERVISOR 248 if (task->hv_task_target) { 249 hv_callbacks.task_destroy(task->hv_task_target); 250 task->hv_task_target = NULL; 251 } 252#endif 253 254 user_ldt = task->i386_ldt; 255 if (user_ldt != 0) { 256 task->i386_ldt = 0; 257 user_ldt_free(user_ldt); 258 } 259 260 task_debug = task->task_debug; 261 if (task_debug != NULL) { 262 task->task_debug = NULL; 263 zfree(ids_zone, task_debug); 264 } 265 } 266} 267 268/* 269 * Set initial default state on a thread as stored in the MACHINE_TASK data. 270 * Note: currently only debug state is supported. 271 */ 272kern_return_t 273machine_thread_inherit_taskwide( 274 thread_t thread, 275 task_t parent_task) 276{ 277 if (parent_task->task_debug) { 278 int flavor; 279 mach_msg_type_number_t count; 280 281 if (task_has_64BitAddr(parent_task)) { 282 flavor = x86_DEBUG_STATE64; 283 count = x86_DEBUG_STATE64_COUNT; 284 } else { 285 flavor = x86_DEBUG_STATE32; 286 count = x86_DEBUG_STATE32_COUNT; 287 } 288 289 return machine_thread_set_state(thread, flavor, parent_task->task_debug, count); 290 } 291 292 return KERN_SUCCESS; 293} 294