summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2018-10-26 20:28:41 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2018-10-26 20:28:41 +0000
commit41c1d52a9f988fb99399cd18b87d3310f5954fde (patch)
tree264c6da26aa0bded7f854246edff4a2fd4e12d43
parente90a8f72aab9a823587873f5575ebddbbfa3e572 (diff)
Use EFI memory map to determine what memory regions are availble just like
we already do on arm64. Prevents using the framebuffer on the cubox-i as regular memory for example.
-rw-r--r--sys/arch/armv7/armv7/armv7_machdep.c180
1 files changed, 121 insertions, 59 deletions
diff --git a/sys/arch/armv7/armv7/armv7_machdep.c b/sys/arch/armv7/armv7/armv7_machdep.c
index 988f64163a2..d9d512d990d 100644
--- a/sys/arch/armv7/armv7/armv7_machdep.c
+++ b/sys/arch/armv7/armv7/armv7_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: armv7_machdep.c,v 1.55 2018/08/06 18:39:13 kettenis Exp $ */
+/* $OpenBSD: armv7_machdep.c,v 1.56 2018/10/26 20:28:40 kettenis Exp $ */
/* $NetBSD: lubbock_machdep.c,v 1.2 2003/07/15 00:25:06 lukem Exp $ */
/*
@@ -125,6 +125,7 @@
#include <dev/cons.h>
#include <dev/ofw/fdt.h>
#include <dev/ofw/openfirm.h>
+#include <dev/acpi/efi.h>
#include <net/if.h>
@@ -152,12 +153,8 @@ char *boot_file = "";
uint8_t *bootmac = NULL;
u_int cpu_reset_address = 0;
-vaddr_t physical_start;
vaddr_t physical_freestart;
-vaddr_t physical_freeend;
-vaddr_t physical_end;
-u_int free_pages;
-int physmem = 0;
+int physmem;
/*int debug_flags;*/
#ifndef PMAP_STATIC_L1S
@@ -348,6 +345,13 @@ copy_io_area_map(pd_entry_t *new_pd)
}
}
+uint64_t mmap_start;
+uint32_t mmap_size;
+uint32_t mmap_desc_size;
+uint32_t mmap_desc_ver;
+
+EFI_MEMORY_DESCRIPTOR *mmap;
+
/*
* u_int initarm(...)
*
@@ -363,14 +367,12 @@ copy_io_area_map(pd_entry_t *new_pd)
u_int
initarm(void *arg0, void *arg1, void *arg2, paddr_t loadaddr)
{
- int loop, loop1, i, physsegs = VM_PHYSSEG_MAX;
+ int loop, loop1;
u_int l1pagetable;
pv_addr_t kernel_l1pt;
- pv_addr_t fdt;
+ pv_addr_t fdt, map;
struct fdt_reg reg;
- paddr_t memstart;
- psize_t memsize;
- paddr_t memend;
+ paddr_t memstart, memend;
void *config;
size_t size;
void *node;
@@ -442,16 +444,24 @@ initarm(void *arg0, void *arg1, void *arg2, paddr_t loadaddr)
memcpy(lladdr, prop, sizeof(lladdr));
bootmac = lladdr;
}
- }
- node = fdt_find_node("/memory");
- if (node == NULL || fdt_get_reg(node, 0, &reg))
- panic("initarm: no memory specificed");
+ 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);
+ }
- memstart = reg.addr;
- memsize = reg.size;
- physical_start = reg.addr;
- physical_end = MIN(reg.addr + reg.size, (paddr_t)-PAGE_SIZE);
+ if (mmap_start != 0)
+ bootstrap_bs_map(NULL, mmap_start, mmap_size, 0,
+ (bus_space_handle_t *)&mmap);
platform_init();
@@ -468,15 +478,10 @@ initarm(void *arg0, void *arg1, void *arg2, paddr_t loadaddr)
#endif /* RAMDISK_HOOKS */
physical_freestart = (((unsigned long)esym - KERNEL_TEXT_BASE + 0xfff) & ~0xfff) + loadaddr;
- physical_freeend = MIN((uint64_t)physical_end, (paddr_t)-PAGE_SIZE);
- physmem = (physical_end - physical_start) / PAGE_SIZE;
-
-#ifdef DEBUG
- /* Tell the user about the memory */
- printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem,
- physical_start, physical_end - 1);
-#endif
+ /* The bootloader has loaded us ubto a 32MB block. */
+ memstart = loadaddr;
+ memend = memstart + 32 * 1024 * 1024;
/*
* Okay, the kernel starts 2MB in from the bottom of physical
@@ -500,13 +505,6 @@ initarm(void *arg0, void *arg1, void *arg2, paddr_t loadaddr)
printf("Allocating page tables\n");
#endif
- free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE;
-
-#ifdef VERBOSE_INIT_ARM
- printf("freestart = 0x%08lx, free_pages = %d (0x%08x)\n",
- physical_freestart, free_pages, free_pages);
-#endif
-
/* Define a macro to simplify memory allocation */
#define valloc_pages(var, np) \
alloc_pages((var).pv_pa, (np)); \
@@ -515,9 +513,8 @@ initarm(void *arg0, void *arg1, void *arg2, paddr_t loadaddr)
#define alloc_pages(var, np) \
(var) = physical_freestart; \
physical_freestart += ((np) * PAGE_SIZE); \
- if (physical_freeend < physical_freestart) \
+ if (physical_freestart > memend) \
panic("initarm: out of memory"); \
- free_pages -= (np); \
memset((char *)(var), 0, ((np) * PAGE_SIZE));
loop1 = 0;
@@ -566,13 +563,17 @@ initarm(void *arg0, void *arg1, void *arg2, paddr_t loadaddr)
kernelstack.pv_va);
#endif
- /*
- * Allocate pages for an FDT copy.
- */
+ /* Relocate the FDT to safe memory. */
size = fdt_get_size(config);
valloc_pages(fdt, round_page(size) / PAGE_SIZE);
memcpy((void *)fdt.pv_pa, config, size);
+ /* Relocate the EFI memory map too. */
+ if (mmap_start != 0) {
+ valloc_pages(map, round_page(mmap_size) / PAGE_SIZE);
+ memcpy((void *)map.pv_pa, mmap, mmap_size);
+ }
+
/*
* XXX Defer this to later so that we can reclaim the memory
*/
@@ -674,6 +675,14 @@ initarm(void *arg0, void *arg1, void *arg2, paddr_t loadaddr)
round_page(fdt_get_size((void *)fdt.pv_pa)),
PROT_READ | PROT_WRITE, PTE_CACHE);
+ /* Map the EFI memory map. */
+ if (mmap_start != 0) {
+ pmap_map_chunk(l1pagetable, map.pv_va, map.pv_pa,
+ round_page(mmap_size),
+ PROT_READ | PROT_WRITE, PTE_CACHE);
+ mmap = (void *)map.pv_va;
+ }
+
/*
* map integrated peripherals at same address in l1pagetable
* so that we can continue to use console.
@@ -741,27 +750,80 @@ initarm(void *arg0, void *arg1, void *arg2, paddr_t loadaddr)
printf("page ");
#endif
uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */
- uvm_page_physload(atop(physical_freestart), atop(physical_freeend),
- atop(physical_freestart), atop(physical_freeend), 0);
- if (physical_start < loadaddr) {
- uvm_page_physload(atop(physical_start), atop(loadaddr),
- atop(physical_start), atop(loadaddr), 0);
- physsegs--;
- }
-
- node = fdt_find_node("/memory");
- for (i = 1; i < physsegs; i++) {
- if (fdt_get_reg(node, i, &reg))
- break;
- if (reg.size == 0)
- continue;
-
- memstart = reg.addr;
- memend = MIN(reg.addr + reg.size, (paddr_t)-PAGE_SIZE);
- physmem += (memend - memstart) / PAGE_SIZE;
- uvm_page_physload(atop(memstart), atop(memend),
- atop(memstart), atop(memend), 0);
+ /* Make what's left of the initial 32MB block available to UVM. */
+ uvm_page_physload(atop(physical_freestart), atop(memend),
+ atop(physical_freestart), atop(memend), 0);
+ physmem = atop(memend - memstart);
+
+ /* Make all other physical memory available to UVM. */
+ if (mmap && mmap_desc_ver == EFI_MEMORY_DESCRIPTOR_VERSION) {
+ EFI_MEMORY_DESCRIPTOR *desc = mmap;
+ 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",
+ desc->Type, desc->PhysicalStart,
+ desc->VirtualStart, desc->NumberOfPages,
+ desc->Attribute);
+ if (desc->Type == EfiConventionalMemory &&
+ desc->NumberOfPages >= 16) {
+ uvm_page_physload(atop(desc->PhysicalStart),
+ atop(desc->PhysicalStart) +
+ desc->NumberOfPages,
+ atop(desc->PhysicalStart),
+ atop(desc->PhysicalStart) +
+ desc->NumberOfPages, 0);
+ physmem += desc->NumberOfPages;
+ }
+ desc = NextMemoryDescriptor(desc, 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, &reg))
+ break;
+ if (reg.size == 0)
+ continue;
+
+ start = reg.addr;
+ end = MIN(reg.addr + reg.size, (paddr_t)-PAGE_SIZE);
+
+ /*
+ * The intial 32MB 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);
+ }
+ }
}
/* Boot strap pmap telling it where the kernel page table is */