1/* 2 * Copyright (c) 2009 Corey Tabaka 3 * Copyright (c) 2015 Intel Corporation 4 * Copyright (c) 2016 Travis Geiselbrecht 5 * 6 * Use of this source code is governed by a MIT-style 7 * license that can be found in the LICENSE file or at 8 * https://opensource.org/licenses/MIT 9 */ 10#include <lk/asm.h> 11#include <arch/x86/descriptor.h> 12 13#define NUM_INT 0x100 14#define ISR_STUB_LEN 16 15 16.text 17 18/* interrupt service routine stubs */ 19.balign ISR_STUB_LEN 20LOCAL_FUNCTION(_isr_vectors) 21.set i, 0 22.rept NUM_INT 23 24.balign ISR_STUB_LEN 25.if i == 8 || (i >= 10 && i <= 14) || i == 17 26 /* error code pushed by exception */ 27 push $i /* interrupt number */ 28 jmp interrupt_common 29.else 30 push $0 /* fill in error code in iframe */ 31 push $i /* interrupt number */ 32 jmp interrupt_common 33.endif 34 35.set i, i + 1 36.endr 37END_FUNCTION(_isr_vectors) 38 39.balign 16 40LOCAL_FUNCTION(interrupt_common) 41 cld 42 pushl %gs /* save segment registers */ 43 pushl %fs 44 pushl %es 45 pushl %ds 46 pusha /* save general purpose registers */ 47 movl $DATA_SELECTOR, %eax /* put known good value in segment registers */ 48 // do not reset %gs, as it is used by the kernel 49 // TODO: when dealing with user space, we need to reset %gs here 50 movl %eax, %fs 51 movl %eax, %es 52 movl %eax, %ds 53 54 movl %esp, %eax /* store pointer to iframe */ 55 pushl %eax 56 57 call x86_exception_handler 58 59 popl %eax /* drop pointer to iframe */ 60 61 popa /* restore general purpose registers */ 62 popl %ds /* restore segment registers */ 63 popl %es 64 popl %fs 65 addl $12, %esp /* drop gs, exception number, and error code */ 66 iret 67END_FUNCTION(interrupt_common) 68 69FUNCTION(setup_idt) 70 /* setup isr stub descriptors in the idt */ 71 movl $_isr_vectors, %esi 72 movl $_idt, %edi 73 movl $NUM_INT, %ecx 74 75.Lloop: 76 movl %esi, %ebx 77 movw %bx, (%edi) /* low word in IDT(n).low */ 78 shrl $16, %ebx 79 movw %bx, 6(%edi) /* high word in IDT(n).high */ 80 81 addl $ISR_STUB_LEN, %esi/* index the next ISR stub */ 82 addl $8, %edi /* index the next IDT entry */ 83 84 loop .Lloop 85 86 ret 87END_FUNCTION(setup_idt) 88 89.data 90 91.balign 8 92DATA(_idtr) 93 .short _idt_end - _idt - 1 /* IDT limit */ 94 .int _idt 95END_DATA(_idtr) 96 97/* interrupt descriptor table (IDT) */ 98.balign 8 99DATA(_idt) 100.set i, 0 101.rept NUM_INT-1 102 .short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */ 103 .short CODE_SELECTOR /* selector */ 104 .byte 0 105 .byte 0x8e /* present, ring 0, 32-bit interrupt gate */ 106 .short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */ 107 108.set i, i + 1 109.endr 110 111END_DATA(_idt) 112 113DATA(_idt_end) 114