]> rtime.felk.cvut.cz Git - jailhouse.git/blob - inmates/lib/x86/int.c
inmates: Factor our interrupt library services
[jailhouse.git] / inmates / lib / x86 / int.c
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2014
5  *
6  * Authors:
7  *  Jan Kiszka <jan.kiszka@siemens.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  */
12
13 #include <inmate.h>
14
15 #define NUM_IDT_DESC            64
16
17 #define X2APIC_EOI              0x80b
18 #define X2APIC_SPIV             0x80f
19
20 #define APIC_EOI_ACK            0
21
22 struct desc_table_reg {
23         u16 limit;
24         u64 base;
25 } __attribute__((packed));
26
27 static u32 idt[NUM_IDT_DESC * 4];
28 static int_handler_t int_handler[NUM_IDT_DESC];
29
30 extern u8 irq_entry[];
31
32 static inline void write_idtr(struct desc_table_reg *val)
33 {
34         asm volatile("lidt %0" : : "m" (*val));
35 }
36
37 void int_init(void)
38 {
39         struct desc_table_reg dtr;
40
41         write_msr(X2APIC_SPIV, 0x1ff);
42
43         dtr.limit = NUM_IDT_DESC * 16 - 1;
44         dtr.base = (u64)&idt;
45         write_idtr(&dtr);
46 }
47
48 static void __attribute__((used)) handle_interrupt(unsigned int vector)
49 {
50         int_handler[vector]();
51         write_msr(X2APIC_EOI, APIC_EOI_ACK);
52 }
53
54 void int_set_handler(unsigned int vector, int_handler_t handler)
55 {
56         unsigned long entry = (unsigned long)irq_entry + vector * 16;
57
58         int_handler[vector] = handler;
59
60         idt[vector * 4] = (entry & 0xffff) | (INMATE_CS64 << 16);
61         idt[vector * 4 + 1] = 0x8e00 | (entry & 0xffff0000);
62         idt[vector * 4 + 2] = entry >> 32;
63 }
64
65 #ifdef __x86_64__
66 asm(
67 ".macro irq_prologue vector\n\t"
68         "push %rdi\n\t"
69         "mov $vector,%rdi\n\t"
70         "jmp irq_common\n"
71 ".endm\n\t"
72
73         ".global irq_entry\n\t"
74         ".balign 16\n"
75 "irq_entry:\n"
76 "vector=0\n"
77 ".rept 64\n"
78         "irq_prologue vector\n\t"
79         "vector=vector+1\n\t"
80         ".balign 16\n\t"
81 ".endr\n"
82
83 "irq_common:\n\t"
84         "push %rax\n\t"
85         "push %rcx\n\t"
86         "push %rdx\n\t"
87         "push %rsi\n\t"
88         "push %r8\n\t"
89         "push %r9\n\t"
90         "push %r10\n\t"
91         "push %r11\n\t"
92
93         "call handle_interrupt\n\t"
94
95         "pop %r11\n\t"
96         "pop %r10\n\t"
97         "pop %r9\n\t"
98         "pop %r8\n\t"
99         "pop %rsi\n\t"
100         "pop %rdx\n\t"
101         "pop %rcx\n\t"
102         "pop %rax\n\t"
103         "pop %rdi\n\t"
104
105         "iretq"
106 );
107 #else
108 #error implement me!
109 #endif