]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
d550bbd4 DH |
2 | #ifndef __SPARC_SWITCH_TO_H |
3 | #define __SPARC_SWITCH_TO_H | |
4 | ||
5 | #include <asm/smp.h> | |
6 | ||
7 | extern struct thread_info *current_set[NR_CPUS]; | |
8 | ||
9 | /* | |
10 | * Flush windows so that the VM switch which follows | |
11 | * would not pull the stack from under us. | |
12 | * | |
08a7e621 | 13 | * SWITCH_ENTER and SWITCH_DO_LAZY_FPU do not work yet (e.g. SMP does not work) |
d550bbd4 DH |
14 | * XXX WTF is the above comment? Found in late teen 2.4.x. |
15 | */ | |
16 | #ifdef CONFIG_SMP | |
17 | #define SWITCH_ENTER(prv) \ | |
18 | do { \ | |
19 | if (test_tsk_thread_flag(prv, TIF_USEDFPU)) { \ | |
20 | put_psr(get_psr() | PSR_EF); \ | |
21 | fpsave(&(prv)->thread.float_regs[0], &(prv)->thread.fsr, \ | |
22 | &(prv)->thread.fpqueue[0], &(prv)->thread.fpqdepth); \ | |
23 | clear_tsk_thread_flag(prv, TIF_USEDFPU); \ | |
24 | (prv)->thread.kregs->psr &= ~PSR_EF; \ | |
25 | } \ | |
26 | } while(0) | |
27 | ||
28 | #define SWITCH_DO_LAZY_FPU(next) /* */ | |
29 | #else | |
30 | #define SWITCH_ENTER(prv) /* */ | |
31 | #define SWITCH_DO_LAZY_FPU(nxt) \ | |
32 | do { \ | |
33 | if (last_task_used_math != (nxt)) \ | |
34 | (nxt)->thread.kregs->psr&=~PSR_EF; \ | |
35 | } while(0) | |
36 | #endif | |
37 | ||
38 | #define prepare_arch_switch(next) do { \ | |
39 | __asm__ __volatile__( \ | |
40 | ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \ | |
41 | "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \ | |
42 | "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \ | |
43 | "save %sp, -0x40, %sp\n\t" \ | |
44 | "restore; restore; restore; restore; restore; restore; restore"); \ | |
45 | } while(0) | |
46 | ||
47 | /* Much care has gone into this code, do not touch it. | |
48 | * | |
49 | * We need to loadup regs l0/l1 for the newly forked child | |
50 | * case because the trap return path relies on those registers | |
51 | * holding certain values, gcc is told that they are clobbered. | |
52 | * Gcc needs registers for 3 values in and 1 value out, so we | |
53 | * clobber every non-fixed-usage register besides l2/l3/o4/o5. -DaveM | |
54 | * | |
55 | * Hey Dave, that do not touch sign is too much of an incentive | |
56 | * - Anton & Pete | |
57 | */ | |
58 | #define switch_to(prev, next, last) do { \ | |
59 | SWITCH_ENTER(prev); \ | |
60 | SWITCH_DO_LAZY_FPU(next); \ | |
61 | cpumask_set_cpu(smp_processor_id(), mm_cpumask(next->active_mm)); \ | |
62 | __asm__ __volatile__( \ | |
63 | "sethi %%hi(here - 0x8), %%o7\n\t" \ | |
64 | "mov %%g6, %%g3\n\t" \ | |
65 | "or %%o7, %%lo(here - 0x8), %%o7\n\t" \ | |
66 | "rd %%psr, %%g4\n\t" \ | |
67 | "std %%sp, [%%g6 + %4]\n\t" \ | |
68 | "rd %%wim, %%g5\n\t" \ | |
69 | "wr %%g4, 0x20, %%psr\n\t" \ | |
70 | "nop\n\t" \ | |
71 | "std %%g4, [%%g6 + %3]\n\t" \ | |
72 | "ldd [%2 + %3], %%g4\n\t" \ | |
73 | "mov %2, %%g6\n\t" \ | |
74 | ".globl patchme_store_new_current\n" \ | |
75 | "patchme_store_new_current:\n\t" \ | |
76 | "st %2, [%1]\n\t" \ | |
77 | "wr %%g4, 0x20, %%psr\n\t" \ | |
78 | "nop\n\t" \ | |
79 | "nop\n\t" \ | |
80 | "nop\n\t" /* LEON needs all 3 nops: load to %sp depends on CWP. */ \ | |
81 | "ldd [%%g6 + %4], %%sp\n\t" \ | |
82 | "wr %%g5, 0x0, %%wim\n\t" \ | |
83 | "ldd [%%sp + 0x00], %%l0\n\t" \ | |
84 | "ldd [%%sp + 0x38], %%i6\n\t" \ | |
85 | "wr %%g4, 0x0, %%psr\n\t" \ | |
86 | "nop\n\t" \ | |
87 | "nop\n\t" \ | |
88 | "jmpl %%o7 + 0x8, %%g0\n\t" \ | |
89 | " ld [%%g3 + %5], %0\n\t" \ | |
90 | "here:\n" \ | |
91 | : "=&r" (last) \ | |
92 | : "r" (&(current_set[hard_smp_processor_id()])), \ | |
93 | "r" (task_thread_info(next)), \ | |
94 | "i" (TI_KPSR), \ | |
95 | "i" (TI_KSP), \ | |
96 | "i" (TI_TASK) \ | |
97 | : "g1", "g2", "g3", "g4", "g5", "g7", \ | |
98 | "l0", "l1", "l3", "l4", "l5", "l6", "l7", \ | |
99 | "i0", "i1", "i2", "i3", "i4", "i5", \ | |
100 | "o0", "o1", "o2", "o3", "o7"); \ | |
101 | } while(0) | |
102 | ||
f05a6865 SR |
103 | void fpsave(unsigned long *fpregs, unsigned long *fsr, |
104 | void *fpqueue, unsigned long *fpqdepth); | |
105 | void synchronize_user_stack(void); | |
d550bbd4 DH |
106 | |
107 | #endif /* __SPARC_SWITCH_TO_H */ |