]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/x86_64/cswitch.s
xnu-6153.11.26.tar.gz
[apple/xnu.git] / osfmk / x86_64 / cswitch.s
index 6abb9a22c25e2e9121ec663ed4718da382cdf4b2..e09e1e1793906686bf94078317b582f2ed1a66bd 100644 (file)
 /*
  */
 
-#include <platforms.h>
 
 #include <i386/asm.h>
 #include <i386/proc_reg.h>
 #include <assym.s>
 
-#ifdef SYMMETRY
-#include <sqt/asm_macros.h>
-#endif
+/*
+ * void Load_context(
+ *                   thread_t thread)    // %rdi
+ *
+ * Loads the first thread context to run on a CPU,
+ * i.e. without switching from a previous thread.
+ *
+ * returns 'old' thread in %rax (which is always NULL)
+ */
+Entry(Load_context)
+       movq    %rdi, %rdx                      /* move thread arg to rdx */
 
-#if    AT386
-#include <i386/mp.h>
-#endif /* AT386 */
+       movq    %rdx,%gs:CPU_ACTIVE_THREAD      /* new thread is active */
+       movq    TH_KERNEL_STACK(%rdx),%rdx      /* get its kernel stack */
+       lea     -IKS_SIZE(%rdx),%rcx
+       add     EXT(kernel_stack_size)(%rip),%rcx /* point to stack top */
 
-Entry(Load_context)
-       movq    TH_KERNEL_STACK(%rdi),%rcx      /* get kernel stack */
-       leaq    -IKS_SIZE-IEL_SIZE(%rcx),%rdx
-       addq    EXT(kernel_stack_size)(%rip),%rdx /* point to stack top */
-       movq    %rcx,%gs:CPU_ACTIVE_STACK       /* store stack address */
-       movq    %rdx,%gs:CPU_KERNEL_STACK       /* store stack top */
+       movq    %rdx,%gs:CPU_ACTIVE_STACK       /* set current stack */
+       movq    %rcx,%gs:CPU_KERNEL_STACK       /* set stack top */
 
-       movq    %rdx,%rsp
-       movq    %rdx,%rbp
+       movq    KSS_RSP(%rcx),%rsp              /* switch stacks */
+       movq    KSS_RBX(%rcx),%rbx              /* restore registers */
+       movq    KSS_RBP(%rcx),%rbp
+       movq    KSS_R12(%rcx),%r12
+       movq    KSS_R13(%rcx),%r13
+       movq    KSS_R14(%rcx),%r14
+       movq    KSS_R15(%rcx),%r15
 
-       xorq    %rdi,%rdi                       /* return zero (no old thread) */
-       call    EXT(thread_continue)
+       xorl    %eax, %eax                      /* set return value to zero (no old thread) */
 
+       jmp    *KSS_RIP(%rcx)                   /* return old thread */
 
 /*
  * thread_t Switch_context(
- *             thread_t old,                           // %rsi
- *             thread_continue_t continuation,         // %rdi
+ *             thread_t old,                           // %rdi
+ *             thread_continue_t continuation,         // %rsi
  *             thread_t new)                           // %rdx
+ *
+ * returns 'old' thread in %rax
  */
 Entry(Switch_context)
        popq    %rax                            /* pop return PC */
@@ -110,7 +121,7 @@ Entry(Switch_context)
        /* new thread in %rdx */
        movq    %rdx,%gs:CPU_ACTIVE_THREAD      /* new thread is active */
        movq    TH_KERNEL_STACK(%rdx),%rdx      /* get its kernel stack */
-       lea     -IKS_SIZE-IEL_SIZE(%rdx),%rcx
+       lea     -IKS_SIZE(%rdx),%rcx
        add     EXT(kernel_stack_size)(%rip),%rcx /* point to stack top */
 
        movq    %rdx,%gs:CPU_ACTIVE_STACK       /* set current stack */
@@ -123,14 +134,21 @@ Entry(Switch_context)
        movq    KSS_R13(%rcx),%r13
        movq    KSS_R14(%rcx),%r14
        movq    KSS_R15(%rcx),%r15
-       jmp     *KSS_RIP(%rcx)                  /* return old thread */
-
+       jmp     *KSS_RIP(%rcx)                  /* return old thread in %rax */
 
+/*
+ * machine_stack_attach sets this as the RIP of newly-attached stacks
+ * %rbx is the C routine to call
+ * %rax is the parameter to pass to the C routine
+ *
+ * This stub is needed to convert the return value of the old thread from Switch_context
+ * in %rax into a parameter to thread_continue passed in %rdi, because using the
+ * same register for the first argument and first retval makes too much sense for the SysV ABI.
+ */
 Entry(Thread_continue)
-       movq    %rax, %rdi                      /* load thread argument */
-       xorq    %rbp,%rbp                       /* zero frame pointer */
+       movq    %rax, %rdi                      /* this is the old thread from Switch_context */
        call    *%rbx                           /* call real continuation */
-
+       int3                                    /* (should never return) */
 
 /*
  * thread_t Shutdown_context(
@@ -140,9 +158,7 @@ Entry(Thread_continue)
  *
  * saves the kernel context of the thread,
  * switches to the interrupt stack,
- * continues the thread (with thread_continue),
  * then runs routine on the interrupt stack.
- *
  */
 Entry(Shutdown_context)
        movq    %gs:CPU_KERNEL_STACK,%rcx       /* get old kernel stack top */
@@ -152,7 +168,8 @@ Entry(Shutdown_context)
        movq    %r13,KSS_R13(%rcx)
        movq    %r14,KSS_R14(%rcx)
        movq    %r15,KSS_R15(%rcx)
-       popq    KSS_RIP(%rcx)                   /* save return PC */
+       popq    %r8                             /* extract return PC */
+       movq    %r8,KSS_RIP(%rcx)               /* save return PC */
        movq    %rsp,KSS_RSP(%rcx)              /* save SP */
 
        movq    %gs:CPU_ACTIVE_STACK,%rcx       /* get old kernel stack */
@@ -161,7 +178,15 @@ Entry(Shutdown_context)
 
        movq    %gs:CPU_INT_STACK_TOP,%rsp      /* switch to interrupt stack */
 
+       movq    %rsp, %gs:CPU_ACTIVE_STACK
+       movq    EXT(kernel_stack_size)(%rip),%rcx /* point to stack top */
+       subq    %rcx, %gs:CPU_ACTIVE_STACK
+
+       pushq   %r8                             /* set up a call frame on new stack */
+       pushq   %rbp
+       movq    %rsp, %rbp
+
        movq    %rdx,%rdi                       /* processor arg to routine */
        call    *%rsi                           /* call routine to run */
-       hlt                                     /* (should never return) */
+       int3                                    /* (should never return) */