]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/locore.s
xnu-1228.5.20.tar.gz
[apple/xnu.git] / osfmk / i386 / locore.s
index 166c843f51a9bbd879fed59ce5168129801aa0e8..ac1bb007a7a44a711303f18311f692432b69b032 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -223,99 +223,151 @@ Entry(timer_grab)
  */
 
 /*
- * Low 32-bits of nanotime returned in %eax.
+ * Nanotime returned in %edx:%eax.
  * Computed from tsc based on the scale factor
  * and an implicit 32 bit shift.
+ * This code must match what _rtc_nanotime_read does in
+ * i386/machine_routines_asm.s.  Failure to do so can
+ * result in "weird" timing results.
  *
- * Uses %esi, %edi, %ebx, %ecx and %edx.
+ * Uses %eax, %ebx, %ecx, %edx, %esi, %edi.
  */
 #define RNT_INFO               _rtc_nanotime_info
-#define NANOTIME32                                                                                       \
-0:     movl    RNT_INFO+RNT_TSC_BASE,%esi                                               ;\
-       movl    RNT_INFO+RNT_TSC_BASE+4,%edi                                     ;\
-       rdtsc                                                                                                    ;\
-       subl    %esi,%eax                                       /* tsc - tsc_base */ ;\
-       sbbl    %edi,%edx                                                                                ;\
-       movl    RNT_INFO+RNT_SCALE,%ecx                                                  ;\
-       movl    %edx,%ebx                                       /* delta * scale */  ;\
-       mull    %ecx                                                                                     ;\
-       movl    %ebx,%eax                                                                                ;\
-       movl    %edx,%ebx                                                                                ;\
-       mull    %ecx                                                                                     ;\
-       addl    %ebx,%eax                                                                                ;\
-       addl    RNT_INFO+RNT_NS_BASE,%eax       /* add ns_base */        ;\
-       cmpl    RNT_INFO+RNT_TSC_BASE,%esi                                               ;\
-       jne             0b                                                                                               ;\
-       cmpl    RNT_INFO+RNT_TSC_BASE+4,%edi                                     ;\
-       jne             0b
+#define NANOTIME                                                       \
+       lea     RNT_INFO,%edi                                           ; \
+0:                                                                     ; \
+       movl    RNT_GENERATION(%edi),%esi       /* being updated? */    ; \
+       testl   %esi,%esi                                               ; \
+       jz      0b                              /* wait until done */   ; \
+       rdtsc                                                           ; \
+       subl    RNT_TSC_BASE(%edi),%eax                                 ; \
+       sbbl    RNT_TSC_BASE+4(%edi),%edx       /* tsc - tsc_base */    ; \
+       movl    RNT_SCALE(%edi),%ecx            /* * scale factor */    ; \
+       movl    %edx,%ebx                                               ; \
+       mull    %ecx                                                    ; \
+       movl    %ebx,%eax                                               ; \
+       movl    %edx,%ebx                                               ; \
+       mull    %ecx                                                    ; \
+       addl    %ebx,%eax                                               ; \
+       adcl    $0,%edx                                                 ; \
+       addl    RNT_NS_BASE(%edi),%eax          /* + ns_base */         ; \
+       adcl    RNT_NS_BASE+4(%edi),%edx                                ; \
+       cmpl    RNT_GENERATION(%edi),%esi       /* check for update */  ; \
+       jne     0b                              /* do it all again */
+
 
 /*
- * Add 32-bit ns delta in register dreg to timer pointed to by register treg.
+ * Add 64-bit delta in register dreg : areg to timer pointed to by register treg.
  */
-#define TIMER_UPDATE(treg,dreg)                                                      \
-       addl    TIMER_LOW(treg),dreg            /* add delta low bits     */ ;\
-       adcl    $0,TIMER_HIGHCHK(treg)          /* add carry check bits   */ ;\
-       movl    dreg,TIMER_LOW(treg)            /* store updated low bit  */ ;\
-       movl    TIMER_HIGHCHK(treg),dreg        /* copy high check bits   */ ;\
-       movl    dreg,TIMER_HIGH(treg)           /*   to high bita         */
+#define TIMER_UPDATE(treg,dreg,areg)                                                                     \
+       addl    TIMER_LOW(treg),areg            /* add low bits */                              ; \
+       adcl    dreg,TIMER_HIGH(treg)           /* add carry high bits */               ; \
+       movl    areg,TIMER_LOW(treg)            /* store updated low bit */             ; \
+       movl    TIMER_HIGH(treg),dreg           /* copy high bits */                    ; \
+       movl    dreg,TIMER_HIGHCHK(treg)        /* to high check */
 
 /*
  * Add time delta to old timer and start new.
  */
-#define TIMER_EVENT(old,new)                                                  \
-       NANOTIME32                              /* eax low bits nanosecs  */ ;\
-       movl    %gs:CPU_PROCESSOR,%ecx          /* get current processor  */ ;\
-       movl    CURRENT_TIMER(%ecx),%ecx        /* get current timer      */ ;\
-       movl    %eax,%edx                       /* save timestamp in %edx */ ;\
-       subl    TIMER_TSTAMP(%ecx),%eax         /* compute elapsed time   */ ;\
-       TIMER_UPDATE(%ecx,%eax)                 /* update timer struct    */ ;\
-       addl    $(new##_TIMER-old##_TIMER),%ecx /* point to new timer     */ ;\
-       movl    %edx,TIMER_TSTAMP(%ecx)         /* set timestamp          */ ;\
-       movl    %gs:CPU_PROCESSOR,%edx          /* get current processor  */ ;\
-       movl    %ecx,CURRENT_TIMER(%edx)        /* set current timer      */
-
+#define TIMER_EVENT(old,new)                                                                                     \
+       NANOTIME                                                        /* edx:eax nanosecs */                  ; \
+       movl    %eax,%esi                                       /* save timestamp */                    ; \
+       movl    %edx,%edi                                       /* save timestamp */                    ; \
+       movl    %gs:CPU_PROCESSOR,%ebx          /* get current processor */             ; \
+       movl    THREAD_TIMER(%ebx),%ecx         /* get current timer */                 ; \
+       subl    TIMER_TSTAMP(%ecx),%eax         /* compute elapsed time */              ; \
+       sbbl    TIMER_TSTAMP+4(%ecx),%edx       /* compute elapsed time */              ; \
+       TIMER_UPDATE(%ecx,%edx,%eax)            /* update timer */                              ; \
+       addl    $(new##_TIMER-old##_TIMER),%ecx /* point to new timer */        ; \
+       movl    %esi,TIMER_TSTAMP(%ecx)         /* set timestamp */                             ; \
+       movl    %edi,TIMER_TSTAMP+4(%ecx)       /* set timestamp */                             ; \
+       movl    %ecx,THREAD_TIMER(%ebx)         /* set current timer */                 ; \
+       movl    %esi,%eax                                       /* restore timestamp */                 ; \
+       movl    %edi,%edx                                       /* restore timestamp */                 ; \
+       movl    CURRENT_STATE(%ebx),%ecx        /* current state */                             ; \
+       subl    TIMER_TSTAMP(%ecx),%eax         /* compute elapsed time */              ; \
+       sbbl    TIMER_TSTAMP+4(%ecx),%edx       /* compute elapsed time */              ; \
+       TIMER_UPDATE(%ecx,%edx,%eax)            /* update timer */                              ; \
+       addl    $(new##_STATE-old##_STATE),%ecx /* point to new state */        ; \
+       movl    %ecx,CURRENT_STATE(%ebx)        /* set current state */                 ; \
+       movl    %esi,TIMER_TSTAMP(%ecx)         /* set timestamp */                             ; \
+       movl    %edi,TIMER_TSTAMP+4(%ecx)       /* set timestamp */
 
 /*
  * Update time on user trap entry.
- * Uses %eax,%ecx,%edx,%esi.
+ * Uses %eax,%ebx,%ecx,%edx,%esi,%edi.
  */
 #define        TIME_TRAP_UENTRY        TIMER_EVENT(USER,SYSTEM)
 
 /*
  * update time on user trap exit.
- * Uses %eax,%ecx,%edx,%esi.
+ * Uses %eax,%ebx,%ecx,%edx,%esi,%edi.
  */
 #define        TIME_TRAP_UEXIT         TIMER_EVENT(SYSTEM,USER)
 
 /*
  * update time on interrupt entry.
- * Uses %eax,%ecx,%edx,%esi.
- */
-#define        TIME_INT_ENTRY \
-       NANOTIME32                              /* eax low bits nanosecs  */ ;\
-       movl    %gs:CPU_PROCESSOR,%ecx          /* get current processor  */ ;\
-       movl    CURRENT_TIMER(%ecx),%ecx        /* get current timer      */ ;\
-       movl    %eax,%edx                       /* save timestamp in %edx */ ;\
-       subl    TIMER_TSTAMP(%ecx),%eax         /* compute elapsed time   */ ;\
-       TIMER_UPDATE(%ecx,%eax)                 /* update timer struct    */ ;\
-       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */ ;\
-       addl    $(SYSTEM_TIMER),%ecx            /* point to sys timer     */ ;\
-       movl    %edx,TIMER_TSTAMP(%ecx)         /* set timestamp          */
+ * Uses %eax,%ebx,%ecx,%edx,%esi,%edi.
+ * Saves processor state info on stack.
+ */
+#define        TIME_INT_ENTRY                                                                                                    \
+       NANOTIME                                                        /* edx:eax nanosecs */                  ; \
+       movl    %eax,%gs:CPU_INT_EVENT_TIME             /* save in cpu data */          ; \
+       movl    %edx,%gs:CPU_INT_EVENT_TIME+4   /* save in cpu data */          ; \
+       movl    %eax,%esi                                       /* save timestamp */                    ; \
+       movl    %edx,%edi                                       /* save timestamp */                    ; \
+       movl    %gs:CPU_PROCESSOR,%ebx          /* get current processor */             ; \
+       movl    THREAD_TIMER(%ebx),%ecx         /* get current timer */                 ; \
+       subl    TIMER_TSTAMP(%ecx),%eax         /* compute elapsed time */              ; \
+       sbbl    TIMER_TSTAMP+4(%ecx),%edx       /* compute elapsed time */              ; \
+       TIMER_UPDATE(%ecx,%edx,%eax)            /* update timer */                              ; \
+       movl    KERNEL_TIMER(%ebx),%ecx         /* point to kernel timer */             ; \
+       movl    %esi,TIMER_TSTAMP(%ecx)         /* set timestamp */                             ; \
+       movl    %edi,TIMER_TSTAMP+4(%ecx)       /* set timestamp */                             ; \
+       movl    %esi,%eax                                       /* restore timestamp */                 ; \
+       movl    %edi,%edx                                       /* restore timestamp */                 ; \
+       movl    CURRENT_STATE(%ebx),%ecx        /* get current state */                 ; \
+       pushl   %ecx                                            /* save state */                                ; \
+       subl    TIMER_TSTAMP(%ecx),%eax         /* compute elapsed time */              ; \
+       sbbl    TIMER_TSTAMP+4(%ecx),%edx       /* compute elapsed time */              ; \
+       TIMER_UPDATE(%ecx,%edx,%eax)            /* update timer */                              ; \
+       leal    IDLE_STATE(%ebx),%eax           /* get idle state */                    ; \
+       cmpl    %eax,%ecx                                       /* compare current state */             ; \
+       je              0f                                                      /* skip if equal */                             ; \
+       leal    SYSTEM_STATE(%ebx),%ecx         /* get system state */                  ; \
+       movl    %ecx,CURRENT_STATE(%ebx)        /* set current state */                 ; \
+0:     movl    %esi,TIMER_TSTAMP(%ecx)         /* set timestamp */                             ; \
+       movl    %edi,TIMER_TSTAMP+4(%ecx)       /* set timestamp */
 
 /*
  * update time on interrupt exit.
- * Uses %eax, %ecx, %edx, %esi.
- */
-#define        TIME_INT_EXIT \
-       NANOTIME32                              /* eax low bits nanosecs  */ ;\
-       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */ ;\
-       addl    $(SYSTEM_TIMER),%ecx            /* point to sys timer     */ ;\
-       movl    %eax,%edx                       /* save timestamp in %edx */ ;\
-       subl    TIMER_TSTAMP(%ecx),%eax         /* compute elapsed time   */ ;\
-       TIMER_UPDATE(%ecx,%eax)                 /* update timer struct    */ ;\
-       movl    %gs:CPU_PROCESSOR,%ecx          /* get current processor  */ ;\
-       movl    CURRENT_TIMER(%ecx),%ecx        /* interrupted timer      */ ;\
-       movl    %edx,TIMER_TSTAMP(%ecx)         /* set timestamp          */
+ * Uses %eax,%ebx,%ecx,%edx,%esi,%edi.
+ * Restores processor state info from stack.
+ */
+#define        TIME_INT_EXIT                                                                                                     \
+       NANOTIME                                                        /* edx:eax nanosecs */                  ; \
+       movl    %eax,%gs:CPU_INT_EVENT_TIME             /* save in cpu data */          ; \
+       movl    %edx,%gs:CPU_INT_EVENT_TIME+4   /* save in cpu data */          ; \
+       movl    %eax,%esi                                       /* save timestamp */                    ; \
+       movl    %edx,%edi                                       /* save timestamp */                    ; \
+       movl    %gs:CPU_PROCESSOR,%ebx          /* get current processor */             ; \
+       movl    KERNEL_TIMER(%ebx),%ecx         /* point to kernel timer */             ; \
+       subl    TIMER_TSTAMP(%ecx),%eax         /* compute elapsed time */              ; \
+       sbbl    TIMER_TSTAMP+4(%ecx),%edx       /* compute elapsed time */              ; \
+       TIMER_UPDATE(%ecx,%edx,%eax)            /* update timer */                              ; \
+       movl    THREAD_TIMER(%ebx),%ecx         /* interrupted timer */                 ; \
+       movl    %esi,TIMER_TSTAMP(%ecx)         /* set timestamp */                             ; \
+       movl    %edi,TIMER_TSTAMP+4(%ecx)       /* set timestamp */                             ; \
+       movl    %esi,%eax                                       /* restore timestamp */                 ; \
+       movl    %edi,%edx                                       /* restore timestamp */                 ; \
+       movl    CURRENT_STATE(%ebx),%ecx        /* get current state */                 ; \
+       subl    TIMER_TSTAMP(%ecx),%eax         /* compute elapsed time */              ; \
+       sbbl    TIMER_TSTAMP+4(%ecx),%edx       /* compute elapsed time */              ; \
+       TIMER_UPDATE(%ecx,%edx,%eax)            /* update timer */                              ; \
+       popl    %ecx                                            /* restore state */                             ; \
+       movl    %ecx,CURRENT_STATE(%ebx)        /* set current state */                 ; \
+       movl    %esi,TIMER_TSTAMP(%ecx)         /* set timestamp */                             ; \
+       movl    %edi,TIMER_TSTAMP+4(%ecx)       /* set timestamp */
 
 #endif /* STAT_TIME */
 
@@ -413,7 +465,7 @@ Entry(db_task_gen_prot)
 Entry(db_task_start)
        movl    %esp,%edx
        subl    $(ISS32_SIZE),%edx
-       movl    %edx,%esp               /* allocate i386_saved_state on stack */
+       movl    %edx,%esp               /* allocate x86_saved_state on stack */
        movl    %eax,R_ERR(%esp)
        movl    %ebx,R_TRAPNO(%esp)
        pushl   %edx
@@ -460,10 +512,10 @@ Entry(call_continuation)
        pushl   %eax
        call    EXT(thread_terminate)
        
-
+       
        
 /*******************************************************************************************************
- *     
+ *
  * All 64 bit task 'exceptions' enter lo_alltraps:
  *     esp     -> x86_saved_state_t
  * 
@@ -483,11 +535,26 @@ Entry(lo_alltraps)
        jne     1f
        movl    R64_CS(%esp),%eax       /* 64-bit user mode */
 1:
-       testb   $3,%eax
+       testb   $3,%al
        jz      trap_from_kernel
                                                /* user mode trap */
        TIME_TRAP_UENTRY
 
+       movl    %gs:CPU_ACTIVE_THREAD,%ecx
+       movl    ACT_TASK(%ecx),%ebx
+
+       /* Check for active vtimers in the current task */
+       cmpl    $0,TASK_VTIMERS(%ebx)
+       jz              1f
+
+       /* Set a pending AST */
+       orl             $(AST_BSD),%gs:CPU_PENDING_AST
+
+       /* Set a thread AST (atomic) */
+       lock
+       orl             $(AST_BSD),ACT_AST(%ecx)
+       
+1:
        movl    %gs:CPU_KERNEL_STACK,%ebx
        xchgl   %ebx,%esp                       /* switch to kernel stack */
        sti
@@ -510,6 +577,7 @@ LEXT(return_from_trap)
        sti                             /* interrupts always enabled on return to user mode */
 
        pushl   %ebx                    /* save PCB stack */
+       xorl    %ebp,%ebp               /* Clear framepointer */
        CCALL1(i386_astintr, $0)        /* take the AST */
        cli
        popl    %esp                    /* switch back to PCB stack (w/exc link) */
@@ -524,7 +592,7 @@ LEXT(ret_to_user)
        jmp     EXT(lo64_ret_to_user)
 
 
-       
+
 /*
  * Trap from kernel mode.  No need to switch stacks.
  * Interrupts must be off here - we will set them to state at time of trap
@@ -532,7 +600,12 @@ LEXT(ret_to_user)
  */
 trap_from_kernel:
        movl    %esp, %eax              /* saved state addr */
-       CCALL1(kernel_trap, %eax)       /* to kernel trap routine */
+       pushl   R_EIP(%esp)             /* Simulate a CALL from fault point */
+       pushl   %ebp                    /* Extend framepointer chain */
+       movl    %esp, %ebp
+       CCALL1(kernel_trap, %eax)       /* Call kernel trap handler */
+       popl    %ebp
+       addl    $4, %esp
        cli
 
        movl    %gs:CPU_PENDING_AST,%eax                /* get pending asts */
@@ -597,6 +670,21 @@ Entry(lo_allintrs)
        
        TIME_INT_ENTRY                  /* do timing */
 
+       movl    %gs:CPU_ACTIVE_THREAD,%ecx
+       movl    ACT_TASK(%ecx),%ebx
+
+       /* Check for active vtimers in the current task */
+       cmpl    $0,TASK_VTIMERS(%ebx)
+       jz              1f
+
+       /* Set a pending AST */
+       orl             $(AST_BSD),%gs:CPU_PENDING_AST
+
+       /* Set a thread AST (atomic) */
+       lock
+       orl             $(AST_BSD),ACT_AST(%ecx)
+       
+1:
        incl    %gs:CPU_PREEMPTION_LEVEL
        incl    %gs:CPU_INTERRUPT_LEVEL
 
@@ -607,9 +695,6 @@ Entry(lo_allintrs)
        xorl    %eax,%eax
        movl    %eax,%gs:CPU_INT_STATE  /* clear intr state pointer */
 
-       .globl  EXT(return_to_iret)
-LEXT(return_to_iret)                   /* (label for kdb_kintr and hardclock) */
-
        decl    %gs:CPU_INTERRUPT_LEVEL
        decl    %gs:CPU_PREEMPTION_LEVEL
 
@@ -638,7 +723,7 @@ LEXT(return_to_iret)                        /* (label for kdb_kintr and hardclock) */
        jne     3f
        movl    R64_CS(%esp),%eax       /* 64-bit user mode */
 3:
-       testb   $3,%eax                 /* user mode, */
+       testb   $3,%al                  /* user mode, */
        jnz     ast_from_interrupt_user /* go handle potential ASTs */
        /*
         * we only want to handle preemption requests if
@@ -676,7 +761,7 @@ int_from_intstack:
        incl    %gs:CPU_PREEMPTION_LEVEL
        incl    %gs:CPU_INTERRUPT_LEVEL
 
-       movl    %esp, %edx              /* i386_saved_state */
+       movl    %esp, %edx              /* x86_saved_state */
        CCALL1(PE_incoming_interrupt, %edx)
 
        decl    %gs:CPU_INTERRUPT_LEVEL
@@ -702,7 +787,7 @@ ast_from_interrupt_user:
  * 32bit Tasks
  * System call entries via INTR_GATE or sysenter:
  *
- *     esp      -> i386_saved_state_t
+ *     esp      -> x86_saved_state32_t
  *     cr3      -> kernel directory
  *     esp      -> low based stack
  *     gs       -> CPU_DATA_GS
@@ -724,42 +809,83 @@ Entry(lo_sysenter)
                                                /* > 0 => unix */
        
 Entry(lo_unix_scall)
-        TIME_TRAP_UENTRY
+       TIME_TRAP_UENTRY
+
+       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
+       movl    ACT_TASK(%ecx),%ebx                     /* point to current task  */
+       addl    $1,TASK_SYSCALLS_UNIX(%ebx)     /* increment call count   */
+
+       /* Check for active vtimers in the current task */
+       cmpl    $0,TASK_VTIMERS(%ebx)
+       jz              1f
+
+       /* Set a pending AST */
+       orl             $(AST_BSD),%gs:CPU_PENDING_AST
 
+       /* Set a thread AST (atomic) */
+       lock
+       orl             $(AST_BSD),ACT_AST(%ecx)
+       
+1:
        movl    %gs:CPU_KERNEL_STACK,%ebx
        xchgl   %ebx,%esp               /* switch to kernel stack */
 
        sti
-       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
-       movl    ACT_TASK(%ecx),%ecx             /* point to current task  */
-       addl    $1,TASK_SYSCALLS_UNIX(%ecx)     /* increment call count   */
 
        CCALL1(unix_syscall, %ebx)
        /*
         * always returns through thread_exception_return
         */
-       
+
 
 Entry(lo_mach_scall)
        TIME_TRAP_UENTRY
 
+       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
+       movl    ACT_TASK(%ecx),%ebx                     /* point to current task  */
+       addl    $1,TASK_SYSCALLS_MACH(%ebx)     /* increment call count   */
+
+       /* Check for active vtimers in the current task */
+       cmpl    $0,TASK_VTIMERS(%ebx)
+       jz              1f
+
+       /* Set a pending AST */
+       orl             $(AST_BSD),%gs:CPU_PENDING_AST
+
+       /* Set a thread AST (atomic) */
+       lock
+       orl             $(AST_BSD),ACT_AST(%ecx)
+       
+1:
        movl    %gs:CPU_KERNEL_STACK,%ebx
        xchgl   %ebx,%esp               /* switch to kernel stack */
 
        sti
-       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
-       movl    ACT_TASK(%ecx),%ecx             /* point to current task  */
-       addl    $1,TASK_SYSCALLS_MACH(%ecx)     /* increment call count   */
 
        CCALL1(mach_call_munger, %ebx)
        /*
         * always returns through thread_exception_return
         */
 
-       
+
 Entry(lo_mdep_scall)
-        TIME_TRAP_UENTRY
+       TIME_TRAP_UENTRY
 
+       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
+       movl    ACT_TASK(%ecx),%ebx                     /* point to current task  */
+
+       /* Check for active vtimers in the current task */
+       cmpl    $0,TASK_VTIMERS(%ebx)
+       jz              1f
+
+       /* Set a pending AST */
+       orl             $(AST_BSD),%gs:CPU_PENDING_AST
+
+       /* Set a thread AST (atomic) */
+       lock
+       orl             $(AST_BSD),ACT_AST(%ecx)
+       
+1:
        movl    %gs:CPU_KERNEL_STACK,%ebx
        xchgl   %ebx,%esp               /* switch to kernel stack */
 
@@ -769,21 +895,37 @@ Entry(lo_mdep_scall)
        /*
         * always returns through thread_exception_return
         */
-       
+
 
 Entry(lo_diag_scall)
        TIME_TRAP_UENTRY
 
+       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
+       movl    ACT_TASK(%ecx),%ebx                     /* point to current task  */
+
+       /* Check for active vtimers in the current task */
+       cmpl    $0,TASK_VTIMERS(%ebx)
+       jz              1f
+
+       /* Set a pending AST */
+       orl             $(AST_BSD),%gs:CPU_PENDING_AST
+
+       /* Set a thread AST (atomic) */
+       lock
+       orl             $(AST_BSD),ACT_AST(%ecx)
+       
+1:
        movl    %gs:CPU_KERNEL_STACK,%ebx       // Get the address of the kernel stack
        xchgl   %ebx,%esp               // Switch to it, saving the previous
 
        CCALL1(diagCall, %ebx)          // Call diagnostics
-       cli                             // Disable interruptions just in case they were enabled
-       popl    %esp                    // Get back the original stack
        
        cmpl    $0,%eax                 // What kind of return is this?
-       jne     EXT(return_to_user)     // Normal return, do not check asts...
-                               
+       je      2f
+       cli                             // Disable interruptions just in case they were enabled
+       popl    %esp                    // Get back the original stack
+       jmp     EXT(return_to_user)     // Normal return, do not check asts...
+2:     
        CCALL3(i386_exception, $EXC_SYSCALL, $0x6000, $1)
                // pass what would be the diag syscall
                // error return - cause an exception
@@ -824,47 +966,94 @@ Entry(lo_syscall)
        cmpl    $(SYSCALL_CLASS_DIAG<<SYSCALL_CLASS_SHIFT), %ebx
        je      EXT(lo64_diag_scall)
 
+       movl    %gs:CPU_KERNEL_STACK,%ebx
+       xchgl   %ebx,%esp               /* switch to kernel stack */
+
+       sti
+
        /* Syscall class unknown */
        CCALL3(i386_exception, $(EXC_SYSCALL), %eax, $1)
        /* no return */
 
+
 Entry(lo64_unix_scall)
-        TIME_TRAP_UENTRY
+       TIME_TRAP_UENTRY
+
+       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
+       movl    ACT_TASK(%ecx),%ebx                     /* point to current task  */
+       addl    $1,TASK_SYSCALLS_UNIX(%ebx)     /* increment call count   */
 
+       /* Check for active vtimers in the current task */
+       cmpl    $0,TASK_VTIMERS(%ebx)
+       jz              1f
+
+       /* Set a pending AST */
+       orl             $(AST_BSD),%gs:CPU_PENDING_AST
+
+       /* Set a thread AST (atomic) */
+       lock
+       orl             $(AST_BSD),ACT_AST(%ecx)
+       
+1:
        movl    %gs:CPU_KERNEL_STACK,%ebx
        xchgl   %ebx,%esp               /* switch to kernel stack */
 
        sti
-       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
-       movl    ACT_TASK(%ecx),%ecx             /* point to current task  */
-       addl    $1,TASK_SYSCALLS_UNIX(%ecx)     /* increment call count   */
 
        CCALL1(unix_syscall64, %ebx)
        /*
         * always returns through thread_exception_return
         */
-       
+
 
 Entry(lo64_mach_scall)
        TIME_TRAP_UENTRY
 
+       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
+       movl    ACT_TASK(%ecx),%ebx                     /* point to current task  */
+       addl    $1,TASK_SYSCALLS_MACH(%ebx)     /* increment call count   */
+
+       /* Check for active vtimers in the current task */
+       cmpl    $0,TASK_VTIMERS(%ebx)
+       jz              1f
+
+       /* Set a pending AST */
+       orl             $(AST_BSD),%gs:CPU_PENDING_AST
+
+       lock
+       orl             $(AST_BSD),ACT_AST(%ecx)
+       
+1:
        movl    %gs:CPU_KERNEL_STACK,%ebx
        xchgl   %ebx,%esp               /* switch to kernel stack */
 
        sti
-       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
-       movl    ACT_TASK(%ecx),%ecx             /* point to current task  */
-       addl    $1,TASK_SYSCALLS_MACH(%ecx)     /* increment call count   */
 
        CCALL1(mach_call_munger64, %ebx)
        /*
         * always returns through thread_exception_return
         */
 
-       
+
+
 Entry(lo64_mdep_scall)
-        TIME_TRAP_UENTRY
+       TIME_TRAP_UENTRY
+
+       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
+       movl    ACT_TASK(%ecx),%ebx                     /* point to current task  */
 
+       /* Check for active vtimers in the current task */
+       cmpl    $0,TASK_VTIMERS(%ebx)
+       jz              1f
+
+       /* Set a pending AST */
+       orl             $(AST_BSD),%gs:CPU_PENDING_AST
+
+       /* Set a thread AST (atomic) */
+       lock
+       orl             $(AST_BSD),ACT_AST(%ecx)
+       
+1:
        movl    %gs:CPU_KERNEL_STACK,%ebx
        xchgl   %ebx,%esp               /* switch to kernel stack */
 
@@ -874,29 +1063,42 @@ Entry(lo64_mdep_scall)
        /*
         * always returns through thread_exception_return
         */
-       
+
 
 Entry(lo64_diag_scall)
        TIME_TRAP_UENTRY
 
-       movl    %gs:CPU_KERNEL_STACK,%ebx       // Get the address of the kernel stack
-       xchgl   %ebx,%esp               // Switch to it, saving the previous
+       movl    %gs:CPU_ACTIVE_THREAD,%ecx      /* get current thread     */
+       movl    ACT_TASK(%ecx),%ebx                     /* point to current task  */
+
+       /* Check for active vtimers in the current task */
+       cmpl    $0,TASK_VTIMERS(%ebx)
+       jz              1f
+
+       /* Set a pending AST */
+       orl             $(AST_BSD),%gs:CPU_PENDING_AST
+
+       /* Set a thread AST (atomic) */
+       lock
+       orl             $(AST_BSD),ACT_AST(%ecx)
        
-       pushl   %ebx                    // Push the previous stack
+1:
+       movl    %gs:CPU_KERNEL_STACK,%ebx // Get the address of the kernel stack
+       xchgl   %ebx,%esp               // Switch to it, saving the previous
+
        CCALL1(diagCall64, %ebx)        // Call diagnostics
+               
+       cmpl    $0,%eax                 // What kind of return is this?
+       je      2f
        cli                             // Disable interruptions just in case they were enabled
        popl    %esp                    // Get back the original stack
-       
-       cmpl    $0,%eax                 // What kind of return is this?
-       jne     EXT(return_to_user)     // Normal return, do not check asts...
-                               
+       jmp     EXT(return_to_user)     // Normal return, do not check asts...
+2:     
        CCALL3(i386_exception, $EXC_SYSCALL, $0x6000, $1)
+               // pass what would be the diag syscall
+               // error return - cause an exception
        /* no return */
-       
 
-                       
-/******************************************************************************************************
-                       
 /*\f*/
 /*
  * Utility routines.
@@ -909,20 +1111,20 @@ Entry(lo64_diag_scall)
  * arg1:       kernel address
  * arg2:       byte count
  */
-ENTRY(copyinphys_user)
+Entry(copyinphys_user)
        movl    $(USER_WINDOW_SEL),%ecx /* user data segment access through kernel window */
        mov     %cx,%ds
 
-ENTRY(copyinphys_kern)
+Entry(copyinphys_kern)
        movl    $(PHYS_WINDOW_SEL),%ecx /* physical access through kernel window */
        mov     %cx,%es
        jmp     copyin_common
 
-ENTRY(copyin_user)
+Entry(copyin_user)
        movl    $(USER_WINDOW_SEL),%ecx /* user data segment access through kernel window */
        mov     %cx,%ds
 
-ENTRY(copyin_kern)
+Entry(copyin_kern)
 
 copyin_common:
        pushl   %esi
@@ -1074,7 +1276,6 @@ copyout_fail:
        movl    $(EFAULT),%eax          /* return error for failure */
        jmp     copyout_ret             /* pop frame and return */
 
-
 /*
  * io register must not be used on slaves (no AT bus)
  */
@@ -1357,70 +1558,6 @@ rdmsr_fail:
        RECOVERY_SECTION
        RECOVER_TABLE_END
 
-
-
-ENTRY(dr6)
-       movl    %db6, %eax
-       ret
-
-/*     dr<i>(address, type, len, persistence)
- */
-ENTRY(dr0)
-       movl    S_ARG0, %eax
-       movl    %eax,EXT(dr_addr)
-       movl    %eax, %db0
-       movl    $0, %ecx
-       jmp     0f
-ENTRY(dr1)
-       movl    S_ARG0, %eax
-       movl    %eax,EXT(dr_addr)+1*4
-       movl    %eax, %db1
-       movl    $2, %ecx
-       jmp     0f
-ENTRY(dr2)
-       movl    S_ARG0, %eax
-       movl    %eax,EXT(dr_addr)+2*4
-       movl    %eax, %db2
-       movl    $4, %ecx
-       jmp     0f
-
-ENTRY(dr3)
-       movl    S_ARG0, %eax
-       movl    %eax,EXT(dr_addr)+3*4
-       movl    %eax, %db3
-       movl    $6, %ecx
-
-0:
-       pushl   %ebp
-       movl    %esp, %ebp
-
-       movl    %db7, %edx
-       movl    %edx,EXT(dr_addr)+4*4
-       andl    dr_msk(,%ecx,2),%edx    /* clear out new entry */
-       movl    %edx,EXT(dr_addr)+5*4
-       movzbl  B_ARG3, %eax
-       andb    $3, %al
-       shll    %cl, %eax
-       orl     %eax, %edx
-
-       movzbl  B_ARG1, %eax
-       andb    $3, %al
-       addb    $0x10, %cl
-       shll    %cl, %eax
-       orl     %eax, %edx
-
-       movzbl  B_ARG2, %eax
-       andb    $3, %al
-       addb    $0x2, %cl
-       shll    %cl, %eax
-       orl     %eax, %edx
-
-       movl    %edx, %db7
-       movl    %edx,EXT(dr_addr)+7*4
-       movl    %edx, %eax
-       leave
-       ret
-
        .data
 dr_msk:
        .long   ~0x000f0003
@@ -1433,15 +1570,6 @@ ENTRY(dr_addr)
 
        .text
 
-ENTRY(get_cr0)
-       movl    %cr0, %eax
-       ret
-
-ENTRY(set_cr0)
-       movl    4(%esp), %eax
-       movl    %eax, %cr0
-       ret
-
 #ifndef        SYMMETRY
 
 /*