2 * GeekOS IDT initialization code
3 * Copyright (c) 2001, David H. Hovemeyer <daveho@cs.umd.edu>
6 * This is free software. You are permitted to use,
7 * redistribute, and modify it as specified in the file "COPYING".
10 #include <geekos/kassert.h>
11 #include <geekos/defs.h>
12 #include <geekos/idt.h>
13 #include <geekos/serial.h>
15 /* ----------------------------------------------------------------------
16 * Private data and functions
17 * ---------------------------------------------------------------------- */
22 static union IDT_Descriptor s_IDT[ NUM_IDT_ENTRIES ];
24 // JRL: why??? Should just call Alloc_Page(), otherwise we have dependencies all over the place
25 //static union IDT_Descriptor *s_IDT = (union IDT_Descriptor *)IDT_LOCATION;
28 * These symbols are defined in lowlevel.asm, and define the
29 * size of the interrupt entry point table and the sizes
30 * of the individual entry points. This gives us sufficient
31 * information to build the IDT.
33 extern char g_entryPointTableStart, g_entryPointTableEnd;
34 extern int g_handlerSizeNoErr, g_handlerSizeErr;
37 * Table of C interrupt handler functions.
38 * Note that this is public only because it is used
39 * in lowlevel.asm. Other code should not refer to it.
41 Interrupt_Handler g_interruptTable[ NUM_IDT_ENTRIES ];
48 Print("IDT Contents:\n");
50 for (i=0;i<NUM_IDT_ENTRIES/16;i++) {
51 if (s_IDT[i].ig.present) {
52 Print("%d: segmentselector=%u, offset=%u, offsetLow=%u, segmentSelector=%u, reserved=%u, signature=%u, dpl=%u, present=%u, offsetHigh=%u\n",
54 s_IDT[i].ig.segmentSelector,
55 (s_IDT[i].ig.offsetHigh<<16) + s_IDT[i].ig.offsetLow,
56 s_IDT[i].ig.offsetLow,
57 s_IDT[i].ig.segmentSelector,
59 s_IDT[i].ig.signature,
62 s_IDT[i].ig.offsetHigh);
71 SerialPrint("IDT Contents:\n");
73 for (i=0;i<NUM_IDT_ENTRIES;i++) {
74 if (s_IDT[i].ig.present) {
75 SerialPrint("%d: segmentselector=%u, offset=%u, offsetLow=%u, segmentSelector=%u, reserved=%u, signature=%u, dpl=%u, present=%u, offsetHigh=%u\n",
77 s_IDT[i].ig.segmentSelector,
78 (s_IDT[i].ig.offsetHigh<<16) + s_IDT[i].ig.offsetLow,
79 s_IDT[i].ig.offsetLow,
80 s_IDT[i].ig.segmentSelector,
82 s_IDT[i].ig.signature,
85 s_IDT[i].ig.offsetHigh);
93 /* ----------------------------------------------------------------------
95 * ---------------------------------------------------------------------- */
98 * Initialize the Interrupt Descriptor Table.
99 * This will allow us to install C handler functions
100 * for interrupts, both processor-generated and
101 * those generated by external hardware.
106 ushort_t limitAndBase[3];
107 ulong_t idtBaseAddr = (ulong_t) s_IDT;
108 ulong_t tableBaseAddr = (ulong_t) &g_entryPointTableStart;
111 PrintBoth("Initializing IDT\n");
113 /* Make sure the layout of the entry point table is as we expect. */
114 KASSERT(g_handlerSizeNoErr == g_handlerSizeErr);
115 KASSERT((&g_entryPointTableEnd - &g_entryPointTableStart) ==
116 g_handlerSizeNoErr * NUM_IDT_ENTRIES);
120 * We're taking advantage of the fact that all of the
121 * entry points are laid out consecutively, and that they
122 * are all padded to be the same size.
124 for (i = 0, addr = tableBaseAddr; i < NUM_IDT_ENTRIES; ++i) {
126 * All interrupts except for the syscall interrupt
127 * must have kernel privilege to access.
129 int dpl = (i == SYSCALL_INT) ? USER_PRIVILEGE : KERNEL_PRIVILEGE;
130 Init_Interrupt_Gate(&s_IDT[i], addr, dpl);
131 addr += g_handlerSizeNoErr;
135 * Cruft together a 16 bit limit and 32 bit base address
136 * to load into the IDTR.
138 limitAndBase[0] = 8 * NUM_IDT_ENTRIES;
139 limitAndBase[1] = idtBaseAddr & 0xffff;
140 limitAndBase[2] = idtBaseAddr >> 16;
142 /* Install the new table in the IDTR. */
143 Load_IDTR(limitAndBase);
147 * Initialize an interrupt gate with given handler address
148 * and descriptor privilege level.
150 void Init_Interrupt_Gate(union IDT_Descriptor* desc, ulong_t addr,
153 desc->ig.offsetLow = addr & 0xffff;
154 desc->ig.segmentSelector = KERNEL_CS;
155 desc->ig.reserved = 0;
156 desc->ig.signature = 0x70; /* == 01110000b */
158 desc->ig.present = 1;
159 desc->ig.offsetHigh = addr >> 16;
163 * Install a C handler function for given interrupt.
164 * This is a lower-level notion than an "IRQ", which specifically
165 * means an interrupt triggered by external hardware.
166 * This function can install a handler for ANY interrupt.
168 void Install_Interrupt_Handler(int interrupt, Interrupt_Handler handler)
170 KASSERT(interrupt >= 0 && interrupt < NUM_IDT_ENTRIES);
171 g_interruptTable[interrupt] = handler;