|
|
1.1 root 1: .globl entry, __switch_context, __exit_context, halt
2:
3: .text
4: .align 4
5:
6: /*
7: * Entry point
8: * We start execution from here.
9: * It is assumed that CPU is in 32-bit protected mode and
10: * all segments are 4GB and base zero (flat model).
11: */
12: entry:
13: /* Save boot context and switch to our main context.
14: * Main context is statically defined in C.
15: */
16: pushl %cs
17: call __switch_context
18:
19: /* We get here when the main context switches back to
20: * the boot context.
21: * Return to previous bootloader.
22: */
23: ret
24:
25: /*
26: * Switch execution context
27: * This saves registers, segments, and GDT in the stack, then
28: * switches the stack, and restores everything from the new stack.
29: * This function takes no argument. New stack pointer is
30: * taken from global variable __context, and old stack pointer
31: * is also saved to __context. This way we can just jump to
32: * this routine to get back to the original context.
33: *
34: * Call this routine with lcall or pushl %cs; call.
35: */
36: __switch_context:
37: /* Save everything in current stack */
38: pushfl /* 56 */
39: pushl %ds /* 52 */
40: pushl %es /* 48 */
41: pushl %fs /* 44 */
42: pushl %gs /* 40 */
43: pushal /* 8 */
44: subl $8, %esp
45: movw %ss, (%esp) /* 0 */
46: sgdt 2(%esp) /* 2 */
47:
48: #if 0
49: /* Swap %cs and %eip on the stack, so lret will work */
50: movl 60(%esp), %eax
51: xchgl %eax, 64(%esp)
52: movl %eax, 60(%esp)
53: #endif
54:
55: /* At this point we don't know if we are on flat segment
56: * or relocated. So compute the address offset from %eip.
57: * Assuming CS.base==DS.base==SS.base.
58: */
59: call 1f
60: 1: popl %ebx
61: subl $1b, %ebx
62:
63: /* Interrupts are not allowed... */
64: cli
65:
66: /* Current context pointer is our stack pointer */
67: movl %esp, %esi
68:
69: /* Normalize the ctx pointer */
70: subl %ebx, %esi
71:
72: /* Swap it with new value */
73: xchgl %esi, __context(%ebx)
74:
75: /* Adjust new ctx pointer for current address offset */
76: addl %ebx, %esi
77:
78: /* Load new %ss and %esp to temporary */
79: movzwl (%esi), %edx
80: movl 20(%esi), %eax
81:
82: /* Load new GDT */
83: lgdt 2(%esi)
84:
85: /* Load new stack segment with new GDT */
86: movl %edx, %ss
87:
88: /* Set new stack pointer, but we have to adjust it because
89: * pushal saves %esp value before pushal, and we want the value
90: * after pushal.
91: */
92: leal -32(%eax), %esp
93:
94: /* Load the rest from new stack */
95: popal
96: popl %gs
97: popl %fs
98: popl %es
99: popl %ds
100: popfl
101:
102: /* Finally, load new %cs and %eip */
103: lret
104:
105: __exit_context:
106: /* Get back to the original context */
107: pushl %cs
108: call __switch_context
109:
110: /* We get here if the other context attempt to switch to this
111: * dead context. This should not happen. */
112:
113: halt:
114: cli
115: hlt
116: jmp halt
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.