X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/b0d623f7f2ae71ed96e60569f61f9a9a27016e80..2a1bd2d3eef5c7a7bb14f4bb9fdbca9a96ee4752:/osfmk/i386/machine_task.c diff --git a/osfmk/i386/machine_task.c b/osfmk/i386/machine_task.c index c05d69bef..bdfff77ac 100644 --- a/osfmk/i386/machine_task.c +++ b/osfmk/i386/machine_task.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 2000-2008 Apple Inc. All rights reserved. + * Copyright (c) 2000-2016 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,34 +22,34 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ */ -/* +/* * Mach Operating System * Copyright (c) 1991,1990 Carnegie Mellon University * All Rights Reserved. - * + * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. - * + * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * + * * Carnegie Mellon requests users of this software to return to - * + * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 - * + * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ @@ -57,174 +57,200 @@ #include #include #include +#include + +#if HYPERVISOR +#include +#endif extern zone_t ids_zone; kern_return_t machine_task_set_state( - task_t task, - int flavor, - thread_state_t state, - mach_msg_type_number_t state_count) + task_t task, + int flavor, + thread_state_t state, + mach_msg_type_number_t state_count) { switch (flavor) { - case x86_DEBUG_STATE32: - { - x86_debug_state32_t *tstate = (x86_debug_state32_t*) state; - if ((task_has_64BitAddr(task)) || - (state_count != x86_DEBUG_STATE32_COUNT) || - (!debug_state_is_valid32(tstate))) { - return KERN_INVALID_ARGUMENT; - } + case x86_DEBUG_STATE32: + { + x86_debug_state32_t *tstate = (x86_debug_state32_t*) state; + if ((task_has_64Bit_addr(task)) || + (state_count != x86_DEBUG_STATE32_COUNT) || + (!debug_state_is_valid32(tstate))) { + return KERN_INVALID_ARGUMENT; + } - if (task->task_debug == NULL) { - task->task_debug = zalloc(ids_zone); - } + if (task->task_debug == NULL) { + task->task_debug = zalloc(ids_zone); + } - copy_debug_state32(tstate, (x86_debug_state32_t*) task->task_debug, FALSE); - - return KERN_SUCCESS; - break; + copy_debug_state32(tstate, (x86_debug_state32_t*) task->task_debug, FALSE); + + return KERN_SUCCESS; + } + case x86_DEBUG_STATE64: + { + x86_debug_state64_t *tstate = (x86_debug_state64_t*) state; + + if ((!task_has_64Bit_addr(task)) || + (state_count != x86_DEBUG_STATE64_COUNT) || + (!debug_state_is_valid64(tstate))) { + return KERN_INVALID_ARGUMENT; } - case x86_DEBUG_STATE64: - { - x86_debug_state64_t *tstate = (x86_debug_state64_t*) state; - - if ((!task_has_64BitAddr(task)) || - (state_count != x86_DEBUG_STATE64_COUNT) || - (!debug_state_is_valid64(tstate))) { - return KERN_INVALID_ARGUMENT; - } - if (task->task_debug == NULL) { - task->task_debug = zalloc(ids_zone); - } - - copy_debug_state64(tstate, (x86_debug_state64_t*) task->task_debug, FALSE); - - return KERN_SUCCESS; - break; + if (task->task_debug == NULL) { + task->task_debug = zalloc(ids_zone); + } + + copy_debug_state64(tstate, (x86_debug_state64_t*) task->task_debug, FALSE); + + return KERN_SUCCESS; + } + case x86_DEBUG_STATE: + { + x86_debug_state_t *tstate = (x86_debug_state_t*) state; + + if (state_count != x86_DEBUG_STATE_COUNT) { + return KERN_INVALID_ARGUMENT; } - case x86_DEBUG_STATE: - { - x86_debug_state_t *tstate = (x86_debug_state_t*) state; - if (state_count != x86_DEBUG_STATE_COUNT) { - return KERN_INVALID_ARGUMENT; + if ((tstate->dsh.flavor == x86_DEBUG_STATE32) && + (tstate->dsh.count == x86_DEBUG_STATE32_COUNT) && + (!task_has_64Bit_addr(task)) && + debug_state_is_valid32(&tstate->uds.ds32)) { + if (task->task_debug == NULL) { + task->task_debug = zalloc(ids_zone); } - if ((tstate->dsh.flavor == x86_DEBUG_STATE32) && - (tstate->dsh.count == x86_DEBUG_STATE32_COUNT) && - (!task_has_64BitAddr(task)) && - debug_state_is_valid32(&tstate->uds.ds32)) { - - if (task->task_debug == NULL) { - task->task_debug = zalloc(ids_zone); - } - - copy_debug_state32(&tstate->uds.ds32, (x86_debug_state32_t*) task->task_debug, FALSE); - return KERN_SUCCESS; - - } else if ((tstate->dsh.flavor == x86_DEBUG_STATE64) && - (tstate->dsh.count == x86_DEBUG_STATE64_COUNT) && - task_has_64BitAddr(task) && - debug_state_is_valid64(&tstate->uds.ds64)) { - - if (task->task_debug == NULL) { - task->task_debug = zalloc(ids_zone); - } - - copy_debug_state64(&tstate->uds.ds64, (x86_debug_state64_t*) task->task_debug, FALSE); - return KERN_SUCCESS; - } else { - return KERN_INVALID_ARGUMENT; + copy_debug_state32(&tstate->uds.ds32, (x86_debug_state32_t*) task->task_debug, FALSE); + return KERN_SUCCESS; + } else if ((tstate->dsh.flavor == x86_DEBUG_STATE64) && + (tstate->dsh.count == x86_DEBUG_STATE64_COUNT) && + task_has_64Bit_addr(task) && + debug_state_is_valid64(&tstate->uds.ds64)) { + if (task->task_debug == NULL) { + task->task_debug = zalloc(ids_zone); } - break; - } - default: - { + copy_debug_state64(&tstate->uds.ds64, (x86_debug_state64_t*) task->task_debug, FALSE); + return KERN_SUCCESS; + } else { return KERN_INVALID_ARGUMENT; - break; } } + default: + { + return KERN_INVALID_ARGUMENT; + } + } } -kern_return_t -machine_task_get_state(task_t task, - int flavor, - thread_state_t state, - mach_msg_type_number_t *state_count) +kern_return_t +machine_task_get_state(task_t task, + int flavor, + thread_state_t state, + mach_msg_type_number_t *state_count) { switch (flavor) { - case x86_DEBUG_STATE32: - { - x86_debug_state32_t *tstate = (x86_debug_state32_t*) state; + case x86_DEBUG_STATE32: + { + x86_debug_state32_t *tstate = (x86_debug_state32_t*) state; - if ((task_has_64BitAddr(task)) || (*state_count != x86_DEBUG_STATE32_COUNT)) { - return KERN_INVALID_ARGUMENT; - } + if ((task_has_64Bit_addr(task)) || (*state_count != x86_DEBUG_STATE32_COUNT)) { + return KERN_INVALID_ARGUMENT; + } - if (task->task_debug == NULL) { - bzero(state, sizeof(*tstate)); - } else { - copy_debug_state32((x86_debug_state32_t*) task->task_debug, tstate, TRUE); - } + if (task->task_debug == NULL) { + bzero(state, sizeof(*tstate)); + } else { + copy_debug_state32((x86_debug_state32_t*) task->task_debug, tstate, TRUE); + } - return KERN_SUCCESS; - break; + return KERN_SUCCESS; + } + case x86_DEBUG_STATE64: + { + x86_debug_state64_t *tstate = (x86_debug_state64_t*) state; + + if ((!task_has_64Bit_addr(task)) || (*state_count != x86_DEBUG_STATE64_COUNT)) { + return KERN_INVALID_ARGUMENT; } - case x86_DEBUG_STATE64: - { - x86_debug_state64_t *tstate = (x86_debug_state64_t*) state; - if ((!task_has_64BitAddr(task)) || (*state_count != x86_DEBUG_STATE64_COUNT)) { - return KERN_INVALID_ARGUMENT; - } + if (task->task_debug == NULL) { + bzero(state, sizeof(*tstate)); + } else { + copy_debug_state64((x86_debug_state64_t*) task->task_debug, tstate, TRUE); + } + + return KERN_SUCCESS; + } + case x86_DEBUG_STATE: + { + x86_debug_state_t *tstate = (x86_debug_state_t*)state; + + if (*state_count != x86_DEBUG_STATE_COUNT) { + return KERN_INVALID_ARGUMENT; + } + + if (task_has_64Bit_addr(task)) { + tstate->dsh.flavor = x86_DEBUG_STATE64; + tstate->dsh.count = x86_DEBUG_STATE64_COUNT; if (task->task_debug == NULL) { - bzero(state, sizeof(*tstate)); + bzero(&tstate->uds.ds64, sizeof(tstate->uds.ds64)); } else { - copy_debug_state64((x86_debug_state64_t*) task->task_debug, tstate, TRUE); - } + copy_debug_state64((x86_debug_state64_t*)task->task_debug, &tstate->uds.ds64, TRUE); + } + } else { + tstate->dsh.flavor = x86_DEBUG_STATE32; + tstate->dsh.count = x86_DEBUG_STATE32_COUNT; - return KERN_SUCCESS; - break; - } - case x86_DEBUG_STATE: - { - x86_debug_state_t *tstate = (x86_debug_state_t*)state; - - if (*state_count != x86_DEBUG_STATE_COUNT) - return(KERN_INVALID_ARGUMENT); - - if (task_has_64BitAddr(task)) { - tstate->dsh.flavor = x86_DEBUG_STATE64; - tstate->dsh.count = x86_DEBUG_STATE64_COUNT; - - if (task->task_debug == NULL) { - bzero(&tstate->uds.ds64, sizeof(tstate->uds.ds64)); - } else { - copy_debug_state64((x86_debug_state64_t*)task->task_debug, &tstate->uds.ds64, TRUE); - } + if (task->task_debug == NULL) { + bzero(&tstate->uds.ds32, sizeof(tstate->uds.ds32)); } else { - tstate->dsh.flavor = x86_DEBUG_STATE32; - tstate->dsh.count = x86_DEBUG_STATE32_COUNT; - - if (task->task_debug == NULL) { - bzero(&tstate->uds.ds32, sizeof(tstate->uds.ds32)); - } else { - copy_debug_state32((x86_debug_state32_t*)task->task_debug, &tstate->uds.ds32, TRUE); - } + copy_debug_state32((x86_debug_state32_t*)task->task_debug, &tstate->uds.ds32, TRUE); } - - return KERN_SUCCESS; - break; } - default: - { - return KERN_INVALID_ARGUMENT; - break; + + return KERN_SUCCESS; + } + default: + { + return KERN_INVALID_ARGUMENT; + } + } +} + +/* + * This is called when a task is terminated, and also on exec(). + * Clear machine-dependent state that is stored on the task. + */ +void +machine_task_terminate(task_t task) +{ + if (task) { + user_ldt_t user_ldt; + void *task_debug; + +#if HYPERVISOR + if (task->hv_task_target) { + hv_callbacks.task_destroy(task->hv_task_target); + task->hv_task_target = NULL; + } +#endif + + user_ldt = task->i386_ldt; + if (user_ldt != 0) { + task->i386_ldt = 0; + user_ldt_free(user_ldt); + } + + task_debug = task->task_debug; + if (task_debug != NULL) { + task->task_debug = NULL; + zfree(ids_zone, task_debug); } } } @@ -235,14 +261,14 @@ machine_task_get_state(task_t task, */ kern_return_t machine_thread_inherit_taskwide( - thread_t thread, - task_t parent_task) + thread_t thread, + task_t parent_task) { if (parent_task->task_debug) { int flavor; mach_msg_type_number_t count; - if (task_has_64BitAddr(parent_task)) { + if (task_has_64Bit_addr(parent_task)) { flavor = x86_DEBUG_STATE64; count = x86_DEBUG_STATE64_COUNT; } else { @@ -255,3 +281,25 @@ machine_thread_inherit_taskwide( return KERN_SUCCESS; } + +void +machine_task_init(task_t new_task, + task_t parent_task, + boolean_t inherit_memory) +{ + new_task->uexc_range_start = 0; + new_task->uexc_range_size = 0; + new_task->uexc_handler = 0; + + new_task->i386_ldt = 0; + + if (parent_task != TASK_NULL) { + if (inherit_memory && parent_task->i386_ldt) { + new_task->i386_ldt = user_ldt_copy(parent_task->i386_ldt); + } + new_task->xstate = parent_task->xstate; + } else { + assert(fpu_default != UNDEFINED); + new_task->xstate = fpu_default; + } +}