| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /*
- * Copyright (c) 2009 Corey Tabaka
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- /* The magic number for the Multiboot header. */
- #define MULTIBOOT_HEADER_MAGIC 0x1BADB002
- /* The flags for the Multiboot header. */
- #if defined(__ELF__) && 0
- #define MULTIBOOT_HEADER_FLAGS 0x00000002
- #else
- #define MULTIBOOT_HEADER_FLAGS 0x00010002
- #endif
- /* The magic number passed by a Multiboot-compliant boot loader. */
- #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
- #define NUM_INT 0x31
- #define NUM_EXC 0x14
- .text
- .global _start
- _start:
- jmp real_start
- .align 4
- multiboot_header:
- /* magic */
- .int MULTIBOOT_HEADER_MAGIC
- /* flags */
- .int MULTIBOOT_HEADER_FLAGS
- /* checksum */
- .int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
- #if !defined(__ELF__) || 1
- /* header_addr */
- .int multiboot_header
- /* load_addr */
- .int _start
- /* load_end_addr */
- .int __bss_start
- /* bss_end_addr */
- .int __bss_end
- /* entry_addr */
- .int real_start
- #endif
- real_start:
- cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
- jne 0f
- movl %ebx, (_multiboot_info)
- 0:
- /* setup isr stub descriptors in the idt */
- movl $_isr, %esi
- movl $_idt, %edi
- movl $NUM_INT, %ecx
-
- .Lloop:
- movl %esi, %ebx
- movw %bx, (%edi) /* low word in IDT(n).low */
- shrl $16, %ebx
- movw %bx, 6(%edi) /* high word in IDT(n).high */
-
- addl $isr_stub_len, %esi/* index the next ISR stub */
- addl $8, %edi /* index the next IDT entry */
-
- loop .Lloop
-
- lidt _idtr
- xorl %eax, %eax
- movl %eax, %cr3
- lgdt _gdtr
-
- movw $datasel, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %fs
- movw %ax, %ss
- movw %ax, %gs
- movw %ax, %ss
-
- movl $_kstack, %esp
-
- /* zero the bss section */
- movl $__bss_start, %edi /* starting address of the bss */
- movl $__bss_end, %ecx /* find the length of the bss in bytes */
- subl %edi, %ecx
- shrl $2, %ecx /* convert to 32 bit words, since the bss is aligned anyway */
- 2:
- movl $0, (%edi)
- addl $4, %edi
- loop 2b
-
- /* call the main module */
- call kmain
-
- 0: /* just sit around waiting for interrupts */
- hlt /* interrupts will unhalt the processor */
- pause
- jmp 0b /* so jump back to halt to conserve power */
- /* interrupt service routine stubs */
- _isr:
- .set i, 0
- .rept NUM_INT
- .set isr_stub_start, .
- .if i == 8 || (i >= 10 && i <= 14) || i == 17
- nop /* error code pushed by exception */
- nop /* 2 nops are the same length as push byte */
- pushl $i /* interrupt number */
- jmp interrupt_common
- .else
- pushl $0 /* fill in error code in iframe */
- pushl $i /* interrupt number */
- jmp interrupt_common
- .endif
- /* figure out the length of a single isr stub (usually 6 or 9 bytes) */
- .set isr_stub_len, . - isr_stub_start
- .set i, i + 1
- .endr
- /* annoying, but force AS to use the same (longer) encoding of jmp for all of the stubs */
- .fill 256
- interrupt_common:
- pushl %gs /* save segment registers */
- pushl %fs
- pushl %es
- pushl %ds
- pusha /* save general purpose registers */
- movl $datasel, %eax /* put known good value in segment registers */
- movl %eax, %gs
- movl %eax, %fs
- movl %eax, %es
- movl %eax, %ds
- movl %esp, %eax /* store stack switch pivot. push esp has errata on some cpus, so use mov/push */
- pushl %eax
- movl %esp, %eax /* store pointer to iframe, using same method */
- pushl %eax
-
- incl critical_section_count
- call platform_irq
-
- cmpl $0,%eax
- je 0f
- call thread_preempt
- 0:
- decl critical_section_count
- popl %eax /* drop pointer to iframe */
- popl %eax /* restore task_esp, stack switch can occur here if task_esp is modified */
- movl %eax, %esp
- popa /* restore general purpose registers */
- popl %ds /* restore segment registers */
- popl %es
- popl %fs
- popl %gs
- addl $8, %esp /* drop exception number and error code */
- iret
- .data
- .align 4
- /* define the heap end as read-write data containing the default end of the
- * heap. dynamic memory length discovery can update this value during init.
- * other archs can define this statically based on the memory layout of the
- * platform.
- */
- .global _heap_end
- _heap_end:
- .int 4096*1024 /* default to 4MB total */
- .global _multiboot_info
- _multiboot_info:
- .int 0
- .global _gdtr
- _gdtr:
- .short _gdt_end - _gdt - 1
- .int _gdt
- .global _gdt
- _gdt:
- .int 0
- .int 0
- /* ring 0 descriptors */
- .set codesel, . - _gdt
- _code_gde:
- .short 0xffff /* limit 15:00 */
- .short 0x0000 /* base 15:00 */
- .byte 0x00 /* base 23:16 */
- .byte 0b10011010 /* P(1) DPL(00) S(1) 1 C(0) R(1) A(0) */
- .byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
- .byte 0x0 /* base 31:24 */
-
- .set datasel, . - _gdt
- _data_gde:
- .short 0xffff /* limit 15:00 */
- .short 0x0000 /* base 15:00 */
- .byte 0x00 /* base 23:16 */
- .byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
- .byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
- .byte 0x0 /* base 31:24 */
-
- .set videosel, . - _gdt
- _video_gde:
- .short 0xffff /* limit 15:00 */
- .short 0x8000 /* base 15:00 */
- .byte 0x0b /* base 23:16 */
- .byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
- .byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
- .byte 0x0 /* base 31:24 */
-
- .if 1
- /* ring 3 descriptors */
- .set user_codesel, . - _gdt
- _user_code_gde:
- .short 0xffff /* limit 15:00 */
- .short 0x0000 /* base 15:00 */
- .byte 0x00 /* base 23:16 */
- .byte 0b11111010 /* P(1) DPL(11) S(1) 1 C(0) R(1) A(0) */
- .byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
- .byte 0x0 /* base 31:24 */
-
- .set user_datasel, . - _gdt
- _user_data_gde:
- .short 0xffff /* limit 15:00 */
- .short 0x0000 /* base 15:00 */
- .byte 0x00 /* base 23:16 */
- .byte 0b11110010 /* P(1) DPL(11) S(1) 0 E(0) W(1) A(0) */
- .byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
- .byte 0x0 /* base 31:24 */
- .endif
- /* TSS descriptor */
- .if 1
- .set tsssel, . - _gdt
- _tss_gde:
- .short 0 /* limit 15:00 */
- .short 0 /* base 15:00 */
- .byte 0 /* base 23:16 */
- .byte 0xe9 /* P(1) DPL(11) 0 10 B(0) 1 */
- .byte 0x00 /* G(0) 0 0 AVL(0) limit 19:16 */
- .short 0 /* base 31:24 */
- .endif
- .global _gdt_end
- _gdt_end:
- .global _idtr
- _idtr:
- .short _idt_end - _idt - 1 /* IDT limit */
- .int _idt
- /* interrupt descriptor table (IDT) */
- .global _idt
- _idt:
- .set i, 0
- .rept NUM_INT-1
- .short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
- .short codesel /* selector */
- .byte 0
- .byte 0x8e /* present, ring 0, 32-bit interrupt gate */
- .short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
-
- .set i, i + 1
- .endr
- /* syscall int (ring 3) */
- _idt30:
- .short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
- .short codesel /* selector */
- .byte 0
- .byte 0xee /* present, ring 3, 32-bit interrupt gate */
- .short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
- .global _idt_end
- _idt_end:
- .bss
- .align 4096
- .global _kstack
- .fill 4096
- _kstack:
|