/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This 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, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #include #include #include #include extern kern_return_t chud_copy_savearea_to_threadstate(thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t *count, struct savearea *sv); extern kern_return_t chud_copy_threadstate_to_savearea(struct savearea *sv, thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t *count); __private_extern__ void chudxnu_cancel_all_callbacks(void) { extern void chudxnu_exit_callback_cancel(void); extern void chudxnu_thread_timer_callback_cancel(void); chudxnu_cpu_timer_callback_cancel_all(); chudxnu_trap_callback_cancel(); chudxnu_interrupt_callback_cancel(); chudxnu_perfmon_ast_callback_cancel(); chudxnu_cpusig_callback_cancel(); chudxnu_kdebug_callback_cancel(); chudxnu_exit_callback_cancel(); chudxnu_thread_timer_callback_cancel(); } #pragma mark **** cpu timer **** static timer_call_data_t cpu_timer_call[NCPUS] = {{0}, {0}}; static uint64_t t_deadline[NCPUS] = {0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL}; typedef void (*chudxnu_cpu_timer_callback_func_t)(thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t count); static chudxnu_cpu_timer_callback_func_t cpu_timer_callback_fn[NCPUS] = {NULL, NULL}; static void chudxnu_private_cpu_timer_callback(timer_call_param_t param0, timer_call_param_t param1) { int cpu; boolean_t oldlevel; struct ppc_thread_state64 state; mach_msg_type_number_t count; oldlevel = ml_set_interrupts_enabled(FALSE); cpu = cpu_number(); count = PPC_THREAD_STATE64_COUNT; if(chudxnu_thread_get_state(current_act(), PPC_THREAD_STATE64, (thread_state_t)&state, &count, FALSE)==KERN_SUCCESS) { if(cpu_timer_callback_fn[cpu]) { (cpu_timer_callback_fn[cpu])(PPC_THREAD_STATE64, (thread_state_t)&state, count); } } ml_set_interrupts_enabled(oldlevel); } __private_extern__ kern_return_t chudxnu_cpu_timer_callback_enter(chudxnu_cpu_timer_callback_func_t func, uint32_t time, uint32_t units) { int cpu; boolean_t oldlevel; oldlevel = ml_set_interrupts_enabled(FALSE); cpu = cpu_number(); timer_call_cancel(&(cpu_timer_call[cpu])); // cancel any existing callback for this cpu cpu_timer_callback_fn[cpu] = func; clock_interval_to_deadline(time, units, &(t_deadline[cpu])); timer_call_setup(&(cpu_timer_call[cpu]), chudxnu_private_cpu_timer_callback, NULL); timer_call_enter(&(cpu_timer_call[cpu]), t_deadline[cpu]); ml_set_interrupts_enabled(oldlevel); return KERN_SUCCESS; } __private_extern__ kern_return_t chudxnu_cpu_timer_callback_cancel(void) { int cpu; boolean_t oldlevel; oldlevel = ml_set_interrupts_enabled(FALSE); cpu = cpu_number(); timer_call_cancel(&(cpu_timer_call[cpu])); t_deadline[cpu] = t_deadline[cpu] | ~(t_deadline[cpu]); // set to max value cpu_timer_callback_fn[cpu] = NULL; ml_set_interrupts_enabled(oldlevel); return KERN_SUCCESS; } __private_extern__ kern_return_t chudxnu_cpu_timer_callback_cancel_all(void) { int cpu; for(cpu=0; cpu=16) { retval = KERN_FAILURE; } else { retval = hw_cpu_sync(temp, LockTimeOut); /* wait for the other processor */ if(!retval) { retval = KERN_FAILURE; } else { retval = KERN_SUCCESS; } } } else { retval = KERN_INVALID_ARGUMENT; } ml_set_interrupts_enabled(oldlevel); return retval; } #pragma mark **** thread timer **** static thread_call_t thread_timer_call = NULL; typedef void (*chudxnu_thread_timer_callback_func_t)(uint32_t arg); static chudxnu_thread_timer_callback_func_t thread_timer_callback_fn = NULL; static void chudxnu_private_thread_timer_callback(thread_call_param_t param0, thread_call_param_t param1) { if(thread_timer_call) { thread_call_free(thread_timer_call); thread_timer_call = NULL; if(thread_timer_callback_fn) { (thread_timer_callback_fn)((uint32_t)param0); } } } __private_extern__ kern_return_t chudxnu_thread_timer_callback_enter(chudxnu_thread_timer_callback_func_t func, uint32_t arg, uint32_t time, uint32_t units) { if(!thread_timer_call) { uint64_t t_delay; thread_timer_callback_fn = func; thread_timer_call = thread_call_allocate((thread_call_func_t)chudxnu_private_thread_timer_callback, (thread_call_param_t)arg); clock_interval_to_deadline(time, units, &t_delay); thread_call_enter_delayed(thread_timer_call, t_delay); return KERN_SUCCESS; } else { return KERN_FAILURE; // thread timer call already pending } } __private_extern__ kern_return_t chudxnu_thread_timer_callback_cancel(void) { if(thread_timer_call) { thread_call_free(thread_timer_call); thread_timer_call = NULL; } thread_timer_callback_fn = NULL; return KERN_SUCCESS; }