1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#include "pstate.h"
#include <asm/asi.h>
#define ASI_BP ASI_M_BYPASS
#define REGWIN_SZ 0x40
.globl __switch_context, __switch_context_nosave, __exit_context, halt
.text
.align 4
.register %g2, #scratch
.register %g3, #scratch
.register %g6, #scratch
.register %g7, #scratch
/*
* Switch execution context
* This saves registers in the stack, then
* switches the stack, and restores everything from the new stack.
* This function takes no argument. New stack pointer is
* taken from global variable __context, and old stack pointer
* is also saved to __context. This way we can just jump to
* this routine to get back to the original context.
*/
/* XXX: totally bogus for sparc, need to save and restore all windows */
__switch_context:
/* make sure caller's windows are on caller's stack */
flushw;
/* Save everything in current stack */
setx __context, %g2, %g1
stx %g3, [%g1 + 24]
stx %g4, [%g1 + 32]
stx %g5, [%g1 + 40]
stx %g6, [%g1 + 48]
stx %g7, [%g1 + 56]
stx %o0, [%g1 + 64]
stx %o1, [%g1 + 72]
stx %o2, [%g1 + 80]
stx %o3, [%g1 + 88]
stx %o4, [%g1 + 96]
stx %o5, [%g1 + 104]
stx %o6, [%g1 + 112]
stx %o7, [%g1 + 120]
stx %l0, [%g1 + 128]
stx %l1, [%g1 + 136]
stx %l2, [%g1 + 144]
stx %l3, [%g1 + 152]
stx %l4, [%g1 + 160]
stx %l5, [%g1 + 168]
stx %l6, [%g1 + 176]
stx %l7, [%g1 + 184]
stx %i0, [%g1 + 192]
stx %i1, [%g1 + 200]
stx %i2, [%g1 + 208]
stx %i3, [%g1 + 216]
stx %i4, [%g1 + 224]
stx %i5, [%g1 + 232]
stx %i6, [%g1 + 240]
stx %i7, [%g1 + 248]
__switch_context_nosave:
/* Interrupts are not allowed... */
/* make sure caller's windows are on caller's stack */
flushw
/* Load all registers
*/
setx __context, %g2, %g1
ldx [%g1], %g1
ldx [%g1 + 16], %g2
ldx [%g1 + 24], %g3
ldx [%g1 + 32], %g4
ldx [%g1 + 40], %g5
ldx [%g1 + 48], %g6
ldx [%g1 + 56], %g7
ldx [%g1 + 64], %o0
ldx [%g1 + 72], %o1
ldx [%g1 + 80], %o2
ldx [%g1 + 88], %o3
ldx [%g1 + 96], %o4
ldx [%g1 + 104], %o5
ldx [%g1 + 112], %o6
ldx [%g1 + 120], %o7
ldx [%g1 + 128], %l0
ldx [%g1 + 136], %l1
ldx [%g1 + 144], %l2
ldx [%g1 + 152], %l3
ldx [%g1 + 160], %l4
ldx [%g1 + 168], %l5
ldx [%g1 + 176], %l6
ldx [%g1 + 184], %l7
ldx [%g1 + 192], %i0
ldx [%g1 + 200], %i1
ldx [%g1 + 208], %i2
ldx [%g1 + 216], %i3
ldx [%g1 + 224], %i4
ldx [%g1 + 232], %i5
ldx [%g1 + 240], %i6
ldx [%g1 + 248], %i7
ldx [%g1 + 256], %g1
/* Finally, load new %pc */
jmp %g1
clr %g1
__exit_context:
/* Get back to the original context */
call __switch_context
nop
/* We get here if the other context attempt to switch to this
* dead context. This should not happen. */
halt:
b halt
nop
|