Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef __SPARC64_SWITCH_TO_64_H
0003 #define __SPARC64_SWITCH_TO_64_H
0004 
0005 #include <asm/visasm.h>
0006 
0007 #define prepare_arch_switch(next)       \
0008 do {                        \
0009     flushw_all();               \
0010 } while (0)
0011 
0012     /* See what happens when you design the chip correctly?
0013      *
0014      * We tell gcc we clobber all non-fixed-usage registers except
0015      * for l0/l1.  It will use one for 'next' and the other to hold
0016      * the output value of 'last'.  'next' is not referenced again
0017      * past the invocation of switch_to in the scheduler, so we need
0018      * not preserve it's value.  Hairy, but it lets us remove 2 loads
0019      * and 2 stores in this critical code path.  -DaveM
0020      */
0021 #define switch_to(prev, next, last)                 \
0022 do {    save_and_clear_fpu();                       \
0023     __asm__ __volatile__("wr %%g0, %0, %%asi"           \
0024     : : "r" (ASI_AIUS));                        \
0025     trap_block[current_thread_info()->cpu].thread =         \
0026         task_thread_info(next);                 \
0027     __asm__ __volatile__(                       \
0028     "mov    %%g4, %%g7\n\t"                     \
0029     "stx    %%i6, [%%sp + 2047 + 0x70]\n\t"             \
0030     "stx    %%i7, [%%sp + 2047 + 0x78]\n\t"             \
0031     "rdpr   %%wstate, %%o5\n\t"                 \
0032     "stx    %%o6, [%%g6 + %6]\n\t"                  \
0033     "stb    %%o5, [%%g6 + %5]\n\t"                  \
0034     "rdpr   %%cwp, %%o5\n\t"                    \
0035     "stb    %%o5, [%%g6 + %8]\n\t"                  \
0036     "wrpr   %%g0, 15, %%pil\n\t"                    \
0037     "mov    %4, %%g6\n\t"                       \
0038     "ldub   [%4 + %8], %%g1\n\t"                    \
0039     "wrpr   %%g1, %%cwp\n\t"                    \
0040     "ldx    [%%g6 + %6], %%o6\n\t"                  \
0041     "ldub   [%%g6 + %5], %%o5\n\t"                  \
0042     "ldub   [%%g6 + %7], %%o7\n\t"                  \
0043     "wrpr   %%o5, 0x0, %%wstate\n\t"                \
0044     "ldx    [%%sp + 2047 + 0x70], %%i6\n\t"             \
0045     "ldx    [%%sp + 2047 + 0x78], %%i7\n\t"             \
0046     "ldx    [%%g6 + %9], %%g4\n\t"                  \
0047     "wrpr   %%g0, 14, %%pil\n\t"                    \
0048     "brz,pt %%o7, switch_to_pc\n\t"                 \
0049     " mov   %%g7, %0\n\t"                       \
0050     "sethi  %%hi(ret_from_fork), %%g1\n\t"              \
0051     "jmpl   %%g1 + %%lo(ret_from_fork), %%g0\n\t"           \
0052     " nop\n\t"                          \
0053     ".globl switch_to_pc\n\t"                   \
0054     "switch_to_pc:\n\t"                     \
0055     : "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \
0056       "=r" (__local_per_cpu_offset)                 \
0057     : "0" (task_thread_info(next)),                 \
0058       "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD),            \
0059       "i" (TI_CWP), "i" (TI_TASK)                   \
0060     : "cc",                             \
0061             "g1", "g2", "g3",                   "g7",       \
0062             "l1", "l2", "l3", "l4", "l5", "l6", "l7",       \
0063       "i0", "i1", "i2", "i3", "i4", "i5",               \
0064       "o0", "o1", "o2", "o3", "o4", "o5",       "o7");      \
0065 } while(0)
0066 
0067 void synchronize_user_stack(void);
0068 struct pt_regs;
0069 void fault_in_user_windows(struct pt_regs *);
0070 
0071 #endif /* __SPARC64_SWITCH_TO_64_H */