]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ia32/x86desc.cpp
update
[l4.git] / kernel / fiasco / src / kern / ia32 / x86desc.cpp
1
2 INTERFACE:
3
4 #include "l4_types.h"
5
6 class X86desc
7 {
8 public:
9   enum
10     {
11       Accessed            = 0x01,
12       Access_kernel       = 0x00,
13       Access_user         = 0x60,
14       Access_present      = 0x80,
15
16       Access_tss          = 0x09,
17       Access_intr_gate    = 0x0e,
18       Access_trap_gate    = 0x0f,
19
20       Long_mode           = 0x02, // XXX for code segments
21     };
22 };
23
24
25 class Gdt_entry : public X86desc
26 {
27 public:
28   enum
29   {
30     Access_type_user    = 0x10,
31     Access_code_read    = 0x1a,
32     Access_data_write   = 0x12,
33     Size_32             = 0x04,
34   };
35
36   Unsigned16   limit_low;
37   Unsigned16   base_low;
38   Unsigned8    base_med;
39   Unsigned8    access;
40   Unsigned8    limit_high;
41   Unsigned8    base_high;
42
43
44 } __attribute__((packed));
45
46
47 class Idt_entry : public X86desc
48 {
49 private:
50   Unsigned16 _offset_low;
51   Unsigned16 _selector;
52   Unsigned8  _ist;
53   Unsigned8  _access;
54   Unsigned16 _offset_high;
55 } __attribute__((packed));
56
57
58
59 class Pseudo_descriptor
60 {
61   Unsigned16 _limit;
62   Mword _base;
63 } __attribute__((packed));
64
65
66
67 //----------------------------------------------------------------------------
68 IMPLEMENTATION [ia32 | ux]:
69
70 PUBLIC inline
71 Address Idt_entry::offset() const
72 { return (Address)_offset_low | ((Address)_offset_high << 16); }
73
74 PUBLIC inline
75 Idt_entry::Idt_entry()
76 {}
77
78 // interrupt gate
79 PUBLIC inline
80 Idt_entry::Idt_entry(Address entry, Unsigned16 selector, Unsigned8 access, unsigned = 0)
81 {
82   _offset_low  = entry & 0x0000ffff;
83   _selector    = selector;
84   _ist         = 0;
85   _access      = access | X86desc::Access_present;
86   _offset_high = (entry & 0xffff0000) >> 16;
87 }
88
89 // task gate
90 PUBLIC inline
91 Idt_entry::Idt_entry(Unsigned16 selector, Unsigned8 access)
92 {
93   _offset_low  = 0;
94   _selector    = selector;
95   _ist         = 0;
96   _access      = access | X86desc::Access_present;
97   _offset_high = 0;
98 }
99
100 PUBLIC inline
101 Address
102 Gdt_entry::base() const
103 {
104   return (Address)base_low | ((Address)base_med  << 16)
105          | ((Address)base_high << 24);
106 }
107
108 //----------------------------------------------------------------------------
109 INTERFACE [amd64]:
110 EXTENSION
111 class Idt_entry
112 {
113 private:
114   Unsigned32   _offset_high1;
115   Unsigned32   _ignored;
116 };
117
118
119 //-----------------------------------------------------------------------------
120 IMPLEMENTATION [amd64]:
121
122 #include <panic.h>
123
124 PUBLIC inline
125 Address Idt_entry::offset() const
126 {
127   return (Address)_offset_low | ((Address)_offset_high << 16)
128          | ((Address)_offset_high1 << 32);
129 }
130
131 // interrupt gate
132 PUBLIC inline
133 Idt_entry::Idt_entry(Address entry, Unsigned16 selector, Unsigned8 access, Unsigned8 ist_entry = 0)
134 {
135   _offset_low   = entry & 0x000000000000ffffLL;
136   _selector     = selector;
137   _ist          = ist_entry;
138   _access       = access | Access_present;
139   _offset_high  = (entry & 0x00000000ffff0000LL) >> 16;
140   _offset_high1 = (entry & 0xffffffff00000000LL) >> 32;
141   _ignored      = 0;
142 }
143
144
145 PUBLIC inline
146 Address
147 Gdt_entry::base() const
148 {
149   Address b = (Address)base_low | ((Address)base_med  << 16)
150               | ((Address)base_high << 24);
151   if (access & 0x10)
152     return b;
153
154   return b | ((Unsigned64 const *)this)[1] << 32;
155 }
156
157 // task gate
158 PUBLIC
159 Idt_entry::Idt_entry(Unsigned16, Unsigned8)
160 { panic("AMD64 does not support task gates"); }
161
162
163 IMPLEMENTATION[debug]:
164
165 #include <cstdio>
166
167
168 PUBLIC
169 const char*
170 X86desc::type_str() const
171 {
172   static char const * const desc_type[32] =
173     {
174       "reserved",          "16-bit tss (avail)",
175       "ldt",               "16-bit tss (busy)",
176       "16-bit call gate",  "task gate",
177       "16-bit int gate",   "16-bit trap gate",
178       "reserved",          "32-bit tss (avail)",
179       "reserved",          "32-bit tss (busy)",
180       "32-bit call gate",  "reserved",
181       "32-bit int gate",   "32-bit trap gate",
182       "data r/o",          "data r/o acc",
183       "data r/w",          "data r/w acc",
184       "data r/o exp-dn",   "data r/o exp-dn",
185       "data r/w exp-dn",   "data r/w exp-dn acc",
186       "code x/o",          "code x/o acc", 
187       "code x/r",          "code x/r acc",
188       "code x/r conf",     "code x/o conf acc",
189       "code x/r conf",     "code x/r conf acc"
190     };
191
192   Unsigned8 const *t = (Unsigned8 const *)this;
193
194   return desc_type[t[5] & 0x1f];
195 }
196
197 PUBLIC
198 void
199 Gdt_entry::show() const
200 {
201   static char const modes[] = { 16, 64, 32, -1 };
202   // segment descriptor
203   Address b = base();
204   printf("%016lx-%016lx dpl=%d %dbit %s %02X (\033[33;1m%s\033[m)\n",
205          b, b + size(), (access & 0x60) >> 5,
206          modes[mode()],
207          access & 0x10 ? "code/data" : "system   ",
208          access & 0x1f, type_str());
209 }
210
211 PUBLIC inline
212 unsigned
213 Idt_entry::selector() const
214 { return _selector; }
215
216 PUBLIC
217 void
218 Idt_entry::show() const
219 {
220   if (type() == 0x5)
221     {
222       // Task gate
223
224       printf("--------  sel=%04x dpl=%d %02X (\033[33;1m%s\033[m)\n",
225              selector(), dpl(), type(), type_str());
226     }
227   else
228     {
229       Address o = offset();
230
231       printf("%016lx  sel=%04x dpl=%d %02X (\033[33;1m%s\033[m)\n",
232              o, selector(), dpl(), type(), type_str());
233     }
234 }
235
236
237 PUBLIC
238 void
239 X86desc::show() const
240 {
241   if (present())
242     {
243       if ((access() & 0x16) == 0x06)
244         static_cast<Idt_entry const*>(this)->show();
245       else
246         static_cast<Gdt_entry const*>(this)->show();
247     }
248   else
249     {
250       printf("--------  dpl=%d %02X (\033[33;1m%s\033[m)\n",
251           dpl(), type(), type_str());
252     }
253 }
254
255 IMPLEMENTATION:
256
257 #include <cstring>
258
259 PUBLIC inline
260 X86desc::X86desc()
261 {}
262
263 PUBLIC inline
264 unsigned X86desc::access() const
265 { return ((Unsigned8 const *)this)[5]; }
266
267 PUBLIC inline NEEDS[X86desc::access]
268 int
269 X86desc::present() const
270 {
271   return (access() & 0x80) >> 7;
272 }
273
274 PUBLIC inline NEEDS[X86desc::access]
275 Unsigned8
276 X86desc::type() const
277 {
278   return access() & 0x1f;
279 }
280
281 PUBLIC inline NEEDS[X86desc::access]
282 Unsigned8
283 X86desc::dpl() const
284 {
285   return (access() & 0x60) >> 5;
286 }
287
288 PUBLIC inline NEEDS[X86desc::present, X86desc::dpl]
289 bool
290 X86desc::unsafe() const
291 { return present() && (dpl() != 3); }
292
293 PUBLIC inline
294 Pseudo_descriptor::Pseudo_descriptor()
295 {}
296
297 PUBLIC inline
298 Pseudo_descriptor::Pseudo_descriptor(Address base, Unsigned16 limit)
299   : _limit(limit), _base(base)
300 {}
301
302 PUBLIC inline
303 Address
304 Pseudo_descriptor::base() const
305 {
306   return _base;
307 }
308
309 PUBLIC inline
310 unsigned
311 Idt_entry::ist() const
312 { return _ist; }
313
314 PUBLIC inline
315 Unsigned16
316 Pseudo_descriptor::limit() const
317 { return _limit; }
318
319 PUBLIC inline NEEDS [<cstring>]
320 void
321 Idt_entry::clear()
322 { memset(this, 0, sizeof(*this)); }
323
324 PUBLIC inline
325 Gdt_entry::Gdt_entry(Address base, Unsigned32 limit,
326                      Unsigned8 _access, Unsigned8 szbits)
327 {
328   limit_low  =  limit & 0x0000ffff;
329   base_low   =  base  & 0x0000ffff;
330   base_med   = (base  & 0x00ff0000) >> 16;
331   access     =  _access | Access_present;
332   limit_high = ((limit & 0x000f0000) >> 16) |
333                         (((Unsigned16)szbits) << 4);
334   base_high  = (base  & 0xff000000) >> 24;
335 }
336
337 PUBLIC inline
338 Gdt_entry::Gdt_entry()
339 {}
340
341
342 PUBLIC inline
343 Mword
344 Gdt_entry::limit() const
345 { return (Mword)limit_low | (((Mword)limit_high & 0x0f) << 16); }
346
347 PUBLIC inline NEEDS[Gdt_entry::granularity, Gdt_entry::limit]
348 Mword
349 Gdt_entry::size() const
350 {
351   Mword l = limit();
352   return granularity() ? ((l+1) << 12)-1 : l;
353 }
354
355 PUBLIC inline
356 bool
357 Gdt_entry::avl() const
358 {
359   return (limit_high & 0x10);
360 }
361
362 PUBLIC inline
363 bool
364 Gdt_entry::seg64() const
365 {
366   return (limit_high & 0x20);
367 }
368
369 PUBLIC inline
370 bool
371 Gdt_entry::seg32() const
372 {
373   return (limit_high & 0x40);
374 }
375
376 PUBLIC inline
377 unsigned
378 Gdt_entry::mode() const
379 { return (limit_high >> 5) & 3; }
380
381 PUBLIC inline
382 bool
383 Gdt_entry::granularity() const
384 {
385   return (limit_high & 0x80);
386 }
387
388 PUBLIC inline
389 bool
390 Gdt_entry::writable() const
391 {
392   return (type() & 0x02);
393 }
394
395 PUBLIC inline
396 int
397 Gdt_entry::contents() const
398 {
399   return (type() & 0x0c) >> 2;
400 }
401
402 PUBLIC inline
403 void
404 Gdt_entry::clear()
405 {
406   *(Unsigned64*)this = 0;
407 }
408