Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/boot/init.c need to be fixed.

0001 /*                    The Quest Operating System
0002  *  Copyright (C) 2005-2010  Richard West, Boston University
0003  *
0004  *  This program is free software: you can redistribute it and/or modify
0005  *  it under the terms of the GNU General Public License as published by
0006  *  the Free Software Foundation, either version 3 of the License, or
0007  *  (at your option) any later version.
0008  *
0009  *  This program is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *  GNU General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License
0015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #include "boot/multiboot.h"
0019 #include "arch/i386.h"
0020 #include "arch/i386-percpu.h"
0021 #include "util/cpuid.h"
0022 #include "kernel.h"
0023 #include "fs/filesys.h"
0024 #include "smp/smp.h"
0025 #include "mem/mem.h"
0026 #include "drivers/ata/ata.h"
0027 #include "drivers/pci/pci.h"
0028 #include "util/printf.h"
0029 #include "util/screen.h"
0030 #include "util/debug.h"
0031 #include "util/perfmon.h"
0032 #include "drivers/input/keyboard.h"
0033 #include "sched/sched.h"
0034 
0035 extern descriptor idt[];
0036 
0037 extern uint32 _readwrite_pages, _readonly_pages, _bootstrap_pages;
0038 extern uint32 _kernelstart, _physicalkernelstart;
0039 
0040 /* initial C stack */
0041 uint32 stack[1024] __attribute__ ((aligned (0x1000)));
0042 
0043 /* Each CPU needs a TSS for the SS0, ESP0 fields */
0044 static uint16
0045 alloc_CPU_TSS (tss *tssp)
0046 {
0047   int i;
0048   descriptor *ad = (descriptor *)KERN_GDT;
0049 
0050   /* Search 2KB GDT for first free entry */
0051   for (i = 1; i < 256; i++)
0052     if (!(ad[i].fPresent))
0053       break;
0054 
0055   if (i == 256)
0056     panic ("No free selector for TSS");
0057 
0058   ad[i].uLimit0 = sizeof (tss);
0059   ad[i].uLimit1 = 0;
0060   ad[i].pBase0 = (uint32) tssp & 0xFFFF;
0061   ad[i].pBase1 = ((uint32) tssp >> 16) & 0xFF;
0062   ad[i].pBase2 = (uint32) tssp >> 24;
0063   ad[i].uType = 0x09;
0064   ad[i].uDPL = 0;               /* Only let kernel perform task-switching */
0065   ad[i].fPresent = 1;
0066   ad[i].f0 = 0;
0067   ad[i].fX = 0;
0068   ad[i].fGranularity = 0;       /* Set granularity of tss in bytes */
0069 
0070   tssp->usSS0 = 0x10;
0071   tssp->ulESP0 = (uint32) KERN_STK + 0x1000;
0072 
0073   return i << 3;
0074 
0075 }
0076 static uint16
0077 alloc_idle_TSS (int cpu_num)
0078 {
0079   int i;
0080   descriptor *ad = (descriptor *)KERN_GDT;
0081   quest_tss *pTSS = (quest_tss *) (&idleTSS[cpu_num]);
0082   void idle_task (void);
0083 
0084   /* Search 2KB GDT for first free entry */
0085   for (i = 1; i < 256; i++)
0086     if (!(ad[i].fPresent))
0087       break;
0088 
0089   if (i == 256)
0090     panic ("No free selector for TSS");
0091 
0092   ad[i].uLimit0 = sizeof (idleTSS[cpu_num]) - 1;
0093   ad[i].uLimit1 = 0;
0094   ad[i].pBase0 = (u32) pTSS & 0xFFFF;
0095   ad[i].pBase1 = ((u32) pTSS >> 16) & 0xFF;
0096   ad[i].pBase2 = (u32) pTSS >> 24;
0097   ad[i].uType = 0x09;           /* 32-bit tss */
0098   ad[i].uDPL = 0;               /* Only let kernel perform task-switching */
0099   ad[i].fPresent = 1;
0100   ad[i].f0 = 0;
0101   ad[i].fX = 0;
0102   ad[i].fGranularity = 0;       /* Set granularity of tss in bytes */
0103 
0104   u32 *stk = map_virtual_page (alloc_phys_frame () | 3);
0105 
0106   pTSS->CR3 = (u32) get_pdbr ();
0107   pTSS->initial_EIP = (u32) & idle_task;
0108   stk[1023] = pTSS->initial_EIP;
0109   pTSS->EFLAGS = F_1 | F_IOPL0;
0110 
0111   pTSS->ESP = (u32) &stk[1023];
0112   pTSS->EBP = pTSS->ESP;
0113 
0114   /* Return the index into the GDT for the segment */
0115   return i << 3;
0116 }
0117 
0118 
0119 
0120 /* Allocate a basic TSS */
0121 static uint16
0122 alloc_TSS (void *pPageDirectory, void *pEntry, int mod_num)
0123 {
0124 
0125   int i;
0126   descriptor *ad = (idt + 256); /* Get address of GDT from IDT address */
0127   quest_tss *pTSS = (quest_tss *) ul_tss[mod_num];
0128 
0129   /* Search 2KB GDT for first free entry */
0130   for (i = 1; i < 256; i++)
0131     if (!(ad[i].fPresent))
0132       break;
0133 
0134   if (i == 256)
0135     panic ("No free selector for TSS");
0136 
0137   ad[i].uLimit0 = sizeof (ul_tss[mod_num]) - 1;
0138   ad[i].uLimit1 = 0;
0139   ad[i].pBase0 = (u32) pTSS & 0xFFFF;
0140   ad[i].pBase1 = ((u32) pTSS >> 16) & 0xFF;
0141   ad[i].pBase2 = (u32) pTSS >> 24;
0142   ad[i].uType = 0x09;           /* 32-bit tss */
0143   ad[i].uDPL = 0;               /* Only let kernel perform task-switching */
0144   ad[i].fPresent = 1;
0145   ad[i].f0 = 0;
0146   ad[i].fX = 0;
0147   ad[i].fGranularity = 0;       /* Set granularity of tss in bytes */
0148 
0149   pTSS->CR3 = (u32) pPageDirectory;
0150   pTSS->initial_EIP = (u32) pEntry;
0151 
0152   if (mod_num != 1)
0153     pTSS->EFLAGS = F_1 | F_IF | F_IOPL0;
0154   else
0155     pTSS->EFLAGS = F_1 | F_IF | F_IOPL;       /* Give terminal server access to
0156                                                * screen memory */
0157 
0158   pTSS->ESP = 0x400000 - 100;
0159   pTSS->EBP = 0x400000 - 100;
0160 
0161   semaphore_init (&pTSS->Msem, 1, 0);
0162 
0163   /* Return the index into the GDT for the segment */
0164   return i << 3;
0165 }
0166 
0167 
0168 /* Create an address space for boot modules */
0169 static uint16
0170 load_module (multiboot_module * pmm, int mod_num)
0171 {
0172 
0173   uint32 *plPageDirectory = get_phys_addr (pg_dir[mod_num]);
0174   uint32 *plPageTable = get_phys_addr (pg_table[mod_num]);
0175   void *pStack = get_phys_addr (ul_stack[mod_num]);
0176   /* temporarily map pmm->pe in order to read pph->p_memsz */
0177   Elf32_Ehdr *pe, *pe0 = map_virtual_page ((uint) pmm->pe | 3);
0178   Elf32_Phdr *pph = (void *) pe0 + pe0->e_phoff;
0179   void *pEntry = (void *) pe0->e_entry;
0180   int i, c, j;
0181   uint32 *stack_virt_addr;
0182   uint32 page_count = 1;
0183 
0184   /* find out how many pages for the module */
0185   for (i = 0; i < pe0->e_phnum; i++) {
0186     if (pph->p_type == PT_LOAD)
0187       page_count += (pph->p_memsz >> 12);
0188     pph = (void *) pph + pe0->e_phentsize;
0189   }
0190 
0191   /* now map the entire module */
0192   pe = map_contiguous_virtual_pages ((uint) pmm->pe | 3, page_count);
0193 
0194   unmap_virtual_page (pe0);
0195 
0196   pph = (void *) pe + pe->e_phoff;
0197 
0198   /* Populate ring 3 page directory with kernel mappings */
0199   memcpy (&plPageDirectory[1023], (void *) (((uint32) get_pdbr ()) + 4092),
0200           4);
0201   /* LAPIC/IOAPIC mappings */
0202   memcpy (&plPageDirectory[1019], (void *) (((uint32) get_pdbr ()) + 4076),
0203           4);
0204 
0205   /* Populate ring 3 page directory with entries for its private address
0206      space */
0207   plPageDirectory[0] = (uint32) plPageTable | 7;
0208 
0209   plPageDirectory[1022] = (uint32) get_phys_addr (kls_pg_table[mod_num]) | 3;
0210   kls_pg_table[mod_num][0] = (uint32) get_phys_addr (kl_stack[mod_num]) | 3;
0211 
0212   /* Walk ELF header */
0213   for (i = 0; i < pe->e_phnum; i++) {
0214 
0215     if (pph->p_type == PT_LOAD) {
0216       /* map pages loaded from file */
0217       c = (pph->p_filesz + 0xFFF) >> 12;        /* #pages to load for module */
0218 
0219       for (j = 0; j < c; j++)
0220         plPageTable[((uint32) pph->p_vaddr >> 12) + j] =
0221           (uint32) pmm->pe + (pph->p_offset & 0xFFFFF000) + (j << 12) + 7;
0222 
0223       /* zero remainder of final page */
0224       memset ((void *) pe + pph->p_offset + pph->p_filesz,
0225               0, (pph->p_memsz - pph->p_filesz) & 0x0FFF);
0226 
0227       /* map additional zeroed pages */
0228       c = (pph->p_memsz + 0xFFF) >> 12;
0229 
0230       /* Allocate space for bss section.  Use temporary virtual memory for
0231        * memset call to clear physical frame(s)
0232        */
0233       for (; j <= c; j++) {
0234         uint32 page_frame = (uint32) alloc_phys_frame ();
0235         void *virt_addr = map_virtual_page (page_frame | 3);
0236         memset (virt_addr, 0, 0x1000);
0237         plPageTable[((uint32) pph->p_vaddr >> 12) + j] = page_frame + 7;
0238         unmap_virtual_page (virt_addr);
0239       }
0240     }
0241 
0242     pph = (void *) pph + pe->e_phentsize;
0243   }
0244 
0245   /* map stack */
0246   plPageTable[1023] = (uint32) pStack | 7;
0247 
0248   stack_virt_addr = map_virtual_page ((uint32) pStack | 3);
0249 
0250   /* This sets up the module's stack with command-line args from grub */
0251   memcpy ((char *) stack_virt_addr + 0x1000 - 80, pmm->string, 80);
0252   *(uint32 *) ((char *) stack_virt_addr + 0x1000 - 84) = 0;   /* argv[1] */
0253   *(uint32 *) ((char *) stack_virt_addr + 0x1000 - 88) = 0x400000 - 80;       /* argv[0] */
0254   *(uint32 *) ((char *) stack_virt_addr + 0x1000 - 92) = 0x400000 - 88;       /* argv */
0255   *(uint32 *) ((char *) stack_virt_addr + 0x1000 - 96) = 1;   /* argc -- hard-coded right now */
0256   /* Dummy return address placed here for the simulated "call" to our
0257      library */
0258   *(uint32 *) ((char *) stack_virt_addr + 0x1000 - 100) = 0;  /* NULL return address -- never used */
0259 
0260   unmap_virtual_page (stack_virt_addr);
0261   unmap_virtual_pages (pe, page_count);
0262 
0263   u16 pid = alloc_TSS (plPageDirectory, pEntry, mod_num);
0264   com1_printf ("module %d loaded: task_id=0x%x\n", mod_num, pid);
0265 #if QUEST_SCHED==vcpu
0266   lookup_TSS (pid)->cpu = 0;
0267 #endif
0268   return pid;
0269 }
0270 
0271 
0272 /* Programmable interrupt controller settings */
0273 void
0274 init_pic (void)
0275 {
0276 
0277   /* Remap IRQs to int 0x20-0x2F
0278    * Need to set initialization command words (ICWs) and
0279    * operation command words (OCWs) to PIC master/slave
0280    */
0281 
0282   /* Master PIC */
0283   outb (0x11, 0x20);            /* 8259 (ICW1) - xxx10x01 */
0284   outb (PIC1_BASE_IRQ, 0x21);   /* 8259 (ICW2) - set IRQ0... to int 0x20... */
0285   outb (0x04, 0x21);            /* 8259 (ICW3) - connect IRQ2 to slave 8259 */
0286   outb (0x0D, 0x21);            /* 8259 (ICW4) - Buffered master, normal EOI, 8086 mode */
0287 
0288   /* Slave PIC */
0289   outb (0x11, 0xA0);            /* 8259 (ICW1) - xxx10x01 */
0290   outb (PIC2_BASE_IRQ, 0xA1);   /* 8259 (ICW2) - set IRQ8...to int 0x28... */
0291   outb (0x02, 0xA1);            /* 8259 (ICW3) - slave ID #2 */
0292   outb (0x09, 0xA1);            /* 8259 (ICW4) - Buffered slave, normal EOI, 8086 mode */
0293 
0294 }
0295 
0296 
0297 /* Programmable interval timer settings */
0298 void
0299 init_pit (void)
0300 {
0301 
0302   outb (0x34, 0x43);            /* 8254 (control word) - counter 0, mode 2 */
0303 
0304   /* Set interval timer to interrupt once every 1/HZth second */
0305   outb ((PIT_FREQ / HZ) & 0xFF, 0x40);  /* counter 0 low byte */
0306   outb ((PIT_FREQ / HZ) >> 8, 0x40);    /* counter 0 high byte */
0307 }
0308 
0309 void
0310 initialize_serial_port (void)
0311 {
0312   outb (0, serial_port1 + 1);          /* Turn off interrupts - Port1 */
0313 
0314   /*         PORT 1 - Communication Settings         */
0315 
0316   outb (0x80, serial_port1 + 3);       /* SET DLAB ON */
0317   outb (0x03, serial_port1 + 0);       /* Set Baud rate - Divisor Latch Low Byte */
0318   /* Default 0x03 =  38,400 BPS */
0319   /*         0x01 = 115,200 BPS */
0320   /*         0x02 =  57,600 BPS */
0321   /*         0x06 =  19,200 BPS */
0322   /*         0x0C =   9,600 BPS */
0323   /*         0x18 =   4,800 BPS */
0324   /*         0x30 =   2,400 BPS */
0325   outb (0x00, serial_port1 + 1);       /* Set Baud rate - Divisor Latch High Byte */
0326   outb (0x03, serial_port1 + 3);       /* 8 Bits, No Parity, 1 Stop Bit */
0327   outb (0xC7, serial_port1 + 2);       /* FIFO Control Register */
0328   outb (0x0B, serial_port1 + 4);       /* Turn on DTR, RTS, and OUT2 */
0329   com1_puts ("COM1 initialized.\n");
0330 }
0331 
0332 int
0333 parse_root_type (char *cmdline)
0334 {
0335   char *p, *q;
0336   for (p=cmdline; p[0] && p[1] && p[2] && p[3] && p[4]; p++) {
0337     if (p[0] == 'r' && p[1] == 'o' && p[2] == 'o' &&
0338         p[3] == 't' && p[4] == '=') {
0339       p+=5;
0340       for (q=p; *q && *q != ' '; q++);
0341       *q = '\0';
0342       if (q - p >= 4 &&
0343           p[0] == '(' && p[1] == 'h' && p[2] == 'd' && p[3] == ')')
0344         return VFS_FSYS_EZEXT2;
0345       if (q - p >= 4 &&
0346           p[0] == '(' && p[1] == 'c' && p[2] == 'd' && p[3] == ')')
0347         return VFS_FSYS_EZISO;
0348       if (q - p >= 6 &&
0349           p[0] == '(' && p[1] == 't' && p[2] == 'f' &&
0350           p[3] == 't' && p[4] == 'p' && p[5] == ')')
0351         return VFS_FSYS_EZTFTP;
0352       if (q - p >= 5 &&
0353           p[0] == '(' && p[1] == 'u' && p[2] == 's' &&
0354           p[3] == 'b' && p[4] == ')')
0355         return VFS_FSYS_EZUSB;
0356     }
0357   }
0358   return VFS_FSYS_NONE;
0359 }
0360 
0361 u32 root_type, boot_device=0;
0362 
0363 void
0364 init (multiboot * pmb)
0365 {
0366   int i, j, k, c, num_cpus;
0367   uint16 tss[NR_MODS];
0368   memory_map_t *mmap;
0369   uint32 limit;
0370   Elf32_Phdr *pph;
0371   Elf32_Ehdr *pe;
0372   char brandstring[I386_CPUID_BRAND_STRING_LENGTH];
0373 
0374   /* Initialize Bochs I/O debugging */
0375   outw (0x8A00, 0x8A00);
0376 
0377   initialize_serial_port ();
0378 
0379   pchVideo = (char *)KERN_SCR;
0380 
0381   /* clear screen */
0382   for (i = 0; i < 80 * 25; i++) {
0383     pchVideo[i * 2] = ' ';
0384     pchVideo[i * 2 + 1] = 7;
0385   }
0386 
0387   print ("\n\n\n");
0388 
0389   com1_printf ("cmdline: %s\n", pmb->cmdline);
0390   root_type = parse_root_type (pmb->cmdline);
0391   com1_printf ("root_type=%d\n", root_type);
0392 
0393   if (pmb->flags & 0x2) {
0394     multiboot_drive *d;
0395     boot_device = pmb->boot_device;
0396     printf ("Boot device: %X\n", boot_device);
0397     com1_printf ("Boot device: %X\n", boot_device);
0398     if (pmb->flags & 0x80) {
0399       for (d = pmb->drives_addr, i = 0;
0400            i < pmb->drives_length;
0401            i += d->size, d = (multiboot_drive *) ((uint8 *) d + d->size)) {
0402         printf ("Found drive. number: %X\n", d->number);
0403         com1_printf ("Found drive. number: %X\n", d->number);
0404       }
0405     }
0406   }
0407 
0408   cpuid_get_brand_string (brandstring, I386_CPUID_BRAND_STRING_LENGTH);
0409   printf ("CPUID says: %s\n", brandstring);
0410   if (!cpuid_msr_support ())
0411     panic ("Model-specific registers not supported!\n");
0412   if (!cpuid_tsc_support ())
0413     panic ("Timestamp counter not supported!");
0414   if (!cpuid_rdtscp_support ())
0415     logger_printf ("RDTSCP NOT supported.\n");
0416   else
0417     logger_printf ("RDTSCP supported.\n");
0418   if (cpuid_invariant_tsc_support ()) {
0419      print ("Invariant TSC support detected\n");
0420      com1_printf ("Invariant TSC support detected\n");
0421   }
0422 
0423   for (mmap = (memory_map_t *) pmb->mmap_addr;
0424        (uint32) mmap < pmb->mmap_addr + pmb->mmap_length;
0425        mmap = (memory_map_t *) ((uint32) mmap
0426                                 + mmap->size + 4 /*sizeof (mmap->size) */ )) {
0427 
0428     /*
0429      * Set mm_table bitmap entries to 1 for all pages of RAM that are free.
0430      */
0431     if (mmap->type == 1) {      /* Available RAM -- see 'info multiboot' */
0432       if (mmap->base_addr_high == 0x0) {
0433         /* restrict to 4GB RAM */
0434         for (i = 0; i < (mmap->length_low >> 12); i++)
0435           BITMAP_SET (mm_table, (mmap->base_addr_low >> 12) + i);
0436         limit = (mmap->base_addr_low >> 12) + i;
0437 
0438         if (limit > mm_limit)
0439           mm_limit = limit;
0440       }
0441     }
0442   }
0443 
0444   /*
0445    * Clear bitmap entries for kernel and bootstrap memory areas,
0446    * so as not to use them in dynamic memory allocation.
0447    */
0448   for (i = 0;
0449        i <
0450        (uint32) &_bootstrap_pages + (uint32) &_readwrite_pages +
0451        (uint32) &_readonly_pages; i++)
0452     BITMAP_CLR (mm_table, 256 + i);     /* Kernel starts at 256th physical frame
0453                                          * See quest.ld
0454                                          */
0455 
0456   /*
0457    * --??-- Possible optimization is to free mm_table entries corresponding
0458    * to memory above mm_limit on machines with less physical memory than
0459    * table keeps track of -- currently 4GB.
0460    */
0461 
0462   /* Here, clear mm_table entries for any loadable modules. */
0463   for (i = 0; i < pmb->mods_count; i++) {
0464 
0465     pe = map_virtual_page ((uint32)pmb->mods_addr[i].pe | 3);
0466 
0467     pph = (void *) pe + pe->e_phoff;
0468 
0469     for (j = 0; j < pe->e_phnum; j++) {
0470 
0471       if (pph->p_type == PT_LOAD) {
0472         c = (pph->p_filesz + 0xFFF) >> 12;      /* #pages required for module */
0473 
0474         for (k = 0; k < c; k++)
0475           BITMAP_CLR (mm_table, (((uint32) pe + pph->p_offset) >> 12) + k);
0476       }
0477       pph = (void *) pph + pe->e_phentsize;
0478     }
0479 
0480     unmap_virtual_page (pe);
0481   }
0482 
0483   /* Clear bitmap entries for first megabyte of RAM so we don't
0484    * overwrite BIOS tables we might be interested in later. */
0485   for (i=0; i<256; i++)
0486     BITMAP_CLR (mm_table, i);
0487 
0488   /* Reserve physical frame with GRUB multiboot structure */
0489   BITMAP_CLR (mm_table, (u32) pmb >> 12);
0490 
0491 #if 0
0492   /* Test that mm_table is setup correct */
0493   for (i = 0; i < 2000; i++)
0494     putchar (BITMAP_TST (mm_table, i) ? '1' : '0');
0495   while (1);
0496 #endif
0497 
0498   /* Now safe to call alloc_phys_frame() as all free/allocated memory is
0499    *  marked in the mm_table
0500    */
0501 
0502   init_interrupt_handlers ();
0503 
0504   /* Initialise the programmable interrupt controller (PIC) */
0505   init_pic ();
0506 
0507   /* Initialise the programmable interval timer (PIT) */
0508   init_pit ();
0509 
0510   pow2_init ();                 /* initialize power-of-2 memory allocator */
0511 
0512   /* Setup per-CPU area for bootstrap CPU */
0513   percpu_per_cpu_init ();
0514 
0515   /* Start up other processors, which may allocate pages for stacks */
0516   num_cpus = smp_init ();
0517   if (num_cpus > 1) {
0518     print ("Multi-processing detected.  Number of CPUs: ");
0519     putx (num_cpus);
0520     putchar ('\n');
0521   } else {
0522     print ("Uni-processor mode.\n");
0523   }
0524 
0525   /* Create CPU and IDLE TSSes */
0526   for (i = 0; i < num_cpus; i++) {
0527     cpuTSS_selector[i] = alloc_CPU_TSS (&cpuTSS[i]);
0528     idleTSS_selector[i] = alloc_idle_TSS (i);
0529   }
0530 
0531   /* Load modules from GRUB */
0532   if (!pmb->mods_count)
0533     panic ("No modules available");
0534   for (i = 0; i < pmb->mods_count; i++) {
0535     tss[i] = load_module (pmb->mods_addr + i, i);
0536     lookup_TSS (tss[i])->priority = MIN_PRIO;
0537   }
0538 
0539   /* Remove identity mapping of first 4MB */
0540   *((uint32 *)get_pdbr()) = 0;
0541   flush_tlb_all ();
0542 
0543   /* Load the per-CPU TSS for the bootstrap CPU */
0544   hw_ltr (cpuTSS_selector[0]);
0545 
0546   /* The APs do not begin actually operating until the PIT fires the
0547    * first IRQ after interrupts are re-enabled.  That's why it is safe
0548    * to utilize the dummy TSS without locking the kernel yet. */
0549   smp_secondary_init ();
0550 
0551   /* Load all modules, chasing dependencies */
0552   { extern bool module_load_all (void); module_load_all (); }
0553 
0554   /* count free pages for informational purposes */
0555   u32 *page_table = (u32 *) KERN_PGT;
0556   u32 free_pages = 0;
0557   for (i = 0; i < 1024; i++)
0558     if (page_table[i] == 0)
0559       free_pages++;
0560   printf ("free kernel pages=%d\n", free_pages);
0561   logger_printf ("free kernel pages=%d\n", free_pages);
0562 
0563   /* Start the schedulers */
0564   smp_enable_scheduling ();
0565 
0566 #ifdef ENABLE_GDBSTUB
0567   {
0568 #ifndef GDBSTUB_TCP
0569     void set_debug_traps (void);
0570     set_debug_traps ();
0571     BREAKPOINT ();
0572 #endif
0573   }
0574 #endif
0575 
0576   /* The Shell module is in userspace and therefore interrupts will be
0577    * enabled after this point.  Then, kernel locking will become
0578    * necessary. */
0579 
0580   ltr (tss[0]);
0581   /* task-switch to shell module */
0582   asm volatile ("jmp _sw_init_user_task"::"D" (lookup_TSS (tss[0])));
0583 
0584   /* never return */
0585   panic ("BSP: unreachable");
0586 }
0587 
0588 /*
0589  * Local Variables:
0590  * indent-tabs-mode: nil
0591  * mode: C
0592  * c-file-style: "gnu"
0593  * c-basic-offset: 2
0594  * End:
0595  */
0596 
0597 /* vi: set et sw=2 sts=2: */