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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
#include "cpustate.h"
.globl sparc64_of_client_interface, client_tba
/*
* SAVE_WINDOW_STATE and RESTORE_WINDOW_STATE are used to ensure
* that the CPU window state is preserved across CIF calls. This is
* to workaround a *BSD restriction that window fill/spill traps must
* be minimised during trap table takeover, and likely emulates the
* behaviour of OBP.
*/
.data
.align 8
client_context:
.xword 0
client_stack:
.xword 0
client_window:
.skip 2048
.text
.align 4
.register %g2, #scratch
.register %g3, #scratch
.register %g6, #scratch
.register %g7, #scratch
/*
make some more space on stack since linux kernel only provides 128 bytes
without memory to spill registers (used by gcc in -O0 mode)
*/
sparc64_of_client_interface:
/* Save globals on callers stack */
stx %g1, [%sp + 2047 - 248 + 192]
stx %g2, [%sp + 2047 - 248 + 200]
stx %g3, [%sp + 2047 - 248 + 208]
stx %g4, [%sp + 2047 - 248 + 216]
stx %g5, [%sp + 2047 - 248 + 224]
stx %g6, [%sp + 2047 - 248 + 232]
stx %g7, [%sp + 2047 - 248 + 240]
/* Save existing stack */
setx client_stack, %g6, %g7
stx %sp, [%g7]
/* Save windows */
setx _fcstack_ptr, %g6, %g7
ldx [%g7], %g1
add %g1, -CONTEXT_STATE_SIZE, %g1
stx %g1, [%g7]
/* Save globals */
ldx [%sp + 2047 - 248 + 192], %g7
stx %g7, [%g1 + 0x30]
ldx [%sp + 2047 - 248 + 200], %g7
stx %g7, [%g1 + 0x38]
ldx [%sp + 2047 - 248 + 208], %g7
stx %g7, [%g1 + 0x40]
ldx [%sp + 2047 - 248 + 216], %g7
stx %g7, [%g1 + 0x48]
ldx [%sp + 2047 - 248 + 224], %g7
stx %g7, [%g1 + 0x50]
ldx [%sp + 2047 - 248 + 232], %g7
stx %g7, [%g1 + 0x58]
ldx [%sp + 2047 - 248 + 240], %g7
stx %g7, [%g1 + 0x60]
/* Save %pc */
mov %o7, %g7
add %g7, 8, %g7
stx %g7, [%g1 + 0x4d0]
SAVE_CPU_STATE(cif)
RESET_CPU_WINDOW_STATE(cif)
/* Update __context to point to saved area */
setx __context, %g6, %g7
ldx [%g7], %g3
setx client_context, %g4, %g5
stx %g3, [%g5]
stx %g1, [%g7]
/* Move to OpenBIOS context stack */
setx _fcstack_ptr, %g6, %g7
ldx [%g7], %g6
setx CONTEXT_STACK_SIZE, %g4, %g5
sub %g6, %g5, %g6
stx %g6, [%g7]
setx - 2047 - 192, %g6, %g7
add %g1, %g7, %g7
mov %g7, %sp
/* Call client inteface */
call of_client_interface
ldx [%g1 + 0x70], %o0
/* Restore windows */
setx _fcstack_ptr, %g6, %g7
ldx [%g7], %g1
setx CONTEXT_STACK_SIZE, %g4, %g5
add %g1, %g5, %g1
stx %g1, [%g7]
/* Return value */
stx %o0, [%g1 + 0x70]
/* Restore __context */
setx client_context, %g4, %g5
ldx [%g5], %g3
setx __context, %g6, %g7
stx %g3, [%g7]
RESTORE_CPU_STATE(cif)
add %g1, CONTEXT_STATE_SIZE, %g5
setx _fcstack_ptr, %g6, %g7
stx %g5, [%g7]
/* Restore stack */
setx client_stack, %g6, %g7
ldx [%g7], %sp
/* Restore %pc */
ldx [%g1 + 0x4d0], %o7
/* Restore globals */
ldx [%g1 + 0x38], %g2
ldx [%g1 + 0x40], %g3
ldx [%g1 + 0x48], %g4
ldx [%g1 + 0x50], %g5
ldx [%g1 + 0x58], %g6
ldx [%g1 + 0x60], %g7
jmp %o7
ldx [%g1 + 0x30], %g1
|