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

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

unix.superglobalmegacorp.com

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