This source file includes following definitions.
- setgdt
- gdt_init
- gdt_alloc_cpu
- gdt_init_cpu
- gdt_grow
- gdt_get_slot
- gdt_put_slot
- tss_alloc
- tss_free
- ldt_alloc
- ldt_free
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 #include <sys/cdefs.h>
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/proc.h>
66 #include <sys/lock.h>
67 #include <sys/user.h>
68 #include <sys/rwlock.h>
69
70 #include <uvm/uvm.h>
71
72 #include <machine/gdt.h>
73
74 union descriptor bootstrap_gdt[NGDT];
75 union descriptor *gdt = bootstrap_gdt;
76
77 int gdt_size;
78 int gdt_next;
79 int gdt_free;
80
81 struct rwlock gdt_lock_store = RWLOCK_INITIALIZER("gdtlk");
82
83 void gdt_grow(void);
84 int gdt_get_slot(void);
85 void gdt_put_slot(int);
86
87
88
89
90
91 #define gdt_lock() \
92 do { \
93 if (curproc != NULL) \
94 rw_enter_write(&gdt_lock_store);\
95 } while (0)
96
97 #define gdt_unlock() \
98 do { \
99 if (curproc != NULL) \
100 rw_exit_write(&gdt_lock_store); \
101 } while (0)
102
103
104 void
105 setgdt(int sel, void *base, size_t limit, int type, int dpl, int def32,
106 int gran)
107 {
108 struct segment_descriptor *sd = &gdt[sel].sd;
109 CPU_INFO_ITERATOR cii;
110 struct cpu_info *ci;
111
112 KASSERT(sel < gdt_size);
113
114 setsegment(sd, base, limit, type, dpl, def32, gran);
115 CPU_INFO_FOREACH(cii, ci)
116 if (ci->ci_gdt != NULL && ci->ci_gdt != gdt)
117 ci->ci_gdt[sel].sd = *sd;
118 }
119
120
121
122
123 void
124 gdt_init()
125 {
126 size_t max_len, min_len;
127 struct vm_page *pg;
128 vaddr_t va;
129 struct cpu_info *ci = &cpu_info_primary;
130
131 max_len = MAXGDTSIZ * sizeof(union descriptor);
132 min_len = MINGDTSIZ * sizeof(union descriptor);
133
134 gdt_size = MINGDTSIZ;
135 gdt_next = NGDT;
136 gdt_free = GNULL_SEL;
137
138 gdt = (union descriptor *)uvm_km_valloc(kernel_map, max_len);
139 for (va = (vaddr_t)gdt; va < (vaddr_t)gdt + min_len; va += PAGE_SIZE) {
140 pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
141 if (pg == NULL)
142 panic("gdt_init: no pages");
143 pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
144 VM_PROT_READ | VM_PROT_WRITE);
145 }
146 bcopy(bootstrap_gdt, gdt, NGDT * sizeof(union descriptor));
147 ci->ci_gdt = gdt;
148 setsegment(&ci->ci_gdt[GCPU_SEL].sd, ci, sizeof(struct cpu_info)-1,
149 SDT_MEMRWA, SEL_KPL, 0, 0);
150
151 gdt_init_cpu(ci);
152 }
153
154 #ifdef MULTIPROCESSOR
155
156
157
158 void
159 gdt_alloc_cpu(struct cpu_info *ci)
160 {
161 int max_len = MAXGDTSIZ * sizeof(union descriptor);
162 int min_len = MINGDTSIZ * sizeof(union descriptor);
163
164 ci->ci_gdt = (union descriptor *)uvm_km_valloc(kernel_map, max_len);
165 uvm_map_pageable(kernel_map, (vaddr_t)ci->ci_gdt,
166 (vaddr_t)ci->ci_gdt + min_len, FALSE, FALSE);
167 bzero(ci->ci_gdt, min_len);
168 bcopy(gdt, ci->ci_gdt, gdt_size * sizeof(union descriptor));
169 setsegment(&ci->ci_gdt[GCPU_SEL].sd, ci, sizeof(struct cpu_info)-1,
170 SDT_MEMRWA, SEL_KPL, 0, 0);
171 }
172 #endif
173
174
175
176
177
178
179 void
180 gdt_init_cpu(struct cpu_info *ci)
181 {
182 struct region_descriptor region;
183
184 setregion(®ion, ci->ci_gdt,
185 MAXGDTSIZ * sizeof(union descriptor) - 1);
186 lgdt(®ion);
187 }
188
189
190
191
192 void
193 gdt_grow()
194 {
195 size_t old_len, new_len;
196 CPU_INFO_ITERATOR cii;
197 struct cpu_info *ci;
198 struct vm_page *pg;
199 vaddr_t va;
200
201 old_len = gdt_size * sizeof(union descriptor);
202 gdt_size <<= 1;
203 new_len = old_len << 1;
204
205 CPU_INFO_FOREACH(cii, ci) {
206 for (va = (vaddr_t)(ci->ci_gdt) + old_len;
207 va < (vaddr_t)(ci->ci_gdt) + new_len;
208 va += PAGE_SIZE) {
209 while (
210 (pg =
211 uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO)) ==
212 NULL) {
213 uvm_wait("gdt_grow");
214 }
215 pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
216 VM_PROT_READ | VM_PROT_WRITE);
217 }
218 }
219 }
220
221
222
223
224
225
226
227
228
229 int
230 gdt_get_slot()
231 {
232 int slot;
233
234 gdt_lock();
235
236 if (gdt_free != GNULL_SEL) {
237 slot = gdt_free;
238 gdt_free = gdt[slot].gd.gd_selector;
239 } else {
240 if (gdt_next >= gdt_size) {
241 if (gdt_size >= MAXGDTSIZ)
242 panic("gdt_get_slot: out of GDT descriptors");
243 gdt_grow();
244 }
245 slot = gdt_next++;
246 }
247
248 gdt_unlock();
249 return (slot);
250 }
251
252
253
254
255 void
256 gdt_put_slot(int slot)
257 {
258
259 gdt_lock();
260
261 gdt[slot].gd.gd_type = SDT_SYSNULL;
262 gdt[slot].gd.gd_selector = gdt_free;
263 gdt_free = slot;
264
265 gdt_unlock();
266 }
267
268 int
269 tss_alloc(struct pcb *pcb)
270 {
271 int slot;
272
273 slot = gdt_get_slot();
274 setgdt(slot, &pcb->pcb_tss, sizeof(struct pcb) - 1,
275 SDT_SYS386TSS, SEL_KPL, 0, 0);
276 return GSEL(slot, SEL_KPL);
277 }
278
279 void
280 tss_free(int sel)
281 {
282
283 gdt_put_slot(IDXSEL(sel));
284 }
285
286 #ifdef USER_LDT
287
288
289
290 void
291 ldt_alloc(struct pmap *pmap, union descriptor *ldt, size_t len)
292 {
293 int slot;
294
295 slot = gdt_get_slot();
296 setgdt(slot, ldt, len - 1, SDT_SYSLDT, SEL_KPL, 0, 0);
297 pmap->pm_ldt_sel = GSEL(slot, SEL_KPL);
298 }
299
300 void
301 ldt_free(struct pmap *pmap)
302 {
303 int slot;
304
305 slot = IDXSEL(pmap->pm_ldt_sel);
306
307 gdt_put_slot(slot);
308 }
309 #endif