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 .globl ASM_PFX(mExceptionCodeSize)
28 ASM_PFX(mExceptionCodeSize): .long 9
31 .globl ASM_PFX(InitDescriptor)
33 ASM_PFX(InitDescriptor):
34 movq $GDT_BASE,%rax # EAX=PHYSICAL address of gdt
35 movq %rax, gdtr + 2 # Put address of gdt into the gdtr
40 movq $IDT_BASE,%rax # EAX=PHYSICAL address of idt
41 movq %rax, idtr + 2 # Put address of idt into the idtr
46 # InstallInterruptHandler (
48 # VOID (*Handler)(VOID)
50 .globl ASM_PFX(InstallInterruptHandler)
51 ASM_PFX(InstallInterruptHandler):
52 # Vector:DWORD @ 4(%esp)
53 # Handler:DWORD @ 8(%esp)
56 cli # turn off interrupts
57 subq $0x10, %rsp # open some space on the stack
60 sidt (%rbx) # get fword address of IDT
61 movq 2(%rbx), %rbx # move offset of IDT into RBX
62 addq $0x10, %rsp # correct stack
63 movq %rcx, %rax # Get vector number
64 shlq $4, %rax # multiply by 16 to get offset
65 addq %rax, %rbx # add to IDT base to get entry
66 movq %rdx, %rax # load new address into IDT entry
67 movw %ax, (%rbx) # write bits 15..0 of offset
68 shrq $16, %rax # use ax to copy 31..16 to descriptors
69 movw %ax, 6(%rbx) # write bits 31..16 of offset
70 shrq $16, %rax # use eax to copy 63..32 to descriptors
71 movl %eax, 8(%rbx) # write bits 63..32 of offset
72 popfq # restore flags (possible enabling interrupts)
76 .macro JmpCommonIdtEntry
77 # jmp commonIdtEntry - this must be hand coded to keep the assembler from
78 # using a 8 bit reletive jump when the entries are
79 # within 255 bytes of the common entry. This must
80 # be done to maintain the consistency of the size
82 .byte 0xe9 # jmp 16 bit reletive
83 .long commonIdtEntry - . - 4 # offset to jump to
87 .globl ASM_PFX(SystemExceptionHandler)
88 ASM_PFX(SystemExceptionHandler):
90 push $0x0 # push error code place holder on the stack
93 # db 0e9h # jmp 16 bit reletive
94 # dd commonIdtEntry - $ - 4 # offset to jump to
97 push $0x0 # push error code place holder on the stack
102 push $0x0 # push error code place holder on the stack
107 push $0x0 # push error code place holder on the stack
112 push $0x0 # push error code place holder on the stack
117 push $0x0 # push error code place holder on the stack
122 push $0x0 # push error code place holder on the stack
127 push $0x0 # push error code place holder on the stack
132 # Double fault causes an error code to be pushed so no phony push necessary
139 push $0x0 # push error code place holder on the stack
144 # Invalid TSS causes an error code to be pushed so no phony push necessary
151 # Segment Not Present causes an error code to be pushed so no phony push necessary
158 # Stack fault causes an error code to be pushed so no phony push necessary
165 # GP fault causes an error code to be pushed so no phony push necessary
172 # Page fault causes an error code to be pushed so no phony push necessary
179 push $0x0 # push error code place holder on the stack
184 push $0x0 # push error code place holder on the stack
189 # Alignment check causes an error code to be pushed so no phony push necessary
196 push $0x0 # push error code place holder on the stack
201 push $0x0 # push error code place holder on the stack
207 push $0x0 # push error code place holder on the stack
208 # push xxh # push vector number
210 .byte ( . - INTUnknown - 3 ) / 9 + 20 # vector number
214 .globl ASM_PFX(SystemTimerHandler)
215 ASM_PFX(SystemTimerHandler):
217 push $ASM_PFX(mTimerVector)
221 # +---------------------+
223 # +---------------------+
225 # +---------------------+
227 # +---------------------+
229 # +---------------------+
231 # +---------------------+
233 # +---------------------+ <-- EBP
240 # Since here the stack pointer is 16-byte aligned, so
241 # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
245 ## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax#
246 ## UINT64 R8, R9, R10, R11, R12, R13, R14, R15#
264 ## UINT64 Gs, Fs, Es, Ds, Cs, Ss# insure high 16 bits of each is zero
265 movzx 7*8(%rbp), %rax
267 movzx 4*8(%rbp), %rax
281 ## UINT64 Gdtr[2], Idtr[2]#
297 ## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8#
313 ## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7#
317 ## clear Dr7 while executing debugger itself
324 ## insure all status bits in dr6 are clear...
338 ## FX_SAVE_STATE_X64 FxSaveState#
343 ## UINT64 ExceptionData#
346 ## call into exception handler
347 ## Prepare parameter and call
351 # Per X64 calling convention, allocate maximum parameter stack space
352 # and make sure RSP is 16-byte aligned
357 call ASM_PFX(TimerHandler)
360 call ASM_PFX(ExceptionHandler)
366 ## UINT64 ExceptionData#
369 ## FX_SAVE_STATE_X64 FxSaveState#
375 ## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7#
384 ## skip restore of dr6. We cleared dr6 during the context save.
389 ## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8#
392 addq $8, %rsp # not for Cr1
406 ## UINT64 Gdtr[2], Idtr[2]#
407 ## Best not let anyone mess with these particular registers...
413 ## UINT64 Gs, Fs, Es, Ds, Cs, Ss#
415 # mov gs, rax # not for gs
417 # mov fs, rax # not for fs
418 # (X64 will not use fs and gs, so we do not restore it)
423 pop 4*8(%rbp) # for cs
424 pop 7*8(%rbp) # for ss
426 ## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax#
427 ## UINT64 R8, R9, R10, R11, R12, R13, R14, R15#
430 addq $8, %rsp # not for rbp
431 pop 6*8(%rbp) # for rsp
451 ##############################################################################
453 ##############################################################################
458 gdtr: .short GDT_END - GDT_BASE - 1 # GDT limit
459 .quad 0 # (GDT base gets set above)
460 ##############################################################################
461 # global descriptor table (GDT)
462 ##############################################################################
468 NULL_SEL = .-GDT_BASE
469 .short 0 # limit 15:0
473 .byte 0 # limit 19:16, flags
476 # linear data segment descriptor
477 LINEAR_SEL = .-GDT_BASE
478 .short 0x0FFFF # limit 0xFFFFF
481 .byte 0x092 # present, ring 0, data, expand-up, writable
482 .byte 0x0CF # page-granular, 32-bit
485 # linear code segment descriptor
486 LINEAR_CODE_SEL = .-GDT_BASE
487 .short 0x0FFFF # limit 0xFFFFF
490 .byte 0x09A # present, ring 0, data, expand-up, writable
491 .byte 0x0CF # page-granular, 32-bit
494 # system data segment descriptor
495 SYS_DATA_SEL = .-GDT_BASE
496 .short 0x0FFFF # limit 0xFFFFF
499 .byte 0x092 # present, ring 0, data, expand-up, writable
500 .byte 0x0CF # page-granular, 32-bit
503 # system code segment descriptor
504 SYS_CODE_SEL = .-GDT_BASE
505 .short 0x0FFFF # limit 0xFFFFF
508 .byte 0x09A # present, ring 0, data, expand-up, writable
509 .byte 0x0CF # page-granular, 32-bit
512 # spare segment descriptor
513 SPARE3_SEL = .-GDT_BASE
514 .short 0 # limit 0xFFFFF
517 .byte 0 # present, ring 0, data, expand-up, writable
518 .byte 0 # page-granular, 32-bit
521 # spare segment descriptor
522 SPARE4_SEL = .-GDT_BASE
523 .short 0 # limit 0xFFFFF
526 .byte 0 # present, ring 0, data, expand-up, writable
527 .byte 0 # page-granular, 32-bit
530 # spare segment descriptor
531 SPARE5_SEL = .-GDT_BASE
532 .short 0 # limit 0xFFFFF
535 .byte 0 # present, ring 0, data, expand-up, writable
536 .byte 0 # page-granular, 32-bit
545 idtr: .short IDT_END - IDT_BASE - 1 # IDT limit
546 .quad 0 # (IDT base gets set above)
547 ##############################################################################
548 # interrupt descriptor table (IDT)
550 # Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
551 # mappings. This implementation only uses the system timer and all other
552 # IRQs will remain masked. The descriptors for vectors 33+ are provided
554 ##############################################################################
556 #idt_tag .byte "IDT",0
560 # divide by zero (INT 0)
561 DIV_ZERO_SEL = .-IDT_BASE
562 .short 0 # offset 15:0
563 .short SYS_CODE_SEL # selector 15:0
564 .byte 0 # 0 for interrupt gate
565 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
566 .short 0 # offset 31:16
568 # debug exception (INT 1)
569 DEBUG_EXCEPT_SEL = .-IDT_BASE
570 .short 0 # offset 15:0
571 .short SYS_CODE_SEL # selector 15:0
572 .byte 0 # 0 for interrupt gate
573 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
574 .short 0 # offset 31:16
578 .short 0 # offset 15:0
579 .short SYS_CODE_SEL # selector 15:0
580 .byte 0 # 0 for interrupt gate
581 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
582 .short 0 # offset 31:16
584 # soft breakpoint (INT 3)
585 BREAKPOINT_SEL = .-IDT_BASE
586 .short 0 # offset 15:0
587 .short SYS_CODE_SEL # selector 15:0
588 .byte 0 # 0 for interrupt gate
589 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
590 .short 0 # offset 31:16
593 OVERFLOW_SEL = .-IDT_BASE
594 .short 0 # offset 15:0
595 .short SYS_CODE_SEL # selector 15:0
596 .byte 0 # 0 for interrupt gate
597 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
598 .short 0 # offset 31:16
600 # bounds check (INT 5)
601 BOUNDS_CHECK_SEL = .-IDT_BASE
602 .short 0 # offset 15:0
603 .short SYS_CODE_SEL # selector 15:0
604 .byte 0 # 0 for interrupt gate
605 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
606 .short 0 # offset 31:16
608 # invalid opcode (INT 6)
609 INVALID_OPCODE_SEL = .-IDT_BASE
610 .short 0 # offset 15:0
611 .short SYS_CODE_SEL # selector 15:0
612 .byte 0 # 0 for interrupt gate
613 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
614 .short 0 # offset 31:16
616 # device not available (INT 7)
617 DEV_NOT_AVAIL_SEL = .-IDT_BASE
618 .short 0 # offset 15:0
619 .short SYS_CODE_SEL # selector 15:0
620 .byte 0 # 0 for interrupt gate
621 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
622 .short 0 # offset 31:16
624 # double fault (INT 8)
625 DOUBLE_FAULT_SEL = .-IDT_BASE
626 .short 0 # offset 15:0
627 .short SYS_CODE_SEL # selector 15:0
628 .byte 0 # 0 for interrupt gate
629 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
630 .short 0 # offset 31:16
632 # Coprocessor segment overrun - reserved (INT 9)
633 RSVD_INTR_SEL1 = .-IDT_BASE
634 .short 0 # offset 15:0
635 .short SYS_CODE_SEL # selector 15:0
636 .byte 0 # 0 for interrupt gate
637 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
638 .short 0 # offset 31:16
640 # invalid TSS (INT 0ah)
641 INVALID_TSS_SEL = .-IDT_BASE
642 .short 0 # offset 15:0
643 .short SYS_CODE_SEL # selector 15:0
644 .byte 0 # 0 for interrupt gate
645 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
646 .short 0 # offset 31:16
648 # segment not present (INT 0bh)
649 SEG_NOT_PRESENT_SEL = .-IDT_BASE
650 .short 0 # offset 15:0
651 .short SYS_CODE_SEL # selector 15:0
652 .byte 0 # 0 for interrupt gate
653 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
654 .short 0 # offset 31:16
656 # stack fault (INT 0ch)
657 STACK_FAULT_SEL = .-IDT_BASE
658 .short 0 # offset 15:0
659 .short SYS_CODE_SEL # selector 15:0
660 .byte 0 # 0 for interrupt gate
661 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
662 .short 0 # offset 31:16
664 # general protection (INT 0dh)
665 GP_FAULT_SEL = .-IDT_BASE
666 .short 0 # offset 15:0
667 .short SYS_CODE_SEL # selector 15:0
668 .byte 0 # 0 for interrupt gate
669 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
670 .short 0 # offset 31:16
672 # page fault (INT 0eh)
673 PAGE_FAULT_SEL = .-IDT_BASE
674 .short 0 # offset 15:0
675 .short SYS_CODE_SEL # selector 15:0
676 .byte 0 # 0 for interrupt gate
677 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
678 .short 0 # offset 31:16
680 # Intel reserved - do not use (INT 0fh)
681 RSVD_INTR_SEL2 = .-IDT_BASE
682 .short 0 # offset 15:0
683 .short SYS_CODE_SEL # selector 15:0
684 .byte 0 # 0 for interrupt gate
685 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
686 .short 0 # offset 31:16
688 # floating point error (INT 0x10)
689 FLT_POINT_ERR_SEL = .-IDT_BASE
690 .short 0 # offset 15:0
691 .short SYS_CODE_SEL # selector 15:0
692 .byte 0 # 0 for interrupt gate
693 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
694 .short 0 # offset 31:16
696 # alignment check (INT 0x11)
697 ALIGNMENT_CHECK_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 # machine check (INT 0x12)
705 MACHINE_CHECK_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 # SIMD floating-point exception (INT 0x13)
713 SIMD_EXCEPTION_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
721 .short 0 # offset 15:0
722 .short SYS_CODE_SEL # selector 15:0
723 .byte 0 # 0 for interrupt gate
724 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
725 .short 0 # offset 31:16
728 # 72 unspecified descriptors
733 # IRQ 0 (System timer) - (INT 0x68)
734 IRQ0_SEL = .-IDT_BASE
735 .short 0 # offset 15:0
736 .short SYS_CODE_SEL # selector 15:0
737 .byte 0 # 0 for interrupt gate
738 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
739 .short 0 # offset 31:16
741 # IRQ 1 (8042 Keyboard controller) - (INT 0x69)
742 IRQ1_SEL = .-IDT_BASE
743 .short 0 # offset 15:0
744 .short SYS_CODE_SEL # selector 15:0
745 .byte 0 # 0 for interrupt gate
746 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
747 .short 0 # offset 31:16
749 # Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
750 IRQ2_SEL = .-IDT_BASE
751 .short 0 # offset 15:0
752 .short SYS_CODE_SEL # selector 15:0
753 .byte 0 # 0 for interrupt gate
754 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
755 .short 0 # offset 31:16
757 # IRQ 3 (COM 2) - (INT 6bh)
758 IRQ3_SEL = .-IDT_BASE
759 .short 0 # offset 15:0
760 .short SYS_CODE_SEL # selector 15:0
761 .byte 0 # 0 for interrupt gate
762 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
763 .short 0 # offset 31:16
765 # IRQ 4 (COM 1) - (INT 6ch)
766 IRQ4_SEL = .-IDT_BASE
767 .short 0 # offset 15:0
768 .short SYS_CODE_SEL # selector 15:0
769 .byte 0 # 0 for interrupt gate
770 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
771 .short 0 # offset 31:16
773 # IRQ 5 (LPT 2) - (INT 6dh)
774 IRQ5_SEL = .-IDT_BASE
775 .short 0 # offset 15:0
776 .short SYS_CODE_SEL # selector 15:0
777 .byte 0 # 0 for interrupt gate
778 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
779 .short 0 # offset 31:16
781 # IRQ 6 (Floppy controller) - (INT 6eh)
782 IRQ6_SEL = .-IDT_BASE
783 .short 0 # offset 15:0
784 .short SYS_CODE_SEL # selector 15:0
785 .byte 0 # 0 for interrupt gate
786 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
787 .short 0 # offset 31:16
789 # IRQ 7 (LPT 1) - (INT 6fh)
790 IRQ7_SEL = .-IDT_BASE
791 .short 0 # offset 15:0
792 .short SYS_CODE_SEL # selector 15:0
793 .byte 0 # 0 for interrupt gate
794 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
795 .short 0 # offset 31:16
797 # IRQ 8 (RTC Alarm) - (INT 0x70)
798 IRQ8_SEL = .-IDT_BASE
799 .short 0 # offset 15:0
800 .short SYS_CODE_SEL # selector 15:0
801 .byte 0 # 0 for interrupt gate
802 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
803 .short 0 # offset 31:16
806 IRQ9_SEL = .-IDT_BASE
807 .short 0 # offset 15:0
808 .short SYS_CODE_SEL # selector 15:0
809 .byte 0 # 0 for interrupt gate
810 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
811 .short 0 # offset 31:16
813 # IRQ 10 - (INT 0x72)
814 IRQ10_SEL = .-IDT_BASE
815 .short 0 # offset 15:0
816 .short SYS_CODE_SEL # selector 15:0
817 .byte 0 # 0 for interrupt gate
818 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
819 .short 0 # offset 31:16
821 # IRQ 11 - (INT 0x73)
822 IRQ11_SEL = .-IDT_BASE
823 .short 0 # offset 15:0
824 .short SYS_CODE_SEL # selector 15:0
825 .byte 0 # 0 for interrupt gate
826 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
827 .short 0 # offset 31:16
829 # IRQ 12 (PS/2 mouse) - (INT 0x74)
830 IRQ12_SEL = .-IDT_BASE
831 .short 0 # offset 15:0
832 .short SYS_CODE_SEL # selector 15:0
833 .byte 0 # 0 for interrupt gate
834 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
835 .short 0 # offset 31:16
837 # IRQ 13 (Floating point error) - (INT 0x75)
838 IRQ13_SEL = .-IDT_BASE
839 .short 0 # offset 15:0
840 .short SYS_CODE_SEL # selector 15:0
841 .byte 0 # 0 for interrupt gate
842 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
843 .short 0 # offset 31:16
845 # IRQ 14 (Secondary IDE) - (INT 0x76)
846 IRQ14_SEL = .-IDT_BASE
847 .short 0 # offset 15:0
848 .short SYS_CODE_SEL # selector 15:0
849 .byte 0 # 0 for interrupt gate
850 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
851 .short 0 # offset 31:16
853 # IRQ 15 (Primary IDE) - (INT 0x77)
854 IRQ15_SEL = .-IDT_BASE
855 .short 0 # offset 15:0
856 .short SYS_CODE_SEL # selector 15:0
857 .byte 0 # 0 for interrupt gate
858 .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present
859 .short 0 # offset 31:16