|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.