|
|
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.