]> 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 e2695db69bb6f7b71ba0fb27392e181ebc1daa6f..b3fc4d685fe55565286cae5ec8057247e68d720e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2003-2009 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -37,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>
@@ -45,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>
 
@@ -65,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;
@@ -78,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 {
@@ -130,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,
@@ -168,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;
 }
@@ -188,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;
@@ -218,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)
@@ -231,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(
@@ -311,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,
@@ -337,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
@@ -362,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)
@@ -411,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
@@ -440,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);
@@ -478,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;
 }
 
@@ -516,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.
@@ -547,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