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

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

unix.superglobalmegacorp.com

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