--- /dev/null
+#------------------------------------------------------------------------------\r
+#*\r
+#* Copyright 2006, Intel Corporation \r
+#* All rights reserved. This program and the accompanying materials \r
+#* are licensed and made available under the terms and conditions of the BSD License \r
+#* which accompanies this distribution. The full text of the license may be found at \r
+#* http://opensource.org/licenses/bsd-license.php \r
+#* \r
+#* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+#* \r
+#* CpuInterrupt.S\r
+#* \r
+#* Abstract:\r
+#*\r
+#------------------------------------------------------------------------------\r
+\r
+#PUBLIC SystemTimerHandler\r
+#PUBLIC SystemExceptionHandler\r
+#EXTERNDEF mExceptionCodeSize:DWORD\r
+\r
+#EXTERN TimerHandler: NEAR\r
+#EXTERN ExceptionHandler: NEAR\r
+#EXTERN mTimerVector: DWORD\r
+\r
+ .data\r
+ .globl ASM_PFX(mExceptionCodeSize)\r
+ASM_PFX(mExceptionCodeSize): .long 9\r
+\r
+ .text\r
+ .globl ASM_PFX(InitDescriptor)\r
+\r
+ASM_PFX(InitDescriptor):\r
+ movq $GDT_BASE,%rax # EAX=PHYSICAL address of gdt\r
+ movq %rax, gdtr + 2 # Put address of gdt into the gdtr\r
+ lgdt gdtr\r
+ movq $0x18, %rax\r
+ movq %rax, %gs\r
+ movq %rax, %fs\r
+ movq $IDT_BASE,%rax # EAX=PHYSICAL address of idt\r
+ movq %rax, idtr + 2 # Put address of idt into the idtr\r
+ lidt idtr\r
+ ret\r
+\r
+# VOID\r
+# InstallInterruptHandler (\r
+# UINTN Vector,\r
+# VOID (*Handler)(VOID)\r
+# )\r
+ .globl ASM_PFX(InstallInterruptHandler)\r
+ASM_PFX(InstallInterruptHandler):\r
+# Vector:DWORD @ 4(%esp)\r
+# Handler:DWORD @ 8(%esp)\r
+ push %rbx\r
+ pushfq # save eflags\r
+ cli # turn off interrupts\r
+ subq $0x10, %rsp # open some space on the stack\r
+ movq %rsp, %rbx\r
+ \r
+ sidt (%rbx) # get fword address of IDT\r
+ movq 2(%rbx), %rbx # move offset of IDT into RBX\r
+ addq $0x10, %rsp # correct stack\r
+ movq %rcx, %rax # Get vector number\r
+ shlq $4, %rax # multiply by 16 to get offset\r
+ addq %rax, %rbx # add to IDT base to get entry\r
+ movq %rdx, %rax # load new address into IDT entry\r
+ movw %ax, (%rbx) # write bits 15..0 of offset\r
+ shrq $16, %rax # use ax to copy 31..16 to descriptors\r
+ movw %ax, 6(%rbx) # write bits 31..16 of offset\r
+ shrq $16, %rax # use eax to copy 63..32 to descriptors\r
+ movl %eax, 8(%rbx) # write bits 63..32 of offset\r
+ popfq # restore flags (possible enabling interrupts)\r
+ pop %rbx\r
+ ret\r
+\r
+ .macro JmpCommonIdtEntry\r
+ # jmp commonIdtEntry - this must be hand coded to keep the assembler from\r
+ # using a 8 bit reletive jump when the entries are\r
+ # within 255 bytes of the common entry. This must\r
+ # be done to maintain the consistency of the size\r
+ # of entry points...\r
+ .byte 0xe9 # jmp 16 bit reletive \r
+ .long commonIdtEntry - . - 4 # offset to jump to\r
+ .endm\r
+\r
+ .align 2\r
+ .globl ASM_PFX(SystemExceptionHandler)\r
+ASM_PFX(SystemExceptionHandler):\r
+INT0:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $0x0 \r
+ JmpCommonIdtEntry\r
+# db 0e9h # jmp 16 bit reletive \r
+# dd commonIdtEntry - $ - 4 # offset to jump to\r
+ \r
+INT1:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $0x1 \r
+ JmpCommonIdtEntry\r
+ \r
+INT2:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $0x2 \r
+ JmpCommonIdtEntry\r
+ \r
+INT3:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $0x3 \r
+ JmpCommonIdtEntry\r
+ \r
+INT4:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $0x4 \r
+ JmpCommonIdtEntry\r
+ \r
+INT5:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $0x5 \r
+ JmpCommonIdtEntry\r
+ \r
+INT6:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $0x6 \r
+ JmpCommonIdtEntry\r
+ \r
+INT7:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $0x7 \r
+ JmpCommonIdtEntry\r
+ \r
+INT8:\r
+# Double fault causes an error code to be pushed so no phony push necessary\r
+ nop\r
+ nop\r
+ push $0x8 \r
+ JmpCommonIdtEntry\r
+ \r
+INT9:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $0x9 \r
+ JmpCommonIdtEntry\r
+ \r
+INT10:\r
+# Invalid TSS causes an error code to be pushed so no phony push necessary\r
+ nop\r
+ nop\r
+ push $10\r
+ JmpCommonIdtEntry\r
+ \r
+INT11:\r
+# Segment Not Present causes an error code to be pushed so no phony push necessary\r
+ nop\r
+ nop\r
+ push $11\r
+ JmpCommonIdtEntry\r
+ \r
+INT12:\r
+# Stack fault causes an error code to be pushed so no phony push necessary\r
+ nop\r
+ nop\r
+ push $12\r
+ JmpCommonIdtEntry\r
+ \r
+INT13:\r
+# GP fault causes an error code to be pushed so no phony push necessary\r
+ nop\r
+ nop\r
+ push $13\r
+ JmpCommonIdtEntry\r
+ \r
+INT14:\r
+# Page fault causes an error code to be pushed so no phony push necessary\r
+ nop\r
+ nop\r
+ push $14\r
+ JmpCommonIdtEntry\r
+ \r
+INT15:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $15\r
+ JmpCommonIdtEntry\r
+ \r
+INT16:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $16\r
+ JmpCommonIdtEntry\r
+ \r
+INT17:\r
+# Alignment check causes an error code to be pushed so no phony push necessary\r
+ nop\r
+ nop\r
+ push $17\r
+ JmpCommonIdtEntry\r
+ \r
+INT18:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $18\r
+ JmpCommonIdtEntry\r
+ \r
+INT19:\r
+ push $0x0 # push error code place holder on the stack\r
+ push $19\r
+ JmpCommonIdtEntry\r
+\r
+INTUnknown:\r
+ .rept (32 - 20)\r
+ push $0x0 # push error code place holder on the stack\r
+# push xxh # push vector number\r
+ .byte 0x6a\r
+ .byte ( . - INTUnknown - 3 ) / 9 + 20 # vector number\r
+ JmpCommonIdtEntry\r
+ .endr\r
+\r
+ .globl ASM_PFX(SystemTimerHandler)\r
+ASM_PFX(SystemTimerHandler):\r
+ push $0\r
+ push $ASM_PFX(mTimerVector)\r
+ JmpCommonIdtEntry\r
+\r
+commonIdtEntry:\r
+# +---------------------+\r
+# + EFlags +\r
+# +---------------------+\r
+# + CS +\r
+# +---------------------+\r
+# + EIP +\r
+# +---------------------+\r
+# + Error Code +\r
+# +---------------------+\r
+# + Vector Number +\r
+# +---------------------+\r
+# + EBP +\r
+# +---------------------+ <-- EBP\r
+\r
+ cli\r
+ push %rbp\r
+ movq %rsp,%rbp\r
+\r
+ #\r
+ # Since here the stack pointer is 16-byte aligned, so\r
+ # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64\r
+ # is 16-byte aligned\r
+ # \r
+\r
+## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax#\r
+## UINT64 R8, R9, R10, R11, R12, R13, R14, R15#\r
+ push %r15\r
+ push %r14\r
+ push %r13\r
+ push %r12\r
+ push %r11\r
+ push %r10\r
+ push %r9\r
+ push %r8\r
+ push %rax\r
+ push %rcx\r
+ push %rdx\r
+ push %rbx\r
+ push 6*8(%rbp)\r
+ push (%rbp)\r
+ push %rsi\r
+ push %rdi\r
+ \r
+## UINT64 Gs, Fs, Es, Ds, Cs, Ss# insure high 16 bits of each is zero\r
+ movzx 7*8(%rbp), %rax\r
+ push %rax # for ss\r
+ movzx 4*8(%rbp), %rax\r
+ push %rax # for cs\r
+ movq %ds, %rax\r
+ push %rax\r
+ movq %es, %rax\r
+ push %rax\r
+ movq %fs, %rax\r
+ push %rax\r
+ movq %gs, %rax\r
+ push %rax\r
+\r
+## UINT64 Rip#\r
+ push 3*8(%rbp)\r
+ \r
+## UINT64 Gdtr[2], Idtr[2]#\r
+ subq $16, %rsp\r
+ sidt (%rsp)\r
+ subq $16, %rsp\r
+ sgdt (%rsp)\r
+ \r
+## UINT64 Ldtr, Tr#\r
+ xorq %rax, %rax\r
+ str %ax\r
+ push %rax\r
+ sldt %ax\r
+ push %rax\r
+ \r
+## UINT64 RFlags#\r
+ push 5*8(%rbp)\r
+\r
+## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8#\r
+ movq %cr8, %rax\r
+ push %rax\r
+ movq %cr4, %rax\r
+ orq $0x208, %rax\r
+ movq %rax, %cr4\r
+ push %rax\r
+ movq %cr3, %rax\r
+ push %rax\r
+ movq %cr2, %rax\r
+ push %rax\r
+ xorq %rax, %rax\r
+ push %rax\r
+ movq %cr0, %rax\r
+ push %rax\r
+\r
+## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7#\r
+ movq %dr7, %rax\r
+ push %rax\r
+\r
+## clear Dr7 while executing debugger itself\r
+ xorq %rax, %rax\r
+ movq %rax, %dr7\r
+\r
+ movq %dr6, %rax\r
+ push %rax\r
+ \r
+## insure all status bits in dr6 are clear...\r
+ xorq %rax, %rax\r
+ movq %rax, %dr6\r
+\r
+ movq %dr3, %rax\r
+ push %rax\r
+ movq %dr2, %rax\r
+ push %rax\r
+ movq %dr1, %rax\r
+ push %rax\r
+ movq %dr0, %rax\r
+ push %rax\r
+\r
+\r
+## FX_SAVE_STATE_X64 FxSaveState#\r
+ subq $512, %rsp\r
+ movq %rsp, %rdi\r
+ fxsave (%rdi)\r
+\r
+## UINT64 ExceptionData#\r
+ push 2*8 (%rbp) \r
+ \r
+## call into exception handler\r
+## Prepare parameter and call\r
+ movq 1*8(%rbp), %rcx\r
+ movq %rsp, %rdx\r
+ #\r
+ # Per X64 calling convention, allocate maximum parameter stack space\r
+ # and make sure RSP is 16-byte aligned\r
+ #\r
+ subq $(4*8+8), %rsp\r
+ cmpq $32, %rcx\r
+ jb CallException\r
+ call ASM_PFX(TimerHandler)\r
+ jmp ExceptionDone\r
+CallException:\r
+ call ASM_PFX(ExceptionHandler)\r
+ExceptionDone:\r
+ addq $(4*8+8), %rsp\r
+\r
+ cli\r
+ \r
+## UINT64 ExceptionData#\r
+ addq $8, %rsp\r
+\r
+## FX_SAVE_STATE_X64 FxSaveState#\r
+ movq %rsp, %rsi\r
+ fxrstor (%esi)\r
+ addq $512, %rsp\r
+\r
+\r
+## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7#\r
+ pop %rax\r
+ movq %rax, %dr0\r
+ pop %rax\r
+ movq %rax, %dr1\r
+ pop %rax\r
+ movq %rax, %dr2\r
+ pop %rax\r
+ movq %rax, %dr3\r
+## skip restore of dr6. We cleared dr6 during the context save.\r
+ addq $8, %rsp\r
+ pop %rax\r
+ movq %rax, %dr7\r
+\r
+## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8#\r
+ pop %rax\r
+ movq %rax, %cr0\r
+ addq $8, %rsp # not for Cr1\r
+ pop %rax\r
+ movq %rax, %cr2\r
+ pop %rax\r
+ movq %rax, %cr3\r
+ pop %rax\r
+ movq %rax, %cr4\r
+ pop %rax\r
+ mov %rax, %cr8\r
+ \r
+## UINT64 RFlags#\r
+ pop 5*8(%rbp) \r
+\r
+## UINT64 Ldtr, Tr#\r
+## UINT64 Gdtr[2], Idtr[2]#\r
+## Best not let anyone mess with these particular registers...\r
+ addq $48, %rsp\r
+\r
+## UINT64 Rip#\r
+ pop 3*8(%rbp)\r
+\r
+## UINT64 Gs, Fs, Es, Ds, Cs, Ss#\r
+ pop %rax\r
+ # mov gs, rax # not for gs\r
+ pop %rax\r
+ # mov fs, rax # not for fs\r
+ # (X64 will not use fs and gs, so we do not restore it)\r
+ pop %rax\r
+ movq %rax, %es\r
+ pop %rax\r
+ movq %rax, %ds\r
+ pop 4*8(%rbp) # for cs\r
+ pop 7*8(%rbp) # for ss\r
+\r
+## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax#\r
+## UINT64 R8, R9, R10, R11, R12, R13, R14, R15#\r
+ pop %rdi\r
+ pop %rsi\r
+ addq $8, %rsp # not for rbp\r
+ pop 6*8(%rbp) # for rsp\r
+ pop %rbx\r
+ pop %rdx\r
+ pop %rcx\r
+ pop %rax\r
+ pop %r8\r
+ pop %r9\r
+ pop %r10\r
+ pop %r11\r
+ pop %r12\r
+ pop %r13\r
+ pop %r14\r
+ pop %r15\r
+\r
+ movq %rbp, %rsp\r
+ pop %rbp\r
+ addq $16, %rsp\r
+ iretq\r
+\r
+\r
+##############################################################################\r
+# data\r
+##############################################################################\r
+\r
+ .data\r
+ .align 0x10\r
+\r
+gdtr: .short GDT_END - GDT_BASE - 1 # GDT limit\r
+ .quad 0 # (GDT base gets set above)\r
+##############################################################################\r
+# global descriptor table (GDT)\r
+##############################################################################\r
+\r
+ .align 0x10\r
+\r
+GDT_BASE:\r
+# null descriptor\r
+NULL_SEL = .-GDT_BASE\r
+ .short 0 # limit 15:0\r
+ .short 0 # base 15:0\r
+ .byte 0 # base 23:16\r
+ .byte 0 # type\r
+ .byte 0 # limit 19:16, flags\r
+ .byte 0 # base 31:24\r
+\r
+# linear data segment descriptor\r
+LINEAR_SEL = .-GDT_BASE\r
+ .short 0x0FFFF # limit 0xFFFFF\r
+ .short 0 # base 0\r
+ .byte 0\r
+ .byte 0x092 # present, ring 0, data, expand-up, writable\r
+ .byte 0x0CF # page-granular, 32-bit\r
+ .byte 0\r
+\r
+# linear code segment descriptor\r
+LINEAR_CODE_SEL = .-GDT_BASE\r
+ .short 0x0FFFF # limit 0xFFFFF\r
+ .short 0 # base 0\r
+ .byte 0\r
+ .byte 0x09A # present, ring 0, data, expand-up, writable\r
+ .byte 0x0CF # page-granular, 32-bit\r
+ .byte 0\r
+\r
+# system data segment descriptor\r
+SYS_DATA_SEL = .-GDT_BASE\r
+ .short 0x0FFFF # limit 0xFFFFF\r
+ .short 0 # base 0\r
+ .byte 0\r
+ .byte 0x092 # present, ring 0, data, expand-up, writable\r
+ .byte 0x0CF # page-granular, 32-bit\r
+ .byte 0\r
+\r
+# system code segment descriptor\r
+SYS_CODE_SEL = .-GDT_BASE\r
+ .short 0x0FFFF # limit 0xFFFFF\r
+ .short 0 # base 0\r
+ .byte 0\r
+ .byte 0x09A # present, ring 0, data, expand-up, writable\r
+ .byte 0x0CF # page-granular, 32-bit\r
+ .byte 0\r
+\r
+# spare segment descriptor\r
+SPARE3_SEL = .-GDT_BASE\r
+ .short 0 # limit 0xFFFFF\r
+ .short 0 # base 0\r
+ .byte 0\r
+ .byte 0 # present, ring 0, data, expand-up, writable\r
+ .byte 0 # page-granular, 32-bit\r
+ .byte 0\r
+\r
+# spare segment descriptor\r
+SPARE4_SEL = .-GDT_BASE\r
+ .short 0 # limit 0xFFFFF\r
+ .short 0 # base 0\r
+ .byte 0\r
+ .byte 0 # present, ring 0, data, expand-up, writable\r
+ .byte 0 # page-granular, 32-bit\r
+ .byte 0\r
+\r
+# spare segment descriptor\r
+SPARE5_SEL = .-GDT_BASE\r
+ .short 0 # limit 0xFFFFF\r
+ .short 0 # base 0\r
+ .byte 0\r
+ .byte 0 # present, ring 0, data, expand-up, writable\r
+ .byte 0 # page-granular, 32-bit\r
+ .byte 0\r
+\r
+GDT_END:\r
+\r
+ .align 0x4\r
+\r
+\r
+\r
+idtr: .short IDT_END - IDT_BASE - 1 # IDT limit\r
+ .quad 0 # (IDT base gets set above)\r
+##############################################################################\r
+# interrupt descriptor table (IDT)\r
+#\r
+# Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ\r
+# mappings. This implementation only uses the system timer and all other\r
+# IRQs will remain masked. The descriptors for vectors 33+ are provided\r
+# for convenience.\r
+##############################################################################\r
+\r
+#idt_tag .byte "IDT",0 \r
+ .align 0x4\r
+\r
+IDT_BASE:\r
+# divide by zero (INT 0)\r
+DIV_ZERO_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# debug exception (INT 1)\r
+DEBUG_EXCEPT_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# NMI (INT 2)\r
+NMI_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# soft breakpoint (INT 3)\r
+BREAKPOINT_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# overflow (INT 4)\r
+OVERFLOW_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# bounds check (INT 5)\r
+BOUNDS_CHECK_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# invalid opcode (INT 6)\r
+INVALID_OPCODE_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# device not available (INT 7)\r
+DEV_NOT_AVAIL_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# double fault (INT 8)\r
+DOUBLE_FAULT_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# Coprocessor segment overrun - reserved (INT 9)\r
+RSVD_INTR_SEL1 = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# invalid TSS (INT 0ah)\r
+INVALID_TSS_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# segment not present (INT 0bh)\r
+SEG_NOT_PRESENT_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# stack fault (INT 0ch)\r
+STACK_FAULT_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# general protection (INT 0dh)\r
+GP_FAULT_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# page fault (INT 0eh)\r
+PAGE_FAULT_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# Intel reserved - do not use (INT 0fh)\r
+RSVD_INTR_SEL2 = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# floating point error (INT 0x10)\r
+FLT_POINT_ERR_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# alignment check (INT 0x11)\r
+ALIGNMENT_CHECK_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# machine check (INT 0x12)\r
+MACHINE_CHECK_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# SIMD floating-point exception (INT 0x13)\r
+SIMD_EXCEPTION_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+ .rept (32 - 20)\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+ .endr\r
+\r
+# 72 unspecified descriptors\r
+ .rept 72 * 8\r
+ .byte 0\r
+ .endr\r
+ \r
+# IRQ 0 (System timer) - (INT 0x68)\r
+IRQ0_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 1 (8042 Keyboard controller) - (INT 0x69)\r
+IRQ1_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)\r
+IRQ2_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 3 (COM 2) - (INT 6bh)\r
+IRQ3_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 4 (COM 1) - (INT 6ch)\r
+IRQ4_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 5 (LPT 2) - (INT 6dh)\r
+IRQ5_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 6 (Floppy controller) - (INT 6eh)\r
+IRQ6_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 7 (LPT 1) - (INT 6fh)\r
+IRQ7_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 8 (RTC Alarm) - (INT 0x70)\r
+IRQ8_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 9 - (INT 0x71)\r
+IRQ9_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 10 - (INT 0x72)\r
+IRQ10_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 11 - (INT 0x73)\r
+IRQ11_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 12 (PS/2 mouse) - (INT 0x74)\r
+IRQ12_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 13 (Floating point error) - (INT 0x75)\r
+IRQ13_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 14 (Secondary IDE) - (INT 0x76)\r
+IRQ14_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+# IRQ 15 (Primary IDE) - (INT 0x77)\r
+IRQ15_SEL = .-IDT_BASE\r
+ .short 0 # offset 15:0\r
+ .short SYS_CODE_SEL # selector 15:0\r
+ .byte 0 # 0 for interrupt gate\r
+ .byte 0x0e | 0x80 # (10001110)type = 386 interrupt gate, present\r
+ .short 0 # offset 31:16\r
+\r
+ .rept 1 * 16\r
+ .byte 0\r
+ .endr\r
+\r
+IDT_END:\r
+\r