1 .globl entry, __switch_context, __exit_context, halt, init_exceptions 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 */ 12entry: 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 601: 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 113halt: 114 cli 115 hlt 116 jmp halt 117 118/* 119 * initialize exception handler. All exceptions end up in the same 120 * C function. 121 */ 122 123init_exceptions: 124 pushl %ebx 125 pushl %edi 126 127 /* Initialize the Interrupt Descriptor table */ 128 leal _idt, %edi 129 leal vec0, %ebx 130 movl $(0x08 << 16), %eax /* cs selector */ 131 1321: movw %bx, %ax 133 movl %ebx, %edx 134 movw $0x8E00, %dx /* Interrupt gate - dpl=0, present */ 135 movl %eax, 0(%edi) 136 movl %edx, 4(%edi) 137 addl $6, %ebx 138 addl $8, %edi 139 cmpl $_idt_end, %edi 140 jne 1b 141 142 /* Load the Interrupt descriptor table */ 143 lidt idtarg 144 145 movl $0, %eax 146 popl %edi 147 popl %ebx 148 ret 149 150vec0: 151 pushl $0 /* error code */ 152 pushl $0 /* vector */ 153 jmp int_hand 154vec1: 155 pushl $0 /* error code */ 156 pushl $1 /* vector */ 157 jmp int_hand 158 159vec2: 160 pushl $0 /* error code */ 161 pushl $2 /* vector */ 162 jmp int_hand 163 164vec3: 165 pushl $0 /* error code */ 166 pushl $3 /* vector */ 167 jmp int_hand 168 169vec4: 170 pushl $0 /* error code */ 171 pushl $4 /* vector */ 172 jmp int_hand 173 174vec5: 175 pushl $0 /* error code */ 176 pushl $5 /* vector */ 177 jmp int_hand 178 179vec6: 180 pushl $0 /* error code */ 181 pushl $6 /* vector */ 182 jmp int_hand 183vec7: 184 pushl $0 /* error code */ 185 pushl $7 /* vector */ 186 jmp int_hand 187 188vec8: 189 /* error code */ 190 pushl $8 /* vector */ 191 jmp int_hand 192 .word 0x9090 193 194vec9: 195 pushl $0 /* error code */ 196 pushl $9 /* vector */ 197 jmp int_hand 198 199vec10: 200 /* error code */ 201 pushl $10 /* vector */ 202 jmp int_hand 203 .word 0x9090 204 205vec11: 206 /* error code */ 207 pushl $11 /* vector */ 208 jmp int_hand 209 .word 0x9090 210 211vec12: 212 /* error code */ 213 pushl $12 /* vector */ 214 jmp int_hand 215 .word 0x9090 216 217vec13: 218 /* error code */ 219 pushl $13 /* vector */ 220 jmp int_hand 221 .word 0x9090 222 223vec14: 224 /* error code */ 225 pushl $14 /* vector */ 226 jmp int_hand 227 .word 0x9090 228 229vec15: 230 pushl $0 /* error code */ 231 pushl $15 /* vector */ 232 jmp int_hand 233 234vec16: 235 pushl $0 /* error code */ 236 pushl $16 /* vector */ 237 jmp int_hand 238 239vec17: 240 /* error code */ 241 pushl $17 /* vector */ 242 jmp int_hand 243 .word 0x9090 244 245vec18: 246 pushl $0 /* error code */ 247 pushl $18 /* vector */ 248 jmp int_hand 249 250vec19: 251 pushl $0 /* error code */ 252 pushl $19 /* vector */ 253 jmp int_hand 254 255__divide_error: 256 pushl $0 /* error code */ 257 pushl $20 /* vector */ 258 jmp int_hand 259 .global __divide_error 260 261int_hand: 262 /* At this point on the stack there is: 263 * 0(%esp) vector 264 * 4(%esp) error code 265 * 8(%esp) eip 266 * 12(%esp) cs 267 * 16(%esp) eflags 268 */ 269 pushl %edi 270 pushl %esi 271 pushl %ebp 272 /* Original stack pointer */ 273 leal 32(%esp), %ebp 274 pushl %ebp 275 pushl %ebx 276 pushl %edx 277 pushl %ecx 278 pushl %eax 279 280 pushl %esp /* Pointer to structure on the stack */ 281 282 call x86_exception 283 pop %eax /* Drop the pointer */ 284 285 popl %eax 286 popl %ecx 287 popl %edx 288 popl %ebx 289 popl %ebp /* Ignore saved %esp value */ 290 popl %ebp 291 popl %esi 292 popl %edi 293 294 addl $8, %esp /* pop of the vector and error code */ 295 296 iret 297 298idtarg: 299 .word _idt_end - _idt - 1 /* limit */ 300 .long _idt 301 .word 0 302_idt: 303 .fill 20, 8, 0 # idt is unitiailzed 304_idt_end: 305 306 .globl arch_nvram_size, arch_nvram_get, arch_nvram_put 307arch_nvram_size: 308 xor %eax, %eax 309 ret 310 311arch_nvram_get: 312 ret 313 314arch_nvram_put: 315 ret 316