1 #------------------------------------------------------------------------------
3 #* Copyright 2006, Intel Corporation
4 #* All rights reserved. This program and the accompanying materials
5 #* are licensed and made available under the terms and conditions of the BSD License
6 #* which accompanies this distribution. The full text of the license may be found at
7 #* http://opensource.org/licenses/bsd-license.php
9 #* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 #* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #------------------------------------------------------------------------------
18 #PUBLIC SystemTimerHandler
19 #PUBLIC SystemExceptionHandler
20 #EXTERNDEF mExceptionCodeSize:DWORD
22 #EXTERN TimerHandler: NEAR
23 #EXTERN ExceptionHandler: NEAR
24 #EXTERN mTimerVector: DWORD
27 ASM_GLOBAL ASM_PFX(mExceptionCodeSize)
28 ASM_PFX(mExceptionCodeSize): .long 9
31 ASM_GLOBAL ASM_PFX(InitDescriptor)
33 ASM_PFX(InitDescriptor):
34 movl $GDT_BASE,%eax # EAX=PHYSICAL address of gdt
35 movl %eax, gdtr + 2 # Put address of gdt into the gdtr
37 movl $IDT_BASE,%eax # EAX=PHYSICAL address of idt
38 movl %eax, idtr + 2 # Put address of idt into the idtr
43 # InstallInterruptHandler (
45 # VOID (*Handler)(VOID)
47 ASM_GLOBAL ASM_PFX(InstallInterruptHandler)
48 ASM_PFX(InstallInterruptHandler):
49 # Vector:DWORD @ 4(%esp)
50 # Handler:DWORD @ 8(%esp)
54 cli # turn off interrupts
55 subl $6,%esp # open some space on the stack
57 sidt (%edi) # get fword address of IDT
58 movl 2(%edi), %edi # move offset of IDT into EDI
59 addl $6,%esp # correct stack
60 movl 12(%esp),%eax # Get vector number
61 shl $3,%eax # multiply by 8 to get offset
62 addl %eax,%edi # add to IDT base to get entry
63 movl 16(%esp),%eax # load new address into IDT entry
64 movw %ax,(%edi) # write bits 15..0 of offset
65 shrl $16,%eax # use ax to copy 31..16 to descriptors
66 movw %ax,6(%edi) # write bits 31..16 of offset
67 popf # restore flags (possible enabling interrupts)
71 .macro JmpCommonIdtEntry
72 # jmp commonIdtEntry - this must be hand coded to keep the assembler from
73 # using a 8 bit reletive jump when the entries are
74 # within 255 bytes of the common entry. This must
75 # be done to maintain the consistency of the size
77 .byte 0xe9 # jmp 16 bit reletive
78 .long commonIdtEntry - . - 4 # offset to jump to
82 ASM_GLOBAL ASM_PFX(SystemExceptionHandler)
83 ASM_PFX(SystemExceptionHandler):
85 pushl $0x0 # push error code place holder on the stack
88 # db 0e9h # jmp 16 bit reletive
89 # dd commonIdtEntry - $ - 4 # offset to jump to
92 pushl $0x0 # push error code place holder on the stack
97 pushl $0x0 # push error code place holder on the stack
102 pushl $0x0 # push error code place holder on the stack
107 pushl $0x0 # push error code place holder on the stack
112 pushl $0x0 # push error code place holder on the stack
117 pushl $0x0 # push error code place holder on the stack
122 pushl $0x0 # push error code place holder on the stack
127 # Double fault causes an error code to be pushed so no phony push necessary
134 pushl $0x0 # push error code place holder on the stack
139 # Invalid TSS causes an error code to be pushed so no phony push necessary
146 # Segment Not Present causes an error code to be pushed so no phony push necessary
153 # Stack fault causes an error code to be pushed so no phony push necessary
160 # GP fault causes an error code to be pushed so no phony push necessary
167 # Page fault causes an error code to be pushed so no phony push necessary
174 pushl $0x0 # push error code place holder on the stack
179 pushl $0x0 # push error code place holder on the stack
184 # Alignment check causes an error code to be pushed so no phony push necessary
191 pushl $0x0 # push error code place holder on the stack
196 pushl $0x0 # push error code place holder on the stack
202 pushl $0x0 # push error code place holder on the stack
203 # push xxh # push vector number
205 .byte ( . - INTUnknown - 3 ) / 9 + 20 # vector number
209 ASM_GLOBAL ASM_PFX(SystemTimerHandler)
210 ASM_PFX(SystemTimerHandler):
212 pushl $ASM_PFX(mTimerVector)
216 # +---------------------+
218 # +---------------------+
220 # +---------------------+
222 # +---------------------+
224 # +---------------------+
226 # +---------------------+
228 # +---------------------+ <-- EBP
235 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
238 andl $0xfffffff0,%esp
241 ## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax#
252 ## UINT32 Gs, Fs, Es, Ds, Cs, Ss#
269 ## UINT32 Gdtr[2], Idtr[2]#
285 ## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4#
299 ## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7#
302 ## clear Dr7 while executing debugger itself
308 ## insure all status bits in dr6 are clear...
321 ## FX_SAVE_STATE_IA32 FxSaveState;
326 ## UINT32 ExceptionData;
329 ## Prepare parameter and call
336 call ASM_PFX(TimerHandler)
339 call ASM_PFX(ExceptionHandler)
344 ## UINT32 ExceptionData;
347 ## FX_SAVE_STATE_IA32 FxSaveState;
352 #; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
361 ## skip restore of dr6. We cleared dr6 during the context save.
366 ## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
369 addl $4,%esp # not for Cr1
381 ## UINT32 Gdtr[2], Idtr[2];
382 ## Best not let anyone mess with these particular registers...
388 ## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
389 ## NOTE - modified segment registers could hang the debugger... We
390 ## could attempt to insulate ourselves against this possibility,
391 ## but that poses risks as well.
400 ## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
403 addl $4,%esp # not for ebp
404 addl $4,%esp # not for esp
416 #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
418 #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
423 gdtr: .short GDT_END - GDT_BASE - 1 # GDT limit
424 .long 0 # (GDT base gets set above)
425 #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
426 # global descriptor table (GDT)
427 #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
433 NULL_SEL = .-GDT_BASE
434 .short 0 # limit 15:0
438 .byte 0 # limit 19:16, flags
441 # linear data segment descriptor
442 LINEAR_SEL = .-GDT_BASE
443 .short 0x0FFFF # limit 0xFFFFF
446 .byte 0x092 # present, ring 0, data, expand-up, writable
447 .byte 0x0CF # page-granular, 32-bit
450 # linear code segment descriptor
451 LINEAR_CODE_SEL = .-GDT_BASE
452 .short 0x0FFFF # limit 0xFFFFF
455 .byte 0x09A # present, ring 0, data, expand-up, writable
456 .byte 0x0CF # page-granular, 32-bit
459 # system data segment descriptor
460 SYS_DATA_SEL = .-GDT_BASE
461 .short 0x0FFFF # limit 0xFFFFF
464 .byte 0x092 # present, ring 0, data, expand-up, writable
465 .byte 0x0CF # page-granular, 32-bit
468 # system code segment descriptor
469 SYS_CODE_SEL = .-GDT_BASE
470 .short 0x0FFFF # limit 0xFFFFF
473 .byte 0x09A # present, ring 0, data, expand-up, writable
474 .byte 0x0CF # page-granular, 32-bit
477 # spare segment descriptor
478 SPARE3_SEL = .-GDT_BASE
479 .short 0 # limit 0xFFFFF
482 .byte 0 # present, ring 0, data, expand-up, writable
483 .byte 0 # page-granular, 32-bit
486 # spare segment descriptor
487 SPARE4_SEL = .-GDT_BASE
488 .short 0 # limit 0xFFFFF
491 .byte 0 # present, ring 0, data, expand-up, writable
492 .byte 0 # page-granular, 32-bit
495 # spare segment descriptor
496 SPARE5_SEL = .-GDT_BASE
497 .short 0 # limit 0xFFFFF
500 .byte 0 # present, ring 0, data, expand-up, writable
501 .byte 0 # page-granular, 32-bit
510 idtr: .short IDT_END - IDT_BASE - 1 # IDT limit
511 .long 0 # (IDT base gets set above)
512 #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
513 # interrupt descriptor table (IDT)
515 # Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
516 # mappings. This implementation only uses the system timer and all other
517 # IRQs will remain masked. The descriptors for vectors 33+ are provided
519 #;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
521 #idt_tag .byte "IDT",0
525 # divide by zero (INT 0)
526 DIV_ZERO_SEL = .-IDT_BASE
527 .short 0 # offset 15:0
528 .short SYS_CODE_SEL # selector 15:0
529 .byte 0 # 0 for interrupt gate
530 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
531 .short 0 # offset 31:16
533 # debug exception (INT 1)
534 DEBUG_EXCEPT_SEL = .-IDT_BASE
535 .short 0 # offset 15:0
536 .short SYS_CODE_SEL # selector 15:0
537 .byte 0 # 0 for interrupt gate
538 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
539 .short 0 # offset 31:16
543 .short 0 # offset 15:0
544 .short SYS_CODE_SEL # selector 15:0
545 .byte 0 # 0 for interrupt gate
546 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
547 .short 0 # offset 31:16
549 # soft breakpoint (INT 3)
550 BREAKPOINT_SEL = .-IDT_BASE
551 .short 0 # offset 15:0
552 .short SYS_CODE_SEL # selector 15:0
553 .byte 0 # 0 for interrupt gate
554 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
555 .short 0 # offset 31:16
558 OVERFLOW_SEL = .-IDT_BASE
559 .short 0 # offset 15:0
560 .short SYS_CODE_SEL # selector 15:0
561 .byte 0 # 0 for interrupt gate
562 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
563 .short 0 # offset 31:16
565 # bounds check (INT 5)
566 BOUNDS_CHECK_SEL = .-IDT_BASE
567 .short 0 # offset 15:0
568 .short SYS_CODE_SEL # selector 15:0
569 .byte 0 # 0 for interrupt gate
570 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
571 .short 0 # offset 31:16
573 # invalid opcode (INT 6)
574 INVALID_OPCODE_SEL = .-IDT_BASE
575 .short 0 # offset 15:0
576 .short SYS_CODE_SEL # selector 15:0
577 .byte 0 # 0 for interrupt gate
578 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
579 .short 0 # offset 31:16
581 # device not available (INT 7)
582 DEV_NOT_AVAIL_SEL = .-IDT_BASE
583 .short 0 # offset 15:0
584 .short SYS_CODE_SEL # selector 15:0
585 .byte 0 # 0 for interrupt gate
586 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
587 .short 0 # offset 31:16
589 # double fault (INT 8)
590 DOUBLE_FAULT_SEL = .-IDT_BASE
591 .short 0 # offset 15:0
592 .short SYS_CODE_SEL # selector 15:0
593 .byte 0 # 0 for interrupt gate
594 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
595 .short 0 # offset 31:16
597 # Coprocessor segment overrun - reserved (INT 9)
598 RSVD_INTR_SEL1 = .-IDT_BASE
599 .short 0 # offset 15:0
600 .short SYS_CODE_SEL # selector 15:0
601 .byte 0 # 0 for interrupt gate
602 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
603 .short 0 # offset 31:16
605 # invalid TSS (INT 0ah)
606 INVALID_TSS_SEL = .-IDT_BASE
607 .short 0 # offset 15:0
608 .short SYS_CODE_SEL # selector 15:0
609 .byte 0 # 0 for interrupt gate
610 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
611 .short 0 # offset 31:16
613 # segment not present (INT 0bh)
614 SEG_NOT_PRESENT_SEL = .-IDT_BASE
615 .short 0 # offset 15:0
616 .short SYS_CODE_SEL # selector 15:0
617 .byte 0 # 0 for interrupt gate
618 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
619 .short 0 # offset 31:16
621 # stack fault (INT 0ch)
622 STACK_FAULT_SEL = .-IDT_BASE
623 .short 0 # offset 15:0
624 .short SYS_CODE_SEL # selector 15:0
625 .byte 0 # 0 for interrupt gate
626 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
627 .short 0 # offset 31:16
629 # general protection (INT 0dh)
630 GP_FAULT_SEL = .-IDT_BASE
631 .short 0 # offset 15:0
632 .short SYS_CODE_SEL # selector 15:0
633 .byte 0 # 0 for interrupt gate
634 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
635 .short 0 # offset 31:16
637 # page fault (INT 0eh)
638 PAGE_FAULT_SEL = .-IDT_BASE
639 .short 0 # offset 15:0
640 .short SYS_CODE_SEL # selector 15:0
641 .byte 0 # 0 for interrupt gate
642 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
643 .short 0 # offset 31:16
645 # Intel reserved - do not use (INT 0fh)
646 RSVD_INTR_SEL2 = .-IDT_BASE
647 .short 0 # offset 15:0
648 .short SYS_CODE_SEL # selector 15:0
649 .byte 0 # 0 for interrupt gate
650 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
651 .short 0 # offset 31:16
653 # floating point error (INT 0x10)
654 FLT_POINT_ERR_SEL = .-IDT_BASE
655 .short 0 # offset 15:0
656 .short SYS_CODE_SEL # selector 15:0
657 .byte 0 # 0 for interrupt gate
658 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
659 .short 0 # offset 31:16
661 # alignment check (INT 0x11)
662 ALIGNMENT_CHECK_SEL = .-IDT_BASE
663 .short 0 # offset 15:0
664 .short SYS_CODE_SEL # selector 15:0
665 .byte 0 # 0 for interrupt gate
666 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
667 .short 0 # offset 31:16
669 # machine check (INT 0x12)
670 MACHINE_CHECK_SEL = .-IDT_BASE
671 .short 0 # offset 15:0
672 .short SYS_CODE_SEL # selector 15:0
673 .byte 0 # 0 for interrupt gate
674 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
675 .short 0 # offset 31:16
677 # SIMD floating-point exception (INT 0x13)
678 SIMD_EXCEPTION_SEL = .-IDT_BASE
679 .short 0 # offset 15:0
680 .short SYS_CODE_SEL # selector 15:0
681 .byte 0 # 0 for interrupt gate
682 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
683 .short 0 # offset 31:16
686 .short 0 # offset 15:0
687 .short SYS_CODE_SEL # selector 15:0
688 .byte 0 # 0 for interrupt gate
689 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
690 .short 0 # offset 31:16
693 # 72 unspecified descriptors
696 # IRQ 0 (System timer) - (INT 0x68)
697 IRQ0_SEL = .-IDT_BASE
698 .short 0 # offset 15:0
699 .short SYS_CODE_SEL # selector 15:0
700 .byte 0 # 0 for interrupt gate
701 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
702 .short 0 # offset 31:16
704 # IRQ 1 (8042 Keyboard controller) - (INT 0x69)
705 IRQ1_SEL = .-IDT_BASE
706 .short 0 # offset 15:0
707 .short SYS_CODE_SEL # selector 15:0
708 .byte 0 # 0 for interrupt gate
709 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
710 .short 0 # offset 31:16
712 # Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
713 IRQ2_SEL = .-IDT_BASE
714 .short 0 # offset 15:0
715 .short SYS_CODE_SEL # selector 15:0
716 .byte 0 # 0 for interrupt gate
717 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
718 .short 0 # offset 31:16
720 # IRQ 3 (COM 2) - (INT 6bh)
721 IRQ3_SEL = .-IDT_BASE
722 .short 0 # offset 15:0
723 .short SYS_CODE_SEL # selector 15:0
724 .byte 0 # 0 for interrupt gate
725 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
726 .short 0 # offset 31:16
728 # IRQ 4 (COM 1) - (INT 6ch)
729 IRQ4_SEL = .-IDT_BASE
730 .short 0 # offset 15:0
731 .short SYS_CODE_SEL # selector 15:0
732 .byte 0 # 0 for interrupt gate
733 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
734 .short 0 # offset 31:16
736 # IRQ 5 (LPT 2) - (INT 6dh)
737 IRQ5_SEL = .-IDT_BASE
738 .short 0 # offset 15:0
739 .short SYS_CODE_SEL # selector 15:0
740 .byte 0 # 0 for interrupt gate
741 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
742 .short 0 # offset 31:16
744 # IRQ 6 (Floppy controller) - (INT 6eh)
745 IRQ6_SEL = .-IDT_BASE
746 .short 0 # offset 15:0
747 .short SYS_CODE_SEL # selector 15:0
748 .byte 0 # 0 for interrupt gate
749 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
750 .short 0 # offset 31:16
752 # IRQ 7 (LPT 1) - (INT 6fh)
753 IRQ7_SEL = .-IDT_BASE
754 .short 0 # offset 15:0
755 .short SYS_CODE_SEL # selector 15:0
756 .byte 0 # 0 for interrupt gate
757 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
758 .short 0 # offset 31:16
760 # IRQ 8 (RTC Alarm) - (INT 0x70)
761 IRQ8_SEL = .-IDT_BASE
762 .short 0 # offset 15:0
763 .short SYS_CODE_SEL # selector 15:0
764 .byte 0 # 0 for interrupt gate
765 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
766 .short 0 # offset 31:16
769 IRQ9_SEL = .-IDT_BASE
770 .short 0 # offset 15:0
771 .short SYS_CODE_SEL # selector 15:0
772 .byte 0 # 0 for interrupt gate
773 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
774 .short 0 # offset 31:16
776 # IRQ 10 - (INT 0x72)
777 IRQ10_SEL = .-IDT_BASE
778 .short 0 # offset 15:0
779 .short SYS_CODE_SEL # selector 15:0
780 .byte 0 # 0 for interrupt gate
781 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
782 .short 0 # offset 31:16
784 # IRQ 11 - (INT 0x73)
785 IRQ11_SEL = .-IDT_BASE
786 .short 0 # offset 15:0
787 .short SYS_CODE_SEL # selector 15:0
788 .byte 0 # 0 for interrupt gate
789 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
790 .short 0 # offset 31:16
792 # IRQ 12 (PS/2 mouse) - (INT 0x74)
793 IRQ12_SEL = .-IDT_BASE
794 .short 0 # offset 15:0
795 .short SYS_CODE_SEL # selector 15:0
796 .byte 0 # 0 for interrupt gate
797 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
798 .short 0 # offset 31:16
800 # IRQ 13 (Floating point error) - (INT 0x75)
801 IRQ13_SEL = .-IDT_BASE
802 .short 0 # offset 15:0
803 .short SYS_CODE_SEL # selector 15:0
804 .byte 0 # 0 for interrupt gate
805 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
806 .short 0 # offset 31:16
808 # IRQ 14 (Secondary IDE) - (INT 0x76)
809 IRQ14_SEL = .-IDT_BASE
810 .short 0 # offset 15:0
811 .short SYS_CODE_SEL # selector 15:0
812 .byte 0 # 0 for interrupt gate
813 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
814 .short 0 # offset 31:16
816 # IRQ 15 (Primary IDE) - (INT 0x77)
817 IRQ15_SEL = .-IDT_BASE
818 .short 0 # offset 15:0
819 .short SYS_CODE_SEL # selector 15:0
820 .byte 0 # 0 for interrupt gate
821 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
822 .short 0 # offset 31:16