| #include <arch/asm.h> |
| #include <arch/intel.h> |
| |
| .section ".text" |
| .code32 |
| .globl _start |
| _start: |
| cli |
| lgdt %cs:gdtaddr |
| ljmp $0x10, $1f |
| 1: movl $0x18, %eax |
| movl %eax, %ds |
| movl %eax, %es |
| movl %eax, %ss |
| movl %eax, %fs |
| movl %eax, %gs |
| |
| intel_chip_post_macro(0x13) /* post 13 */ |
| |
| /** clear stack */ |
| cld |
| leal _stack, %edi |
| movl $_estack, %ecx |
| subl %edi, %ecx |
| xorl %eax, %eax |
| rep |
| stosb |
| |
| /** clear bss */ |
| leal _bss, %edi |
| movl $_ebss, %ecx |
| subl %edi, %ecx |
| jz .Lnobss |
| xorl %eax, %eax |
| rep |
| stosb |
| .Lnobss: |
| |
| /* set new stack */ |
| movl $_estack, %esp |
| |
| /* Push the cpu index and struct cpu */ |
| pushl $0 |
| pushl $0 |
| |
| /* push the boot_complete flag */ |
| pushl %ebp |
| |
| /* Save the stack location */ |
| movl %esp, %ebp |
| |
| /* Initialize the Interrupt Descriptor table */ |
| leal _idt, %edi |
| leal vec0, %ebx |
| movl $(0x10 << 16), %eax /* cs selector */ |
| |
| 1: movw %bx, %ax |
| movl %ebx, %edx |
| movw $0x8E00, %dx /* Interrupt gate - dpl=0, present */ |
| movl %eax, 0(%edi) |
| movl %edx, 4(%edi) |
| addl $6, %ebx |
| addl $8, %edi |
| cmpl $_idt_end, %edi |
| jne 1b |
| |
| /* Load the Interrupt descriptor table */ |
| lidt idtarg |
| |
| /* |
| * Now we are finished. Memory is up, data is copied and |
| * bss is cleared. Now we call the main routine and |
| * let it do the rest. |
| */ |
| intel_chip_post_macro(0xfe) /* post fe */ |
| |
| /* Restore the stack location */ |
| movl %ebp, %esp |
| |
| /* The boot_complete flag has already been pushed */ |
| call hardwaremain |
| /*NOTREACHED*/ |
| .Lhlt: |
| intel_chip_post_macro(0xee) /* post ee */ |
| hlt |
| jmp .Lhlt |
| |
| vec0: |
| pushl $0 /* error code */ |
| pushl $0 /* vector */ |
| jmp int_hand |
| vec1: |
| pushl $0 /* error code */ |
| pushl $1 /* vector */ |
| jmp int_hand |
| |
| vec2: |
| pushl $0 /* error code */ |
| pushl $2 /* vector */ |
| jmp int_hand |
| |
| vec3: |
| pushl $0 /* error code */ |
| pushl $3 /* vector */ |
| jmp int_hand |
| |
| vec4: |
| pushl $0 /* error code */ |
| pushl $4 /* vector */ |
| jmp int_hand |
| |
| vec5: |
| pushl $0 /* error code */ |
| pushl $5 /* vector */ |
| jmp int_hand |
| |
| vec6: |
| pushl $0 /* error code */ |
| pushl $6 /* vector */ |
| jmp int_hand |
| |
| vec7: |
| pushl $0 /* error code */ |
| pushl $7 /* vector */ |
| jmp int_hand |
| |
| vec8: |
| /* error code */ |
| pushl $8 /* vector */ |
| jmp int_hand |
| .word 0x9090 |
| |
| vec9: |
| pushl $0 /* error code */ |
| pushl $9 /* vector */ |
| jmp int_hand |
| |
| vec10: |
| /* error code */ |
| pushl $10 /* vector */ |
| jmp int_hand |
| .word 0x9090 |
| |
| vec11: |
| /* error code */ |
| pushl $11 /* vector */ |
| jmp int_hand |
| .word 0x9090 |
| |
| vec12: |
| /* error code */ |
| pushl $12 /* vector */ |
| jmp int_hand |
| .word 0x9090 |
| |
| vec13: |
| /* error code */ |
| pushl $13 /* vector */ |
| jmp int_hand |
| .word 0x9090 |
| |
| vec14: |
| /* error code */ |
| pushl $14 /* vector */ |
| jmp int_hand |
| .word 0x9090 |
| |
| vec15: |
| pushl $0 /* error code */ |
| pushl $15 /* vector */ |
| jmp int_hand |
| |
| vec16: |
| pushl $0 /* error code */ |
| pushl $16 /* vector */ |
| jmp int_hand |
| |
| vec17: |
| /* error code */ |
| pushl $17 /* vector */ |
| jmp int_hand |
| .word 0x9090 |
| |
| vec18: |
| pushl $0 /* error code */ |
| pushl $18 /* vector */ |
| jmp int_hand |
| |
| vec19: |
| pushl $0 /* error code */ |
| pushl $19 /* vector */ |
| jmp int_hand |
| int_hand: |
| /* At this point on the stack there is: |
| * 0(%esp) vector |
| * 4(%esp) error code |
| * 8(%esp) eip |
| * 12(%esp) cs |
| * 16(%esp) eflags |
| */ |
| pushl %edi |
| pushl %esi |
| pushl %ebp |
| /* Original stack pointer */ |
| leal 32(%esp), %ebp |
| pushl %ebp |
| pushl %ebx |
| pushl %edx |
| pushl %ecx |
| pushl %eax |
| |
| pushl %esp /* Pointer to structure on the stack */ |
| call x86_exception |
| pop %eax /* Drop the pointer */ |
| |
| popl %eax |
| popl %ecx |
| popl %edx |
| popl %ebx |
| popl %ebp /* Ignore saved %esp value */ |
| popl %ebp |
| popl %esi |
| popl %edi |
| |
| addl $8, %esp /* pop of the vector and error code */ |
| |
| iret |
| |
| #if CONFIG_GDB_STUB == 1 |
| |
| .globl gdb_stub_breakpoint |
| gdb_stub_breakpoint: |
| popl %eax /* Return address */ |
| pushfl |
| pushl %cs |
| pushl %eax /* Return address */ |
| pushl $0 /* No error code */ |
| pushl $32 /* vector 32 is user defined */ |
| jmp int_hand |
| |
| #endif |
| |
| .globl gdt, gdt_end, gdt_limit, idtarg |
| |
| gdt_limit = gdt_end - gdt - 1 /* compute the table limit */ |
| gdtaddr: |
| .word gdt_limit |
| .long gdt /* we know the offset */ |
| |
| .data |
| |
| /* This is the gdt for GCC part of LinuxBIOS. |
| * It is different from the gdt in ROMCC/ASM part of LinuxBIOS |
| * which is defined in entry32.inc */ |
| gdt: |
| /* selgdt 0, unused */ |
| .word 0x0000, 0x0000 /* dummy */ |
| .byte 0x00, 0x00, 0x00, 0x00 |
| |
| /* selgdt 8, unused */ |
| .word 0x0000, 0x0000 /* dummy */ |
| .byte 0x00, 0x00, 0x00, 0x00 |
| |
| /* selgdt 0x10, flat code segment */ |
| .word 0xffff, 0x0000 |
| .byte 0x00, 0x9b, 0xcf, 0x00 |
| |
| /* selgdt 0x18, flat data segment */ |
| .word 0xffff, 0x0000 |
| .byte 0x00, 0x93, 0xcf, 0x00 |
| |
| /* selgdt 0x20, unused */ |
| .word 0x0000, 0x0000 /* dummy */ |
| .byte 0x00, 0x00, 0x00, 0x00 |
| |
| gdt_end: |
| |
| idtarg: |
| .word _idt_end - _idt - 1 /* limit */ |
| .long _idt |
| .word 0 |
| _idt: |
| .fill 20, 8, 0 # idt is unitiailzed |
| _idt_end: |
| |
| .previous |
| .code32 |