Annotation of OSKit-Mach/oskit/x86/main.c, revision 1.1

1.1     ! root        1: /* main entrypoint (from oskit multiboot_main) for Mach.
        !             2:    It turns out this file is almost entirely machine-dependent.
        !             3: 
        !             4:    This file defines `main', which is the entrypoint from the oskit.
        !             5:    It calls `setup_main' (kern/startup.c) after setting up the machine,
        !             6:    interrupts, paging, and `machine_slot[0]'; setup_main never returns.
        !             7:    This file defines `machine_init', which is called after VM is set up.
        !             8: */
        !             9: 
        !            10: #include <oskit/clientos.h>
        !            11: #include <oskit/machine/base_multiboot.h>
        !            12: #include <oskit/machine/base_stack.h>
        !            13: #include <oskit/machine/physmem.h>
        !            14: #include <oskit/x86/base_cpu.h>
        !            15: #include <oskit/x86/debug_reg.h>
        !            16: #include <oskit/lmm.h>
        !            17: #include <oskit/machine/phys_lmm.h>
        !            18: #include <oskit/machine/base_stack.h>
        !            19: 
        !            20: #include <mach/vm_param.h>
        !            21: #include <mach/vm_prot.h>
        !            22: #include <mach/machine.h>
        !            23: 
        !            24: #include <oskit/x86/proc_reg.h>
        !            25: #include <oskit/x86/paging.h>
        !            26: #include <oskit/x86/base_vm.h>
        !            27: #include <oskit/c/unistd.h>
        !            28: #include <oskit/dev/dev.h>
        !            29: #include <oskit/smp.h>
        !            30: #include "gdt.h"
        !            31: 
        !            32: #include <string.h>
        !            33: 
        !            34: #include "vm_param.h"
        !            35: #include <kern/time_out.h>
        !            36: #include <sys/time.h>
        !            37: #include <vm/vm_page.h>
        !            38: #include <vm/vm_map.h>
        !            39: #include <kern/zalloc.h>
        !            40: #include <i386/machspl.h>
        !            41: #include <i386/pmap.h>
        !            42: #include <i386/mp_desc.h>
        !            43: 
        !            44: #include <kern/cpu_number.h>
        !            45: 
        !            46: /* As of 2000-12-21 the oskit has an incorrect value for this constant
        !            47:    in <oskit/x86/proc_reg.h>, so we redefine it with the correct one.  */
        !            48: #undef CR4_PGE
        !            49: #define CR4_PGE        0x80
        !            50: 
        !            51: static void my_exit (int), (*his_exit) (int);
        !            52: 
        !            53: /* XXX move to intel/pmap.h */
        !            54: extern pt_entry_t *kernel_page_dir;
        !            55: 
        !            56: 
        !            57: #include "assert.h"
        !            58: 
        !            59: extern char    version[];
        !            60: 
        !            61: char **kernel_argv;
        !            62: char *kernel_cmdline;          /* XXX */
        !            63: 
        !            64: void
        !            65: setup_machine_slot (int mycpu)
        !            66: {
        !            67:   struct cpu_info info;
        !            68:   cpuid (&info);
        !            69: 
        !            70:   /* Examine the CPU model information provided by the oskit,
        !            71:      and set machine_slot[0] to describe the CPU to users who ask.  */
        !            72:   switch (info.family)
        !            73:     {
        !            74:     default:
        !            75:     case CPU_FAMILY_386:
        !            76:       machine_slot[mycpu].cpu_type = CPU_TYPE_I386;
        !            77:       break;
        !            78:     case CPU_FAMILY_486:
        !            79:       machine_slot[mycpu].cpu_type = CPU_TYPE_I486;
        !            80:       break;
        !            81:     case CPU_FAMILY_PENTIUM:
        !            82:       machine_slot[mycpu].cpu_type = CPU_TYPE_PENTIUM;
        !            83:       break;
        !            84:     case CPU_FAMILY_PENTIUM_PRO:
        !            85:       machine_slot[mycpu].cpu_type = CPU_TYPE_PENTIUMPRO;
        !            86:       break;
        !            87:     }
        !            88:   machine_slot[mycpu].cpu_subtype = CPU_SUBTYPE_AT386;
        !            89:   machine_slot[mycpu].is_cpu = TRUE;
        !            90: }
        !            91: 
        !            92: int
        !            93: main (int argc, char **argv)
        !            94: {
        !            95:   oskit_clientos_init ();
        !            96: 
        !            97:   printf ("Welcome to %s!\r\n", version);
        !            98: 
        !            99:   /*
        !           100:    * Initialize the PIC prior to any possible call to an spl.
        !           101:    */
        !           102:   picinit();
        !           103: 
        !           104:   /* Tell the oskit base_* code what virtual addresses we are using
        !           105:      to map the linear address space.  It can't keep using the 1:1
        !           106:      kvtolin mapping once we flush the direct mapping below.
        !           107:      We must do this before pmap_bootstrap, because pmap_bootstrap
        !           108:      uses kvtolin to decide where to put its mappings!  */
        !           109:   linear_base_va = -LINEAR_MIN_KERNEL_ADDRESS;
        !           110: 
        !           111:   /* This allocates the kernel page tables and initializes kernel_pmap.  */
        !           112:   pmap_bootstrap();
        !           113: 
        !           114:   /*
        !           115:    * Turn paging on.
        !           116:    * We'll have to temporarily install a direct mapping
        !           117:    * between physical memory and low linear memory,
        !           118:    * until we start using our new kernel segment descriptors.
        !           119:    * One page table (4MB) should do the trick.
        !           120:    * Also, set the WP bit so that on 486 or better processors
        !           121:    * page-level write protection works in kernel mode.
        !           122:    */
        !           123:   kernel_page_dir[lin2pdenum(0)] =
        !           124:     kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS)];
        !           125:   paging_enable((oskit_addr_t) kernel_page_dir);
        !           126:   set_cr0 (get_cr0 () | CR0_WP);
        !           127: 
        !           128:   if (base_cpuid.feature_flags & CPUF_PAGE_GLOBAL_EXT) {
        !           129:     /*
        !           130:      * The processor supports the "global" bit to avoid flushing kernel TLB
        !           131:      * entries, if we turn it on.  pmap_bootstrap checks this feature flag
        !           132:      * and begins use the global bit in page table entries.  But according
        !           133:      * to the x86 specs we cannot set this bit before we do enable_paging
        !           134:      * above; setting CR4_PGE first doesn't work on some processors, in fact.
        !           135:      */
        !           136:     set_cr4 (get_cr4 () | CR4_PGE);
        !           137:   }
        !           138: 
        !           139:   /*
        !           140:    * Initialize and activate the real i386 protected-mode structures.
        !           141:    */
        !           142:   base_gdt_init();     /* reinitialize with linear_base_va */
        !           143:   gdt_init();
        !           144:   idt_init();
        !           145:   int_init();
        !           146:   ldt_init();
        !           147: 
        !           148:   base_cpu_load();             /* Load all the new tables into the CPU.  */
        !           149: 
        !           150:   /* Now reload the TSS using our slot instead of the oskit's.  */
        !           151:   base_gdt[sel_idx (KERNEL_TSS)].access &= ~ACC_TSS_BUSY;
        !           152:   set_tr(KERNEL_TSS);
        !           153: 
        !           154:   /* Arrange a callback to our special exit function below, so we can
        !           155:      try to return to a state the generic oskit reboot code can cope with.  */
        !           156:   his_exit = oskit_libc_exit;
        !           157:   oskit_libc_exit = &my_exit;
        !           158: 
        !           159:   /* Get rid of the temporary direct mapping and flush it out of the TLB.  */
        !           160:   kernel_page_dir[lin2pdenum(0)] = 0;
        !           161:   inval_tlb();
        !           162: 
        !           163:   /* Interrupt stacks are allocated in physical memory,
        !           164:      while kernel stacks are allocated in kernel virtual memory,
        !           165:      so phys_last_addr serves as a convenient dividing point.  */
        !           166:   int_stack_high = phys_mem_max;
        !           167: 
        !           168: #if NCPUS > 1
        !           169:   smp_init_paging ();          /* This maps physical memory SMP needs.  */
        !           170:   if (smp_init () != 0)
        !           171:     printf ("SMP initialization failed!\n");
        !           172:   else
        !           173:     {
        !           174:       int ncpus;
        !           175:       printf ("SMP initialized (maximum %d supported by this kernel).");
        !           176:       ncpus = smp_get_num_cpus ();
        !           177:       if (ncpus == 1)
        !           178:        printf ("Running on a uniprocessor.\n");
        !           179:       else
        !           180:        {
        !           181:          printf ("Detected %d CPUs.\n");
        !           182:          if (ncpus > NCPUS)
        !           183:            printf ("WARNING: This kernel can only use %d CPUs.\n"
        !           184:                    "The remaining %d CPUs will be completely idle!"
        !           185:                    "\nYou should recompile your kernel with --enable-cpus=%d"
        !           186:                    " or higher.\n",
        !           187:                    NCPUS, ncpus - NCPUS, ncpus);
        !           188:        }
        !           189:       master_cpu = smp_find_cur_cpu ();
        !           190:       ivect[SMP_IPI_VECTOR] = (int (*)())pmap_update_interrupt;
        !           191:       intpri[SMP_IPI_VECTOR] = SPL1;
        !           192:       mp_desc_init (master_cpu);
        !           193:     }
        !           194:   interrupt_stack_alloc ();
        !           195: #endif
        !           196: 
        !           197:   setup_machine_slot (master_cpu);
        !           198:   machine_slot[master_cpu].running = TRUE;
        !           199: 
        !           200:   kernel_argv = argv;          /* Stash our args for user_bootstrap to use. */
        !           201: 
        !           202:   { /* XXX */
        !           203:     static char cmdline[1024];
        !           204:     int i;
        !           205:     strcpy (cmdline, argv[0]);
        !           206:     for (i = 1; i < argc; ++i) {
        !           207:       strcat (cmdline, " ");
        !           208:       strcat (cmdline, argv[i]);
        !           209:     }
        !           210:     assert (strlen (cmdline) < sizeof cmdline);
        !           211:     kernel_cmdline = cmdline;
        !           212:   }
        !           213: 
        !           214:   /* Start the system.  This function does not return.  */
        !           215:   setup_main();
        !           216:   /* NOTREACHED */
        !           217:   return -1;
        !           218: }
        !           219: 
        !           220: /* This is the function we install in `oskit_libc_exit' to be called
        !           221:    by _exit, panic, et al.  The oskit provided an original function
        !           222:    (now stored in `his_exit'), that will only work properly if we are
        !           223:    using direct-mapped physical addresses.  So we provide here a
        !           224:    replacement that switches to direct linear addressing and moves
        !           225:    to a physical-addressed stack and PC to call the oskit's function.  */
        !           226: static void
        !           227: my_exit (int rc)
        !           228: {
        !           229:   /* Restore direct virtual->physical mapping and switch to
        !           230:      direct linear addressing code segment, so the oskit
        !           231:      can cope when it tries to turn paging off.  */
        !           232: 
        !           233:   kernel_page_dir[lin2pdenum(0)]
        !           234:     = kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS)];
        !           235:   set_cr4 (get_cr4 () &~ CR4_PGE);
        !           236:   set_pdbr (kvtophys (kernel_page_dir));
        !           237: 
        !           238:   /* Reload the oskit's GDT slots.  */
        !           239:   base_gdt_init ();
        !           240:   base_gdt_load ();
        !           241: 
        !           242:   asm volatile ("      ljmp    %0,$1f  \n" /* Switch to LINEAR_CS,  */
        !           243:                "1:     movw    %w1,%%ds\n" /* Switch %ds to LINEAR_DS.  */
        !           244:                "       movw    %w1,%%es\n" /* Switch %es to LINEAR_DS.  */
        !           245:                "       movw    %w1,%%ss\n" /* Switch %ss to LINEAR_DS.  */
        !           246:                "       movl    %2,%%esp\n" /* and to phys-addr base_stack.  */
        !           247:                "       pushl   %3      \n" /* Push argument (RC).  */
        !           248:                "       pushl   %4      \n" /* Push bogus return address.  */
        !           249:                "       jmp     %*%5" : : /* Jump to oskit, never return.  */
        !           250:                "i" (LINEAR_CS), "r" (LINEAR_DS),
        !           251:                "ir" (kvtophys (&base_stack_end)),
        !           252:                "ir" (rc), "ir" (0),
        !           253:                "r" (kvtophys (his_exit)));
        !           254:   /* NOTREACHED */
        !           255: }
        !           256: 
        !           257: boolean_t pmap_valid_page(x)
        !           258:        vm_offset_t x;
        !           259: {
        !           260:        /* XXX is this OK?  What does it matter for?  */
        !           261:        return (((phys_mem_min <= x) && (x < phys_mem_max)) &&
        !           262:                !(((boot_info.mem_lower * 1024) <= x) && (x < 1024*1024)));
        !           263: }
        !           264: 
        !           265: 
        !           266: 
        !           267: #include <mach/time_value.h>
        !           268: 
        !           269: startrtclock()
        !           270: {
        !           271:        clkstart();
        !           272: }
        !           273: 
        !           274: static void
        !           275: inittodr()
        !           276: {
        !           277:   oskit_timespec_t ts;
        !           278:   oskit_error_t rc;
        !           279:   spl_t s;
        !           280: 
        !           281:   rc = oskit_rtc_get (&ts);
        !           282:   if (rc)
        !           283:     panic (__FUNCTION__);
        !           284: 
        !           285:   s = splhigh();
        !           286: #undef tv_sec                  /* oy */
        !           287:   time.seconds = ts.tv_sec;
        !           288:   time.microseconds = (ts.tv_nsec + 999) / 1000;
        !           289:   splx(s);
        !           290: }
        !           291: 
        !           292: /* This is called from host_set_time at splhigh to reset the hardware clock
        !           293:    to the new value of `time'.  */
        !           294: void
        !           295: resettodr()
        !           296: {
        !           297:   oskit_timespec_t ts = { time.seconds, time.microseconds * 1000 };
        !           298:   oskit_rtc_set (&ts);
        !           299: }
        !           300: 
        !           301: 
        !           302: 
        !           303: void
        !           304: machine_idle (int mycpu)
        !           305: {
        !           306:   asm volatile ("hlt" : : : "memory");
        !           307: }
        !           308: 
        !           309: void
        !           310: halt_cpu ()
        !           311: {
        !           312:   while (1)
        !           313:     asm volatile ("cli; hlt");
        !           314: }
        !           315: 
        !           316: void
        !           317: halt_all_cpus(reboot)
        !           318:        boolean_t       reboot;
        !           319: {
        !           320:   exit(reboot ? 0 : 1);
        !           321: }
        !           322: 
        !           323: 
        !           324: void machine_init()
        !           325: {
        !           326:        /*
        !           327:         * Set up to use floating point.
        !           328:         */
        !           329:        init_fpu();
        !           330: 
        !           331:        /*
        !           332:         * Get the time
        !           333:         */
        !           334:        inittodr();
        !           335: 
        !           336:        /*
        !           337:         * Unmap page 0 to trap NULL references.
        !           338:         * If there is real memory in the first physical page,
        !           339:         * then it will not be accessible through the normal
        !           340:         * direct mapping, so we need to take it out of the LMM.
        !           341:         */
        !           342:        if (phys_mem_min < PAGE_SIZE)
        !           343:          {
        !           344:            void *block = lmm_alloc_gen (&malloc_lmm,
        !           345:                                         PAGE_SIZE - phys_mem_min, 0, 0, 0,
        !           346:                                         phys_mem_min,
        !           347:                                         PAGE_SIZE - phys_mem_min);
        !           348:            if ((oskit_addr_t) block != phys_mem_min)
        !           349:              panic ("cannot allocate first page [%#x,%#x) from physical LMM!",
        !           350:                     phys_mem_min, PAGE_SIZE);
        !           351:            else
        !           352:              {
        !           353:                /*
        !           354:                 * So we have this partial page that we can't use where it is.
        !           355:                 * Rather than waste it, let's map it in someplace else
        !           356:                 * and donate it to someplace that can always use a little
        !           357:                 * chunk of extra wired kernel virtual memory: the zone system.
        !           358:                 */
        !           359:                extern vm_map_t zone_map; /* zalloc.c */
        !           360:                extern zone_t vm_page_zone; /* vm_resident.c */
        !           361:                vm_offset_t kva;
        !           362:                kern_return_t kr;
        !           363:                kr = kmem_alloc_pageable (zone_map, &kva, PAGE_SIZE);
        !           364:                if (kr != KERN_SUCCESS)
        !           365:                  panic ("machine_init: kmem_alloc_pageable zone_map: %#x",
        !           366:                         kr);
        !           367:                pmap_enter (kernel_pmap, kva, 0,
        !           368:                            VM_PROT_READ | VM_PROT_WRITE, TRUE);
        !           369:                kva += phys_mem_min; /* Skip mapping below phys_mem_min.  */
        !           370:                /*
        !           371:                 * The vm_page_zone is always a needy soul early in life.
        !           372:                 */
        !           373:                zcram (vm_page_zone, kva, PAGE_SIZE - phys_mem_min);
        !           374:              }
        !           375:          }
        !           376:        pmap_unmap_page_zero();
        !           377: 
        !           378:        /* Catch interrupt stack overflow.  */
        !           379:        set_b0 (kvtolin (&base_stack_start), DR7_LEN_4, DR7_RW_DATA);
        !           380:        base_gdt_load();        /* necessary after setting debug regs */
        !           381: 
        !           382:        /* That loaded the oskit's selectors.  Now reload ours.  */
        !           383:        asm volatile("ljmp %0,$1f\n\t1:" : : "i" (KERNEL_CS));
        !           384:        set_ds(KERNEL_DS);
        !           385:        set_es(KERNEL_DS);
        !           386:        set_ss(KERNEL_DS);
        !           387: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.