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.


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