--- Gnu-Mach/i386/i386at/model_dep.c 2020/09/02 04:36:58 1.1 +++ Gnu-Mach/i386/i386at/model_dep.c 2020/09/02 04:53:36 1.1.1.7 @@ -1,25 +1,25 @@ -/* +/* * Mach Operating System * Copyright (c) 1991,1990,1989, 1988 Carnegie Mellon University * All Rights Reserved. - * + * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. - * + * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * + * * Carnegie Mellon requests users of this software to return to - * + * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 - * + * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ @@ -32,78 +32,111 @@ * Basic initialization for I386 - ISA bus machines. */ -#include -#include +#include + +#include #include #include #include #include +#include -#include "vm_param.h" -#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include +#include +#include +#include +#include #include +#include +#include #include -#include "proc_reg.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef MACH_XEN +#include +#include +#include +#include +#endif /* MACH_XEN */ + +#if ENABLE_IMMEDIATE_CONSOLE +#include "immc.h" +#endif /* ENABLE_IMMEDIATE_CONSOLE */ /* Location of the kernel's symbol table. Both of these are 0 if none is available. */ #if MACH_KDB +#include +#include + +/* a.out symbol table */ static vm_offset_t kern_sym_start, kern_sym_end; -#else + +/* ELF section header */ +static unsigned elf_shdr_num; +static vm_size_t elf_shdr_size; +static vm_offset_t elf_shdr_addr; +static unsigned elf_shdr_shndx; + +#else /* MACH_KDB */ #define kern_sym_start 0 #define kern_sym_end 0 -#endif +#endif /* MACH_KDB */ + +#define RESERVED_BIOS 0x10000 /* These indicate the total extent of physical memory addresses we're using. They are page-aligned. */ vm_offset_t phys_first_addr = 0; vm_offset_t phys_last_addr; -/* Virtual address of physical memory, for the kvtophys/phystokv macros. */ -vm_offset_t phys_mem_va; - -struct multiboot_info *boot_info; +/* A copy of the multiboot info structure passed by the boot loader. */ +#ifdef MACH_XEN +struct start_info boot_info; +#ifdef MACH_PSEUDO_PHYS +unsigned long *mfn_list; +#if VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS +unsigned long *pfn_list = (void*) PFN_LIST; +#endif +#endif /* MACH_PSEUDO_PHYS */ +#if VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS +unsigned long la_shift = VM_MIN_KERNEL_ADDRESS; +#endif +#else /* MACH_XEN */ +struct multiboot_info boot_info; +#endif /* MACH_XEN */ /* Command line supplied to kernel. */ char *kernel_cmdline = ""; -/* This is used for memory initialization: - it gets bumped up through physical memory - that exists and is not occupied by boot gunk. - It is not necessarily page-aligned. */ -static vm_offset_t avail_next = 0x1000; /* XX end of BIOS data area */ - -/* Possibly overestimated amount of available memory - still remaining to be handed to the VM system. */ -static vm_size_t avail_remaining; - -/* Configuration parameter: - if zero, only use physical memory in the low 16MB of addresses. - Only SCSI still has DMA problems. */ -#ifdef LINUX_DEV -int use_all_mem = 1; -#else -#include "nscsi.h" -#if NSCSI > 0 -int use_all_mem = 0; -#else -int use_all_mem = 1; -#endif -#endif - extern char version[]; -extern void setup_main(); - -void inittodr(); /* forward */ +/* If set, reboot the system on ctrl-alt-delete. */ +boolean_t rebootflag = FALSE; /* exported to kdintr */ -int rebootflag = 0; /* exported to kdintr */ - -/* XX interrupt stack pointer and highwater mark, for locore.S. */ -vm_offset_t int_stack_top, int_stack_high; +/* Interrupt stack. */ +static char int_stack[KERNEL_STACK_SIZE] __aligned(KERNEL_STACK_SIZE); +vm_offset_t int_stack_top, int_stack_base; #ifdef LINUX_DEV extern void linux_init(void); @@ -112,7 +145,7 @@ extern void linux_init(void); /* * Find devices. The system is alive. */ -void machine_init() +void machine_init(void) { /* * Initialize the console. @@ -124,6 +157,9 @@ void machine_init() */ init_fpu(); +#ifdef MACH_HYP + hyp_init(); +#else /* MACH_HYP */ #ifdef LINUX_DEV /* * Initialize Linux drivers. @@ -135,48 +171,82 @@ void machine_init() * Find the devices */ probeio(); +#endif /* MACH_HYP */ /* * Get the time */ inittodr(); +#ifndef MACH_HYP /* * Tell the BIOS not to clear and test memory. */ *(unsigned short *)phystokv(0x472) = 0x1234; +#endif /* MACH_HYP */ +#if VM_MIN_KERNEL_ADDRESS == 0 /* * Unmap page 0 to trap NULL references. + * + * Note that this breaks accessing some BIOS areas stored there. */ pmap_unmap_page_zero(); +#endif +} + +/* Conserve power on processor CPU. */ +void machine_idle (int cpu) +{ +#ifdef MACH_HYP + hyp_idle(); +#else /* MACH_HYP */ + assert (cpu == cpu_number ()); + asm volatile ("hlt" : : : "memory"); +#endif /* MACH_HYP */ +} + +void machine_relax (void) +{ + asm volatile ("rep; nop" : : : "memory"); } /* * Halt a cpu. */ -halt_cpu() +void halt_cpu(void) { +#ifdef MACH_HYP + hyp_halt(); +#else /* MACH_HYP */ asm volatile("cli"); - while(1); + while (TRUE) + machine_idle (cpu_number ()); +#endif /* MACH_HYP */ } /* * Halt the system or reboot. */ -halt_all_cpus(reboot) - boolean_t reboot; +void halt_all_cpus(boolean_t reboot) { if (reboot) { +#ifdef MACH_HYP + hyp_reboot(); +#endif /* MACH_HYP */ kdreboot(); } else { - rebootflag = 1; + rebootflag = TRUE; +#ifdef MACH_HYP + hyp_halt(); +#endif /* MACH_HYP */ + grub_acpi_halt(); printf("In tight loop: hit ctl-alt-del to reboot\n"); (void) spl0(); } - for (;;) - continue; + while (TRUE) + machine_idle (cpu_number ()); } void exit(int rc) @@ -184,57 +254,89 @@ void exit(int rc) halt_all_cpus(0); } -void db_reset_cpu() +void db_halt_cpu(void) { - halt_all_cpus(1); + halt_all_cpus(0); } - -/* - * Compute physical memory size and other parameters. - */ -void -mem_size_init() +void db_reset_cpu(void) { - /* Physical memory on all PCs starts at physical address 0. - XX make it a constant. */ - phys_first_addr = 0; - - phys_last_addr = 0x100000 + (boot_info->mem_upper * 0x400); - avail_remaining - = phys_last_addr - (0x100000 - (boot_info->mem_lower * 0x400) - - 0x1000); - - printf("AT386 boot: physical memory from 0x%x to 0x%x\n", - phys_first_addr, phys_last_addr); - - if ((!use_all_mem) && phys_last_addr > 16 * 1024*1024) { - printf("** Limiting useable memory to 16 Meg to avoid DMA problems.\n"); - /* This is actually enforced below, in init_alloc_aligned. */ - } - - phys_first_addr = round_page(phys_first_addr); - phys_last_addr = trunc_page(phys_last_addr); + halt_all_cpus(1); } /* * Basic PC VM initialization. * Turns on paging and changes the kernel segments to use high linear addresses. */ -i386at_init() +void +i386at_init(void) { /* XXX move to intel/pmap.h */ extern pt_entry_t *kernel_page_dir; + int nb_direct, i; + vm_offset_t addr, delta; /* * Initialize the PIC prior to any possible call to an spl. */ +#ifndef MACH_HYP picinit(); - - /* - * Find memory size parameters. - */ - mem_size_init(); +#else /* MACH_HYP */ + hyp_intrinit(); +#endif /* MACH_HYP */ + + /* + * Read memory map and load it into the physical page allocator. + */ +#ifdef MACH_HYP + biosmem_xen_bootstrap(); +#else /* MACH_HYP */ + biosmem_bootstrap((struct multiboot_raw_info *) &boot_info); +#endif /* MACH_HYP */ + +#ifdef MACH_XEN + kernel_cmdline = (char*) boot_info.cmd_line; +#else /* MACH_XEN */ + /* Copy content pointed by boot_info before losing access to it when it + * is too far in physical memory. */ + if (boot_info.flags & MULTIBOOT_CMDLINE) { + int len = strlen ((char*)phystokv(boot_info.cmdline)) + 1; + if (! init_alloc_aligned(round_page(len), &addr)) + panic("could not allocate memory for multiboot command line"); + kernel_cmdline = (char*) phystokv(addr); + memcpy(kernel_cmdline, (void *)phystokv(boot_info.cmdline), len); + boot_info.cmdline = addr; + } + + if (boot_info.flags & MULTIBOOT_MODS) { + struct multiboot_module *m; + int i; + + if (! init_alloc_aligned( + round_page(boot_info.mods_count * sizeof(*m)), &addr)) + panic("could not allocate memory for multiboot modules"); + m = (void*) phystokv(addr); + memcpy(m, (void*) phystokv(boot_info.mods_addr), boot_info.mods_count * sizeof(*m)); + boot_info.mods_addr = addr; + + for (i = 0; i < boot_info.mods_count; i++) { + vm_size_t size = m[i].mod_end - m[i].mod_start; + if (! init_alloc_aligned(round_page(size), &addr)) + panic("could not allocate memory for multiboot " + "module %d", i); + memcpy((void*) phystokv(addr), (void*) phystokv(m[i].mod_start), size); + m[i].mod_start = addr; + m[i].mod_end = addr + size; + + size = strlen((char*) phystokv(m[i].string)) + 1; + if (! init_alloc_aligned(round_page(size), &addr)) + panic("could not allocate memory for multiboot " + "module command line %d", i); + memcpy((void*) phystokv(addr), (void*) phystokv(m[i].string), size); + m[i].string = addr; + } + } +#endif /* MACH_XEN */ /* * Initialize kernel physical map, mapping the @@ -245,44 +347,113 @@ i386at_init() pmap_bootstrap(); /* - * Turn paging on. + * Load physical segments into the VM system. + * The early allocation functions become unusable after + * this point. + */ + biosmem_setup(); + + /* * We'll have to temporarily install a direct mapping * between physical memory and low linear memory, * until we start using our new kernel segment descriptors. - * One page table (4MB) should do the trick. - * Also, set the WP bit so that on 486 or better processors - * page-level write protection works in kernel mode. */ - kernel_page_dir[lin2pdenum(0)] = +#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS + delta = INIT_VM_MIN_KERNEL_ADDRESS - LINEAR_MIN_KERNEL_ADDRESS; + if ((vm_offset_t)(-delta) < delta) + delta = (vm_offset_t)(-delta); + nb_direct = delta >> PDESHIFT; + for (i = 0; i < nb_direct; i++) + kernel_page_dir[lin2pdenum(INIT_VM_MIN_KERNEL_ADDRESS) + i] = + kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS) + i]; +#endif + /* We need BIOS memory mapped at 0xc0000 & co for Linux drivers */ +#ifdef LINUX_DEV +#if VM_MIN_KERNEL_ADDRESS != 0 + kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] = kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS)]; - set_cr3((unsigned)kernel_page_dir); +#endif +#endif + +#ifdef MACH_PV_PAGETABLES + for (i = 0; i < PDPNUM; i++) + pmap_set_page_readonly_init((void*) kernel_page_dir + i * INTEL_PGBYTES); +#if PAE + pmap_set_page_readonly_init(kernel_pmap->pdpbase); +#endif /* PAE */ +#endif /* MACH_PV_PAGETABLES */ +#if PAE + set_cr3((unsigned)_kvtophys(kernel_pmap->pdpbase)); +#ifndef MACH_HYP + if (!CPU_HAS_FEATURE(CPU_FEATURE_PAE)) + panic("CPU doesn't have support for PAE."); + set_cr4(get_cr4() | CR4_PAE); +#endif /* MACH_HYP */ +#else + set_cr3((unsigned)_kvtophys(kernel_page_dir)); +#endif /* PAE */ +#ifndef MACH_HYP + /* Turn paging on. + * Also set the WP bit so that on 486 or better processors + * page-level write protection works in kernel mode. + */ set_cr0(get_cr0() | CR0_PG | CR0_WP); + set_cr0(get_cr0() & ~(CR0_CD | CR0_NW)); + if (CPU_HAS_FEATURE(CPU_FEATURE_PGE)) + set_cr4(get_cr4() | CR4_PGE); +#endif /* MACH_HYP */ flush_instr_queue(); +#ifdef MACH_PV_PAGETABLES + pmap_clear_bootstrap_pagetable((void *)boot_info.pt_base); +#endif /* MACH_PV_PAGETABLES */ /* * Initialize and activate the real i386 protected-mode structures. */ gdt_init(); idt_init(); +#ifndef MACH_HYP int_init(); +#endif /* MACH_HYP */ ldt_init(); ktss_init(); +#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS /* Get rid of the temporary direct mapping and flush it out of the TLB. */ - kernel_page_dir[lin2pdenum(0)] = 0; - set_cr3((unsigned)kernel_page_dir); - - + for (i = 0 ; i < nb_direct; i++) { +#ifdef MACH_XEN +#ifdef MACH_PSEUDO_PHYS + if (!hyp_mmu_update_pte(kv_to_ma(&kernel_page_dir[lin2pdenum(VM_MIN_KERNEL_ADDRESS) + i]), 0)) +#else /* MACH_PSEUDO_PHYS */ + if (hyp_do_update_va_mapping(VM_MIN_KERNEL_ADDRESS + i * INTEL_PGBYTES, 0, UVMF_INVLPG | UVMF_ALL)) +#endif /* MACH_PSEUDO_PHYS */ + printf("couldn't unmap frame %d\n", i); +#else /* MACH_XEN */ + kernel_page_dir[lin2pdenum(INIT_VM_MIN_KERNEL_ADDRESS) + i] = 0; +#endif /* MACH_XEN */ + } +#endif + /* Keep BIOS memory mapped */ +#ifdef LINUX_DEV +#if VM_MIN_KERNEL_ADDRESS != 0 + kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] = + kernel_page_dir[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS)]; +#endif +#endif - /* XXX We'll just use the initialization stack we're already running on - as the interrupt stack for now. Later this will have to change, - because the init stack will get freed after bootup. */ - asm("movl %%esp,%0" : "=m" (int_stack_top)); + /* Not used after boot, better give it back. */ +#ifdef MACH_XEN + hyp_free_page(0, (void*) VM_MIN_KERNEL_ADDRESS); +#endif /* MACH_XEN */ + + flush_tlb(); + +#ifdef MACH_XEN + hyp_p2m_init(); +#endif /* MACH_XEN */ - /* Interrupt stacks are allocated in physical memory, - while kernel stacks are allocated in kernel virtual memory, - so phys_last_addr serves as a convenient dividing point. */ - int_stack_high = phys_last_addr; + int_stack_base = (vm_offset_t)&int_stack; + int_stack_top = int_stack_base + KERNEL_STACK_SIZE - 4; } /* @@ -291,21 +462,28 @@ i386at_init() */ void c_boot_entry(vm_offset_t bi) { - /* Stash the boot_image_info pointer. */ - boot_info = (struct multiboot_info*)phystokv(bi); +#if ENABLE_IMMEDIATE_CONSOLE + romputc = immc_romputc; +#endif /* ENABLE_IMMEDIATE_CONSOLE */ - /* XXX we currently assume phys_mem_va is always 0 here - - if it isn't, we must tweak the pointers in the boot_info. */ + /* Stash the boot_image_info pointer. */ + boot_info = *(typeof(boot_info)*)phystokv(bi); + int cpu_type; /* Before we do _anything_ else, print the hello message. If there are no initialized console devices yet, it will be stored and printed at the first opportunity. */ - printf(version); + printf("%s", version); printf("\n"); - /* Find the kernel command line, if there is one. */ - if (boot_info->flags & MULTIBOOT_CMDLINE) - kernel_cmdline = (char*)phystokv(boot_info->cmdline); +#ifdef MACH_XEN + printf("Running on %s.\n", boot_info.magic); + if (boot_info.flags & SIF_PRIVILEGED) + panic("Mach can't run as dom0."); +#ifdef MACH_PSEUDO_PHYS + mfn_list = (void*)boot_info.mfn_list; +#endif +#else /* MACH_XEN */ #if MACH_KDB /* @@ -313,21 +491,35 @@ void c_boot_entry(vm_offset_t bi) * We need to do this before i386at_init() * so that the symbol table's memory won't be stomped on. */ - if ((boot_info->flags & MULTIBOOT_AOUT_SYMS) - && boot_info->syms.a.addr) + if ((boot_info.flags & MULTIBOOT_AOUT_SYMS) + && boot_info.syms.a.addr) { vm_size_t symtab_size, strtab_size; - kern_sym_start = (vm_offset_t)phystokv(boot_info->syms.a.addr); - symtab_size = (vm_offset_t)phystokv(boot_info->syms.a.tabsize); - strtab_size = (vm_offset_t)phystokv(boot_info->syms.a.strsize); + kern_sym_start = (vm_offset_t)phystokv(boot_info.syms.a.addr); + symtab_size = (vm_offset_t)phystokv(boot_info.syms.a.tabsize); + strtab_size = (vm_offset_t)phystokv(boot_info.syms.a.strsize); kern_sym_end = kern_sym_start + 4 + symtab_size + strtab_size; - printf("kernel symbol table at %08x-%08x (%d,%d)\n", + printf("kernel symbol table at %08lx-%08lx (%d,%d)\n", kern_sym_start, kern_sym_end, symtab_size, strtab_size); } -#endif MACH_KDB + + if ((boot_info.flags & MULTIBOOT_ELF_SHDR) + && boot_info.syms.e.num) + { + elf_shdr_num = boot_info.syms.e.num; + elf_shdr_size = boot_info.syms.e.size; + elf_shdr_addr = (vm_offset_t)phystokv(boot_info.syms.e.addr); + elf_shdr_shndx = boot_info.syms.e.shndx; + + printf("ELF section header table at %08lx\n", elf_shdr_addr); + } +#endif /* MACH_KDB */ +#endif /* MACH_XEN */ + + cpu_type = discover_x86_cpu_type (); /* * Do basic VM initialization @@ -340,26 +532,40 @@ void c_boot_entry(vm_offset_t bi) */ if (kern_sym_start) { - aout_db_sym_init(kern_sym_start, kern_sym_end, "mach", 0); + aout_db_sym_init((char *)kern_sym_start, (char *)kern_sym_end, "mach", (char *)0); } - /* - * Cause a breakpoint trap to the debugger before proceeding - * any further if the proper option flag was specified - * on the kernel's command line. - * XXX check for surrounding spaces. - */ - if (strstr(kernel_cmdline, "-d ")) { - cninit(); /* need console for debugger */ - Debugger(); + if (elf_shdr_num) + { + elf_db_sym_init(elf_shdr_num,elf_shdr_size, + elf_shdr_addr, elf_shdr_shndx, + "mach", NULL); } -#endif MACH_KDB +#endif /* MACH_KDB */ machine_slot[0].is_cpu = TRUE; machine_slot[0].running = TRUE; - machine_slot[0].cpu_type = CPU_TYPE_I386; machine_slot[0].cpu_subtype = CPU_SUBTYPE_AT386; + switch (cpu_type) + { + default: + printf("warning: unknown cpu type %d, assuming i386\n", cpu_type); + case 3: + machine_slot[0].cpu_type = CPU_TYPE_I386; + break; + case 4: + machine_slot[0].cpu_type = CPU_TYPE_I486; + break; + case 5: + machine_slot[0].cpu_type = CPU_TYPE_PENTIUM; + break; + case 6: + case 15: + machine_slot[0].cpu_type = CPU_TYPE_PENTIUMPRO; + break; + } + /* * Start the system. */ @@ -371,34 +577,34 @@ void c_boot_entry(vm_offset_t bi) #include #include -timemmap(dev,off,prot) +int +timemmap(dev, off, prot) + dev_t dev; + vm_offset_t off; vm_prot_t prot; { extern time_value_t *mtime; -#ifdef lint - dev++; off++; -#endif lint - if (prot & VM_PROT_WRITE) return (-1); return (i386_btop(pmap_extract(pmap_kernel(), (vm_offset_t) mtime))); } -startrtclock() +void +startrtclock(void) { clkstart(); } void -inittodr() +inittodr(void) { time_value_t new_time; new_time.seconds = 0; new_time.microseconds = 0; - (void) readtodc(&new_time.seconds); + (void) readtodc((u_int *)&new_time.seconds); { spl_t s = splhigh(); @@ -408,244 +614,47 @@ inittodr() } void -resettodr() +resettodr(void) { writetodc(); } -unsigned int pmap_free_pages() +unsigned int pmap_free_pages(void) { - return atop(avail_remaining); + return vm_page_atop(phys_last_addr); /* XXX */ } -/* Always returns page-aligned regions. */ boolean_t init_alloc_aligned(vm_size_t size, vm_offset_t *addrp) { - vm_offset_t addr; - extern char start[], end[]; - int i; - - /* Memory regions to skip. */ - vm_offset_t boot_info_start_pa = kvtophys(boot_info); - vm_offset_t boot_info_end_pa = boot_info_start_pa + sizeof(*boot_info); - vm_offset_t cmdline_start_pa = boot_info->flags & MULTIBOOT_CMDLINE - ? boot_info->cmdline : 0; - vm_offset_t cmdline_end_pa = cmdline_start_pa - ? cmdline_start_pa+strlen((char*)phystokv(cmdline_start_pa))+1 - : 0; - vm_offset_t mods_start_pa = boot_info->flags & MULTIBOOT_MODS - ? boot_info->mods_addr : 0; - vm_offset_t mods_end_pa = mods_start_pa - ? mods_start_pa - + boot_info->mods_count * sizeof(struct multiboot_module) - : 0; - - retry: + *addrp = biosmem_bootalloc(vm_page_atop(vm_page_round(size))); - /* Page-align the start address. */ - avail_next = round_page(avail_next); - - /* Check if we have reached the end of memory. */ - if (avail_next == phys_last_addr) + if (*addrp == 0) return FALSE; - /* Tentatively assign the current location to the caller. */ - addr = avail_next; - - /* Bump the pointer past the newly allocated region - and see where that puts us. */ - avail_next += size; - - /* Skip past the I/O and ROM area. */ - if ((avail_next > (boot_info->mem_lower * 0x400)) && (addr < 0x100000)) - { - avail_next = 0x100000; - goto retry; - } - - /* If we're only supposed to use the low 16 megs, enforce that. */ - if ((!use_all_mem) && (addr >= 16 * 1024*1024)) { - return FALSE; - } - - /* Skip our own kernel code, data, and bss. */ - if ((avail_next >= (vm_offset_t)start) && (addr < (vm_offset_t)end)) - { - avail_next = (vm_offset_t)end; - goto retry; - } - - /* Skip any areas occupied by valuable boot_info data. */ - if ((avail_next > boot_info_start_pa) && (addr < boot_info_end_pa)) - { - avail_next = boot_info_end_pa; - goto retry; - } - if ((avail_next > cmdline_start_pa) && (addr < cmdline_end_pa)) - { - avail_next = cmdline_end_pa; - goto retry; - } - if ((avail_next > mods_start_pa) && (addr < mods_end_pa)) - { - avail_next = mods_end_pa; - goto retry; - } - if ((avail_next > kern_sym_start) && (addr < kern_sym_end)) - { - avail_next = kern_sym_end; - goto retry; - } - if (boot_info->flags & MULTIBOOT_MODS) - { - struct multiboot_module *m = (struct multiboot_module *) - phystokv(boot_info->mods_addr); - for (i = 0; i < boot_info->mods_count; i++) - { - if ((avail_next > m[i].mod_start) - && (addr < m[i].mod_end)) - { - avail_next = m[i].mod_end; - goto retry; - } - /* XXX string */ - } - } - - avail_remaining -= size; - - *addrp = addr; return TRUE; } -boolean_t pmap_next_page(addrp) - vm_offset_t *addrp; -{ - return init_alloc_aligned(PAGE_SIZE, addrp); -} - /* Grab a physical page: the standard memory allocation mechanism during system initialization. */ vm_offset_t -pmap_grab_page() +pmap_grab_page(void) { vm_offset_t addr; - if (!pmap_next_page(&addr)) + if (!init_alloc_aligned(PAGE_SIZE, &addr)) panic("Not enough memory to initialize Mach"); return addr; } -boolean_t pmap_valid_page(x) - vm_offset_t x; +boolean_t pmap_valid_page(vm_offset_t x) { /* XXX is this OK? What does it matter for? */ - return (((phys_first_addr <= x) && (x < phys_last_addr)) && - !(((boot_info->mem_lower * 1024) <= x) && (x < 1024*1024))); -} - -#ifndef NBBY -#define NBBY 8 -#endif -#ifndef NBPW -#define NBPW (NBBY * sizeof(int)) -#endif -#define DMA_MAX (16*1024*1024) - -/* - * Allocate contiguous pages below 16 MB - * starting at specified boundary for DMA. - */ -vm_offset_t -alloc_dma_mem(size, align) - vm_size_t size; - vm_offset_t align; -{ - int *bits, i, j, k, n; - int npages, count, bit, mask; - int first_page, last_page; - vm_offset_t addr; - vm_page_t p, prevp; - - npages = round_page(size) / PAGE_SIZE; - mask = align ? (align - 1) / PAGE_SIZE : 0; - - /* - * Allocate bit array. - */ - n = ((DMA_MAX / PAGE_SIZE) + NBPW - 1) / NBPW; - i = n * NBPW; - bits = (unsigned *)kalloc(i); - if (bits == 0) { - printf("alloc_dma_mem: unable alloc bit array\n"); - return (0); - } - bzero((char *)bits, i); - - /* - * Walk the page free list and set a bit for - * every usable page in bit array. - */ - simple_lock(&vm_page_queue_free_lock); - for (p = vm_page_queue_free; p; p = (vm_page_t)p->pageq.next) { - if (p->phys_addr < DMA_MAX) { - i = p->phys_addr / PAGE_SIZE; - bits[i / NBPW] |= 1 << (i % NBPW); - } - } - - /* - * Search for contiguous pages by scanning bit array. - */ - for (i = 0, first_page = -1; i < n; i++) { - for (bit = 1, j = 0; j < NBPW; j++, bit <<= 1) { - if (bits[i] & bit) { - if (first_page < 0) { - k = i * NBPW + j; - if (!mask - || (((k & mask) + npages) - <= mask + 1)) { - first_page = k; - if (npages == 1) - goto found; - count = 1; - } - } else if (++count == npages) - goto found; - } else - first_page = -1; - } - } - addr = 0; - goto out; - - found: - /* - * Remove pages from the free list. - */ - addr = first_page * PAGE_SIZE; - last_page = first_page + npages; - vm_page_free_count -= npages; - p = vm_page_queue_free; - prevp = 0; - while (1) { - i = p->phys_addr / PAGE_SIZE; - if (i >= first_page && i < last_page) { - if (prevp) - prevp->pageq.next = p->pageq.next; - else - vm_page_queue_free = (vm_page_t)p->pageq.next; - p->free = FALSE; - if (--npages == 0) - break; - } else - prevp = p; - p = (vm_page_t)p->pageq.next; - } - - out: - simple_unlock(&vm_page_queue_free_lock); - kfree((vm_offset_t)bits, n * NBPW); - return (addr); + return (((phys_first_addr <= x) && (x < phys_last_addr)) +#ifndef MACH_HYP + && !( + ((boot_info.mem_lower * 1024) <= x) && + (x < 1024*1024)) +#endif /* MACH_HYP */ + ); }