--- Gnu-Mach/i386/i386at/model_dep.c 2020/09/02 04:53:36 1.1.1.7 +++ Gnu-Mach/i386/i386at/model_dep.c 2020/09/02 04:55:38 1.1.1.8 @@ -66,12 +66,12 @@ #include #include #include +#include #include #include #include #include #include -#include #ifdef MACH_XEN #include #include @@ -105,11 +105,6 @@ static unsigned elf_shdr_shndx; #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; - /* A copy of the multiboot info structure passed by the boot loader. */ #ifdef MACH_XEN struct start_info boot_info; @@ -153,6 +148,14 @@ void machine_init(void) cninit(); /* + * Make more free memory. + * + * This is particularly important for the Linux drivers which + * require available DMA memory. + */ + biosmem_free_usable(); + + /* * Set up to use floating point. */ init_fpu(); @@ -241,7 +244,6 @@ void halt_all_cpus(boolean_t reboot) #ifdef MACH_HYP hyp_halt(); #endif /* MACH_HYP */ - grub_acpi_halt(); printf("In tight loop: hit ctl-alt-del to reboot\n"); (void) spl0(); } @@ -264,6 +266,67 @@ void db_reset_cpu(void) halt_all_cpus(1); } +#ifndef MACH_HYP + +static void +register_boot_data(const struct multiboot_raw_info *mbi) +{ + struct multiboot_raw_module *mod; + struct elf_shdr *shdr; + unsigned long tmp; + unsigned int i; + + extern char _start[], _end[]; + + biosmem_register_boot_data(_kvtophys(&_start), _kvtophys(&_end), FALSE); + + /* cmdline and modules are moved to a safe place by i386at_init. */ + + if ((mbi->flags & MULTIBOOT_LOADER_CMDLINE) && (mbi->cmdline != 0)) { + biosmem_register_boot_data(mbi->cmdline, + mbi->cmdline + + strlen((void *)phystokv(mbi->cmdline)) + 1, TRUE); + } + + if (mbi->flags & MULTIBOOT_LOADER_MODULES) { + i = mbi->mods_count * sizeof(struct multiboot_raw_module); + biosmem_register_boot_data(mbi->mods_addr, mbi->mods_addr + i, TRUE); + + tmp = phystokv(mbi->mods_addr); + + for (i = 0; i < mbi->mods_count; i++) { + mod = (struct multiboot_raw_module *)tmp + i; + biosmem_register_boot_data(mod->mod_start, mod->mod_end, TRUE); + + if (mod->string != 0) { + biosmem_register_boot_data(mod->string, + mod->string + + strlen((void *)phystokv(mod->string)) + 1, + TRUE); + } + } + } + + if (mbi->flags & MULTIBOOT_LOADER_SHDR) { + tmp = mbi->shdr_num * mbi->shdr_size; + biosmem_register_boot_data(mbi->shdr_addr, mbi->shdr_addr + tmp, FALSE); + + tmp = phystokv(mbi->shdr_addr); + + for (i = 0; i < mbi->shdr_num; i++) { + shdr = (struct elf_shdr *)(tmp + (i * mbi->shdr_size)); + + if ((shdr->type != ELF_SHT_SYMTAB) + && (shdr->type != ELF_SHT_STRTAB)) + continue; + + biosmem_register_boot_data(shdr->addr, shdr->addr + shdr->size, FALSE); + } + } +} + +#endif /* MACH_HYP */ + /* * Basic PC VM initialization. * Turns on paging and changes the kernel segments to use high linear addresses. @@ -291,6 +354,7 @@ i386at_init(void) #ifdef MACH_HYP biosmem_xen_bootstrap(); #else /* MACH_HYP */ + register_boot_data((struct multiboot_raw_info *) &boot_info); biosmem_bootstrap((struct multiboot_raw_info *) &boot_info); #endif /* MACH_HYP */ @@ -298,7 +362,8 @@ i386at_init(void) 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. */ + * is too far in physical memory. + * Also avoids leaving them in precious areas such as DMA memory. */ if (boot_info.flags & MULTIBOOT_CMDLINE) { int len = strlen ((char*)phystokv(boot_info.cmdline)) + 1; if (! init_alloc_aligned(round_page(len), &addr)) @@ -364,14 +429,14 @@ i386at_init(void) 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]; + kernel_page_dir[lin2pdenum_cont(INIT_VM_MIN_KERNEL_ADDRESS) + i] = + kernel_page_dir[lin2pdenum_cont(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)]; + kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] = + kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS)]; #endif #endif @@ -423,21 +488,21 @@ i386at_init(void) 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)) + if (!hyp_mmu_update_pte(kv_to_ma(&kernel_page_dir[lin2pdenum_cont(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; + kernel_page_dir[lin2pdenum_cont(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)]; + kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] = + kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS)]; #endif #endif @@ -619,11 +684,6 @@ resettodr(void) writetodc(); } -unsigned int pmap_free_pages(void) -{ - return vm_page_atop(phys_last_addr); /* XXX */ -} - boolean_t init_alloc_aligned(vm_size_t size, vm_offset_t *addrp) { @@ -646,15 +706,3 @@ pmap_grab_page(void) panic("Not enough memory to initialize Mach"); return addr; } - -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)) -#ifndef MACH_HYP - && !( - ((boot_info.mem_lower * 1024) <= x) && - (x < 1024*1024)) -#endif /* MACH_HYP */ - ); -}