|
|
1.1 root 1: #include "psr.h"
2: #include "asm/asi.h"
3: #define ASI_BP ASI_M_BYPASS
4: #define REGWIN_SZ 0x40
5:
6: .globl __switch_context, __switch_context_nosave, __exit_context, halt
7:
8: .text
9: .align 4
10:
11: #define STACKFRAME_SZ 0x60
12:
13: /* These are just handy. */
14: #define _SV save %sp, -STACKFRAME_SZ, %sp
15: #define _RS restore
16:
17: #define FLUSH_ALL_KERNEL_WINDOWS \
18: _SV; _SV; _SV; _SV; _SV; _SV; _SV; \
19: _RS; _RS; _RS; _RS; _RS; _RS; _RS;
20:
21: /*
22: * Switch execution context
23: * This saves registers in the stack, then
24: * switches the stack, and restores everything from the new stack.
25: * This function takes no argument. New stack pointer is
26: * taken from global variable __context, and old stack pointer
27: * is also saved to __context. This way we can just jump to
28: * this routine to get back to the original context.
29: */
30:
31: __switch_context:
32: FLUSH_ALL_KERNEL_WINDOWS
33: /* Save everything in stack */
34: st %fp, [%fp + 120 -144]
35: add %fp, -144, %fp
36: st %g1, [%fp + 4]
37: st %g2, [%fp + 8]
38: st %g3, [%fp + 12]
39: st %g4, [%fp + 16]
40: st %g5, [%fp + 20]
41: st %g6, [%fp + 24]
42: st %g7, [%fp + 28]
43:
44: st %o0, [%fp + 32]
45: st %o1, [%fp + 36]
46: st %o2, [%fp + 40]
47: st %o3, [%fp + 44]
48: st %o4, [%fp + 48]
49: st %o5, [%fp + 52]
50: st %sp, [%fp + 56]
51: st %o7, [%fp + 60]
52:
53: st %l0, [%fp + 64]
54: st %l1, [%fp + 68]
55: st %l2, [%fp + 72]
56: st %l3, [%fp + 76]
57: st %l4, [%fp + 80]
58: st %l5, [%fp + 84]
59: st %l6, [%fp + 88]
60: st %l7, [%fp + 92]
61:
62: st %i0, [%fp + 96]
63: st %i1, [%fp + 100]
64: st %i2, [%fp + 104]
65: st %i3, [%fp + 108]
66: st %i4, [%fp + 112]
67: st %i5, [%fp + 116]
68: st %i7, [%fp + 124]
69:
70: /* ctx->return_address: Return to caller */
71: st %o7, [%fp + 128]
72:
73: /* Interrupts are not allowed... */
74:
75: /* Turn on Supervisor, EnableFloating, and all the PIL bits.
76: * Also puts us in register window zero with traps off.
77: */
78: #if 0
79: set (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
80: wr %g2, 0x0, %psr
81: #endif
82: set __context, %g1
83: /* Swap ctx pointer with %fp and jump*/
84: ba __set_context
85: swap [%g1], %fp
86: __switch_context_nosave:
87: set __context, %g1
88: /* load %fp from ctx pointer */
89: ld [%g1], %fp
90: __set_context:
91: /* Load all registers */
92: /* offset 0: %g0, no need to load */
93: ld [%fp + 4], %g1
94: ld [%fp + 8], %g2
95: ld [%fp + 12], %g3
96: ld [%fp + 16], %g4
97: ld [%fp + 20], %g5
98: ld [%fp + 24], %g6
99: ld [%fp + 28], %g7
100:
101: /* offset 32: %o0, loaded from ctx->param */
102: ld [%fp + 36], %o1
103: ld [%fp + 40], %o2
104: ld [%fp + 44], %o3
105: ld [%fp + 48], %o4
106: ld [%fp + 52], %o5
107: ld [%fp + 56], %sp
108: /* offset 60: %o7, loaded from ctx->return_addr */
109:
110: ld [%fp + 64], %l0
111: ld [%fp + 68], %l1
112: ld [%fp + 72], %l2
113: ld [%fp + 76], %l3
114: ld [%fp + 80], %l4
115: ld [%fp + 84], %l5
116: ld [%fp + 88], %l6
117: ld [%fp + 92], %l7
118:
119: ld [%fp + 96], %i0
120: ld [%fp + 100], %i1
121: ld [%fp + 104], %i2
122: ld [%fp + 108], %i3
123: ld [%fp + 112], %i4
124: ld [%fp + 116], %i5
125: ld [%fp + 124], %i7
126:
127: /* ctx->return_addr */
128: ld [%fp + 136], %o7
129:
130: /* ctx->param */
131: ld [%fp + 140], %o0
132:
133: /* ctx->pc, save %g1 to %y and load to %g1 */
134: mov %g1, %y
135: ld [%fp + 128], %g1
136: /* %fp last */
137: ld [%fp + 120], %fp
138: /* Finally, get the new %pc from %g1 and restore %g1*/
139: jmp %g1
140: mov %y, %g1
141:
142: FLUSH_ALL_KERNEL_WINDOWS
143: __exit_context:
144: /* Get back to the original context */
145: call __switch_context
146: nop
147:
148: /* We get here if the other context attempt to switch to this
149: * dead context. This should not happen. */
150:
151: halt:
152: b halt
153: nop
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.