]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/chud/i386/chud_osfmk_callback_i386.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / osfmk / chud / i386 / chud_osfmk_callback_i386.c
index 9800764df57aa5f98306ac334611f94796da4629..b3fc4d685fe55565286cae5ec8057247e68d720e 100644 (file)
@@ -1,23 +1,29 @@
 /*
- * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2003-2009 Apple 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
+ * @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
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * 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,
  * 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@
+ * 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@
  */
 
 #include <stdint.h>
@@ -31,6 +37,8 @@
 #include <kern/kalloc.h>
 #include <kern/thread.h>
 
+#include <libkern/OSAtomic.h>
+
 #include <machine/machine_routines.h>
 #include <machine/cpu_data.h>
 #include <machine/trap.h>
@@ -39,6 +47,7 @@
 #include <chud/chud_xnu_private.h>
 
 #include <i386/misc_protos.h>
+#include <i386/lapic.h>
 #include <i386/mp.h>
 #include <i386/machine_cpu.h>
 
@@ -59,11 +68,9 @@ void chudxnu_cancel_all_callbacks(void)
     chudxnu_interrupt_callback_cancel();
     chudxnu_perfmon_ast_callback_cancel();
     chudxnu_kdebug_callback_cancel();
-    chudxnu_thread_timer_callback_cancel();
     chudxnu_trap_callback_cancel();
-#if XXX
        chudxnu_syscall_callback_cancel();
-#endif
+       chudxnu_dtrace_callback_cancel();
 }
 
 static chudcpu_data_t chudcpu_boot_cpu;
@@ -72,7 +79,6 @@ chudxnu_cpu_alloc(boolean_t boot_processor)
 {
        chudcpu_data_t  *chud_proc_info;
 
-
        if (boot_processor) {
                chud_proc_info = &chudcpu_boot_cpu;
        } else {
@@ -124,11 +130,6 @@ chudxnu_private_cpu_timer_callback(
                                     FALSE) == KERN_SUCCESS) {
                        fn = chud_proc_info->cpu_timer_callback_fn;
                        if (fn) {
-                       KERNEL_DEBUG_CONSTANT(
-                               MACHDBG_CODE(DBG_MACH_CHUD,
-                                       CHUD_TIMER_CALLBACK) | DBG_FUNC_NONE,
-                               (uint32_t)fn, 0,0,0,0);
-                               //state.eip, state.cs, 0, 0);
                                (fn)(
                                x86_THREAD_STATE,
                                (thread_state_t)&state,
@@ -162,11 +163,6 @@ chudxnu_cpu_timer_callback_enter(
        timer_call_enter(&(chud_proc_info->cpu_timer_call),
                         chud_proc_info->t_deadline);
 
-       KERNEL_DEBUG_CONSTANT(
-               MACHDBG_CODE(DBG_MACH_CHUD,
-                            CHUD_TIMER_CALLBACK_ENTER) | DBG_FUNC_NONE,
-               (uint32_t) func, time, units, 0, 0);
-
        ml_set_interrupts_enabled(oldlevel);
        return KERN_SUCCESS;
 }
@@ -182,11 +178,6 @@ chudxnu_cpu_timer_callback_cancel(void)
 
        timer_call_cancel(&(chud_proc_info->cpu_timer_call));
 
-       KERNEL_DEBUG_CONSTANT(
-               MACHDBG_CODE(DBG_MACH_CHUD,
-                            CHUD_TIMER_CALLBACK_CANCEL) | DBG_FUNC_NONE,
-               0, 0, 0, 0, 0);
-
        // set to max value:
        chud_proc_info->t_deadline |= ~(chud_proc_info->t_deadline);
        chud_proc_info->cpu_timer_callback_fn = NULL;
@@ -212,12 +203,21 @@ chudxnu_cpu_timer_callback_cancel_all(void)
        return KERN_SUCCESS;
 }
 
+#if 0
 #pragma mark **** trap ****
-static chudxnu_trap_callback_func_t trap_callback_fn = NULL;
+#endif
+static kern_return_t chud_null_trap(uint32_t trapentry, thread_flavor_t flavor,
+       thread_state_t tstate,  mach_msg_type_number_t count);
+static chudxnu_trap_callback_func_t trap_callback_fn = chud_null_trap;
+
+static kern_return_t chud_null_trap(uint32_t trapentry __unused, thread_flavor_t flavor __unused,
+       thread_state_t tstate __unused,  mach_msg_type_number_t count __unused) {
+       return KERN_FAILURE;
+}
 
 static kern_return_t
 chudxnu_private_trap_callback(
-       int                     trapno,
+       int trapno,
        void                    *regs,
        int                     unused1,
        int                     unused2)
@@ -225,55 +225,95 @@ chudxnu_private_trap_callback(
 #pragma unused (regs)
 #pragma unused (unused1)
 #pragma unused (unused2)
-    kern_return_t retval = KERN_FAILURE;
+       kern_return_t retval = KERN_FAILURE;
        chudxnu_trap_callback_func_t fn = trap_callback_fn;
 
-        if(fn) {
-               boolean_t                       oldlevel;
-               x86_thread_state_t      state;  // once we have an 64bit- independent way to determine if a thread is
-                                                                       // running kernel code, we'll switch to x86_thread_state_t.
-               mach_msg_type_number_t          count;  
-
+       if(fn) {
+               boolean_t oldlevel;
+               x86_thread_state_t state;
+               mach_msg_type_number_t count;
+               thread_t thread = current_thread();
+               
                oldlevel = ml_set_interrupts_enabled(FALSE);
+               
+               /* prevent reentry into CHUD when dtracing */
+               if(thread->t_chud & T_IN_CHUD) {
+                       /* restore interrupts */
+                       ml_set_interrupts_enabled(oldlevel);
+
+                       return KERN_FAILURE;    // not handled - pass off to dtrace
+               }
+
+               /* update the chud state bits */
+               thread->t_chud |= T_IN_CHUD;
 
                count = x86_THREAD_STATE_COUNT;
-               if(chudxnu_thread_get_state(current_thread(),
+               
+               if(chudxnu_thread_get_state(thread,
                                x86_THREAD_STATE,
                                (thread_state_t)&state,
                                &count,
                                FALSE) == KERN_SUCCESS) {
-         
-                 retval = (fn)(
-                                 trapno,
-                                 x86_THREAD_STATE,
-                                 (thread_state_t)&state,
-                                 count);
+                 
+                                       retval = (fn)(
+                                               trapno,
+                                               x86_THREAD_STATE,
+                                               (thread_state_t)&state,
+                                               count);
                }
-    ml_set_interrupts_enabled(oldlevel);
+
+               /* no longer in CHUD */
+               thread->t_chud &= ~(T_IN_CHUD);
+
+               ml_set_interrupts_enabled(oldlevel);
        }
 
-    return retval;
+       return retval;
 }
 
 __private_extern__ kern_return_t
 chudxnu_trap_callback_enter(chudxnu_trap_callback_func_t func)
 {
-    trap_callback_fn = func;
-    perfTrapHook = chudxnu_private_trap_callback;
-    return KERN_SUCCESS;
+       if(OSCompareAndSwapPtr(NULL, chudxnu_private_trap_callback, 
+               (void * volatile *)&perfTrapHook)) {
+
+               chudxnu_trap_callback_func_t old = trap_callback_fn;
+               while(!OSCompareAndSwapPtr(old, func, 
+                       (void * volatile *)&trap_callback_fn)) {
+                       old = trap_callback_fn;
+               }
+               return KERN_SUCCESS;
+       }
+       return KERN_FAILURE;
 }
 
 __private_extern__ kern_return_t
 chudxnu_trap_callback_cancel(void)
 {
-    trap_callback_fn = NULL;
-        perfTrapHook = NULL;
-    return KERN_SUCCESS;
+       if(OSCompareAndSwapPtr(chudxnu_private_trap_callback,  NULL,
+               (void * volatile *)&perfTrapHook)) {
+
+               chudxnu_trap_callback_func_t old = trap_callback_fn;
+               while(!OSCompareAndSwapPtr(old, chud_null_trap, 
+                       (void * volatile *)&trap_callback_fn)) {
+                       old = trap_callback_fn;
+               }
+               return KERN_SUCCESS;
+       }
+       return KERN_FAILURE;
 }
 
+#if 0
 #pragma mark **** ast ****
-static
-chudxnu_perfmon_ast_callback_func_t perfmon_ast_callback_fn = NULL;
+#endif
+static kern_return_t chud_null_ast(thread_flavor_t flavor, thread_state_t tstate,  
+       mach_msg_type_number_t count);
+static chudxnu_perfmon_ast_callback_func_t perfmon_ast_callback_fn = chud_null_ast;
+
+static kern_return_t chud_null_ast(thread_flavor_t flavor __unused,
+       thread_state_t tstate __unused,  mach_msg_type_number_t count __unused) {
+       return KERN_FAILURE;
+}
 
 static kern_return_t
 chudxnu_private_chud_ast_callback(
@@ -305,18 +345,13 @@ chudxnu_private_chud_ast_callback(
                x86_thread_state_t state;
                mach_msg_type_number_t count;
                count = x86_THREAD_STATE_COUNT;
-               
+
                if (chudxnu_thread_get_state(
                        current_thread(),
                        x86_THREAD_STATE,
                        (thread_state_t) &state, &count,
                        TRUE) == KERN_SUCCESS) {
 
-                       KERNEL_DEBUG_CONSTANT(
-                               MACHDBG_CODE(DBG_MACH_CHUD,
-                                   CHUD_AST_CALLBACK) | DBG_FUNC_NONE,
-                               (uint32_t) fn, 0, 0, 0, 0);
-
                        (fn)(
                                x86_THREAD_STATE,
                                (thread_state_t) &state,
@@ -331,17 +366,35 @@ chudxnu_private_chud_ast_callback(
 __private_extern__ kern_return_t
 chudxnu_perfmon_ast_callback_enter(chudxnu_perfmon_ast_callback_func_t func)
 {
-       perfmon_ast_callback_fn = func;
-       perfASTHook = chudxnu_private_chud_ast_callback;
-       return KERN_SUCCESS;
+       if(OSCompareAndSwapPtr(NULL, chudxnu_private_chud_ast_callback,
+               (void * volatile *)&perfASTHook)) {
+               chudxnu_perfmon_ast_callback_func_t old = perfmon_ast_callback_fn;
+
+               while(!OSCompareAndSwapPtr(old, func,
+                       (void * volatile *)&perfmon_ast_callback_fn)) {
+                       old = perfmon_ast_callback_fn;
+               }
+
+               return KERN_SUCCESS;
+       }
+       return KERN_FAILURE;
 }
 
 __private_extern__ kern_return_t
 chudxnu_perfmon_ast_callback_cancel(void)
 {
-    perfmon_ast_callback_fn = NULL;
-    perfASTHook = NULL;
-    return KERN_SUCCESS;
+       if(OSCompareAndSwapPtr(chudxnu_private_chud_ast_callback, NULL,
+               (void * volatile *)&perfASTHook)) {
+               chudxnu_perfmon_ast_callback_func_t old = perfmon_ast_callback_fn;
+
+               while(!OSCompareAndSwapPtr(old, chud_null_ast,
+                       (void * volatile *)&perfmon_ast_callback_fn)) {
+                       old = perfmon_ast_callback_fn;
+               }
+
+               return KERN_SUCCESS;
+       }
+       return KERN_FAILURE;
 }
 
 __private_extern__ kern_return_t
@@ -356,22 +409,21 @@ chudxnu_perfmon_ast_send_urgent(boolean_t urgent)
         *myast |= (AST_CHUD);
     }
 
-    KERNEL_DEBUG_CONSTANT(
-       MACHDBG_CODE(DBG_MACH_CHUD, CHUD_AST_SEND) | DBG_FUNC_NONE,
-       urgent, 0, 0, 0, 0);
-
     ml_set_interrupts_enabled(oldlevel);
     return KERN_SUCCESS;
 }
 
-__private_extern__ kern_return_t
-chudxnu_perfmon_ast_send(void)
-{
-    return chudxnu_perfmon_ast_send_urgent(TRUE);
-}
-
+#if 0
 #pragma mark **** interrupt ****
-static chudxnu_interrupt_callback_func_t interrupt_callback_fn = NULL;
+#endif
+static kern_return_t chud_null_int(uint32_t trapentry, thread_flavor_t flavor, 
+       thread_state_t tstate,  mach_msg_type_number_t count);
+static chudxnu_interrupt_callback_func_t interrupt_callback_fn = chud_null_int;
+
+static kern_return_t chud_null_int(uint32_t trapentry __unused, thread_flavor_t flavor __unused,
+       thread_state_t tstate __unused,  mach_msg_type_number_t count __unused) {
+       return KERN_FAILURE;
+}
 
 static void
 chudxnu_private_interrupt_callback(void *foo)
@@ -405,20 +457,32 @@ chudxnu_private_interrupt_callback(void *foo)
 __private_extern__ kern_return_t
 chudxnu_interrupt_callback_enter(chudxnu_interrupt_callback_func_t func)
 {
-    interrupt_callback_fn = func;
-    lapic_set_pmi_func((i386_intr_func_t)chudxnu_private_interrupt_callback);
-    return KERN_SUCCESS;
+       if(OSCompareAndSwapPtr(chud_null_int, func, 
+               (void * volatile *)&interrupt_callback_fn)) {
+               lapic_set_pmi_func((i386_intr_func_t)chudxnu_private_interrupt_callback);
+
+               return KERN_SUCCESS;
+       }
+    return KERN_FAILURE;
 }
 
 __private_extern__ kern_return_t
 chudxnu_interrupt_callback_cancel(void)
 {
-    interrupt_callback_fn = NULL;
+       chudxnu_interrupt_callback_func_t old = interrupt_callback_fn;
+
+       while(!OSCompareAndSwapPtr(old, chud_null_int,
+               (void * volatile *)&interrupt_callback_fn)) {
+               old = interrupt_callback_fn;
+       }
+
     lapic_set_pmi_func(NULL);
     return KERN_SUCCESS;
 }
 
+#if 0
 #pragma mark **** cpu signal ****
+#endif
 static chudxnu_cpusig_callback_func_t cpusig_callback_fn = NULL;
 
 static          kern_return_t
@@ -434,10 +498,6 @@ chudxnu_private_cpu_signal_handler(int request)
                                             x86_THREAD_STATE,
                                             (thread_state_t) &state, &count,
                                             FALSE) == KERN_SUCCESS) {
-                       KERNEL_DEBUG_CONSTANT(
-                               MACHDBG_CODE(DBG_MACH_CHUD,
-                                       CHUD_CPUSIG_CALLBACK) | DBG_FUNC_NONE,
-                               (uint32_t)fn, request, 0, 0, 0);
                        return (fn)(
                                        request, x86_THREAD_STATE,
                                        (thread_state_t) &state, count);
@@ -472,14 +532,23 @@ chudxnu_cpu_signal_handler(void)
 __private_extern__ kern_return_t
 chudxnu_cpusig_callback_enter(chudxnu_cpusig_callback_func_t func)
 {
-       cpusig_callback_fn = func;
-       return KERN_SUCCESS;
+       if(OSCompareAndSwapPtr(NULL, func, 
+               (void * volatile *)&cpusig_callback_fn)) {
+               return KERN_SUCCESS;
+       }
+       return KERN_FAILURE;
 }
 
 __private_extern__ kern_return_t
 chudxnu_cpusig_callback_cancel(void)
 {
-       cpusig_callback_fn = NULL;
+       chudxnu_cpusig_callback_func_t old = cpusig_callback_fn;
+
+       while(!OSCompareAndSwapPtr(old, NULL,
+               (void * volatile *)&cpusig_callback_fn)) {
+               old = cpusig_callback_fn;
+       }
+
        return KERN_SUCCESS;
 }
 
@@ -510,11 +579,6 @@ chudxnu_cpusig_send(int otherCPU, uint32_t request_code)
                //request.req_type = CPRQchud;          /* set request type */
                request.req_code = request_code;        /* set request */
 
-               KERNEL_DEBUG_CONSTANT(
-                       MACHDBG_CODE(DBG_MACH_CHUD,
-                                    CHUD_CPUSIG_SEND) | DBG_FUNC_NONE,
-                       otherCPU, request_code, 0, 0, 0);
-
                /*
                 * Insert the new request in the target cpu's request queue
                 * and signal target cpu.
@@ -541,50 +605,3 @@ chudxnu_cpusig_send(int otherCPU, uint32_t request_code)
        enable_preemption();
        return retval;
 }
-
-#ifdef XXX
-#pragma mark **** CHUD syscall (PPC) ****
-
-typedef int (*PPCcallEnt)(struct savearea *save);
-extern PPCcallEnt      PPCcalls[];
-
-static chudxnu_syscall_callback_func_t syscall_callback_fn = NULL;
-
-static int
-chudxnu_private_syscall_callback(struct savearea *ssp)
-{
-       if(ssp) {
-               if(syscall_callback_fn) {
-                       struct ppc_thread_state64 state;
-                       kern_return_t retval;
-                       mach_msg_type_number_t count = PPC_THREAD_STATE64_COUNT;
-                       chudxnu_copy_savearea_to_threadstate(PPC_THREAD_STATE64, (thread_state_t)&state, &count, ssp);
-                       ssp->save_r3 = (syscall_callback_fn)(PPC_THREAD_STATE64, (thread_state_t)&state, count);
-               } else {
-                       ssp->save_r3 = KERN_FAILURE;
-               }
-       }
-       
-    return 1; // check for ASTs (always)
-}
-
-__private_extern__ kern_return_t
-chudxnu_syscall_callback_enter(chudxnu_syscall_callback_func_t func)
-{
-       syscall_callback_fn = func;
-       PPCcalls[9] = chudxnu_private_syscall_callback;
-    __asm__ volatile("eieio"); /* force order */
-    __asm__ volatile("sync");  /* force to memory */
-    return KERN_SUCCESS;
-}
-
-__private_extern__ kern_return_t
-chudxnu_syscall_callback_cancel(void)
-{
-       syscall_callback_fn = NULL;
-       PPCcalls[9] = NULL;
-    __asm__ volatile("eieio"); /* force order */
-    __asm__ volatile("sync");  /* force to memory */
-    return KERN_SUCCESS;
-}
-#endif