Annotation of Gnu-Mach/i386/i386at/model_dep.c, revision 1.1.1.4

1.1.1.3   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989, 1988 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.3   root        5:  *
1.1       root        6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
1.1.1.3   root       11:  *
1.1       root       12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.3   root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.3   root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.3   root       22:  *
1.1       root       23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     File:   model_dep.c
                     28:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     29:  *
                     30:  *     Copyright (C) 1986, Avadis Tevanian, Jr., Michael Wayne Young
                     31:  *
                     32:  *     Basic initialization for I386 - ISA bus machines.
                     33:  */
                     34: 
1.1.1.4 ! root       35: #include <string.h>
        !            36: 
        !            37: #include <device/cons.h>
1.1       root       38: 
                     39: #include <mach/vm_param.h>
                     40: #include <mach/vm_prot.h>
                     41: #include <mach/machine.h>
                     42: #include <mach/machine/multiboot.h>
1.1.1.4 ! root       43: #include <mach/xen.h>
1.1       root       44: 
1.1.1.4 ! root       45: #include <i386/vm_param.h>
1.1.1.3   root       46: #include <kern/assert.h>
                     47: #include <kern/cpu_number.h>
1.1.1.4 ! root       48: #include <kern/debug.h>
        !            49: #include <kern/mach_clock.h>
        !            50: #include <kern/printf.h>
1.1       root       51: #include <sys/time.h>
1.1.1.4 ! root       52: #include <sys/types.h>
1.1       root       53: #include <vm/vm_page.h>
1.1.1.4 ! root       54: #include <i386/fpu.h>
        !            55: #include <i386/gdt.h>
        !            56: #include <i386/ktss.h>
        !            57: #include <i386/ldt.h>
1.1       root       58: #include <i386/machspl.h>
1.1.1.4 ! root       59: #include <i386/pic.h>
        !            60: #include <i386/pit.h>
1.1       root       61: #include <i386/pmap.h>
1.1.1.4 ! root       62: #include <i386/proc_reg.h>
        !            63: #include <i386/locore.h>
        !            64: #include <i386/model_dep.h>
        !            65: #include <i386at/autoconf.h>
        !            66: #include <i386at/idt.h>
        !            67: #include <i386at/int_init.h>
        !            68: #include <i386at/kd.h>
        !            69: #include <i386at/rtc.h>
        !            70: #ifdef MACH_XEN
        !            71: #include <xen/console.h>
        !            72: #include <xen/store.h>
        !            73: #include <xen/evt.h>
        !            74: #include <xen/xen.h>
        !            75: #endif /* MACH_XEN */
1.1       root       76: 
                     77: /* Location of the kernel's symbol table.
                     78:    Both of these are 0 if none is available.  */
                     79: #if MACH_KDB
                     80: static vm_offset_t kern_sym_start, kern_sym_end;
                     81: #else
                     82: #define kern_sym_start 0
                     83: #define kern_sym_end   0
                     84: #endif
                     85: 
                     86: /* These indicate the total extent of physical memory addresses we're using.
                     87:    They are page-aligned.  */
                     88: vm_offset_t phys_first_addr = 0;
                     89: vm_offset_t phys_last_addr;
                     90: 
1.1.1.3   root       91: /* A copy of the multiboot info structure passed by the boot loader.  */
1.1.1.4 ! root       92: #ifdef MACH_XEN
        !            93: struct start_info boot_info;
        !            94: #ifdef MACH_PSEUDO_PHYS
        !            95: unsigned long *mfn_list;
        !            96: #if VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS
        !            97: unsigned long *pfn_list = (void*) PFN_LIST;
        !            98: #endif
        !            99: #endif /* MACH_PSEUDO_PHYS */
        !           100: #if VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS
        !           101: unsigned long la_shift = VM_MIN_KERNEL_ADDRESS;
        !           102: #endif
        !           103: #else  /* MACH_XEN */
1.1.1.3   root      104: struct multiboot_info boot_info;
1.1.1.4 ! root      105: #endif /* MACH_XEN */
1.1       root      106: 
                    107: /* Command line supplied to kernel.  */
                    108: char *kernel_cmdline = "";
                    109: 
                    110: /* This is used for memory initialization:
                    111:    it gets bumped up through physical memory
                    112:    that exists and is not occupied by boot gunk.
                    113:    It is not necessarily page-aligned.  */
1.1.1.4 ! root      114: static vm_offset_t avail_next
        !           115: #ifndef MACH_HYP
        !           116:        = 0x1000 /* XX end of BIOS data area */
        !           117: #endif /* MACH_HYP */
        !           118:        ;
1.1       root      119: 
                    120: /* Possibly overestimated amount of available memory
                    121:    still remaining to be handed to the VM system.  */
                    122: static vm_size_t avail_remaining;
                    123: 
                    124: extern char    version[];
                    125: 
                    126: extern void    setup_main();
                    127: 
1.1.1.4 ! root      128: void           halt_all_cpus (boolean_t reboot) __attribute__ ((noreturn));
1.1.1.3   root      129: void           halt_cpu (void) __attribute__ ((noreturn));
                    130: 
1.1       root      131: void           inittodr();     /* forward */
                    132: 
                    133: int            rebootflag = 0; /* exported to kdintr */
                    134: 
                    135: /* XX interrupt stack pointer and highwater mark, for locore.S.  */
                    136: vm_offset_t int_stack_top, int_stack_high;
                    137: 
                    138: #ifdef LINUX_DEV
                    139: extern void linux_init(void);
                    140: #endif
                    141: 
1.1.1.4 ! root      142: boolean_t init_alloc_aligned(vm_size_t size, vm_offset_t *addrp);
        !           143: 
1.1       root      144: /*
                    145:  * Find devices.  The system is alive.
                    146:  */
1.1.1.4 ! root      147: void machine_init(void)
1.1       root      148: {
                    149:        /*
                    150:         * Initialize the console.
                    151:         */
                    152:        cninit();
                    153: 
                    154:        /*
                    155:         * Set up to use floating point.
                    156:         */
                    157:        init_fpu();
                    158: 
1.1.1.4 ! root      159: #ifdef MACH_HYP
        !           160:        hyp_init();
        !           161: #else  /* MACH_HYP */
1.1       root      162: #ifdef LINUX_DEV
                    163:        /*
                    164:         * Initialize Linux drivers.
                    165:         */
                    166:        linux_init();
                    167: #endif
                    168: 
                    169:        /*
                    170:         * Find the devices
                    171:         */
                    172:        probeio();
1.1.1.4 ! root      173: #endif /* MACH_HYP */
1.1       root      174: 
                    175:        /*
                    176:         * Get the time
                    177:         */
                    178:        inittodr();
                    179: 
1.1.1.4 ! root      180: #ifndef MACH_HYP
1.1       root      181:        /*
                    182:         * Tell the BIOS not to clear and test memory.
                    183:         */
                    184:        *(unsigned short *)phystokv(0x472) = 0x1234;
1.1.1.4 ! root      185: #endif /* MACH_HYP */
1.1       root      186: 
                    187:        /*
                    188:         * Unmap page 0 to trap NULL references.
                    189:         */
                    190:        pmap_unmap_page_zero();
                    191: }
                    192: 
1.1.1.3   root      193: /* Conserve power on processor CPU.  */
                    194: void machine_idle (int cpu)
                    195: {
1.1.1.4 ! root      196: #ifdef MACH_HYP
        !           197:   hyp_idle();
        !           198: #else  /* MACH_HYP */
1.1.1.3   root      199:   assert (cpu == cpu_number ());
                    200:   asm volatile ("hlt" : : : "memory");
1.1.1.4 ! root      201: #endif /* MACH_HYP */
        !           202: }
        !           203: 
        !           204: void machine_relax ()
        !           205: {
        !           206:        asm volatile ("rep; nop" : : : "memory");
1.1.1.3   root      207: }
                    208: 
1.1       root      209: /*
                    210:  * Halt a cpu.
                    211:  */
1.1.1.3   root      212: void halt_cpu(void)
1.1       root      213: {
1.1.1.4 ! root      214: #ifdef MACH_HYP
        !           215:        hyp_halt();
        !           216: #else  /* MACH_HYP */
1.1       root      217:        asm volatile("cli");
1.1.1.4 ! root      218:        while (TRUE)
        !           219:          machine_idle (cpu_number ());
        !           220: #endif /* MACH_HYP */
1.1       root      221: }
                    222: 
                    223: /*
                    224:  * Halt the system or reboot.
                    225:  */
1.1.1.3   root      226: void halt_all_cpus(reboot)
1.1       root      227:        boolean_t       reboot;
                    228: {
                    229:        if (reboot) {
1.1.1.4 ! root      230: #ifdef MACH_HYP
        !           231:            hyp_reboot();
        !           232: #endif /* MACH_HYP */
1.1       root      233:            kdreboot();
                    234:        }
                    235:        else {
                    236:            rebootflag = 1;
1.1.1.4 ! root      237: #ifdef MACH_HYP
        !           238:            hyp_halt();
        !           239: #endif /* MACH_HYP */
1.1       root      240:            printf("In tight loop: hit ctl-alt-del to reboot\n");
                    241:            (void) spl0();
                    242:        }
1.1.1.4 ! root      243:        while (TRUE)
        !           244:          machine_idle (cpu_number ());
1.1       root      245: }
                    246: 
                    247: void exit(int rc)
                    248: {
                    249:        halt_all_cpus(0);
                    250: }
                    251: 
1.1.1.4 ! root      252: void db_reset_cpu(void)
1.1       root      253: {
                    254:        halt_all_cpus(1);
                    255: }
                    256: 
                    257: 
                    258: /*
                    259:  * Compute physical memory size and other parameters.
                    260:  */
                    261: void
1.1.1.4 ! root      262: mem_size_init(void)
1.1       root      263: {
1.1.1.4 ! root      264:        vm_offset_t max_phys_size;
        !           265: 
1.1       root      266:        /* Physical memory on all PCs starts at physical address 0.
                    267:           XX make it a constant.  */
                    268:        phys_first_addr = 0;
                    269: 
1.1.1.4 ! root      270: #ifdef MACH_HYP
        !           271:        if (boot_info.nr_pages >= 0x100000) {
        !           272:                printf("Truncating memory size to 4GiB\n");
        !           273:                phys_last_addr = 0xffffffffU;
        !           274:        } else
        !           275:                phys_last_addr = boot_info.nr_pages * 0x1000;
        !           276: #else  /* MACH_HYP */
        !           277:        vm_size_t phys_last_kb;
        !           278: 
        !           279:        if (boot_info.flags & MULTIBOOT_MEM_MAP) {
        !           280:                struct multiboot_mmap *map, *map_end;
        !           281: 
        !           282:                map = (void*) phystokv(boot_info.mmap_addr);
        !           283:                map_end = (void*) map + boot_info.mmap_count;
        !           284: 
        !           285:                while (map + 1 <= map_end) {
        !           286:                        if (map->Type == MB_ARD_MEMORY) {
        !           287:                                unsigned long long start = map->BaseAddr, end = map->BaseAddr + map->Length;;
        !           288: 
        !           289:                                if (start >= 0x100000000ULL) {
        !           290:                                        printf("Ignoring %luMiB RAM region above 4GiB\n", (unsigned long) (map->Length >> 20));
        !           291:                                } else {
        !           292:                                        if (end >= 0x100000000ULL) {
        !           293:                                                printf("Truncating memory region to 4GiB\n");
        !           294:                                                end = 0x0ffffffffU;
        !           295:                                        }
        !           296:                                        if (end > phys_last_addr)
        !           297:                                                phys_last_addr = end;
1.1       root      298: 
1.1.1.4 ! root      299:                                        printf("AT386 boot: physical memory map from 0x%lx to 0x%lx\n",
        !           300:                                                (unsigned long) start,
        !           301:                                                (unsigned long) end);
        !           302:                                }
        !           303:                        }
        !           304:                        map = (void*) map + map->size + sizeof(map->size);
        !           305:                }
        !           306:        } else {
        !           307:                phys_last_kb = 0x400 + boot_info.mem_upper;
        !           308:                /* Avoid 4GiB overflow.  */
        !           309:                if (phys_last_kb < 0x400 || phys_last_kb >= 0x400000) {
        !           310:                        printf("Truncating memory size to 4GiB\n");
        !           311:                        phys_last_addr = 0xffffffffU;
        !           312:                } else
        !           313:                        phys_last_addr = phys_last_kb * 0x400;
        !           314:        }
        !           315: #endif /* MACH_HYP */
        !           316: 
        !           317:        printf("AT386 boot: physical memory from 0x%lx to 0x%lx\n",
1.1       root      318:               phys_first_addr, phys_last_addr);
                    319: 
1.1.1.4 ! root      320:        /* Reserve room for virtual mappings.
        !           321:         * Yes, this loses memory.  Blame i386.  */
        !           322:        max_phys_size = VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS - VM_KERNEL_MAP_SIZE;
        !           323:        if (phys_last_addr - phys_first_addr > max_phys_size) {
        !           324:                phys_last_addr = phys_first_addr + max_phys_size;
        !           325:                printf("Truncating memory to %luMiB\n", (phys_last_addr - phys_first_addr) / (1024 * 1024));
        !           326:                /* TODO Xen: be nice, free lost memory */
1.1       root      327:        }
                    328: 
                    329:        phys_first_addr = round_page(phys_first_addr);
                    330:        phys_last_addr = trunc_page(phys_last_addr);
1.1.1.4 ! root      331: 
        !           332: #ifdef MACH_HYP
        !           333:        /* Memory is just contiguous */
        !           334:        avail_remaining = phys_last_addr;
        !           335: #else  /* MACH_HYP */
        !           336:        avail_remaining
        !           337:          = phys_last_addr - (0x100000 - (boot_info.mem_lower * 0x400)
        !           338:                              - 0x1000);
        !           339: #endif /* MACH_HYP */
1.1       root      340: }
                    341: 
                    342: /*
                    343:  * Basic PC VM initialization.
                    344:  * Turns on paging and changes the kernel segments to use high linear addresses.
                    345:  */
1.1.1.4 ! root      346: void
        !           347: i386at_init(void)
1.1       root      348: {
                    349:        /* XXX move to intel/pmap.h */
                    350:        extern pt_entry_t *kernel_page_dir;
1.1.1.4 ! root      351:        int nb_direct, i;
        !           352:        vm_offset_t addr, delta;
1.1       root      353: 
                    354:        /*
                    355:         * Initialize the PIC prior to any possible call to an spl.
                    356:         */
1.1.1.4 ! root      357: #ifndef        MACH_HYP
1.1       root      358:        picinit();
1.1.1.4 ! root      359: #else  /* MACH_HYP */
        !           360:        hyp_intrinit();
        !           361: #endif /* MACH_HYP */
1.1       root      362: 
                    363:        /*
                    364:         * Find memory size parameters.
                    365:         */
                    366:        mem_size_init();
                    367: 
1.1.1.4 ! root      368: #ifdef MACH_XEN
        !           369:        kernel_cmdline = (char*) boot_info.cmd_line;
        !           370: #else  /* MACH_XEN */
        !           371:        /* Copy content pointed by boot_info before losing access to it when it
        !           372:         * is too far in physical memory.  */
        !           373:        if (boot_info.flags & MULTIBOOT_CMDLINE) {
        !           374:                int len = strlen ((char*)phystokv(boot_info.cmdline)) + 1;
        !           375:                assert(init_alloc_aligned(round_page(len), &addr));
        !           376:                kernel_cmdline = (char*) phystokv(addr);
        !           377:                memcpy(kernel_cmdline, (char*)phystokv(boot_info.cmdline), len);
        !           378:                boot_info.cmdline = addr;
        !           379:        }
        !           380: 
        !           381:        if (boot_info.flags & MULTIBOOT_MODS) {
        !           382:                struct multiboot_module *m;
        !           383:                int i;
        !           384: 
        !           385:                assert(init_alloc_aligned(round_page(boot_info.mods_count * sizeof(*m)), &addr));
        !           386:                m = (void*) phystokv(addr);
        !           387:                memcpy(m, (void*) phystokv(boot_info.mods_addr), boot_info.mods_count * sizeof(*m));
        !           388:                boot_info.mods_addr = addr;
        !           389: 
        !           390:                for (i = 0; i < boot_info.mods_count; i++) {
        !           391:                        vm_size_t size = m[i].mod_end - m[i].mod_start;
        !           392:                        assert(init_alloc_aligned(round_page(size), &addr));
        !           393:                        memcpy((void*) phystokv(addr), (void*) phystokv(m[i].mod_start), size);
        !           394:                        m[i].mod_start = addr;
        !           395:                        m[i].mod_end = addr + size;
        !           396: 
        !           397:                        size = strlen((char*) phystokv(m[i].string)) + 1;
        !           398:                        assert(init_alloc_aligned(round_page(size), &addr));
        !           399:                        memcpy((void*) phystokv(addr), (void*) phystokv(m[i].string), size);
        !           400:                        m[i].string = addr;
        !           401:                }
        !           402:        }
        !           403: #endif /* MACH_XEN */
        !           404: 
1.1       root      405:        /*
                    406:         *      Initialize kernel physical map, mapping the
                    407:         *      region from loadpt to avail_start.
                    408:         *      Kernel virtual address starts at VM_KERNEL_MIN_ADDRESS.
                    409:         *      XXX make the BIOS page (page 0) read-only.
                    410:         */
                    411:        pmap_bootstrap();
                    412: 
                    413:        /*
                    414:         * We'll have to temporarily install a direct mapping
                    415:         * between physical memory and low linear memory,
                    416:         * until we start using our new kernel segment descriptors.
                    417:         */
1.1.1.4 ! root      418: #if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS
        !           419:        delta = INIT_VM_MIN_KERNEL_ADDRESS - LINEAR_MIN_KERNEL_ADDRESS;
        !           420:        if ((vm_offset_t)(-delta) < delta)
        !           421:                delta = (vm_offset_t)(-delta);
        !           422:        nb_direct = delta >> PDESHIFT;
        !           423:        for (i = 0; i < nb_direct; i++)
        !           424:                kernel_page_dir[lin2pdenum(INIT_VM_MIN_KERNEL_ADDRESS) + i] =
        !           425:                        kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS) + i];
        !           426: #endif
        !           427:        /* We need BIOS memory mapped at 0xc0000 & co for Linux drivers */
        !           428: #ifdef LINUX_DEV
        !           429: #if VM_MIN_KERNEL_ADDRESS != 0
        !           430:        kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] =
1.1       root      431:                kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS)];
1.1.1.4 ! root      432: #endif
        !           433: #endif
        !           434: 
        !           435: #ifdef MACH_PV_PAGETABLES
        !           436:        for (i = 0; i < PDPNUM; i++)
        !           437:                pmap_set_page_readonly_init((void*) kernel_page_dir + i * INTEL_PGBYTES);
        !           438: #if PAE
        !           439:        pmap_set_page_readonly_init(kernel_pmap->pdpbase);
        !           440: #endif /* PAE */
        !           441: #endif /* MACH_PV_PAGETABLES */
        !           442: #if PAE
        !           443:        set_cr3((unsigned)_kvtophys(kernel_pmap->pdpbase));
        !           444: #ifndef        MACH_HYP
        !           445:        if (!CPU_HAS_FEATURE(CPU_FEATURE_PAE))
        !           446:                panic("CPU doesn't have support for PAE.");
        !           447:        set_cr4(get_cr4() | CR4_PAE);
        !           448: #endif /* MACH_HYP */
        !           449: #else
        !           450:        set_cr3((unsigned)_kvtophys(kernel_page_dir));
        !           451: #endif /* PAE */
        !           452: #ifndef        MACH_HYP
        !           453:        /* Turn paging on.
        !           454:         * Also set the WP bit so that on 486 or better processors
        !           455:         * page-level write protection works in kernel mode.
        !           456:         */
1.1       root      457:        set_cr0(get_cr0() | CR0_PG | CR0_WP);
1.1.1.4 ! root      458:        set_cr0(get_cr0() & ~(CR0_CD | CR0_NW));
        !           459:        if (CPU_HAS_FEATURE(CPU_FEATURE_PGE))
        !           460:                set_cr4(get_cr4() | CR4_PGE);
        !           461: #endif /* MACH_HYP */
1.1       root      462:        flush_instr_queue();
1.1.1.4 ! root      463: #ifdef MACH_PV_PAGETABLES
        !           464:        pmap_clear_bootstrap_pagetable((void *)boot_info.pt_base);
        !           465: #endif /* MACH_PV_PAGETABLES */
        !           466: 
        !           467:        /* Interrupt stacks are allocated in physical memory,
        !           468:           while kernel stacks are allocated in kernel virtual memory,
        !           469:           so phys_last_addr serves as a convenient dividing point.  */
        !           470:        int_stack_high = phystokv(phys_last_addr);
1.1       root      471: 
                    472:        /*
                    473:         * Initialize and activate the real i386 protected-mode structures.
                    474:         */
                    475:        gdt_init();
                    476:        idt_init();
1.1.1.4 ! root      477: #ifndef        MACH_HYP
1.1       root      478:        int_init();
1.1.1.4 ! root      479: #endif /* MACH_HYP */
1.1       root      480:        ldt_init();
                    481:        ktss_init();
                    482: 
1.1.1.4 ! root      483: #if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS
1.1       root      484:        /* Get rid of the temporary direct mapping and flush it out of the TLB.  */
1.1.1.4 ! root      485:        for (i = 0 ; i < nb_direct; i++) {
        !           486: #ifdef MACH_XEN
        !           487: #ifdef MACH_PSEUDO_PHYS
        !           488:                if (!hyp_mmu_update_pte(kv_to_ma(&kernel_page_dir[lin2pdenum(VM_MIN_KERNEL_ADDRESS) + i]), 0))
        !           489: #else  /* MACH_PSEUDO_PHYS */
        !           490:                if (hyp_do_update_va_mapping(VM_MIN_KERNEL_ADDRESS + i * INTEL_PGBYTES, 0, UVMF_INVLPG | UVMF_ALL))
        !           491: #endif /* MACH_PSEUDO_PHYS */
        !           492:                        printf("couldn't unmap frame %d\n", i);
        !           493: #else  /* MACH_XEN */
        !           494:                kernel_page_dir[lin2pdenum(INIT_VM_MIN_KERNEL_ADDRESS) + i] = 0;
        !           495: #endif /* MACH_XEN */
        !           496:        }
        !           497: #endif
        !           498:        /* Keep BIOS memory mapped */
        !           499: #ifdef LINUX_DEV
        !           500: #if VM_MIN_KERNEL_ADDRESS != 0
        !           501:        kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] =
        !           502:                kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS)];
        !           503: #endif
        !           504: #endif
1.1       root      505: 
1.1.1.4 ! root      506:        /* Not used after boot, better give it back.  */
        !           507: #ifdef MACH_XEN
        !           508:        hyp_free_page(0, (void*) VM_MIN_KERNEL_ADDRESS);
        !           509: #endif /* MACH_XEN */
        !           510: 
        !           511:        flush_tlb();
        !           512: 
        !           513: #ifdef MACH_XEN
        !           514:        hyp_p2m_init();
        !           515: #endif /* MACH_XEN */
1.1       root      516: 
                    517:        /* XXX We'll just use the initialization stack we're already running on
                    518:           as the interrupt stack for now.  Later this will have to change,
                    519:           because the init stack will get freed after bootup.  */
                    520:        asm("movl %%esp,%0" : "=m" (int_stack_top));
                    521: }
                    522: 
                    523: /*
                    524:  *     C boot entrypoint - called by boot_entry in boothdr.S.
                    525:  *     Running in 32-bit flat mode, but without paging yet.
                    526:  */
                    527: void c_boot_entry(vm_offset_t bi)
                    528: {
                    529:        /* Stash the boot_image_info pointer.  */
1.1.1.4 ! root      530:        boot_info = *(typeof(boot_info)*)phystokv(bi);
        !           531:        int cpu_type;
1.1       root      532: 
                    533:        /* Before we do _anything_ else, print the hello message.
                    534:           If there are no initialized console devices yet,
                    535:           it will be stored and printed at the first opportunity.  */
1.1.1.4 ! root      536:        printf("%s", version);
1.1       root      537:        printf("\n");
                    538: 
1.1.1.4 ! root      539: #ifdef MACH_XEN
        !           540:        printf("Running on %s.\n", boot_info.magic);
        !           541:        if (boot_info.flags & SIF_PRIVILEGED)
        !           542:                panic("Mach can't run as dom0.");
        !           543: #ifdef MACH_PSEUDO_PHYS
        !           544:        mfn_list = (void*)boot_info.mfn_list;
        !           545: #endif
        !           546: #else  /* MACH_XEN */
1.1       root      547: 
                    548: #if    MACH_KDB
                    549:        /*
                    550:         * Locate the kernel's symbol table, if the boot loader provided it.
                    551:         * We need to do this before i386at_init()
                    552:         * so that the symbol table's memory won't be stomped on.
                    553:         */
1.1.1.3   root      554:        if ((boot_info.flags & MULTIBOOT_AOUT_SYMS)
                    555:            && boot_info.syms.a.addr)
1.1       root      556:        {
                    557:                vm_size_t symtab_size, strtab_size;
                    558: 
1.1.1.3   root      559:                kern_sym_start = (vm_offset_t)phystokv(boot_info.syms.a.addr);
                    560:                symtab_size = (vm_offset_t)phystokv(boot_info.syms.a.tabsize);
                    561:                strtab_size = (vm_offset_t)phystokv(boot_info.syms.a.strsize);
1.1       root      562:                kern_sym_end = kern_sym_start + 4 + symtab_size + strtab_size;
                    563: 
1.1.1.4 ! root      564:                printf("kernel symbol table at %08lx-%08lx (%d,%d)\n",
1.1       root      565:                       kern_sym_start, kern_sym_end,
                    566:                       symtab_size, strtab_size);
                    567:        }
1.1.1.3   root      568: #endif /* MACH_KDB */
1.1.1.4 ! root      569: #endif /* MACH_XEN */
        !           570: 
        !           571:        cpu_type = discover_x86_cpu_type ();
1.1       root      572: 
                    573:        /*
                    574:         * Do basic VM initialization
                    575:         */
                    576:        i386at_init();
                    577: 
                    578: #if    MACH_KDB
                    579:        /*
                    580:         * Initialize the kernel debugger's kernel symbol table.
                    581:         */
                    582:        if (kern_sym_start)
                    583:        {
                    584:                aout_db_sym_init(kern_sym_start, kern_sym_end, "mach", 0);
                    585:        }
1.1.1.3   root      586: #endif /* MACH_KDB */
1.1       root      587: 
                    588:        machine_slot[0].is_cpu = TRUE;
                    589:        machine_slot[0].running = TRUE;
                    590:        machine_slot[0].cpu_subtype = CPU_SUBTYPE_AT386;
                    591: 
1.1.1.4 ! root      592:        switch (cpu_type)
1.1.1.2   root      593:          {
                    594:          default:
1.1.1.4 ! root      595:            printf("warning: unknown cpu type %d, assuming i386\n", cpu_type);
        !           596:          case 3:
1.1.1.2   root      597:            machine_slot[0].cpu_type = CPU_TYPE_I386;
                    598:            break;
                    599:          case 4:
                    600:            machine_slot[0].cpu_type = CPU_TYPE_I486;
                    601:            break;
                    602:          case 5:
                    603:            machine_slot[0].cpu_type = CPU_TYPE_PENTIUM;
                    604:            break;
                    605:          case 6:
1.1.1.4 ! root      606:          case 15:
1.1.1.2   root      607:            machine_slot[0].cpu_type = CPU_TYPE_PENTIUMPRO;
                    608:            break;
                    609:          }
                    610: 
1.1       root      611:        /*
                    612:         * Start the system.
                    613:         */
                    614:        setup_main();
                    615: 
                    616: }
                    617: 
                    618: #include <mach/vm_prot.h>
                    619: #include <vm/pmap.h>
                    620: #include <mach/time_value.h>
                    621: 
1.1.1.4 ! root      622: int
1.1       root      623: timemmap(dev,off,prot)
                    624:        vm_prot_t prot;
                    625: {
                    626:        extern time_value_t *mtime;
                    627: 
                    628: #ifdef lint
                    629:        dev++; off++;
1.1.1.3   root      630: #endif /* lint */
1.1       root      631: 
                    632:        if (prot & VM_PROT_WRITE) return (-1);
                    633: 
                    634:        return (i386_btop(pmap_extract(pmap_kernel(), (vm_offset_t) mtime)));
                    635: }
                    636: 
1.1.1.4 ! root      637: void
        !           638: startrtclock(void)
1.1       root      639: {
                    640:        clkstart();
                    641: }
                    642: 
                    643: void
1.1.1.4 ! root      644: inittodr(void)
1.1       root      645: {
                    646:        time_value_t    new_time;
                    647: 
                    648:        new_time.seconds = 0;
                    649:        new_time.microseconds = 0;
                    650: 
1.1.1.4 ! root      651:        (void) readtodc((u_int *)&new_time.seconds);
1.1       root      652: 
                    653:        {
                    654:            spl_t       s = splhigh();
                    655:            time = new_time;
                    656:            splx(s);
                    657:        }
                    658: }
                    659: 
                    660: void
1.1.1.4 ! root      661: resettodr(void)
1.1       root      662: {
                    663:        writetodc();
                    664: }
                    665: 
1.1.1.4 ! root      666: unsigned int pmap_free_pages(void)
1.1       root      667: {
                    668:        return atop(avail_remaining);
                    669: }
                    670: 
                    671: /* Always returns page-aligned regions.  */
1.1.1.4 ! root      672: boolean_t
1.1       root      673: init_alloc_aligned(vm_size_t size, vm_offset_t *addrp)
                    674: {
                    675:        vm_offset_t addr;
1.1.1.4 ! root      676: 
        !           677: #ifdef MACH_HYP
        !           678:        /* There is none */
        !           679:        if (!avail_next)
        !           680:                avail_next = _kvtophys(boot_info.pt_base) + (boot_info.nr_pt_frames + 3) * 0x1000;
        !           681: #else  /* MACH_HYP */
1.1       root      682:        extern char start[], end[];
                    683:        int i;
1.1.1.3   root      684:        static int wrapped = 0;
1.1       root      685: 
                    686:        /* Memory regions to skip.  */
1.1.1.3   root      687:        vm_offset_t cmdline_start_pa = boot_info.flags & MULTIBOOT_CMDLINE
                    688:                ? boot_info.cmdline : 0;
1.1       root      689:        vm_offset_t cmdline_end_pa = cmdline_start_pa
                    690:                ? cmdline_start_pa+strlen((char*)phystokv(cmdline_start_pa))+1
                    691:                : 0;
1.1.1.3   root      692:        vm_offset_t mods_start_pa = boot_info.flags & MULTIBOOT_MODS
                    693:                ? boot_info.mods_addr : 0;
1.1       root      694:        vm_offset_t mods_end_pa = mods_start_pa
                    695:                ? mods_start_pa
1.1.1.3   root      696:                  + boot_info.mods_count * sizeof(struct multiboot_module)
1.1       root      697:                : 0;
                    698: 
                    699:        retry:
1.1.1.4 ! root      700: #endif /* MACH_HYP */
1.1       root      701: 
                    702:        /* Page-align the start address.  */
                    703:        avail_next = round_page(avail_next);
                    704: 
1.1.1.4 ! root      705: #ifndef MACH_HYP
1.1.1.3   root      706:        /* Start with memory above 16MB, reserving the low memory for later. */
1.1.1.4 ! root      707:        /* Don't care on Xen */
        !           708:        if (!wrapped && phys_last_addr > 16 * 1024*1024)
1.1.1.3   root      709:          {
                    710:            if (avail_next < 16 * 1024*1024)
                    711:              avail_next = 16 * 1024*1024;
                    712:            else if (avail_next == phys_last_addr)
                    713:              {
                    714:                /* We have used all the memory above 16MB, so now start on
                    715:                   the low memory.  This will wind up at the end of the list
                    716:                   of free pages, so it should not have been allocated to any
                    717:                   other use in early initialization before the Linux driver
                    718:                   glue initialization needs to allocate low memory.  */
                    719:                avail_next = 0x1000;
                    720:                wrapped = 1;
                    721:              }
                    722:          }
1.1.1.4 ! root      723: #endif /* MACH_HYP */
1.1.1.3   root      724: 
1.1       root      725:        /* Check if we have reached the end of memory.  */
1.1.1.4 ! root      726:         if (avail_next == 
        !           727:                (
        !           728: #ifndef MACH_HYP
        !           729:                wrapped ? 16 * 1024*1024 : 
        !           730: #endif /* MACH_HYP */
        !           731:                phys_last_addr))
1.1       root      732:                return FALSE;
                    733: 
                    734:        /* Tentatively assign the current location to the caller.  */
                    735:        addr = avail_next;
                    736: 
                    737:        /* Bump the pointer past the newly allocated region
                    738:           and see where that puts us.  */
                    739:        avail_next += size;
                    740: 
1.1.1.4 ! root      741: #ifndef MACH_HYP
1.1       root      742:        /* Skip past the I/O and ROM area.  */
1.1.1.4 ! root      743:        if (boot_info.flags & MULTIBOOT_MEM_MAP)
        !           744:        {
        !           745:                struct multiboot_mmap *map, *map_end, *current = NULL, *next = NULL;
        !           746:                unsigned long long minimum_next = ~0ULL;
        !           747: 
        !           748:                map = (void*) phystokv(boot_info.mmap_addr);
        !           749:                map_end = (void*) map + boot_info.mmap_count;
        !           750: 
        !           751:                /* Find both our current map, and the next one */
        !           752:                while (map + 1 <= map_end)
        !           753:                {
        !           754:                        if (map->Type == MB_ARD_MEMORY)
        !           755:                        {
        !           756:                                unsigned long long start = map->BaseAddr;
        !           757:                                unsigned long long end = start + map->Length;;
        !           758: 
        !           759:                                if (start <= addr && avail_next <= end)
        !           760:                                {
        !           761:                                        /* Ok, fits in the current map */
        !           762:                                        current = map;
        !           763:                                        break;
        !           764:                                }
        !           765:                                else if (avail_next <= start && start < minimum_next)
        !           766:                                {
        !           767:                                        /* This map is not far from avail_next */
        !           768:                                        next = map;
        !           769:                                        minimum_next = start;
        !           770:                                }
        !           771:                        }
        !           772:                        map = (void*) map + map->size + sizeof(map->size);
        !           773:                }
        !           774: 
        !           775:                if (!current) {
        !           776:                        /* Area does not fit in the current map, switch to next
        !           777:                         * map if any */
        !           778:                        if (!next || next->BaseAddr >= phys_last_addr)
        !           779:                        {
        !           780:                                /* No further reachable map, we have reached
        !           781:                                 * the end of memory, but possibly wrap around
        !           782:                                 * 16MiB. */
        !           783:                                avail_next = phys_last_addr;
        !           784:                                goto retry;
        !           785:                        }
        !           786: 
        !           787:                        /* Start from next map */
        !           788:                        avail_next = next->BaseAddr;
        !           789:                        goto retry;
        !           790:                }
        !           791:        }
        !           792:        else if ((avail_next > (boot_info.mem_lower * 0x400)) && (addr < 0x100000))
1.1       root      793:        {
                    794:                avail_next = 0x100000;
                    795:                goto retry;
                    796:        }
                    797: 
                    798:        /* Skip our own kernel code, data, and bss.  */
1.1.1.4 ! root      799:        if ((phystokv(avail_next) > (vm_offset_t)start) && (phystokv(addr) < (vm_offset_t)end))
1.1       root      800:        {
1.1.1.4 ! root      801:                avail_next = _kvtophys(end);
1.1       root      802:                goto retry;
                    803:        }
                    804: 
                    805:        /* Skip any areas occupied by valuable boot_info data.  */
                    806:        if ((avail_next > cmdline_start_pa) && (addr < cmdline_end_pa))
                    807:        {
                    808:                avail_next = cmdline_end_pa;
                    809:                goto retry;
                    810:        }
                    811:        if ((avail_next > mods_start_pa) && (addr < mods_end_pa))
                    812:        {
                    813:                avail_next = mods_end_pa;
                    814:                goto retry;
                    815:        }
1.1.1.4 ! root      816:        if ((phystokv(avail_next) > kern_sym_start) && (phystokv(addr) < kern_sym_end))
1.1       root      817:        {
1.1.1.4 ! root      818:                avail_next = _kvtophys(kern_sym_end);
1.1       root      819:                goto retry;
                    820:        }
1.1.1.3   root      821:        if (boot_info.flags & MULTIBOOT_MODS)
1.1       root      822:        {
                    823:                struct multiboot_module *m = (struct multiboot_module *)
1.1.1.3   root      824:                        phystokv(boot_info.mods_addr);
                    825:                for (i = 0; i < boot_info.mods_count; i++)
1.1       root      826:                {
                    827:                        if ((avail_next > m[i].mod_start)
                    828:                            && (addr < m[i].mod_end))
                    829:                        {
                    830:                                avail_next = m[i].mod_end;
                    831:                                goto retry;
                    832:                        }
                    833:                        /* XXX string */
                    834:                }
                    835:        }
1.1.1.4 ! root      836: #endif /* MACH_HYP */
1.1       root      837: 
                    838:        avail_remaining -= size;
                    839: 
                    840:        *addrp = addr;
                    841:        return TRUE;
                    842: }
                    843: 
                    844: boolean_t pmap_next_page(addrp)
                    845:        vm_offset_t *addrp;
                    846: {
                    847:        return init_alloc_aligned(PAGE_SIZE, addrp);
                    848: }
                    849: 
                    850: /* Grab a physical page:
                    851:    the standard memory allocation mechanism
                    852:    during system initialization.  */
                    853: vm_offset_t
1.1.1.4 ! root      854: pmap_grab_page(void)
1.1       root      855: {
                    856:        vm_offset_t addr;
                    857:        if (!pmap_next_page(&addr))
                    858:                panic("Not enough memory to initialize Mach");
                    859:        return addr;
                    860: }
                    861: 
                    862: boolean_t pmap_valid_page(x)
                    863:        vm_offset_t x;
                    864: {
                    865:        /* XXX is this OK?  What does it matter for?  */
1.1.1.4 ! root      866:        return (((phys_first_addr <= x) && (x < phys_last_addr))
        !           867: #ifndef MACH_HYP
        !           868:                && !(
        !           869:                ((boot_info.mem_lower * 1024) <= x) && 
        !           870:                (x < 1024*1024))
        !           871: #endif /* MACH_HYP */
        !           872:                );
1.1       root      873: }

unix.superglobalmegacorp.com

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