summaryrefslogtreecommitdiff
path: root/i386/i386at/model_dep.c
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2016-09-05 23:47:22 +0200
committerRichard Braun <rbraun@sceen.net>2016-09-06 00:02:03 +0200
commitae902513130a14ffded5d00216e8729d3f5ed7fa (patch)
tree3f14e5be9f791d0a32721f8463fd85b913dce959 /i386/i386at/model_dep.c
parentf6a2436d282a06e5f34789c8c5917e838fa26643 (diff)
Make early physical page allocation truely reliable
Import upstream biosmem changes and adjust for local modifications. Specifically, this change makes the biosmem module reliably track all boot data by storing their addresses in a sorted array. This allows both the early page allocator and the biosmem_free_usable function to accurately find any range of free pages. * i386/i386at/biosmem.c: Remove inclusion of <i386at/elf.h>. (_start, _end): Remove variable declarations. (BIOSMEM_MAX_BOOT_DATA): New macro. (struct biosmem_boot_data): New type. (biosmem_boot_data_array, biosmem_nr_boot_data): New variables. (biosmem_heap_start, biosmem_heap_bottom, biosmem_heap_top, biosmem_heap_end): Change type to phys_addr_t. (biosmem_panic_inval_boot_data): New variable. (biosmem_panic_too_many_boot_data): Likewise. (biosmem_panic_toobig_msg): Variable renamed ... (biosmem_panic_too_big_msg): ... to this. (biosmem_register_boot_data): New function. (biosmem_unregister_boot_data): Likewise. (biosmem_map_adjust): Update reference to panic message. (biosmem_map_find_avail): Add detailed description. (biosmem_save_cmdline_sizes): Remove function. (biosmem_find_heap_clip): Likewise. (biosmem_find_heap): Likewise. (biosmem_find_avail_clip, biosmem_find_avail): New functions. (biosmem_setup_allocator): Receive const multiboot info, replace calls to biosmem_find_heap with calls to biosmem_find_avail and update accordingly. Register the heap as boot data. (biosmem_xen_bootstrap): Register the Xen boot info and the heap as boot data. (biosmem_bootstrap): Receive const multiboot information. Remove call to biosmem_save_cmdline_sizes. (biosmem_bootalloc): Remove assertion on the VM system state. (biosmem_type_desc, biosmem_map_show): Build only if DEBUG is true. (biosmem_unregister_temporary_boot_data): New function. (biosmem_free_usable_range): Change address range format. (biosmem_free_usable_entry): Rewrite to use biosmem_find_avail without abusing it. (biosmem_free_usable): Call biosmem_unregister_temporary_boot_data, update call to biosmem_free_usable_entry. * i386/i386at/biosmem.h (biosmem_register_boot_data): New function. (biosmem_bootalloc): Update description. (biosmem_bootstrap): Update description and declaration. (biosmem_free_usable): Likewise. * i386/i386at/model_dep.c: Include <i386at/elf.h>. (machine_init): Update call to biosmem_free_usable. (register_boot_data): New function. (i386at_init): Call register_boot_data where appropriate.
Diffstat (limited to 'i386/i386at/model_dep.c')
-rw-r--r--i386/i386at/model_dep.c65
1 files changed, 62 insertions, 3 deletions
diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c
index 8e98bd9e..87d6cefa 100644
--- a/i386/i386at/model_dep.c
+++ b/i386/i386at/model_dep.c
@@ -66,6 +66,7 @@
#include <i386/model_dep.h>
#include <i386at/autoconf.h>
#include <i386at/biosmem.h>
+#include <i386at/elf.h>
#include <i386at/idt.h>
#include <i386at/int_init.h>
#include <i386at/kd.h>
@@ -158,9 +159,7 @@ void machine_init(void)
* This is particularly important for the Linux drivers which
* require available DMA memory.
*/
-#ifndef MACH_HYP
- biosmem_free_usable((struct multiboot_raw_info *) &boot_info);
-#endif /* MACH_HYP */
+ biosmem_free_usable();
/*
* Set up to use floating point.
@@ -274,6 +273,65 @@ 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[];
+
+ /* XXX For now, register all boot data as permanent */
+
+ biosmem_register_boot_data(_kvtophys(&_start), _kvtophys(&_end), FALSE);
+
+ if ((mbi->flags & MULTIBOOT_LOADER_CMDLINE) && (mbi->cmdline != 0)) {
+ biosmem_register_boot_data(mbi->cmdline,
+ mbi->cmdline + strlen((void *)mbi->cmdline) + 1, FALSE);
+ }
+
+ 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, FALSE);
+
+ 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, FALSE);
+
+ if (mod->string != 0) {
+ biosmem_register_boot_data(mod->string,
+ mod->string + strlen((void *)mod->string) + 1,
+ FALSE);
+ }
+ }
+ }
+
+ 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.
@@ -301,6 +359,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 */