-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathidt.c
164 lines (147 loc) · 5.28 KB
/
idt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/**
* This file sets up the Interrupt Descriptor Table.
* Both the IRQs and ISRs are handled in isr.c.
*/
#include "idt.h"
#include "common.h"
#include "kernio.h"
#include "stdint.h"
// A struct describing an interrupt gate.
struct idt_entry_struct
{
uint16_t base_lo; // The lower 16 bits of the address to jump to when this interrupt fires.
uint16_t sel; // Kernel segment selector.
uint8_t always0; // This must always be zero.
uint8_t flags; // More flags. See documentation.
uint16_t base_hi; // The upper 16 bits of the address to jump to.
} __attribute__((packed));
typedef struct idt_entry_struct idt_entry_t;
// A struct describing a pointer to an array of interrupt handlers.
// This is in a format suitable for giving to 'lidt'.
struct idt_ptr_struct
{
uint16_t limit;
uint32_t base; // The address of the first element in our idt_entry_t array.
} __attribute__((packed));
typedef struct idt_ptr_struct idt_ptr_t;
// These extern directives let us access the addresses of our ASM ISR handlers.
extern void isr0 ();
extern void isr1 ();
extern void isr2 ();
extern void isr3 ();
extern void isr4 ();
extern void isr5 ();
extern void isr6 ();
extern void isr7 ();
extern void isr8 ();
extern void isr9 ();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
// IRQ Handlers
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();
extern void load_idt(idt_ptr_t *);
static void idt_set_gate(uint8_t,uint32_t,uint16_t,uint8_t);
idt_entry_t idt_entries[256];
idt_ptr_t idt_ptr;
void init_idt()
{
idt_ptr.limit = sizeof(idt_entry_t) * 256 -1;
idt_ptr.base = (uint32_t)&idt_entries;
memset(&idt_entries, 0, sizeof(idt_entry_t)*256);
idt_set_gate( 0, (uint32_t)isr0 , 0x08, 0x8E);
idt_set_gate( 1, (uint32_t)isr1 , 0x08, 0x8E);
idt_set_gate( 2, (uint32_t)isr2, 0x08, 0x8E);
idt_set_gate( 3, (uint32_t)isr3, 0x08, 0x8E);
idt_set_gate( 4, (uint32_t)isr4, 0x08, 0x8E);
idt_set_gate( 5, (uint32_t)isr5, 0x08, 0x8E);
idt_set_gate( 6, (uint32_t)isr6, 0x08, 0x8E);
idt_set_gate( 7, (uint32_t)isr7, 0x08, 0x8E);
idt_set_gate( 8, (uint32_t)isr8, 0x08, 0x8E);
idt_set_gate( 9, (uint32_t)isr9, 0x08, 0x8E);
idt_set_gate(10, (uint32_t)isr10, 0x08, 0x8E);
idt_set_gate(11, (uint32_t)isr11, 0x08, 0x8E);
idt_set_gate(12, (uint32_t)isr12, 0x08, 0x8E);
idt_set_gate(13, (uint32_t)isr13, 0x08, 0x8E);
idt_set_gate(14, (uint32_t)isr14, 0x08, 0x8E);
idt_set_gate(15, (uint32_t)isr15, 0x08, 0x8E);
idt_set_gate(16, (uint32_t)isr16, 0x08, 0x8E);
idt_set_gate(17, (uint32_t)isr17, 0x08, 0x8E);
idt_set_gate(18, (uint32_t)isr18, 0x08, 0x8E);
idt_set_gate(19, (uint32_t)isr19, 0x08, 0x8E);
idt_set_gate(20, (uint32_t)isr20, 0x08, 0x8E);
idt_set_gate(21, (uint32_t)isr21, 0x08, 0x8E);
idt_set_gate(22, (uint32_t)isr22, 0x08, 0x8E);
idt_set_gate(23, (uint32_t)isr23, 0x08, 0x8E);
idt_set_gate(24, (uint32_t)isr24, 0x08, 0x8E);
idt_set_gate(25, (uint32_t)isr25, 0x08, 0x8E);
idt_set_gate(26, (uint32_t)isr26, 0x08, 0x8E);
idt_set_gate(27, (uint32_t)isr27, 0x08, 0x8E);
idt_set_gate(28, (uint32_t)isr28, 0x08, 0x8E);
idt_set_gate(29, (uint32_t)isr29, 0x08, 0x8E);
idt_set_gate(30, (uint32_t)isr30, 0x08, 0x8E);
idt_set_gate(31, (uint32_t)isr31, 0x08, 0x8E);
// IRQ entries
idt_set_gate(32, (uint32_t)irq0, 0x08, 0x8E);
idt_set_gate(33, (uint32_t)irq1, 0x08, 0x8E);
idt_set_gate(34, (uint32_t)irq2, 0x08, 0x8E);
idt_set_gate(35, (uint32_t)irq3, 0x08, 0x8E);
idt_set_gate(36, (uint32_t)irq4, 0x08, 0x8E);
idt_set_gate(37, (uint32_t)irq5, 0x08, 0x8E);
idt_set_gate(38, (uint32_t)irq6, 0x08, 0x8E);
idt_set_gate(39, (uint32_t)irq7, 0x08, 0x8E);
idt_set_gate(40, (uint32_t)irq8, 0x08, 0x8E);
idt_set_gate(41, (uint32_t)irq9, 0x08, 0x8E);
idt_set_gate(42, (uint32_t)irq10, 0x08, 0x8E);
idt_set_gate(43, (uint32_t)irq11, 0x08, 0x8E);
idt_set_gate(44, (uint32_t)irq12, 0x08, 0x8E);
idt_set_gate(45, (uint32_t)irq13, 0x08, 0x8E);
idt_set_gate(46, (uint32_t)irq14, 0x08, 0x8E);
idt_set_gate(47, (uint32_t)irq15, 0x08, 0x8E);
printf("Flushing IDT.\n");
load_idt(&idt_ptr);
}
static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
{
idt_entries[num].base_lo = base & 0xFFFF;
idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
idt_entries[num].sel = sel;
idt_entries[num].always0 = 0;
// We must uncomment the OR below when we get to using user-mode.
// It sets the interrupt gate's privilege level to 3.
idt_entries[num].flags = flags /* | 0x60 */;
}