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 / gdt.c
1 /*
2  * Initialize kernel GDT.
3  * Copyright (c) 2001,2004 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/segment.h>
12 #include <geekos/int.h>
13 #include <geekos/tss.h>
14 #include <geekos/gdt.h>
15 #include <libc/string.h>
16
17
18 /*
19  * This is defined in lowlevel.asm.
20  */
21 extern void Load_GDTR(ushort_t* limitAndBase);
22
23 /* ----------------------------------------------------------------------
24  * Data
25  * ---------------------------------------------------------------------- */
26
27 /*
28  * Number of entries in the kernel GDT.
29  */
30 #define NUM_GDT_ENTRIES 16
31
32 /*
33  * This is the kernel's global descriptor table.
34  */
35 struct Segment_Descriptor *s_GDT=(struct Segment_Descriptor *)GDT_LOCATION;
36
37 /*
38  * Number of allocated GDT entries.
39  */
40 static int s_numAllocated = 0;
41
42
43
44
45
46 void DumpGDT()
47 {
48   int i;
49   Print("GDT Contents:\n");
50
51   for (i=0;i<NUM_GDT_ENTRIES;i++) { 
52     if (s_GDT[i].present) { 
53       Print("%d: base=%u, limit=%u, sizeLow=%u,  baseLow=%u, type=%u, system=%u, dpl=%u, preent=%u, sizeHigh=%u, avail=%u, reserved=%u, dbBit=%u, granularity=%u, baseHigh=%u\n", 
54             i,
55             (s_GDT[i].baseHigh<<24) + s_GDT[i].baseLow,
56             (s_GDT[i].sizeHigh<<16) + s_GDT[i].sizeLow,
57             s_GDT[i].sizeLow,
58             s_GDT[i].baseLow,
59             s_GDT[i].type,
60             s_GDT[i].system,
61             s_GDT[i].dpl,
62             s_GDT[i].present,
63             s_GDT[i].sizeHigh,
64             s_GDT[i].avail,
65             s_GDT[i].reserved,
66             s_GDT[i].dbBit,
67             s_GDT[i].granularity,
68             s_GDT[i].baseHigh  );
69     } else {
70       Print("%d: Not Present\n",i);
71     }
72   }
73 }
74
75
76 /* ----------------------------------------------------------------------
77  * Functions
78  * ---------------------------------------------------------------------- */
79
80 /*
81  * Allocate an descriptor from the GDT.
82  * Returns null if there are none left.
83  */
84 struct Segment_Descriptor* Allocate_Segment_Descriptor(void)
85 {
86     struct Segment_Descriptor* result = 0;
87     int i;
88     bool iflag;
89
90     iflag = Begin_Int_Atomic();
91
92     /* Note; entry 0 is unused (thus never allocated) */
93     for (i = 1; i < NUM_GDT_ENTRIES; ++i) {
94         struct Segment_Descriptor *desc = &s_GDT[ i ];
95         if (desc->avail) {
96             ++s_numAllocated;
97             desc->avail = 0;
98             result = desc;
99             break;
100         }
101     }
102
103     End_Int_Atomic(iflag);
104
105     return result;
106 }
107
108 /*
109  * Free a segment descriptor.
110  */
111 void Free_Segment_Descriptor(struct Segment_Descriptor* desc)
112 {
113     bool iflag = Begin_Int_Atomic();
114
115     KASSERT(!desc->avail);
116
117     Init_Null_Segment_Descriptor(desc);
118     desc->avail = 1;
119     --s_numAllocated;
120
121     End_Int_Atomic(iflag);
122 }
123
124 /*
125  * Get the index (int the GDT) of given segment descriptor.
126  */
127 int Get_Descriptor_Index(struct Segment_Descriptor* desc)
128 {
129     return (int) (desc - s_GDT);
130 }
131
132 /*
133  * Initialize the kernel's GDT.
134  */
135 void Init_GDT(void)
136 {
137     ushort_t limitAndBase[3];
138     ulong_t gdtBaseAddr = (ulong_t) s_GDT;
139     struct Segment_Descriptor* desc;
140     int i;
141
142     Print("GDT Placed at %x, %d entries\n",GDT_LOCATION,NUM_GDT_ENTRIES);
143
144     KASSERT(sizeof(struct Segment_Descriptor) == 8);
145
146     /* Clear out entries. */
147     for (i = 0; i < NUM_GDT_ENTRIES; ++i) {
148         desc = &s_GDT[ i ];
149         Init_Null_Segment_Descriptor(desc);
150         desc->avail = 1;
151     }
152
153     /* Kernel code segment. */
154     desc = Allocate_Segment_Descriptor();
155     Init_Code_Segment_Descriptor(
156         desc,
157         0,               /* base address */
158         0x100000,        /* num pages (== 2^20) */
159         0                /* privilege level (0 == kernel) */
160     );
161     KASSERT(Get_Descriptor_Index(desc) == (KERNEL_CS >> 3));
162
163     /* Kernel data segment. */
164     desc = Allocate_Segment_Descriptor();
165     Init_Data_Segment_Descriptor(
166         desc,
167         0,               /* base address */
168         0x100000,        /* num pages (== 2^20) */
169         0                /* privilege level (0 == kernel) */
170     );
171     KASSERT(Get_Descriptor_Index(desc) == (KERNEL_DS >> 3));
172
173     /* Activate the kernel GDT. */
174     limitAndBase[0] = sizeof(struct Segment_Descriptor) * NUM_GDT_ENTRIES;
175     limitAndBase[1] = gdtBaseAddr & 0xffff;
176     limitAndBase[2] = gdtBaseAddr >> 16;
177     Load_GDTR(limitAndBase);
178 }