summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2016-01-30 01:25:52 +0100
committerRichard Braun <rbraun@sceen.net>2016-01-30 01:51:48 +0100
commit945f51bfe865e122d73986dd8219762450ffc0f3 (patch)
tree858283023412ddf46f7504cad5f5aa26dbce0496
parentc29915fccda96258dbccf49b052ee4ddd7d51169 (diff)
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.
-rw-r--r--i386/Makefrag.am4
-rw-r--r--i386/i386/vm_param.h9
-rw-r--r--i386/i386at/biosmem.c89
-rw-r--r--i386/i386at/biosmem.h4
-rw-r--r--i386/i386at/model_dep.c4
-rw-r--r--i386/include/mach/i386/vm_types.h4
6 files changed, 102 insertions, 12 deletions
diff --git a/i386/Makefrag.am b/i386/Makefrag.am
index e6cfedd7..0c5faa32 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 da3126c0..3769ef70 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 5b4fbddc..bf18cf65 100644
--- a/i386/i386at/biosmem.c
+++ b/i386/i386at/biosmem.c
@@ -24,6 +24,7 @@
#include <kern/macros.h>
#include <kern/printf.h>
#include <mach/vm_param.h>
+#include <mach/xen.h>
#include <mach/machine/multiboot.h>
#include <sys/types.h>
#include <vm/vm_page.h>
@@ -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 0cc4f8a6..1db63f9f 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 dbb9d8b6..7638b832 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 41272e39..4a58b1cb 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.