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 20/* 21 * pushq $i occupies 5 bytes when i >= 0x80 compare to 22 * 2 bytes when i < 0x80, use align to fill the gap 23 * to make sure isr_stub_len correct for each interrupts 24 */ 25.balign ISR_STUB_LEN 26LOCAL_FUNCTION(_isr_vectors) 27_isr: 28.set i, 0 29.rept NUM_INT 30 31.balign ISR_STUB_LEN 32.if i == 8 || (i >= 10 && i <= 14) || i == 17 33 /* error code pushed by exception */ 34 push $i /* interrupt number */ 35 jmp interrupt_common 36.else 37 push $0 /* fill in error code in iframe */ 38 push $i /* interrupt number */ 39 jmp interrupt_common 40.endif 41 42.set i, i + 1 43.endr 44END_FUNCTION(_isr_vectors) 45 46.balign 16 47LOCAL_FUNCTION(interrupt_common) 48 /* clear the direction bit */ 49 cld 50 51 /* save general purpose registers */ 52 pushq %r15 53 pushq %r14 54 pushq %r13 55 pushq %r12 56 pushq %r11 57 pushq %r10 58 pushq %r9 59 pushq %r8 60 pushq %rax 61 pushq %rcx 62 pushq %rdx 63 pushq %rbx 64 pushq %rbp 65 pushq %rsi 66 pushq %rdi 67 68 /* TODO: deal with swapgs if coming from user space */ 69 70 /* pass the iframe using rdi */ 71 movq %rsp, %rdi 72 73 call x86_exception_handler 74 75 /* restore general purpose registers */ 76 popq %rdi 77 popq %rsi 78 popq %rbp 79 popq %rbx 80 popq %rdx 81 popq %rcx 82 popq %rax 83 popq %r8 84 popq %r9 85 popq %r10 86 popq %r11 87 popq %r12 88 popq %r13 89 popq %r14 90 popq %r15 91 92 /* drop vector number and error code*/ 93 addq $16, %rsp 94 iretq 95END_FUNCTION(interrupt_common) 96 97FUNCTION(setup_idt) 98 /* setup isr stub descriptors in the idt */ 99 mov $_isr_vectors, %rsi 100 mov $_idt, %rdi 101 movl $NUM_INT, %ecx 102 103.Lloop: 104 mov %rsi, %rbx 105 movw %bx, (%rdi) /* offset [0:15] in IDT(n).low */ 106 shr $16, %rbx 107 movw %bx, 6(%rdi) /* offset [16:31] in IDT(n).high */ 108 shr $16, %rbx 109 movl %ebx, 8(%rdi) /* offset [32:63] */ 110 111 add $ISR_STUB_LEN, %rsi /* index the next ISR stub */ 112 add $16, %rdi /* index the next IDT entry */ 113 114 loop .Lloop 115 116 ret 117END_FUNCTION(setup_idt) 118 119.data 120 121.balign 8 122DATA(_idtr) 123 .short _idt_end - _idt - 1 /* IDT limit */ 124 .quad _idt 125END_DATA(_idtr) 126 127.balign 16 128/* interrupt descriptor table (IDT) */ 129DATA(_idt) 130 131.set i, 0 132.rept NUM_INT 133 .short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */ 134 .short CODE_64_SELECTOR /* selector */ 135 .byte 0 136 .byte 0x8e /* present, ring 0, 64-bit interrupt gate */ 137 .short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */ 138 .short 0 /* ISR offset */ 139 .short 0 /* ISR offset */ 140 .short 0 /* 32bits Reserved */ 141 .short 0 /* 32bits Reserved */ 142 143.set i, i + 1 144.endr 145 146END_DATA(_idt) 147 148DATA(_idt_end) 149 150 151