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.


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