diff options
-rw-r--r-- | sys/arch/arm64/arm64/machdep.c | 162 | ||||
-rw-r--r-- | sys/arch/arm64/include/vmparam.h | 6 |
2 files changed, 135 insertions, 33 deletions
diff --git a/sys/arch/arm64/arm64/machdep.c b/sys/arch/arm64/arm64/machdep.c index 6e2c67d0dd9..63d9b5d14b9 100644 --- a/sys/arch/arm64/arm64/machdep.c +++ b/sys/arch/arm64/arm64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.17 2017/05/03 22:35:49 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.18 2017/05/27 09:54:43 kettenis Exp $ */ /* * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se> * @@ -48,6 +48,8 @@ #include <machine/db_machdep.h> #include <ddb/db_extern.h> +#include <dev/acpi/efi.h> + char *boot_args = NULL; char *boot_file = ""; @@ -729,19 +731,24 @@ cache_setup(void) } } +uint64_t mmap_start; +uint32_t mmap_size; +uint32_t mmap_desc_size; +uint32_t mmap_desc_ver; + +EFI_MEMORY_DESCRIPTOR *mmap; + void collect_kernel_args(char *); void process_kernel_args(void); void initarm(struct arm64_bootparams *abp) { - //struct efi_map_header *efihdr; vaddr_t vstart, vend; struct cpu_info *pcpup; long kvo = abp->kern_delta; //caddr_t kmdp; - paddr_t memstart; - psize_t memsize; + paddr_t memstart, memend; void *config = abp->arg2; void *fdt = NULL; int (*map_func_save)(bus_space_tag_t, bus_addr_t, bus_size_t, int, @@ -760,7 +767,7 @@ initarm(struct arm64_bootparams *abp) node = fdt_find_node("/chosen"); if (node != NULL) { - char *args, *duid; + char *args, *duid, *prop; int len; len = fdt_node_property(node, "bootargs", &args); @@ -770,14 +777,20 @@ initarm(struct arm64_bootparams *abp) len = fdt_node_property(node, "openbsd,bootduid", &duid); if (len == sizeof(bootduid)) memcpy(bootduid, duid, sizeof(bootduid)); - } - node = fdt_find_node("/memory"); - if (node == NULL || fdt_get_reg(node, 0, ®)) - panic("initarm: no memory specificed"); - - memstart = reg.addr; - memsize = reg.size; + len = fdt_node_property(node, "openbsd,uefi-mmap-start", &prop); + if (len == sizeof(mmap_start)) + mmap_start = bemtoh64((uint64_t *)prop); + len = fdt_node_property(node, "openbsd,uefi-mmap-size", &prop); + if (len == sizeof(mmap_size)) + mmap_size = bemtoh32((uint32_t *)prop); + len = fdt_node_property(node, "openbsd,uefi-mmap-desc-size", &prop); + if (len == sizeof(mmap_desc_size)) + mmap_desc_size = bemtoh32((uint32_t *)prop); + len = fdt_node_property(node, "openbsd,uefi-mmap-desc-ver", &prop); + if (len == sizeof(mmap_desc_ver)) + mmap_desc_ver = bemtoh32((uint32_t *)prop); + } /* Set the pcpu data, this is needed by pmap_bootstrap */ // smp @@ -793,10 +806,6 @@ initarm(struct arm64_bootparams *abp) cache_setup(); - { - extern char bootargs[MAX_BOOT_STRING]; - printf("memsize %llx %llx bootargs [%s]\n", memstart, memsize, bootargs); - } process_kernel_args(); // XXX @@ -805,10 +814,13 @@ initarm(struct arm64_bootparams *abp) void _start(void); long kernbase = (long)&_start & ~0x00fff; - /* Bootstrap enough of pmap to enter the kernel proper */ + /* The bootloader has loaded us into a 64MB block. */ + memstart = KERNBASE + kvo; + memend = memstart + 64 * 1024 * 1024; + + /* Bootstrap enough of pmap to enter the kernel proper. */ vstart = pmap_bootstrap(kvo, abp->kern_l1pt, - kernbase, esym, - memstart, memstart + memsize); + kernbase, esym, memstart, memend); // XX correctly sized? proc0paddr = (struct user *)abp->kern_stack; @@ -824,26 +836,46 @@ initarm(struct arm64_bootparams *abp) copy_dst_page = vstart; vstart += PAGE_SIZE; - /* - * Allocate pages for an FDT copy. - */ + /* Relocate the FDT to safe memory. */ if (fdt_get_size(config) != 0) { uint32_t csize, size = round_page(fdt_get_size(config)); + paddr_t pa; vaddr_t va; - paddr_t fpa = pmap_steal_avail(size, PAGE_SIZE, NULL); - memcpy((void*)fpa, config, size); // copy to physical address - for (va = (vaddr_t)vstart, csize = size; - csize > 0; - csize -= PAGE_SIZE, va += PAGE_SIZE, fpa += PAGE_SIZE) - { - pmap_kenter_cache(va, fpa, PROT_READ, PMAP_CACHE_WB); - } + pa = pmap_steal_avail(size, PAGE_SIZE, NULL); + memcpy((void *)pa, config, size); /* copy to physical */ + for (va = vstart, csize = size; csize > 0; + csize -= PAGE_SIZE, va += PAGE_SIZE, pa += PAGE_SIZE) + pmap_kenter_cache(va, pa, PROT_READ, PMAP_CACHE_WB); fdt = (void *)vstart; vstart += size; } + /* Relocate the EFI memory map too. */ + if (mmap_start != 0) { + uint32_t csize, size = round_page(mmap_size); + paddr_t pa, startpa, endpa; + vaddr_t va; + + startpa = trunc_page(mmap_start); + endpa = round_page(mmap_start + mmap_size); + for (pa = startpa, va = vstart; pa < endpa; + pa += PAGE_SIZE, va += PAGE_SIZE) + pmap_kenter_cache(va, pa, PROT_READ, PMAP_CACHE_WB); + pa = pmap_steal_avail(size, PAGE_SIZE, NULL); + memcpy((void *)pa, (caddr_t)vstart + (mmap_start - startpa), + mmap_size); /* copy to physical */ + pmap_kremove(vstart, endpa - startpa); + + for (va = vstart, csize = size; csize > 0; + csize -= PAGE_SIZE, va += PAGE_SIZE, pa += PAGE_SIZE) + pmap_kenter_cache(va, pa, PROT_READ, PMAP_CACHE_WB); + + mmap = (void *)vstart; + vstart += size; + } + /* * Managed KVM space is what we have claimed up to end of * mapped kernel buffers. @@ -882,8 +914,78 @@ initarm(struct arm64_bootparams *abp) uvmexp.pagesize = PAGE_SIZE; uvm_setpagesize(); + /* Make what's left of the initial 64MB block available to UVM. */ pmap_physload_avail(); + /* Make all other physical memory available to UVM. */ + if (mmap && mmap_desc_ver == EFI_MEMORY_DESCRIPTOR_VERSION) { + int i; + + /* + * Load all memory marked as EfiConventionalMemory. + * Don't bother with blocks smaller than 64KB. The + * initial 64MB memory block should be marked as + * EfiLoaderData so it won't be added again here. + */ + for (i = 0; i < mmap_size / mmap_desc_size; i++) { + printf("type 0x%x pa 0x%llx va 0x%llx pages 0x%llx attr 0x%llx\n", + mmap->Type, mmap->PhysicalStart, + mmap->VirtualStart, mmap->NumberOfPages, + mmap->Attribute); + if (mmap->Type == EfiConventionalMemory && + mmap->NumberOfPages >= 16) { + uvm_page_physload(atop(mmap->PhysicalStart), + atop(mmap->PhysicalStart) + + mmap->NumberOfPages, + atop(mmap->PhysicalStart), + atop(mmap->PhysicalStart) + + mmap->NumberOfPages, 0); + physmem += mmap->NumberOfPages; + } + mmap = NextMemoryDescriptor(mmap, mmap_desc_size); + } + } else { + paddr_t start, end; + int i; + + node = fdt_find_node("/memory"); + if (node == NULL) + panic("%s: no memory specified", __func__); + + for (i = 0; i < VM_PHYSSEG_MAX; i++) { + if (fdt_get_reg(node, i, ®)) + break; + if (reg.size == 0) + continue; + + start = reg.addr; + end = MIN(reg.addr + reg.size, (paddr_t)-PAGE_SIZE); + + /* + * The intial 64MB block is not excluded, so we need + * to make sure we don't add it here. + */ + if (start < memend && end > memstart) { + if (start < memstart) { + uvm_page_physload(atop(start), + atop(memstart), atop(start), + atop(memstart), 0); + physmem += atop(memstart - start); + } + if (end > memend) { + uvm_page_physload(atop(memend), + atop(end), atop(memend), + atop(end), 0); + physmem += atop(end - memend); + } + } else { + uvm_page_physload(atop(start), atop(end), + atop(start), atop(end), 0); + physmem += atop(end - start); + } + } + } + #ifdef DDB db_machine_init(); diff --git a/sys/arch/arm64/include/vmparam.h b/sys/arch/arm64/include/vmparam.h index 2bb7aaf4ac9..e317163ec25 100644 --- a/sys/arch/arm64/include/vmparam.h +++ b/sys/arch/arm64/include/vmparam.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmparam.h,v 1.1 2016/12/17 23:38:33 patrick Exp $ */ +/* $OpenBSD: vmparam.h,v 1.2 2017/05/27 09:54:43 kettenis Exp $ */ /* $NetBSD: vmparam.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */ /*- @@ -105,8 +105,8 @@ /* virtual sizes (bytes) for various kernel submaps */ #define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) -#define VM_PHYSSEG_MAX 2 -#define VM_PHYSSEG_STRAT VM_PSTRAT_RANDOM +#define VM_PHYSSEG_MAX 32 +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH #define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ #endif /* _MACHINE_VMPARAM_H_ */ |