]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ia32/x86desc.cpp
e70ff20cac61bdeec28cba6ca0a7817b6bdc07da
[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   Address l = size();
205   printf("%016lx-%016lx dpl=%d %dbit %s %02X (\033[33;1m%s\033[m)\n",
206             b, b+l, (access & 0x60) >> 5, 
207              modes[mode()],
208              access & 0x10 ? "code/data" : "system   ",
209              access & 0x1f, type_str());
210 }
211
212 PUBLIC inline
213 unsigned
214 Idt_entry::selector() const
215 { return _selector; }
216
217 PUBLIC
218 void
219 Idt_entry::show() const
220 {
221   if (type() == 0x5)
222     {
223       // Task gate
224
225       printf("--------  sel=%04x dpl=%d %02X (\033[33;1m%s\033[m)\n",
226              selector(), dpl(), type(), type_str());
227     }
228   else
229     {
230       Address o = offset();
231
232       printf("%016lx  sel=%04x dpl=%d %02X (\033[33;1m%s\033[m)\n",
233              o, selector(), dpl(), type(), type_str());
234     }
235 }
236
237
238 PUBLIC
239 void
240 X86desc::show() const
241 {
242   if (present())
243     {
244       if ((access() & 0x16) == 0x06)
245         static_cast<Idt_entry const*>(this)->show();
246       else
247         static_cast<Gdt_entry const*>(this)->show();
248     }
249   else
250     {
251       printf("--------  dpl=%d %02X (\033[33;1m%s\033[m)\n",
252           dpl(), type(), type_str());
253     }
254 }
255
256 IMPLEMENTATION:
257
258 #include <cstring>
259
260 PUBLIC inline
261 X86desc::X86desc()
262 {}
263
264 PUBLIC inline
265 unsigned X86desc::access() const
266 { return ((Unsigned8 const *)this)[5]; }
267
268 PUBLIC inline NEEDS[X86desc::access]
269 int
270 X86desc::present() const
271 {
272   return (access() & 0x80) >> 7;
273 }
274
275 PUBLIC inline NEEDS[X86desc::access]
276 Unsigned8
277 X86desc::type() const
278 {
279   return access() & 0x1f;
280 }
281
282 PUBLIC inline NEEDS[X86desc::access]
283 Unsigned8
284 X86desc::dpl() const
285 {
286   return (access() & 0x60) >> 5;
287 }
288
289 PUBLIC inline NEEDS[X86desc::present, X86desc::dpl]
290 bool
291 X86desc::unsafe() const
292 { return present() && (dpl() != 3); }
293
294 PUBLIC inline
295 Pseudo_descriptor::Pseudo_descriptor()
296 {}
297
298 PUBLIC inline
299 Pseudo_descriptor::Pseudo_descriptor(Address base, Unsigned16 limit)
300   : _limit(limit), _base(base)
301 {}
302
303 PUBLIC inline
304 Address
305 Pseudo_descriptor::base() const
306 {
307   return _base;
308 }
309
310 PUBLIC inline
311 unsigned
312 Idt_entry::ist() const
313 { return _ist; }
314
315 PUBLIC inline
316 Unsigned16
317 Pseudo_descriptor::limit() const
318 { return _limit; }
319
320 PUBLIC inline NEEDS [<cstring>]
321 void
322 Idt_entry::clear()
323 { memset(this, 0, sizeof(*this)); }
324
325 PUBLIC inline
326 Gdt_entry::Gdt_entry(Address base, Unsigned32 limit,
327                      Unsigned8 _access, Unsigned8 szbits)
328 {
329   limit_low  =  limit & 0x0000ffff;
330   base_low   =  base  & 0x0000ffff;
331   base_med   = (base  & 0x00ff0000) >> 16;
332   access     =  _access | Access_present;
333   limit_high = ((limit & 0x000f0000) >> 16) |
334                         (((Unsigned16)szbits) << 4);
335   base_high  = (base  & 0xff000000) >> 24;
336 }
337
338 PUBLIC inline
339 Gdt_entry::Gdt_entry()
340 {}
341
342
343 PUBLIC inline
344 Mword
345 Gdt_entry::limit() const
346 { return (Mword)limit_low | (((Mword)limit_high & 0x0f) << 16); }
347
348 PUBLIC inline NEEDS[Gdt_entry::granularity, Gdt_entry::limit]
349 Mword
350 Gdt_entry::size() const
351 {
352   Mword l = limit();
353   return (granularity()) ? ((l+1) << 12)-1 : l;
354 }
355
356 PUBLIC inline
357 bool
358 Gdt_entry::avl() const
359 {
360   return (limit_high & 0x10);
361 }
362
363 PUBLIC inline
364 bool
365 Gdt_entry::seg64() const
366 {
367   return (limit_high & 0x20);
368 }
369
370 PUBLIC inline
371 bool
372 Gdt_entry::seg32() const
373 {
374   return (limit_high & 0x40);
375 }
376
377 PUBLIC inline
378 unsigned
379 Gdt_entry::mode() const
380 { return (limit_high >> 5) & 3; }
381
382 PUBLIC inline
383 bool
384 Gdt_entry::granularity() const
385 {
386   return (limit_high & 0x80);
387 }
388
389 PUBLIC inline
390 bool
391 Gdt_entry::writable() const
392 {
393   return (type() & 0x02);
394 }
395
396 PUBLIC inline
397 int
398 Gdt_entry::contents() const
399 {
400   return (type() & 0x0c) >> 2;
401 }
402
403 PUBLIC inline
404 void
405 Gdt_entry::clear()
406 {
407   *(Unsigned64*)this = 0;
408 }
409