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