diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-04-01 14:01:14 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-09-14 14:48:10 +0200 |
commit | cffbf7da5b877fb86feb080f1a1022a5d134f63e (patch) | |
tree | 75c6eff2ed416c768d73ee573bb58075ade80b27 /i386/i386at | |
parent | 4b7cc639b7804143c890af424e3dc7cceef59d38 (diff) |
XXX pmm from x15, userspace crashes soon
Diffstat (limited to 'i386/i386at')
-rw-r--r-- | i386/i386at/biosmem.c | 71 | ||||
-rw-r--r-- | i386/i386at/biosmem.h | 4 | ||||
-rw-r--r-- | i386/i386at/model_dep.c | 310 | ||||
-rw-r--r-- | i386/i386at/model_dep.h | 14 |
4 files changed, 109 insertions, 290 deletions
diff --git a/i386/i386at/biosmem.c b/i386/i386at/biosmem.c index d666f1b..6181eb3 100644 --- a/i386/i386at/biosmem.c +++ b/i386/i386at/biosmem.c @@ -16,23 +16,33 @@ */ #include <kern/assert.h> -#include <kern/init.h> #include <kern/macros.h> -#include <kern/panic.h> -#include <kern/param.h> -#include <kern/printk.h> -#include <kern/stddef.h> -#include <kern/stdint.h> -#include <kern/string.h> -#include <kern/types.h> -#include <machine/biosmem.h> -#include <machine/boot.h> -#include <machine/cpu.h> -#include <machine/elf.h> -#include <machine/multiboot.h> -#include <vm/vm_kmem.h> +#include <kern/debug.h> +#include <kern/printf.h> +#include <stddef.h> +#include <string.h> +#include <sys/types.h> #include <vm/vm_page.h> +#include "biosmem.h" +#include "x15/elf.h" +#include "x15/multiboot.h" + +/* Mach glue. */ +#define __bootdata /* nothing */ +#define __boot /* nothing */ +#define __init /* nothing */ +#define boot_memmove memmove +#define boot_memset(P,C,S) memset((char *) phystokv(P), C, S) +#define boot_strlen(P) strlen((char *) phystokv(P)) +#define boot_panic panic +#define printk printf +#define BOOT_VTOP(addr) _kvtophys(addr) + +/* XXX */ +extern char _boot; +extern char _end; + /* * Maximum number of entries in the BIOS memory map. * @@ -115,7 +125,7 @@ biosmem_map_build(const struct multiboot_raw_info *mbi) struct biosmem_map_entry *start, *entry, *end; unsigned long addr; - addr = mbi->mmap_addr; + addr = phystokv(mbi->mmap_addr); mb_entry = (struct multiboot_raw_mmap_entry *)addr; mb_end = (struct multiboot_raw_mmap_entry *)(addr + mbi->mmap_length); start = biosmem_map; @@ -373,16 +383,16 @@ biosmem_save_cmdline_sizes(struct multiboot_raw_info *mbi) uint32_t i; if (mbi->flags & MULTIBOOT_LOADER_CMDLINE) - mbi->unused0 = boot_strlen((char *)(unsigned long)mbi->cmdline) + 1; + mbi->unused0 = boot_strlen((unsigned long)mbi->cmdline) + 1; if (mbi->flags & MULTIBOOT_LOADER_MODULES) { unsigned long addr; - addr = mbi->mods_addr; + addr = phystokv(mbi->mods_addr); for (i = 0; i < mbi->mods_count; i++) { mod = (struct multiboot_raw_module *)addr + i; - mod->reserved = boot_strlen((char *)(unsigned long)mod->string) + 1; + mod->reserved = boot_strlen((unsigned long)mod->string) + 1; } } } @@ -391,6 +401,8 @@ static void __boot biosmem_find_boot_data_update(uint32_t min, uint32_t *start, uint32_t *end, uint32_t data_start, uint32_t data_end) { + assert (data_start < data_end); + if ((min <= data_start) && (data_start < *start)) { *start = data_start; *end = data_end; @@ -419,21 +431,20 @@ biosmem_find_boot_data(const struct multiboot_raw_info *mbi, uint32_t min, struct elf_shdr *shdr; uint32_t i, start, end = end; unsigned long tmp; - start = max; - biosmem_find_boot_data_update(min, &start, &end, (unsigned long)&_boot, + biosmem_find_boot_data_update(min, &start, &end, + BOOT_VTOP((unsigned long)&_boot), BOOT_VTOP((unsigned long)&_end)); if ((mbi->flags & MULTIBOOT_LOADER_CMDLINE) && (mbi->cmdline != 0)) biosmem_find_boot_data_update(min, &start, &end, mbi->cmdline, mbi->cmdline + mbi->unused0); - if (mbi->flags & MULTIBOOT_LOADER_MODULES) { i = mbi->mods_count * sizeof(struct multiboot_raw_module); biosmem_find_boot_data_update(min, &start, &end, mbi->mods_addr, mbi->mods_addr + i); - tmp = mbi->mods_addr; + tmp = phystokv(mbi->mods_addr); for (i = 0; i < mbi->mods_count; i++) { mod = (struct multiboot_raw_module *)tmp + i; @@ -450,7 +461,7 @@ biosmem_find_boot_data(const struct multiboot_raw_info *mbi, uint32_t min, tmp = mbi->shdr_num * mbi->shdr_size; biosmem_find_boot_data_update(min, &start, &end, mbi->shdr_addr, mbi->shdr_addr + tmp); - tmp = mbi->shdr_addr; + tmp = phystokv(mbi->shdr_addr); for (i = 0; i < mbi->shdr_num; i++) { shdr = (struct elf_shdr *)(tmp + (i * mbi->shdr_size)); @@ -458,7 +469,6 @@ biosmem_find_boot_data(const struct multiboot_raw_info *mbi, uint32_t min, if ((shdr->type != ELF_SHT_SYMTAB) && (shdr->type != ELF_SHT_STRTAB)) continue; - biosmem_find_boot_data_update(min, &start, &end, shdr->addr, shdr->addr + shdr->size); } @@ -516,6 +526,10 @@ biosmem_setup_allocator(struct multiboot_raw_info *mbi) biosmem_heap_start = max_heap_start; biosmem_heap_end = max_heap_end; biosmem_heap_cur = biosmem_heap_end; + + /* Mach pmap glue. */ + extern vm_offset_t phys_last_addr; + phys_last_addr = (vm_offset_t) max_heap_end; } void __boot @@ -596,7 +610,7 @@ biosmem_bootalloc(unsigned int nr_pages) boot_panic(biosmem_panic_nomem_msg); biosmem_heap_cur = addr; - return boot_memset((void *)addr, 0, size); + return boot_memset(addr, 0, size); } phys_addr_t __boot @@ -688,10 +702,15 @@ biosmem_setup(void) biosmem_map_show(); +#if notyet cpu = cpu_current(); max_phys_end = (cpu->phys_addr_width == 0) ? (uint64_t)-1 : (uint64_t)1 << cpu->phys_addr_width; +#else + max_phys_end = (uint64_t)1 << 32; + (void) cpu; +#endif for (i = 0; i < ARRAY_SIZE(biosmem_segments); i++) { if (biosmem_segment_size(i) == 0) @@ -713,7 +732,7 @@ biosmem_free_usable_range(phys_addr_t start, phys_addr_t end) (unsigned long long)((end - start) >> 10)); while (start < end) { - page = vm_page_lookup(start); + page = vm_page_lookup_pa(start); assert(page != NULL); vm_page_manage(page); start += PAGE_SIZE; diff --git a/i386/i386at/biosmem.h b/i386/i386at/biosmem.h index b32e027..c4b59f5 100644 --- a/i386/i386at/biosmem.h +++ b/i386/i386at/biosmem.h @@ -18,8 +18,8 @@ #ifndef _X86_BIOSMEM_H #define _X86_BIOSMEM_H -#include <kern/types.h> -#include <machine/multiboot.h> +#include <sys/types.h> +#include "x15/multiboot.h" /* * Address where the address of the Extended BIOS Data Area segment can be diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c index 04cf695..e1ad794 100644 --- a/i386/i386at/model_dep.c +++ b/i386/i386at/model_dep.c @@ -49,6 +49,7 @@ #include <kern/mach_clock.h> #include <kern/printf.h> #include <kern/startup.h> +#include <kern/thread.h> #include <sys/time.h> #include <sys/types.h> #include <vm/vm_page.h> @@ -70,6 +71,12 @@ #include <i386at/rtc.h> #include <i386at/model_dep.h> #include <i386at/acpihalt.h> +#define multiboot_module x15_multiboot_module +#define multiboot_info x15_multiboot_info +#include <i386/x15/multiboot.h> +#include <i386at/biosmem.h> +#undef multiboot_module +#undef multiboot_info #ifdef MACH_XEN #include <xen/console.h> #include <xen/store.h> @@ -127,27 +134,13 @@ struct multiboot_info boot_info; /* 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 -#ifndef MACH_HYP - = RESERVED_BIOS /* XX end of BIOS data area */ -#endif /* MACH_HYP */ - ; - -/* Possibly overestimated amount of available memory - still remaining to be handed to the VM system. */ -static vm_size_t avail_remaining; - extern char version[]; /* If set, reboot the system on ctrl-alt-delete. */ boolean_t rebootflag = FALSE; /* exported to kdintr */ -/* XX interrupt stack pointer and highwater mark, for locore.S. */ -vm_offset_t int_stack_top, int_stack_high; +/* Interrupt stack. */ +vm_offset_t int_stack_top, int_stack_base; #ifdef LINUX_DEV extern void linux_init(void); @@ -275,7 +268,8 @@ void db_reset_cpu(void) halt_all_cpus(1); } - +#if 0 +/* XXX: Port XEN bits to biosmem. */ /* * Compute physical memory size and other parameters. */ @@ -359,6 +353,7 @@ mem_size_init(void) - RESERVED_BIOS); #endif /* MACH_HYP */ } +#endif /* 0 */ /* * Basic PC VM initialization. @@ -370,7 +365,7 @@ 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; + vm_offset_t delta; /* * Initialize the PIC prior to any possible call to an spl. @@ -384,44 +379,7 @@ i386at_init(void) /* * Find memory size parameters. */ - mem_size_init(); - -#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; - assert(init_alloc_aligned(round_page(len), &addr)); - 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; - - assert(init_alloc_aligned(round_page(boot_info.mods_count * sizeof(*m)), &addr)); - 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; - assert(init_alloc_aligned(round_page(size), &addr)); - 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; - assert(init_alloc_aligned(round_page(size), &addr)); - memcpy((void*) phystokv(addr), (void*) phystokv(m[i].string), size); - m[i].string = addr; - } - } -#endif /* MACH_XEN */ + biosmem_bootstrap((struct multiboot_raw_info *) &boot_info); /* * Initialize kernel physical map, mapping the @@ -485,10 +443,42 @@ i386at_init(void) pmap_clear_bootstrap_pagetable((void *)boot_info.pt_base); #endif /* MACH_PV_PAGETABLES */ - /* 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 = phystokv(phys_last_addr); + /* Load the pages into the vm_page module. */ + biosmem_setup(); + + /* Initialize physical memory management. */ + vm_page_setup(); + vm_page_info(); + + /* Initialize the slab allocator. */ + slab_bootstrap(); + slab_init(); + + { +#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) { + size_t len = strlen((const char *) + phystokv(boot_info.cmdline)); + kernel_cmdline = (char *) kalloc(len); + memcpy(kernel_cmdline, + (const void *) phystokv(boot_info.cmdline), + len + 1); + } +#endif + } + + /* Bootstrap the thread module so that we can allocate an + interrupt stack. */ + thread_bootstrap(); + + /* Allocate interrupt stack. */ + int_stack_base = thread_bootstrap_stack_alloc(); + int_stack_top = int_stack_base + KERNEL_STACK_SIZE - 4; /* * Initialize and activate the real i386 protected-mode structures. @@ -534,11 +524,6 @@ i386at_init(void) #ifdef MACH_XEN hyp_p2m_init(); #endif /* MACH_XEN */ - - /* 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)); } /* @@ -704,201 +689,6 @@ resettodr(void) writetodc(); } -unsigned int pmap_free_pages(void) -{ - return atop(avail_remaining); -} - -/* Always returns page-aligned regions. */ -boolean_t -init_alloc_aligned(vm_size_t size, vm_offset_t *addrp) -{ - vm_offset_t addr; - -#ifdef MACH_HYP - /* There is none */ - if (!avail_next) - avail_next = _kvtophys(boot_info.pt_base) + (boot_info.nr_pt_frames + 3) * 0x1000; -#else /* MACH_HYP */ - extern char start[], end[]; - int i; - static int wrapped = 0; - - /* Memory regions to skip. */ - 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: -#endif /* MACH_HYP */ - - /* Page-align the start address. */ - avail_next = round_page(avail_next); - -#ifndef MACH_HYP - /* Start with memory above 16MB, reserving the low memory for later. */ - /* Don't care on Xen */ - if (!wrapped && phys_last_addr > 16 * 1024*1024) - { - if (avail_next < 16 * 1024*1024) - avail_next = 16 * 1024*1024; - else if (avail_next == phys_last_addr) - { - /* We have used all the memory above 16MB, so now start on - the low memory. This will wind up at the end of the list - of free pages, so it should not have been allocated to any - other use in early initialization before the Linux driver - glue initialization needs to allocate low memory. */ - avail_next = RESERVED_BIOS; - wrapped = 1; - } - } -#endif /* MACH_HYP */ - - /* Check if we have reached the end of memory. */ - if (avail_next == - ( -#ifndef MACH_HYP - wrapped ? 16 * 1024*1024 : -#endif /* MACH_HYP */ - phys_last_addr)) - 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; - -#ifndef MACH_HYP - /* Skip past the I/O and ROM area. */ - if (boot_info.flags & MULTIBOOT_MEM_MAP) - { - struct multiboot_mmap *map, *map_end, *current = NULL, *next = NULL; - unsigned long long minimum_next = ~0ULL; - - map = (void*) phystokv(boot_info.mmap_addr); - map_end = (void*) map + boot_info.mmap_count; - - /* Find both our current map, and the next one */ - while (map + 1 <= map_end) - { - if (map->Type == MB_ARD_MEMORY) - { - unsigned long long start = map->BaseAddr; - unsigned long long end = start + map->Length;; - - if (start <= addr && avail_next <= end) - { - /* Ok, fits in the current map */ - current = map; - break; - } - else if (avail_next <= start && start < minimum_next) - { - /* This map is not far from avail_next */ - next = map; - minimum_next = start; - } - } - map = (void*) map + map->size + sizeof(map->size); - } - - if (!current) { - /* Area does not fit in the current map, switch to next - * map if any */ - if (!next || next->BaseAddr >= phys_last_addr) - { - /* No further reachable map, we have reached - * the end of memory, but possibly wrap around - * 16MiB. */ - avail_next = phys_last_addr; - goto retry; - } - - /* Start from next map */ - avail_next = next->BaseAddr; - goto retry; - } - } - else if ((avail_next > (boot_info.mem_lower * 0x400)) && (addr < 0x100000)) - { - avail_next = 0x100000; - goto retry; - } - - /* Skip our own kernel code, data, and bss. */ - if ((phystokv(avail_next) > (vm_offset_t)start) && (phystokv(addr) < (vm_offset_t)end)) - { - avail_next = _kvtophys(end); - goto retry; - } - - /* Skip any areas occupied by valuable boot_info data. */ - 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 ((phystokv(avail_next) > kern_sym_start) && (phystokv(addr) < kern_sym_end)) - { - avail_next = _kvtophys(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 */ - } - } -#endif /* MACH_HYP */ - - avail_remaining -= size; - - *addrp = addr; - return TRUE; -} - -boolean_t pmap_next_page(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(void) -{ - vm_offset_t addr; - if (!pmap_next_page(&addr)) - 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? */ diff --git a/i386/i386at/model_dep.h b/i386/i386at/model_dep.h index aa24032..a27d9b3 100644 --- a/i386/i386at/model_dep.h +++ b/i386/i386at/model_dep.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Free Software Foundation. + * Copyright (c) 2013-2015 Free Software Foundation. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,16 @@ extern int timemmap(dev_t dev, vm_offset_t off, vm_prot_t prot); void inittodr(void); -boolean_t init_alloc_aligned(vm_size_t size, vm_offset_t *addrp); +/* + * Interrupt stack. + * + * We allocate the interrupt stacks from the kernels stack cache. As + * the stacks are naturally aligned, it is easy to find the base + * address given a stack pointer. + */ +extern vm_offset_t int_stack_top, int_stack_base; + +/* Check whether P points to the interrupt stack. */ +#define ON_INT_STACK(P) (((P) & ~(KERNEL_STACK_SIZE-1)) == int_stack_base) #endif /* _MODEL_DEP_H_ */ |