]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_cpu.c
Update
[l4.git] / l4 / pkg / bootstrap / server / src / ARCH-amd64 / boot32 / boot_cpu.c
1 /*
2  * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *          Frank Mehnert <fm3@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #include <assert.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <unistd.h>
14
15 #include "types.h"
16 #include "boot_cpu.h"
17 #include "boot_paging.h"
18
19
20 unsigned  KERNEL_CS_64          = 0x20; // XXX
21
22 enum
23 {
24   PML4ESHIFT            = 38,
25   PML4EMASK             = 0x1ff,
26   PDPESHIFT             = 30,
27   PDPEMASK              = 0x1ff,
28   PDESHIFT              = 21,
29   PDEMASK               = 0x1ff,
30   PTESHIFT              = 12,
31   PTEMASK               = 0x1ff,
32
33   INTEL_PTE_VALID       = 0x0000000000000001LL,
34   INTEL_PTE_WRITE       = 0x0000000000000002LL,
35   INTEL_PTE_USER        = 0x0000000000000004LL,
36   INTEL_PTE_WTHRU       = 0x00000008,
37   INTEL_PTE_NCACHE      = 0x00000010,
38   INTEL_PTE_REF         = 0x00000020,
39   INTEL_PTE_MOD         = 0x00000040,
40   INTEL_PTE_GLOBAL      = 0x00000100,
41   INTEL_PTE_AVAIL       = 0x00000e00,
42   INTEL_PTE_PFN         = 0x000ffffffffff000LL,
43
44   INTEL_PDE_VALID       = 0x0000000000000001LL,
45   INTEL_PDE_WRITE       = 0x0000000000000002LL,
46   INTEL_PDE_USER        = 0x0000000000000004LL,
47   INTEL_PDE_WTHRU       = 0x00000008,
48   INTEL_PDE_NCACHE      = 0x00000010,
49   INTEL_PDE_REF         = 0x00000020,
50   INTEL_PDE_MOD         = 0x00000040,
51   INTEL_PDE_SUPERPAGE   = 0x0000000000000080LL,
52   INTEL_PDE_GLOBAL      = 0x00000100,
53   INTEL_PDE_AVAIL       = 0x00000e00,
54   INTEL_PDE_PFN         = 0x000ffffffffff000LL,
55
56   INTEL_PDPE_VALID      = 0x0000000000000001LL,
57   INTEL_PDPE_WRITE      = 0x0000000000000002LL,
58   INTEL_PDPE_USER       = 0x0000000000000004LL,
59   INTEL_PDPE_PFN        = 0x000ffffffffff000LL,
60
61   INTEL_PML4E_VALID     = 0x0000000000000001LL,
62   INTEL_PML4E_WRITE     = 0x0000000000000002LL,
63   INTEL_PML4E_USER      = 0x0000000000000004LL,
64   INTEL_PML4E_PFN       = 0x000ffffffffff000LL,
65
66   CPUF_4MB_PAGES        = 0x00000008,
67
68   CR0_PG                = 0x80000000,
69   CR4_PSE               = 0x00000010,
70   CR4_PAE               = 0x00000020,
71   EFL_AC                = 0x00040000,
72   EFL_ID                = 0x00200000,
73   EFER_LME              = 0x00000100,
74
75   BASE_TSS              = 0x08,
76   KERNEL_CS             = 0x10,
77   KERNEL_DS             = 0x18,
78
79   DBF_TSS               = 0x28, // XXX check this value
80
81   ACC_TSS               = 0x09,
82   ACC_TSS_BUSY          = 0x02,
83   ACC_CODE_R            = 0x1a,
84   ACC_DATA_W            = 0x12,
85   ACC_PL_K              = 0x00,
86   ACC_P                 = 0x80,
87   SZ_32                 = 0x4,
88   SZ_16                 = 0x0,
89   SZ_G                  = 0x8,
90   SZ_CODE_64            = 0x2, // XXX 64 Bit Code Segment
91
92   GDTSZ                 = (0x30/8), // XXX check this value
93   IDTSZ                 = 256,
94 };
95
96
97 struct pseudo_descriptor
98 {
99   l4_uint16_t pad;
100   l4_uint16_t limit;
101   l4_uint32_t linear_base;
102 };
103
104 struct x86_desc
105 {
106   l4_uint16_t limit_low;                /* limit 0..15 */
107   l4_uint16_t base_low;         /* base  0..15 */
108   l4_uint8_t  base_med;         /* base  16..23 */
109   l4_uint8_t  access;           /* access byte */
110   l4_uint8_t  limit_high:4;     /* limit 16..19 */
111   l4_uint8_t  granularity:4;    /* granularity */
112   l4_uint8_t  base_high;                /* base 24..31 */
113 } __attribute__((packed));
114
115 struct x86_gate
116 {
117   l4_uint16_t offset_low;       /* offset 0..15 */
118   l4_uint16_t selector;
119   l4_uint8_t  word_count;
120   l4_uint8_t  access;
121   l4_uint16_t offset_high;      /* offset 16..31 */
122 } __attribute__((packed));
123
124 struct x86_tss
125 {
126   l4_uint32_t back_link;
127   l4_uint32_t esp0, ss0;
128   l4_uint32_t esp1, ss1;
129   l4_uint32_t esp2, ss2;
130   l4_uint32_t cr3;
131   l4_uint32_t eip, eflags;
132   l4_uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
133   l4_uint32_t es, cs, ss, ds, fs, gs;
134   l4_uint32_t ldt;
135   l4_uint16_t trace_trap;
136   l4_uint16_t io_bit_map_offset;
137 };
138
139 struct gate_init_entry
140 {
141   l4_uint32_t entrypoint;
142   l4_uint16_t vector;
143   l4_uint16_t type;
144 };
145
146 struct trap_state
147 {
148   l4_uint32_t gs, fs, es, ds;
149   l4_uint32_t edi, esi, ebp, cr2, ebx, edx, ecx, eax;
150   l4_uint32_t trapno, err;
151   l4_uint32_t eip, cs, eflags, esp, ss;
152 };
153
154 static l4_uint32_t       cpu_feature_flags;
155 static l4_uint32_t        base_pml4_pa;
156 static struct x86_tss   base_tss;
157 static struct x86_desc  base_gdt[GDTSZ];
158 static struct x86_gate  base_idt[IDTSZ];
159
160 static void handle_dbf(void);
161 static char           dbf_stack[2048];
162 static struct x86_tss dbf_tss =
163   {
164     0/*back_link*/,
165     0/*esp0*/, 0/*ss0*/, 0/*esp1*/, 0/*ss1*/, 0/*esp2*/, 0/*ss2*/,
166     0/*cr3*/,
167     (l4_uint32_t)handle_dbf/*eip*/, 0x00000082/*eflags*/,
168     0/*eax*/, 0/*ecx*/, 0/*edx*/, 0/*ebx*/,
169     (l4_uint32_t)dbf_stack + sizeof(dbf_stack)/*esp*/,
170     0/*ebp*/, 0/*esi*/, 0/*edi*/,
171     KERNEL_DS/*es*/, KERNEL_CS/*cs*/, KERNEL_DS/*ss*/,
172     KERNEL_DS/*ds*/, KERNEL_DS/*fs*/, KERNEL_DS/*gs*/,
173     0/*ldt*/, 0/*trace_trap*/, 0x8000/*io_bit_map_offset*/
174   };
175
176 static inline l4_uint64_t* find_pml4e(l4_uint32_t pml4_pa, l4_uint64_t la)
177 { return (&((l4_uint64_t*)pml4_pa)[(la >> PML4ESHIFT) & PML4EMASK]); }
178
179 static inline l4_uint64_t* find_pdpe(l4_uint32_t pdp_pa, l4_uint64_t la)
180 { return (&((l4_uint64_t*)pdp_pa)[(la >> PDPESHIFT) & PDPEMASK]); }
181
182 static inline l4_uint64_t* find_pde(l4_uint32_t pdir_pa, l4_uint64_t la)
183 { return (&((l4_uint64_t*)pdir_pa)[(la >> PDESHIFT) & PDEMASK]); }
184
185 static inline l4_uint64_t* find_pte(l4_uint32_t ptab_pa, l4_uint64_t la)
186 { return (&((l4_uint64_t*)ptab_pa)[(la >> PTESHIFT) & PTEMASK]); }
187
188 static inline l4_uint32_t get_eflags(void)
189 { l4_uint32_t efl; asm volatile("pushf ; popl %0" : "=r" (efl)); return efl; }
190
191 static inline void set_eflags(l4_uint32_t efl)
192 { asm volatile("pushl %0 ; popf" : : "r" (efl) : "memory"); }
193
194 static inline void set_ds(l4_uint16_t ds)
195 { asm volatile("movw %w0,%%ds" : : "r" (ds)); }
196
197 static inline void set_es(l4_uint16_t es)
198 { asm volatile("movw %w0,%%es" : : "r" (es)); }
199
200 static inline void set_fs(l4_uint16_t fs)
201 { asm volatile("movw %w0,%%fs" : : "r" (fs)); }
202
203 static inline void set_gs(l4_uint16_t gs)
204 { asm volatile("movw %w0,%%gs" : : "r" (gs)); }
205
206 static inline void set_ss(l4_uint16_t ss)
207 { asm volatile("movw %w0,%%ss" : : "r" (ss)); }
208
209 static inline l4_uint16_t get_ss(void)
210 { l4_uint16_t ss; asm volatile("movw %%ss,%w0" : "=r" (ss)); return ss; }
211
212 #define set_idt(pseudo_desc) \
213  asm volatile("lidt %0" : : "m" ((pseudo_desc)->limit) : "memory")
214
215 #define set_gdt(pseudo_desc) \
216  asm volatile("lgdt %0" : : "m" ((pseudo_desc)->limit) : "memory")
217
218 #define set_tr(seg) \
219  asm volatile("ltr %0" : : "rm" ((l4_uint16_t)(seg)))
220
221 #define get_esp() \
222  ({ register l4_uint32_t _temp__; \
223     asm("movl %%esp, %0" : "=r" (_temp__)); _temp__; })
224
225 #define get_cr0() \
226  ({ register l4_uint32_t _temp__; \
227     asm volatile("mov %%cr0, %0" : "=r" (_temp__)); _temp__; })
228
229 #define set_cr3(value) \
230  ({ register l4_uint32_t _temp__ = (value); \
231     asm volatile("mov %0, %%cr3" : : "r" (_temp__)); })
232
233 #define get_cr4() \
234  ({ register l4_uint32_t _temp__; \
235     asm volatile("mov %%cr4, %0" : "=r" (_temp__)); _temp__; })
236
237 #define set_cr4(value) \
238  ({ register l4_uint32_t _temp__ = (value); \
239     asm volatile("mov %0, %%cr4" : : "r" (_temp__)); })
240
241
242 static inline void enable_longmode(void)
243 {
244   l4_uint32_t dummy;
245   asm volatile("rdmsr; bts $8, %%eax; wrmsr"
246                :"=a"(dummy), "=d"(dummy) : "c"(0xc0000080));
247 }
248
249 static inline void
250 fill_descriptor(struct x86_desc *desc, l4_uint32_t base, l4_uint32_t limit,
251                 l4_uint8_t access, l4_uint8_t sizebits)
252 {
253   if (limit > 0xfffff)
254     {
255       limit >>= 12;
256       sizebits |= SZ_G;
257     }
258   desc->limit_low = limit & 0xffff;
259   desc->base_low = base & 0xffff;
260   desc->base_med = (base >> 16) & 0xff;
261   desc->access = access | ACC_P;
262   desc->limit_high = limit >> 16;
263   desc->granularity = sizebits;
264   desc->base_high = base >> 24;
265 }
266
267 static inline void
268 fill_gate(struct x86_gate *gate, l4_uint32_t offset,
269           l4_uint16_t selector, l4_uint8_t access)
270 {
271   gate->offset_low  = offset & 0xffff;
272   gate->selector    = selector;
273   gate->word_count  = 0;
274   gate->access      = access | ACC_P;
275   gate->offset_high = (offset >> 16) & 0xffff;
276 }
277
278 static inline void
279 paging_enable(l4_uint32_t pml4)
280 {
281   /* Enable Physical l4_uint64_t Extension (PAE). */
282   set_cr4(get_cr4() | CR4_PAE);
283
284   /* Load the page map level 4.  */
285   set_cr3(pml4);
286
287   /* Enable long mode. */
288   enable_longmode();
289
290   /* Turn on paging and switch to long mode. */
291   asm volatile("movl  %0,%%cr0 ; jmp  1f ; 1:" : : "r" (get_cr0() | CR0_PG));
292 }
293
294 static void
295 panic(const char *str)
296 {
297   printf("PANIC: %s\n", str);
298   while (1)
299     ;
300   _exit(-1);
301 }
302
303 static void
304 cpuid(void)
305 {
306   int orig_eflags = get_eflags();
307
308   /* Check for a dumb old 386 by trying to toggle the AC flag.  */
309   set_eflags(orig_eflags ^ EFL_AC);
310   if ((get_eflags() ^ orig_eflags) & EFL_AC)
311     {
312       /* It's a 486 or better.  Now try toggling the ID flag.  */
313       set_eflags(orig_eflags ^ EFL_ID);
314       if ((get_eflags() ^ orig_eflags) & EFL_ID)
315         {
316           int highest_val, dummy;
317           asm volatile("cpuid"
318                         : "=a" (highest_val)
319                         : "a" (0) : "ebx", "ecx", "edx");
320
321           if (highest_val >= 1)
322             {
323               asm volatile("cpuid"
324                            : "=a" (dummy),
325                              "=d" (cpu_feature_flags)
326                            : "a" (1)
327                            : "ebx", "ecx");
328             }
329         }
330     }
331
332   set_eflags(orig_eflags);
333 }
334
335 extern struct gate_init_entry boot_idt_inittab[];
336 static void
337 base_idt_init(void)
338 {
339   struct x86_gate *dst = base_idt;
340   const struct gate_init_entry *src = boot_idt_inittab;
341
342   while (src->entrypoint)
343     {
344       if ((src->type & 0x1f) == 0x05)
345         // task gate
346         fill_gate(&dst[src->vector], 0, src->entrypoint, src->type);
347       else
348         // interrupt gate
349         fill_gate(&dst[src->vector], src->entrypoint, KERNEL_CS, src->type);
350       src++;
351     }
352 }
353
354 static void
355 base_gdt_init(void)
356 {
357   /* Initialize the base TSS descriptor.  */
358   fill_descriptor(&base_gdt[BASE_TSS / 8],
359                   (l4_uint32_t)&base_tss, sizeof(base_tss) - 1,
360                   ACC_PL_K | ACC_TSS, 0);
361   /* Initialize the TSS descriptor for the double fault handler */
362   fill_descriptor(&base_gdt[DBF_TSS / 8],
363                   (l4_uint32_t)&dbf_tss, sizeof(dbf_tss) - 1,
364                   ACC_PL_K | ACC_TSS, 0);
365   /* Initialize the 32-bit kernel code and data segment descriptors
366      to point to the base of the kernel linear space region.  */
367   fill_descriptor(&base_gdt[KERNEL_CS / 8], 0, 0xffffffff,
368                   ACC_PL_K | ACC_CODE_R, SZ_32);
369   fill_descriptor(&base_gdt[KERNEL_DS / 8], 0, 0xffffffff,
370                   ACC_PL_K | ACC_DATA_W, SZ_32);
371   /* XXX Initialize the 64-bit kernel code segment descriptor */
372   fill_descriptor(&base_gdt[KERNEL_CS_64 / 8], 0, 0xffffffff,
373                   ACC_PL_K | ACC_CODE_R, SZ_CODE_64);
374 }
375
376 static void
377 base_tss_init(void)
378 {
379   base_tss.ss0 = KERNEL_DS;
380   base_tss.esp0 = get_esp(); /* only temporary */
381   base_tss.io_bit_map_offset = sizeof(base_tss);
382 }
383
384 static void
385 base_gdt_load(void)
386 {
387   struct pseudo_descriptor pdesc;
388
389   /* Create a pseudo-descriptor describing the GDT.  */
390   pdesc.limit = sizeof(base_gdt) - 1;
391   pdesc.linear_base = (l4_uint32_t)&base_gdt;
392
393   /* Load it into the CPU.  */
394   set_gdt(&pdesc);
395
396   /* Reload all the segment registers from the new GDT. */
397   asm volatile("ljmp  %0,$1f ;  1:" : : "i" (KERNEL_CS));
398   set_ds(KERNEL_DS);
399   set_es(KERNEL_DS);
400   set_ss(KERNEL_DS);
401   set_fs(0);
402   set_gs(0);
403 }
404
405 static void
406 base_idt_load(void)
407 {
408   struct pseudo_descriptor pdesc;
409
410   /* Create a pseudo-descriptor describing the GDT.  */
411   pdesc.limit = sizeof(base_idt) - 1;
412   pdesc.linear_base = (l4_uint32_t)&base_idt;
413   set_idt(&pdesc);
414 }
415
416 static void
417 base_tss_load(void)
418 {
419   /* Make sure the TSS isn't marked busy.  */
420   base_gdt[BASE_TSS / 8].access &= ~ACC_TSS_BUSY;
421   asm volatile ("" : : : "memory");
422   set_tr(BASE_TSS);
423 }
424
425 void
426 base_cpu_setup(void)
427 {
428   cpuid();
429   base_idt_init();
430   base_gdt_init();
431   base_tss_init();
432   // force tables to memory before loading segment registers
433   asm volatile ("" : : : "memory");
434   base_gdt_load();
435   base_idt_load();
436   base_tss_load();
437 }
438
439 struct ptab64_mem_info_t ptab64_mem_info;
440
441 static void
442 ptab_alloc(l4_uint32_t *out_ptab_pa)
443 {
444   static char pool[6 << 12] __attribute__((aligned(4096)));
445   static l4_uint32_t pdirs;
446   static int initialized;
447
448   if (! initialized)
449     {
450       initialized = 1;
451       ptab64_mem_info.addr = (l4_uint32_t)pool;
452       ptab64_mem_info.size = sizeof(pool);
453       memset(pool, 0, sizeof(pool));
454       pdirs = ((l4_uint32_t)pool + PAGE_SIZE - 1) & ~PAGE_MASK;
455     }
456
457   if (pdirs > (l4_uint32_t)pool + sizeof(pool))
458     panic("Cannot allocate page table -- increase ptab_alloc::pool");
459
460   *out_ptab_pa = pdirs;
461   pdirs += PAGE_SIZE;
462 }
463
464 static void
465 pdir_map_range(l4_uint32_t pml4_pa, l4_uint64_t la, l4_uint64_t pa,
466                l4_uint64_t size, l4_uint32_t mapping_bits)
467 {
468   assert(size);
469   assert(la+size-1 > la); // avoid 4GB wrap around
470
471   while (size > 0)
472     {
473       l4_uint64_t *pml4e = find_pml4e(pml4_pa, la);
474
475       /* Create new pml4e with corresponding pdp (page directory pointer)
476        * if no valid entry exists. */
477       if (!(*pml4e & INTEL_PML4E_VALID))
478         {
479           l4_uint32_t pdp_pa;
480
481           /* Allocate new page for pdp. */
482           ptab_alloc(&pdp_pa);
483
484           /* Set the pml4 to point to it. */
485           *pml4e = (pdp_pa & INTEL_PML4E_PFN)
486             | INTEL_PML4E_VALID | INTEL_PML4E_USER | INTEL_PML4E_WRITE;
487         }
488
489       do
490         {
491           l4_uint64_t *pdpe = find_pdpe(*pml4e & INTEL_PML4E_PFN, la);
492
493           /* Create new pdpe with corresponding pd (page directory)
494            * if no valid entry exists. */
495           if (!(*pdpe & INTEL_PDPE_VALID))
496             {
497               l4_uint32_t pd_pa;
498
499               /* Allocate new page for pd. */
500               ptab_alloc(&pd_pa);
501
502               /* Set the pdpe to point to it. */
503               *pdpe = (pd_pa & INTEL_PDPE_PFN)
504                 | INTEL_PDPE_VALID | INTEL_PDPE_USER | INTEL_PDPE_WRITE;
505             }
506
507           do
508             {
509               l4_uint64_t *pde = find_pde(*pdpe & INTEL_PDPE_PFN, la);
510
511               /* Use a 2MB page if we can.  */
512               if (superpage_aligned(la) && superpage_aligned(pa)
513                   && (size >= SUPERPAGE_SIZE))
514                   //&& (cpu_feature_flags & CPUF_4MB_PAGES)) XXX
515                 {
516                   /* a failed assertion here may indicate a memory wrap
517                      around problem */
518                   assert(!(*pde & INTEL_PDE_VALID));
519                   /* XXX what if an empty page table exists
520                      from previous finer-granularity mappings? */
521                   *pde = pa | mapping_bits | INTEL_PDE_SUPERPAGE;
522                   la += SUPERPAGE_SIZE;
523                   pa += SUPERPAGE_SIZE;
524                   size -= SUPERPAGE_SIZE;
525                 }
526               else
527                 {
528                   /* Find the page table, creating one if necessary.  */
529                   if (!(*pde & INTEL_PDE_VALID))
530                     {
531                       l4_uint32_t ptab_pa;
532
533                       /* Allocate a new page table.  */
534                       ptab_alloc(&ptab_pa);
535
536                       /* Set the pde to point to it.  */
537                       *pde = (ptab_pa & INTEL_PTE_PFN)
538                         | INTEL_PDE_VALID | INTEL_PDE_USER | INTEL_PDE_WRITE;
539                     }
540                   assert(!(*pde & INTEL_PDE_SUPERPAGE));
541
542
543                   /* Use normal 4KB page mappings.  */
544                   do
545                     {
546                       l4_uint64_t *pte = find_pte(*pde & INTEL_PDE_PFN, la);
547                       assert(!(*pte & INTEL_PTE_VALID));
548
549                       /* Insert the mapping.  */
550                       *pte = pa | mapping_bits;
551
552                       /* Advance to the next page.  */
553                       //pte++;
554                       la += PAGE_SIZE;
555                       pa += PAGE_SIZE;
556                       size -= PAGE_SIZE;
557                     }
558                   while ((size > 0) && !superpage_aligned(la));
559                 }
560             }
561           while ((size > 0) && !pd_aligned(la));
562         }
563       while ((size > 0) && !pdp_aligned(la));
564     }
565 }
566
567 void
568 base_paging_init(l4_uint64_t phys_mem_max)
569 {
570   ptab_alloc(&base_pml4_pa);
571
572   // Establish one-to-one mappings for the physical memory
573   pdir_map_range(base_pml4_pa, 0, 0, phys_mem_max,
574                  INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER);
575
576   //dbf_tss.cr3 = base_pml4_pa;
577
578   // XXX Turn on paging and activate long mode
579   paging_enable(base_pml4_pa);
580 }
581
582 void trap_dump_panic(const struct trap_state *st);
583 void trap_dump_panic(const struct trap_state *st)
584 {
585   int from_user = st->cs & 3;
586   int i;
587
588   printf("EAX %08x EBX %08x ECX %08x EDX %08x\n",
589          st->eax, st->ebx, st->ecx, st->edx);
590   printf("ESI %08x EDI %08x EBP %08x ESP %08x\n",
591          st->esi, st->edi, st->ebp,
592          from_user ? st->esp : (l4_uint32_t)&st->esp);
593   printf("EIP %08x EFLAGS %08x\n", st->eip, st->eflags);
594   printf("CS %04x SS %04x DS %04x ES %04x FS %04x GS %04x\n",
595          st->cs & 0xffff, from_user ? st->ss & 0xffff : get_ss(),
596          st->ds & 0xffff, st->es & 0xffff,
597          st->fs & 0xffff, st->gs & 0xffff);
598   printf("trapno %d, error %08x, from %s mode\n",
599          st->trapno, st->err, from_user ? "user" : "kernel");
600
601   if (st->trapno == 0x0d)
602     {
603       if (st->err & 1)
604         printf("(external event");
605       else
606         printf("(internal event");
607       if (st->err & 2)
608         printf(" regarding IDT gate descriptor no. 0x%02x)\n", st->err >> 3);
609       else
610         printf(" regarding %s entry no. 0x%02x)\n",
611                st->err & 4 ? "LDT" : "GDT", st->err >> 3);
612     }
613   else if (st->trapno == 0x0e)
614     printf("page fault linear address %08x\n", st->cr2);
615
616   if (!from_user)
617     for (i = 0; i < 32; i++)
618       printf("%08x%c", (&st->esp)[i], ((i & 7) == 7) ? '\n' : ' ');
619
620   panic("Unexpected trap while booting Fiasco!");
621 }
622
623 static void
624 handle_dbf(void)
625 {
626   /*
627   printf("\n"
628          "EAX %08x EBX %08x ECX %08x EDX %08x\n"
629          "ESI %08x EDI %08x EBP %08x ESP %08x\n"
630          "EIP %08x EFLAGS %08x\n"
631          "CS %04x SS %04x DS %04x ES %04x FS %04x GS %04x\n\n",
632          base_tss.eax, base_tss.ebx, base_tss.ecx, base_tss.edx,
633          base_tss.esi, base_tss.edi, base_tss.ebp, base_tss.esp,
634          base_tss.eip, base_tss.eflags,
635          base_tss.cs & 0xffff, base_tss.ss & 0xffff, base_tss.ds & 0xffff,
636          base_tss.es & 0xffff, base_tss.fs & 0xffff, base_tss.gs & 0xffff);
637   */
638   panic("Unexpected DOUBLE FAULT while booting Fiasco!");
639 }