1 TITLE CpuInterrupt.asm:
2 ;------------------------------------------------------------------------------
4 ;* Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
5 ;* This program and the accompanying materials
6 ;* are licensed and made available under the terms and conditions of the BSD License
7 ;* which accompanies this distribution. The full text of the license may be found at
8 ;* http://opensource.org/licenses/bsd-license.php
10 ;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 ;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 ;------------------------------------------------------------------------------
22 PUBLIC SystemTimerHandler
23 PUBLIC SystemExceptionHandler
24 EXTERNDEF mExceptionCodeSize:DWORD
31 EXTERN TimerHandler: NEAR
32 EXTERN ExceptionHandler: NEAR
33 EXTERN mTimerVector: DWORD
35 mExceptionCodeSize DD 9
38 lea eax, [GDT_BASE] ; EAX=PHYSICAL address of gdt
39 mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
41 lea eax, [IDT_BASE] ; EAX=PHYSICAL address of idt
42 mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
48 ; InstallInterruptHandler (
50 ; VOID (*Handler)(VOID)
52 InstallInterruptHandler PROC C \
58 cli ; turn off interrupts
59 sub esp, 6 ; open some space on the stack
61 sidt es:[edi] ; get fword address of IDT
62 mov edi, es:[edi+2] ; move offset of IDT into EDI
63 add esp, 6 ; correct stack
64 mov eax, Vector ; Get vector number
65 shl eax, 3 ; multiply by 8 to get offset
66 add edi, eax ; add to IDT base to get entry
67 mov eax, Handler ; load new address into IDT entry
68 mov word ptr es:[edi], ax ; write bits 15..0 of offset
69 shr eax, 16 ; use ax to copy 31..16 to descriptors
70 mov word ptr es:[edi+6], ax ; write bits 31..16 of offset
71 popfd ; restore flags (possible enabling interrupts)
75 InstallInterruptHandler ENDP
77 JmpCommonIdtEntry macro
78 ; jmp commonIdtEntry - this must be hand coded to keep the assembler from
79 ; using a 8 bit reletive jump when the entries are
80 ; within 255 bytes of the common entry. This must
81 ; be done to maintain the consistency of the size
83 db 0e9h ; jmp 16 bit reletive
84 dd commonIdtEntry - $ - 4 ; offset to jump to
88 SystemExceptionHandler PROC
90 push 0h ; 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 0h ; push error code place holder on the stack
102 push 0h ; push error code place holder on the stack
107 push 0h ; push error code place holder on the stack
112 push 0h ; push error code place holder on the stack
117 push 0h ; push error code place holder on the stack
122 push 0h ; push error code place holder on the stack
127 push 0h ; 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 0h ; 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 0h ; push error code place holder on the stack
184 push 0h ; 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 0h ; push error code place holder on the stack
201 push 0h ; push error code place holder on the stack
207 push 0h ; push error code place holder on the stack
208 ; push xxh ; push vector number
210 db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number
213 SystemExceptionHandler ENDP
215 SystemTimerHandler PROC
219 SystemTimerHandler ENDP
222 ; +---------------------+
224 ; +---------------------+
226 ; +---------------------+
228 ; +---------------------+
230 ; +---------------------+
232 ; +---------------------+
234 ; +---------------------+ <-- EBP
241 ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
247 ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
252 lea ecx, [ebp + 6 * 4]
254 push dword ptr [ebp] ; EBP
258 ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
261 movzx eax, word ptr [ebp + 4 * 4]
273 push dword ptr [ebp + 3 * 4]
275 ;; UINT32 Gdtr[2], Idtr[2];
289 push dword ptr [ebp + 5 * 4]
291 ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
305 ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
308 ;; clear Dr7 while executing debugger itself
314 ;; insure all status bits in dr6 are clear...
327 ;; FX_SAVE_STATE_IA32 FxSaveState;
330 db 0fh, 0aeh, 00000111y ;fxsave [edi]
332 ;; UINT32 ExceptionData;
333 push dword ptr [ebp + 2 * 4]
335 ;; Prepare parameter and call
338 mov eax, dword ptr [ebp + 1 * 4]
345 call ExceptionHandler
350 ;; UINT32 ExceptionData;
353 ;; FX_SAVE_STATE_IA32 FxSaveState;
355 db 0fh, 0aeh, 00001110y ; fxrstor [esi]
358 ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
367 ;; skip restore of dr6. We cleared dr6 during the context save.
372 ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
375 add esp, 4 ; not for Cr1
384 pop dword ptr [ebp + 5 * 4]
387 ;; UINT32 Gdtr[2], Idtr[2];
388 ;; Best not let anyone mess with these particular registers...
392 pop dword ptr [ebp + 3 * 4]
394 ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
395 ;; NOTE - modified segment registers could hang the debugger... We
396 ;; could attempt to insulate ourselves against this possibility,
397 ;; but that poses risks as well.
403 pop dword ptr [ebp + 4 * 4]
406 ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
409 add esp, 4 ; not for ebp
410 add esp, 4 ; not for esp
422 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
424 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
428 gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
429 dd 0 ; (GDT base gets set above)
430 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
431 ; global descriptor table (GDT)
432 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
439 NULL_SEL equ $-GDT_BASE
444 db 0 ; limit 19:16, flags
447 ; linear data segment descriptor
448 LINEAR_SEL equ $-GDT_BASE
449 dw 0FFFFh ; limit 0xFFFFF
452 db 092h ; present, ring 0, data, expand-up, writable
453 db 0CFh ; page-granular, 32-bit
456 ; linear code segment descriptor
457 LINEAR_CODE_SEL equ $-GDT_BASE
458 dw 0FFFFh ; limit 0xFFFFF
461 db 09Ah ; present, ring 0, data, expand-up, writable
462 db 0CFh ; page-granular, 32-bit
465 ; system data segment descriptor
466 SYS_DATA_SEL equ $-GDT_BASE
467 dw 0FFFFh ; limit 0xFFFFF
470 db 092h ; present, ring 0, data, expand-up, writable
471 db 0CFh ; page-granular, 32-bit
474 ; system code segment descriptor
475 SYS_CODE_SEL equ $-GDT_BASE
476 dw 0FFFFh ; limit 0xFFFFF
479 db 09Ah ; present, ring 0, data, expand-up, writable
480 db 0CFh ; page-granular, 32-bit
483 ; spare segment descriptor
484 SPARE3_SEL equ $-GDT_BASE
488 db 0 ; present, ring 0, data, expand-up, writable
489 db 0 ; page-granular, 32-bit
492 ; spare segment descriptor
493 SPARE4_SEL equ $-GDT_BASE
497 db 0 ; present, ring 0, data, expand-up, writable
498 db 0 ; page-granular, 32-bit
501 ; spare segment descriptor
502 SPARE5_SEL equ $-GDT_BASE
506 db 0 ; present, ring 0, data, expand-up, writable
507 db 0 ; page-granular, 32-bit
516 idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
517 dd 0 ; (IDT base gets set above)
518 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
519 ; interrupt descriptor table (IDT)
521 ; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
522 ; mappings. This implementation only uses the system timer and all other
523 ; IRQs will remain masked. The descriptors for vectors 33+ are provided
525 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
532 ; divide by zero (INT 0)
533 DIV_ZERO_SEL equ $-IDT_BASE
535 dw SYS_CODE_SEL ; selector 15:0
536 db 0 ; 0 for interrupt gate
537 db 0eh OR 80h ; type = 386 interrupt gate, present
540 ; debug exception (INT 1)
541 DEBUG_EXCEPT_SEL equ $-IDT_BASE
543 dw SYS_CODE_SEL ; selector 15:0
544 db 0 ; 0 for interrupt gate
545 db 0eh OR 80h ; type = 386 interrupt gate, present
549 NMI_SEL equ $-IDT_BASE
551 dw SYS_CODE_SEL ; selector 15:0
552 db 0 ; 0 for interrupt gate
553 db 0eh OR 80h ; type = 386 interrupt gate, present
556 ; soft breakpoint (INT 3)
557 BREAKPOINT_SEL equ $-IDT_BASE
559 dw SYS_CODE_SEL ; selector 15:0
560 db 0 ; 0 for interrupt gate
561 db 0eh OR 80h ; type = 386 interrupt gate, present
565 OVERFLOW_SEL equ $-IDT_BASE
567 dw SYS_CODE_SEL ; selector 15:0
568 db 0 ; 0 for interrupt gate
569 db 0eh OR 80h ; type = 386 interrupt gate, present
572 ; bounds check (INT 5)
573 BOUNDS_CHECK_SEL equ $-IDT_BASE
575 dw SYS_CODE_SEL ; selector 15:0
576 db 0 ; 0 for interrupt gate
577 db 0eh OR 80h ; type = 386 interrupt gate, present
580 ; invalid opcode (INT 6)
581 INVALID_OPCODE_SEL equ $-IDT_BASE
583 dw SYS_CODE_SEL ; selector 15:0
584 db 0 ; 0 for interrupt gate
585 db 0eh OR 80h ; type = 386 interrupt gate, present
588 ; device not available (INT 7)
589 DEV_NOT_AVAIL_SEL equ $-IDT_BASE
591 dw SYS_CODE_SEL ; selector 15:0
592 db 0 ; 0 for interrupt gate
593 db 0eh OR 80h ; type = 386 interrupt gate, present
596 ; double fault (INT 8)
597 DOUBLE_FAULT_SEL equ $-IDT_BASE
599 dw SYS_CODE_SEL ; selector 15:0
600 db 0 ; 0 for interrupt gate
601 db 0eh OR 80h ; type = 386 interrupt gate, present
604 ; Coprocessor segment overrun - reserved (INT 9)
605 RSVD_INTR_SEL1 equ $-IDT_BASE
607 dw SYS_CODE_SEL ; selector 15:0
608 db 0 ; 0 for interrupt gate
609 db 0eh OR 80h ; type = 386 interrupt gate, present
612 ; invalid TSS (INT 0ah)
613 INVALID_TSS_SEL equ $-IDT_BASE
615 dw SYS_CODE_SEL ; selector 15:0
616 db 0 ; 0 for interrupt gate
617 db 0eh OR 80h ; type = 386 interrupt gate, present
620 ; segment not present (INT 0bh)
621 SEG_NOT_PRESENT_SEL equ $-IDT_BASE
623 dw SYS_CODE_SEL ; selector 15:0
624 db 0 ; 0 for interrupt gate
625 db 0eh OR 80h ; type = 386 interrupt gate, present
628 ; stack fault (INT 0ch)
629 STACK_FAULT_SEL equ $-IDT_BASE
631 dw SYS_CODE_SEL ; selector 15:0
632 db 0 ; 0 for interrupt gate
633 db 0eh OR 80h ; type = 386 interrupt gate, present
636 ; general protection (INT 0dh)
637 GP_FAULT_SEL equ $-IDT_BASE
639 dw SYS_CODE_SEL ; selector 15:0
640 db 0 ; 0 for interrupt gate
641 db 0eh OR 80h ; type = 386 interrupt gate, present
644 ; page fault (INT 0eh)
645 PAGE_FAULT_SEL equ $-IDT_BASE
647 dw SYS_CODE_SEL ; selector 15:0
648 db 0 ; 0 for interrupt gate
649 db 0eh OR 80h ; type = 386 interrupt gate, present
652 ; Intel reserved - do not use (INT 0fh)
653 RSVD_INTR_SEL2 equ $-IDT_BASE
655 dw SYS_CODE_SEL ; selector 15:0
656 db 0 ; 0 for interrupt gate
657 db 0eh OR 80h ; type = 386 interrupt gate, present
660 ; floating point error (INT 10h)
661 FLT_POINT_ERR_SEL equ $-IDT_BASE
663 dw SYS_CODE_SEL ; selector 15:0
664 db 0 ; 0 for interrupt gate
665 db 0eh OR 80h ; type = 386 interrupt gate, present
668 ; alignment check (INT 11h)
669 ALIGNMENT_CHECK_SEL equ $-IDT_BASE
671 dw SYS_CODE_SEL ; selector 15:0
672 db 0 ; 0 for interrupt gate
673 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
676 ; machine check (INT 12h)
677 MACHINE_CHECK_SEL equ $-IDT_BASE
679 dw SYS_CODE_SEL ; selector 15:0
680 db 0 ; 0 for interrupt gate
681 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
684 ; SIMD floating-point exception (INT 13h)
685 SIMD_EXCEPTION_SEL equ $-IDT_BASE
687 dw SYS_CODE_SEL ; selector 15:0
688 db 0 ; 0 for interrupt gate
689 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
694 dw SYS_CODE_SEL ; selector 15:0
695 db 0 ; 0 for interrupt gate
696 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
700 ; 72 unspecified descriptors
703 ; IRQ 0 (System timer) - (INT 68h)
704 IRQ0_SEL equ $-IDT_BASE
706 dw SYS_CODE_SEL ; selector 15:0
707 db 0 ; 0 for interrupt gate
708 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
711 ; IRQ 1 (8042 Keyboard controller) - (INT 69h)
712 IRQ1_SEL equ $-IDT_BASE
714 dw SYS_CODE_SEL ; selector 15:0
715 db 0 ; 0 for interrupt gate
716 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
719 ; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
720 IRQ2_SEL equ $-IDT_BASE
722 dw SYS_CODE_SEL ; selector 15:0
723 db 0 ; 0 for interrupt gate
724 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
727 ; IRQ 3 (COM 2) - (INT 6bh)
728 IRQ3_SEL equ $-IDT_BASE
730 dw SYS_CODE_SEL ; selector 15:0
731 db 0 ; 0 for interrupt gate
732 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
735 ; IRQ 4 (COM 1) - (INT 6ch)
736 IRQ4_SEL equ $-IDT_BASE
738 dw SYS_CODE_SEL ; selector 15:0
739 db 0 ; 0 for interrupt gate
740 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
743 ; IRQ 5 (LPT 2) - (INT 6dh)
744 IRQ5_SEL equ $-IDT_BASE
746 dw SYS_CODE_SEL ; selector 15:0
747 db 0 ; 0 for interrupt gate
748 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
751 ; IRQ 6 (Floppy controller) - (INT 6eh)
752 IRQ6_SEL equ $-IDT_BASE
754 dw SYS_CODE_SEL ; selector 15:0
755 db 0 ; 0 for interrupt gate
756 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
759 ; IRQ 7 (LPT 1) - (INT 6fh)
760 IRQ7_SEL equ $-IDT_BASE
762 dw SYS_CODE_SEL ; selector 15:0
763 db 0 ; 0 for interrupt gate
764 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
767 ; IRQ 8 (RTC Alarm) - (INT 70h)
768 IRQ8_SEL equ $-IDT_BASE
770 dw SYS_CODE_SEL ; selector 15:0
771 db 0 ; 0 for interrupt gate
772 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
776 IRQ9_SEL equ $-IDT_BASE
778 dw SYS_CODE_SEL ; selector 15:0
779 db 0 ; 0 for interrupt gate
780 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
784 IRQ10_SEL equ $-IDT_BASE
786 dw SYS_CODE_SEL ; selector 15:0
787 db 0 ; 0 for interrupt gate
788 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
792 IRQ11_SEL equ $-IDT_BASE
794 dw SYS_CODE_SEL ; selector 15:0
795 db 0 ; 0 for interrupt gate
796 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
799 ; IRQ 12 (PS/2 mouse) - (INT 74h)
800 IRQ12_SEL equ $-IDT_BASE
802 dw SYS_CODE_SEL ; selector 15:0
803 db 0 ; 0 for interrupt gate
804 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
807 ; IRQ 13 (Floating point error) - (INT 75h)
808 IRQ13_SEL equ $-IDT_BASE
810 dw SYS_CODE_SEL ; selector 15:0
811 db 0 ; 0 for interrupt gate
812 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
815 ; IRQ 14 (Secondary IDE) - (INT 76h)
816 IRQ14_SEL equ $-IDT_BASE
818 dw SYS_CODE_SEL ; selector 15:0
819 db 0 ; 0 for interrupt gate
820 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
823 ; IRQ 15 (Primary IDE) - (INT 77h)
824 IRQ15_SEL equ $-IDT_BASE
826 dw SYS_CODE_SEL ; selector 15:0
827 db 0 ; 0 for interrupt gate
828 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present