From 945f51bfe865e122d73986dd8219762450ffc0f3 Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Sat, 30 Jan 2016 01:25:52 +0100 Subject: Fix early page allocation on Xen The Xen target was completely ignored when porting the biosmem and vm_page physical memory allocators. Let's fix this. * i386/Makefrag.am (libkernel_a_SOURCES): Add i386/i386at/biosmem.{c,h}. * i386/i386/vm_page.h (VM_PAGE_MAX_SEGS, VM_PAGE_DIRECTMAP_LIMIT, VM_PAGE_HIGHMEM_LIMIT): Define for Xen. * i386/i386at/biosmem.c: Include mach/xen.h. (biosmem_panic_setup_msg): Comment out for Xen since it's unused. (biosmem_map_build, biosmem_map_build_simple, biosmem_save_cmdline_sizes, biosmem_find_boot_data_update, biosmem_find_boot_data, biosmem_setup_allocator): Likewise. (biosmem_bootstrap_common): New function. (biosmem_xen_bootstrap): Likewise, for Xen. (biosmem_bootalloc): Perform bottom-up allocations for Xen. * i386/i386at/biosmem.h (biosmem_xen_bootstrap): New prototype, for Xen. * i386/i386at/model_dep.c (i386at_init): Call biosmem_xen_bootstrap instead of biosmem_bootstrap on Xen. * i386/include/mach/i386/vm_types.h (phys_addr_t): Define as an unsigned 64-bits integer when PAE is enabled. --- i386/Makefrag.am | 4 +- i386/i386/vm_param.h | 9 ++++ i386/i386at/biosmem.c | 89 ++++++++++++++++++++++++++++++++++----- i386/i386at/biosmem.h | 4 ++ i386/i386at/model_dep.c | 4 ++ i386/include/mach/i386/vm_types.h | 4 ++ 6 files changed, 102 insertions(+), 12 deletions(-) diff --git a/i386/Makefrag.am b/i386/Makefrag.am index e6cfedd..0c5faa3 100644 --- a/i386/Makefrag.am +++ b/i386/Makefrag.am @@ -20,6 +20,8 @@ libkernel_a_SOURCES += \ i386/i386at/autoconf.c \ i386/i386at/autoconf.h \ + i386/i386at/biosmem.c \ + i386/i386at/biosmem.h \ i386/i386at/conf.c \ i386/i386at/cons_conf.c \ i386/i386at/idt.h \ @@ -29,8 +31,6 @@ libkernel_a_SOURCES += \ if PLATFORM_at libkernel_a_SOURCES += \ - i386/i386at/biosmem.c \ - i386/i386at/biosmem.h \ i386/i386at/boothdr.S \ i386/i386at/com.c \ i386/i386at/com.h \ diff --git a/i386/i386/vm_param.h b/i386/i386/vm_param.h index da3126c..3769ef7 100644 --- a/i386/i386/vm_param.h +++ b/i386/i386/vm_param.h @@ -108,6 +108,14 @@ */ #define VM_PAGE_DMA_LIMIT DECL_CONST(0x1000000, UL) +#ifdef MACH_XEN +/* TODO Completely check Xen physical/virtual layout */ +#define VM_PAGE_MAX_SEGS 3 +#define VM_PAGE_DIRECTMAP_LIMIT (VM_MAX_KERNEL_ADDRESS \ + - VM_MIN_KERNEL_ADDRESS \ + - VM_KERNEL_MAP_SIZE) +#define VM_PAGE_HIGHMEM_LIMIT DECL_CONST(0x10000000000000, ULL) +#else /* MACH_XEN */ #ifdef __LP64__ #define VM_PAGE_MAX_SEGS 4 #define VM_PAGE_DMA32_LIMIT DECL_CONST(0x100000000, UL) @@ -125,6 +133,7 @@ #define VM_PAGE_HIGHMEM_LIMIT DECL_CONST(0xfffff000, UL) #endif /* PAE */ #endif /* __LP64__ */ +#endif /* MACH_XEN */ /* * Physical segment indexes. diff --git a/i386/i386at/biosmem.c b/i386/i386at/biosmem.c index 5b4fbdd..bf18cf6 100644 --- a/i386/i386at/biosmem.c +++ b/i386/i386at/biosmem.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -108,8 +109,10 @@ static uint32_t biosmem_heap_end __bootdata; static char biosmem_panic_toobig_msg[] __bootdata = "biosmem: too many memory map entries"; +#ifndef MACH_HYP static char biosmem_panic_setup_msg[] __bootdata = "biosmem: unable to set up the early memory allocator"; +#endif /* MACH_HYP */ static char biosmem_panic_noseg_msg[] __bootdata = "biosmem: unable to find any memory segment"; static char biosmem_panic_inval_msg[] __bootdata @@ -117,6 +120,8 @@ static char biosmem_panic_inval_msg[] __bootdata static char biosmem_panic_nomem_msg[] __bootdata = "biosmem: unable to allocate memory"; +#ifndef MACH_HYP + static void __boot biosmem_map_build(const struct multiboot_raw_info *mbi) { @@ -161,6 +166,8 @@ biosmem_map_build_simple(const struct multiboot_raw_info *mbi) biosmem_map_size = 2; } +#endif /* MACH_HYP */ + static int __boot biosmem_map_entry_is_invalid(const struct biosmem_map_entry *entry) { @@ -375,6 +382,8 @@ biosmem_segment_size(unsigned int seg_index) return biosmem_segments[seg_index].end - biosmem_segments[seg_index].start; } +#ifndef MACH_HYP + static void __boot biosmem_save_cmdline_sizes(struct multiboot_raw_info *mbi) { @@ -530,17 +539,14 @@ biosmem_setup_allocator(struct multiboot_raw_info *mbi) biosmem_heap_cur = biosmem_heap_end; } -void __boot -biosmem_bootstrap(struct multiboot_raw_info *mbi) +#endif /* MACH_HYP */ + +static void __boot +biosmem_bootstrap_common(void) { phys_addr_t phys_start, phys_end, last_addr; int error; - if (mbi->flags & MULTIBOOT_LOADER_MMAP) - biosmem_map_build(mbi); - else - biosmem_map_build_simple(mbi); - biosmem_map_adjust(); phys_start = BIOSMEM_BASE; @@ -585,6 +591,61 @@ biosmem_bootstrap(struct multiboot_raw_info *mbi) biosmem_set_segment(VM_PAGE_SEG_HIGHMEM, phys_start, phys_end); out: + /* XXX phys_last_addr must be part of the direct physical mapping */ + phys_last_addr = last_addr; +} + +#ifdef MACH_HYP + +void +biosmem_xen_bootstrap(void) +{ + struct biosmem_map_entry *entry; + + entry = biosmem_map; + entry->base_addr = 0; + entry->length = boot_info.nr_pages << PAGE_SHIFT; + entry->type = BIOSMEM_TYPE_AVAILABLE; + + biosmem_map_size = 1; + + biosmem_bootstrap_common(); + + biosmem_heap_start = _kvtophys(boot_info.pt_base) + + (boot_info.nr_pt_frames + 3) * 0x1000; + biosmem_heap_end = boot_info.nr_pages << PAGE_SHIFT; + +#ifndef __LP64__ + /* TODO Check that this actually makes sense */ + if (biosmem_heap_end > VM_PAGE_DIRECTMAP_LIMIT) + biosmem_heap_end = VM_PAGE_DIRECTMAP_LIMIT; +#endif /* __LP64__ */ + + /* + * XXX Allocation on Xen must be bottom-up : + * At the "start of day", only 512k are available after the boot + * data. The pmap module then creates a 4g mapping so all physical + * memory is available, but it uses this allocator to do so. + * Therefore, it must return pages from this small 512k regions + * first. + */ + biosmem_heap_cur = biosmem_heap_start; +} + +#else /* MACH_HYP */ + +void __boot +biosmem_bootstrap(struct multiboot_raw_info *mbi) +{ + phys_addr_t phys_start, phys_end, last_addr; + int error; + + if (mbi->flags & MULTIBOOT_LOADER_MMAP) + biosmem_map_build(mbi); + else + biosmem_map_build_simple(mbi); + + biosmem_bootstrap_common(); /* * The kernel and modules command lines will be memory mapped later @@ -592,11 +653,10 @@ out: */ biosmem_save_cmdline_sizes(mbi); biosmem_setup_allocator(mbi); - - /* XXX phys_last_addr must be part of the direct physical mapping */ - phys_last_addr = last_addr; } +#endif /* MACH_HYP */ + unsigned long __boot biosmem_bootalloc(unsigned int nr_pages) { @@ -609,13 +669,22 @@ biosmem_bootalloc(unsigned int nr_pages) if (size == 0) boot_panic(biosmem_panic_inval_msg); +#ifdef MACH_HYP + addr = biosmem_heap_cur; +#else /* MACH_HYP */ /* Top-down allocation to avoid unnecessarily filling DMA segments */ addr = biosmem_heap_cur - size; +#endif /* MACH_HYP */ if ((addr < biosmem_heap_start) || (addr > biosmem_heap_cur)) boot_panic(biosmem_panic_nomem_msg); +#ifdef MACH_HYP + biosmem_heap_cur += size; +#else /* MACH_HYP */ biosmem_heap_cur = addr; +#endif /* MACH_HYP */ + return addr; } diff --git a/i386/i386at/biosmem.h b/i386/i386at/biosmem.h index 0cc4f8a..1db63f9 100644 --- a/i386/i386at/biosmem.h +++ b/i386/i386at/biosmem.h @@ -47,7 +47,11 @@ * * It is called before paging is enabled. */ +#ifdef MACH_HYP +void biosmem_xen_bootstrap(void); +#else /* MACH_HYP */ void biosmem_bootstrap(struct multiboot_raw_info *mbi); +#endif /* MACH_HYP */ /* * Allocate contiguous physical pages during bootstrap. diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c index dbb9d8b..7638b83 100644 --- a/i386/i386at/model_dep.c +++ b/i386/i386at/model_dep.c @@ -286,7 +286,11 @@ i386at_init(void) /* * 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; diff --git a/i386/include/mach/i386/vm_types.h b/i386/include/mach/i386/vm_types.h index 41272e3..4a58b1c 100644 --- a/i386/include/mach/i386/vm_types.h +++ b/i386/include/mach/i386/vm_types.h @@ -79,7 +79,11 @@ typedef vm_offset_t * vm_offset_array_t; /* * A type for physical addresses. */ +#ifdef PAE +typedef unsigned long long phys_addr_t; +#else /* PAE */ typedef unsigned long phys_addr_t; +#endif /* PAE */ /* * A vm_size_t is the proper type for e.g. -- cgit v1.2.3