Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


(no commit message)
[palacios.git] / palacios / src / geekos / idt.c
1 /*
2  * GeekOS IDT initialization code
3  * Copyright (c) 2001, David H. Hovemeyer <daveho@cs.umd.edu>
4  * $Revision: 1.1.1.1 $
5  * 
6  * This is free software.  You are permitted to use,
7  * redistribute, and modify it as specified in the file "COPYING".
8  */
9
10 #include <geekos/kassert.h>
11 #include <geekos/defs.h>
12 #include <geekos/idt.h>
13 #include <geekos/serial.h>
14
15 /* ----------------------------------------------------------------------
16  * Private data and functions
17  * ---------------------------------------------------------------------- */
18
19 /*
20  * Allocated
21  */
22 //static union IDT_Descriptor s_IDT[ NUM_IDT_ENTRIES ];
23 static union IDT_Descriptor *s_IDT = (union IDT_Descriptor *)IDT_LOCATION;
24
25
26 /*
27  * These symbols are defined in lowlevel.asm, and define the
28  * size of the interrupt entry point table and the sizes
29  * of the individual entry points.  This gives us sufficient
30  * information to build the IDT.
31  */
32 extern char g_entryPointTableStart, g_entryPointTableEnd;
33 extern int g_handlerSizeNoErr, g_handlerSizeErr;
34
35 /*
36  * Table of C interrupt handler functions.
37  * Note that this is public only because it is used
38  * in lowlevel.asm.  Other code should not refer to it.
39  */
40 Interrupt_Handler g_interruptTable[ NUM_IDT_ENTRIES ];
41
42
43
44 void DumpIDT()
45 {
46   int i;
47   Print("IDT Contents:\n");
48
49   for (i=0;i<NUM_IDT_ENTRIES/16;i++) { 
50     if (s_IDT[i].ig.present) { 
51       Print("%d: segmentselector=%u, offset=%u, offsetLow=%u, segmentSelector=%u, reserved=%u, signature=%u, dpl=%u, present=%u, offsetHigh=%u\n",
52             i,
53             s_IDT[i].ig.segmentSelector,
54             (s_IDT[i].ig.offsetHigh<<16) + s_IDT[i].ig.offsetLow,
55             s_IDT[i].ig.offsetLow,
56             s_IDT[i].ig.segmentSelector,
57             s_IDT[i].ig.reserved,
58             s_IDT[i].ig.signature,
59             s_IDT[i].ig.dpl,
60             s_IDT[i].ig.present,
61             s_IDT[i].ig.offsetHigh);
62     }
63   }
64 }
65
66
67 void SerialDumpIDT()
68 {
69   int i;
70   SerialPrint("IDT Contents:\n");
71
72   for (i=0;i<NUM_IDT_ENTRIES;i++) { 
73     if (s_IDT[i].ig.present) { 
74       SerialPrint("%d: segmentselector=%u, offset=%u, offsetLow=%u, segmentSelector=%u, reserved=%u, signature=%u, dpl=%u, present=%u, offsetHigh=%u\n",
75             i,
76             s_IDT[i].ig.segmentSelector,
77             (s_IDT[i].ig.offsetHigh<<16) + s_IDT[i].ig.offsetLow,
78             s_IDT[i].ig.offsetLow,
79             s_IDT[i].ig.segmentSelector,
80             s_IDT[i].ig.reserved,
81             s_IDT[i].ig.signature,
82             s_IDT[i].ig.dpl,
83             s_IDT[i].ig.present,
84             s_IDT[i].ig.offsetHigh);
85       SerialPrint("\n");
86     }
87   }
88 }
89
90
91
92 /* ----------------------------------------------------------------------
93  * Public functions
94  * ---------------------------------------------------------------------- */
95
96 /*
97  * Initialize the Interrupt Descriptor Table.
98  * This will allow us to install C handler functions
99  * for interrupts, both processor-generated and
100  * those generated by external hardware.
101  */
102 void Init_IDT(void)
103 {
104     int i;
105     ushort_t limitAndBase[3];
106     ulong_t idtBaseAddr = (ulong_t) s_IDT;
107     ulong_t tableBaseAddr = (ulong_t) &g_entryPointTableStart;
108     ulong_t addr;
109
110     PrintBoth("Initializing IDT\n");
111
112     /* Make sure the layout of the entry point table is as we expect. */
113     KASSERT(g_handlerSizeNoErr == g_handlerSizeErr);
114     KASSERT((&g_entryPointTableEnd - &g_entryPointTableStart) ==
115              g_handlerSizeNoErr * NUM_IDT_ENTRIES);
116
117     /*
118      * Build the IDT.
119      * We're taking advantage of the fact that all of the
120      * entry points are laid out consecutively, and that they
121      * are all padded to be the same size.
122      */
123     for (i = 0, addr = tableBaseAddr; i < NUM_IDT_ENTRIES; ++i) {
124         /*
125          * All interrupts except for the syscall interrupt
126          * must have kernel privilege to access.
127          */
128         int dpl = (i == SYSCALL_INT) ? USER_PRIVILEGE : KERNEL_PRIVILEGE;
129         Init_Interrupt_Gate(&s_IDT[i], addr, dpl);
130         addr += g_handlerSizeNoErr;
131     }
132
133     /*
134      * Cruft together a 16 bit limit and 32 bit base address
135      * to load into the IDTR.
136      */
137     limitAndBase[0] = 8 * NUM_IDT_ENTRIES;
138     limitAndBase[1] = idtBaseAddr & 0xffff;
139     limitAndBase[2] = idtBaseAddr >> 16;
140
141     /* Install the new table in the IDTR. */
142     Load_IDTR(limitAndBase);
143 }
144
145 /*
146  * Initialize an interrupt gate with given handler address
147  * and descriptor privilege level.
148  */
149 void Init_Interrupt_Gate(union IDT_Descriptor* desc, ulong_t addr,
150         int dpl)
151 {
152     desc->ig.offsetLow = addr & 0xffff;
153     desc->ig.segmentSelector = KERNEL_CS;
154     desc->ig.reserved = 0;
155     desc->ig.signature = 0x70;  /* == 01110000b */
156     desc->ig.dpl = dpl;
157     desc->ig.present = 1;
158     desc->ig.offsetHigh = addr >> 16;
159 }
160
161 /*
162  * Install a C handler function for given interrupt.
163  * This is a lower-level notion than an "IRQ", which specifically
164  * means an interrupt triggered by external hardware.
165  * This function can install a handler for ANY interrupt.
166  */
167 void Install_Interrupt_Handler(int interrupt, Interrupt_Handler handler)
168 {
169     KASSERT(interrupt >= 0 && interrupt < NUM_IDT_ENTRIES);
170     g_interruptTable[interrupt] = handler;
171 }