1110f0d93SGleb Natapov #include "libcflat.h" 2110f0d93SGleb Natapov #include "isr.h" 3110f0d93SGleb Natapov #include "vm.h" 4110f0d93SGleb Natapov #include "desc.h" 5110f0d93SGleb Natapov 6110f0d93SGleb Natapov extern char isr_entry_point[]; 7110f0d93SGleb Natapov 8110f0d93SGleb Natapov asm ( 9110f0d93SGleb Natapov "isr_entry_point: \n" 10110f0d93SGleb Natapov #ifdef __x86_64__ 11110f0d93SGleb Natapov "push %r15 \n\t" 12110f0d93SGleb Natapov "push %r14 \n\t" 13110f0d93SGleb Natapov "push %r13 \n\t" 14110f0d93SGleb Natapov "push %r12 \n\t" 15110f0d93SGleb Natapov "push %r11 \n\t" 16110f0d93SGleb Natapov "push %r10 \n\t" 17110f0d93SGleb Natapov "push %r9 \n\t" 18110f0d93SGleb Natapov "push %r8 \n\t" 19110f0d93SGleb Natapov #endif 20110f0d93SGleb Natapov "push %"R "di \n\t" 21110f0d93SGleb Natapov "push %"R "si \n\t" 22110f0d93SGleb Natapov "push %"R "bp \n\t" 23110f0d93SGleb Natapov "push %"R "sp \n\t" 24110f0d93SGleb Natapov "push %"R "bx \n\t" 25110f0d93SGleb Natapov "push %"R "dx \n\t" 26110f0d93SGleb Natapov "push %"R "cx \n\t" 27110f0d93SGleb Natapov "push %"R "ax \n\t" 28110f0d93SGleb Natapov #ifdef __x86_64__ 29110f0d93SGleb Natapov "mov %rsp, %rdi \n\t" 30110f0d93SGleb Natapov "callq *8*16(%rsp) \n\t" 31110f0d93SGleb Natapov #else 32110f0d93SGleb Natapov "push %esp \n\t" 33110f0d93SGleb Natapov "calll *4+4*8(%esp) \n\t" 34110f0d93SGleb Natapov "add $4, %esp \n\t" 35110f0d93SGleb Natapov #endif 36110f0d93SGleb Natapov "pop %"R "ax \n\t" 37110f0d93SGleb Natapov "pop %"R "cx \n\t" 38110f0d93SGleb Natapov "pop %"R "dx \n\t" 39110f0d93SGleb Natapov "pop %"R "bx \n\t" 40110f0d93SGleb Natapov "pop %"R "bp \n\t" 41110f0d93SGleb Natapov "pop %"R "bp \n\t" 42110f0d93SGleb Natapov "pop %"R "si \n\t" 43110f0d93SGleb Natapov "pop %"R "di \n\t" 44110f0d93SGleb Natapov #ifdef __x86_64__ 45110f0d93SGleb Natapov "pop %r8 \n\t" 46110f0d93SGleb Natapov "pop %r9 \n\t" 47110f0d93SGleb Natapov "pop %r10 \n\t" 48110f0d93SGleb Natapov "pop %r11 \n\t" 49110f0d93SGleb Natapov "pop %r12 \n\t" 50110f0d93SGleb Natapov "pop %r13 \n\t" 51110f0d93SGleb Natapov "pop %r14 \n\t" 52110f0d93SGleb Natapov "pop %r15 \n\t" 53110f0d93SGleb Natapov #endif 54110f0d93SGleb Natapov ".globl isr_iret_ip\n\t" 55110f0d93SGleb Natapov #ifdef __x86_64__ 56110f0d93SGleb Natapov "add $8, %rsp \n\t" 57110f0d93SGleb Natapov "isr_iret_ip: \n\t" 58110f0d93SGleb Natapov "iretq \n\t" 59110f0d93SGleb Natapov #else 60110f0d93SGleb Natapov "add $4, %esp \n\t" 61110f0d93SGleb Natapov "isr_iret_ip: \n\t" 62110f0d93SGleb Natapov "iretl \n\t" 63110f0d93SGleb Natapov #endif 64110f0d93SGleb Natapov ); 65110f0d93SGleb Natapov 66110f0d93SGleb Natapov void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs)) 67110f0d93SGleb Natapov { 68110f0d93SGleb Natapov u8 *thunk = vmalloc(50); 69110f0d93SGleb Natapov 70110f0d93SGleb Natapov set_idt_entry(vec, thunk, 0); 71110f0d93SGleb Natapov 72110f0d93SGleb Natapov #ifdef __x86_64__ 73110f0d93SGleb Natapov /* sub $8, %rsp */ 74110f0d93SGleb Natapov *thunk++ = 0x48; *thunk++ = 0x83; *thunk++ = 0xec; *thunk++ = 0x08; 75110f0d93SGleb Natapov /* mov $func_low, %(rsp) */ 76110f0d93SGleb Natapov *thunk++ = 0xc7; *thunk++ = 0x04; *thunk++ = 0x24; 77110f0d93SGleb Natapov *(u32 *)thunk = (ulong)func; thunk += 4; 78110f0d93SGleb Natapov /* mov $func_high, %(rsp+4) */ 79110f0d93SGleb Natapov *thunk++ = 0xc7; *thunk++ = 0x44; *thunk++ = 0x24; *thunk++ = 0x04; 80110f0d93SGleb Natapov *(u32 *)thunk = (ulong)func >> 32; thunk += 4; 81110f0d93SGleb Natapov /* jmp isr_entry_point */ 82110f0d93SGleb Natapov *thunk ++ = 0xe9; 83110f0d93SGleb Natapov *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4); 84110f0d93SGleb Natapov #else 85110f0d93SGleb Natapov /* push $func */ 86110f0d93SGleb Natapov *thunk++ = 0x68; 87110f0d93SGleb Natapov *(u32 *)thunk = (ulong)func; thunk += 4; 88110f0d93SGleb Natapov /* jmp isr_entry_point */ 89110f0d93SGleb Natapov *thunk++ = 0xe9; 90110f0d93SGleb Natapov *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4); 91110f0d93SGleb Natapov #endif 92110f0d93SGleb Natapov } 9357b4317dSBandan Das 9457b4317dSBandan Das void handle_external_interrupt(int vector) 9557b4317dSBandan Das { 9657b4317dSBandan Das idt_entry_t *idt = &boot_idt[vector]; 9757b4317dSBandan Das unsigned long entry = 98*74b225a7SPaolo Bonzini idt->offset0 | ((unsigned long)idt->offset1 << 16); 99*74b225a7SPaolo Bonzini #ifdef __x86_64__ 100*74b225a7SPaolo Bonzini unsigned long tmp; 101*74b225a7SPaolo Bonzini entry |= ((unsigned long)idt->offset2 << 32); 102*74b225a7SPaolo Bonzini #endif 10357b4317dSBandan Das 10457b4317dSBandan Das asm volatile( 10557b4317dSBandan Das #ifdef __x86_64__ 10657b4317dSBandan Das "mov %%rsp, %[sp]\n\t" 10757b4317dSBandan Das "and $0xfffffffffffffff0, %%rsp\n\t" 10857b4317dSBandan Das "push $%c[ss]\n\t" 10957b4317dSBandan Das "push %[sp]\n\t" 11057b4317dSBandan Das #endif 11157b4317dSBandan Das "pushf\n\t" 112*74b225a7SPaolo Bonzini "orl $0x200, (%%"R"sp)\n\t" 11357b4317dSBandan Das "push $%c[cs]\n\t" 11457b4317dSBandan Das "call *%[entry]\n\t" 11557b4317dSBandan Das : 11657b4317dSBandan Das #ifdef __x86_64__ 11757b4317dSBandan Das [sp]"=&r"(tmp) 11857b4317dSBandan Das #endif 11957b4317dSBandan Das : 12057b4317dSBandan Das [entry]"r"(entry), 12157b4317dSBandan Das [ss]"i"(KERNEL_DS), 12257b4317dSBandan Das [cs]"i"(KERNEL_CS) 12357b4317dSBandan Das ); 12457b4317dSBandan Das } 125