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