Module Name:    src
Committed By:   skrll
Date:           Sat Dec 12 09:27:32 UTC 2020

Modified Files:
        src/sys/arch/aarch64/aarch64: aarch64_machdep.c
        src/sys/arch/arm/arm32: arm32_kvminit.c
        src/sys/arch/evbarm/conf: files.fdt
        src/sys/arch/evbarm/fdt: fdt_machdep.c platform.h
        src/sys/dev/fdt: files.fdt
Added Files:
        src/sys/dev/fdt: fdt_memory.c fdt_memory.h
Removed Files:
        src/sys/arch/evbarm/fdt: fdt_memory.c fdt_memory.h

Log Message:
Move evbarm/fdt/fdt_memory.[ch] to sys/dev/fdt and simplify the api and
some operations.  This allows other architectures to use it.


To generate a diff of this commit:
cvs rdiff -u -r1.55 -r1.56 src/sys/arch/aarch64/aarch64/aarch64_machdep.c
cvs rdiff -u -r1.66 -r1.67 src/sys/arch/arm/arm32/arm32_kvminit.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/evbarm/conf/files.fdt
cvs rdiff -u -r1.82 -r1.83 src/sys/arch/evbarm/fdt/fdt_machdep.c
cvs rdiff -u -r1.4 -r0 src/sys/arch/evbarm/fdt/fdt_memory.c
cvs rdiff -u -r1.1 -r0 src/sys/arch/evbarm/fdt/fdt_memory.h
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/evbarm/fdt/platform.h
cvs rdiff -u -r0 -r1.1 src/sys/dev/fdt/fdt_memory.c \
    src/sys/dev/fdt/fdt_memory.h
cvs rdiff -u -r1.56 -r1.57 src/sys/dev/fdt/files.fdt

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/aarch64/aarch64/aarch64_machdep.c
diff -u src/sys/arch/aarch64/aarch64/aarch64_machdep.c:1.55 src/sys/arch/aarch64/aarch64/aarch64_machdep.c:1.56
--- src/sys/arch/aarch64/aarch64/aarch64_machdep.c:1.55	Wed Dec  9 08:51:05 2020
+++ src/sys/arch/aarch64/aarch64/aarch64_machdep.c	Sat Dec 12 09:27:31 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: aarch64_machdep.c,v 1.55 2020/12/09 08:51:05 skrll Exp $ */
+/* $NetBSD: aarch64_machdep.c,v 1.56 2020/12/12 09:27:31 skrll Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: aarch64_machdep.c,v 1.55 2020/12/09 08:51:05 skrll Exp $");
+__KERNEL_RCSID(1, "$NetBSD: aarch64_machdep.c,v 1.56 2020/12/12 09:27:31 skrll Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_cpuoptions.h"
@@ -72,8 +72,8 @@ __KERNEL_RCSID(1, "$NetBSD: aarch64_mach
 #include <aarch64/vmparam.h>
 #include <aarch64/kcore.h>
 
-#include <arch/evbarm/fdt/platform.h>
 #include <arm/fdt/arm_fdtvar.h>
+#include <dev/fdt/fdt_memory.h>
 
 #ifdef VERBOSE_INIT_ARM
 #define VPRINTF(...)	printf(__VA_ARGS__)
@@ -193,7 +193,7 @@ cpu_kernel_vm_init(uint64_t memory_start
 
 	VPRINTF("%s: kernel phys start %lx end %lx+%lx\n", __func__,
 	    kernstart_phys, kernend_phys, kernend_extra);
-	fdt_add_reserved_memory_range(kernstart_phys,
+	fdt_memory_remove_range(kernstart_phys,
 	     kernend_phys - kernstart_phys + kernend_extra);
 }
 

Index: src/sys/arch/arm/arm32/arm32_kvminit.c
diff -u src/sys/arch/arm/arm32/arm32_kvminit.c:1.66 src/sys/arch/arm/arm32/arm32_kvminit.c:1.67
--- src/sys/arch/arm/arm32/arm32_kvminit.c:1.66	Fri Oct 30 18:54:36 2020
+++ src/sys/arch/arm/arm32/arm32_kvminit.c	Sat Dec 12 09:27:31 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: arm32_kvminit.c,v 1.66 2020/10/30 18:54:36 skrll Exp $	*/
+/*	$NetBSD: arm32_kvminit.c,v 1.67 2020/12/12 09:27:31 skrll Exp $	*/
 
 /*
  * Copyright (c) 2002, 2003, 2005  Genetec Corporation.  All rights reserved.
@@ -127,7 +127,7 @@
 #include "opt_multiprocessor.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: arm32_kvminit.c,v 1.66 2020/10/30 18:54:36 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: arm32_kvminit.c,v 1.67 2020/12/12 09:27:31 skrll Exp $");
 
 #include <sys/param.h>
 
@@ -150,6 +150,7 @@ __KERNEL_RCSID(0, "$NetBSD: arm32_kvmini
 #if defined(FDT)
 #include <arch/evbarm/fdt/platform.h>
 #include <arm/fdt/arm_fdtvar.h>
+#include <dev/fdt/fdt_memory.h>
 #endif
 
 #ifdef MULTIPROCESSOR
@@ -251,7 +252,7 @@ arm32_bootmem_init(paddr_t memstart, psi
 	bmi->bmi_kernelend = kernelend;
 
 #if defined(FDT)
-	fdt_add_reserved_memory_range(bmi->bmi_kernelstart,
+	fdt_memory_remove_range(bmi->bmi_kernelstart,
 	    bmi->bmi_kernelend - bmi->bmi_kernelstart);
 #endif
 
@@ -400,7 +401,7 @@ valloc_pages(struct bootmem_info *bmi, p
 	KASSERT((armreg_ttbr_read() & ~(L1_TABLE_SIZE - 1)) != free_pv->pv_pa);
 
 #if defined(FDT)
-	fdt_add_reserved_memory_range(free_pv->pv_pa, nbytes);
+	fdt_memory_remove_range(free_pv->pv_pa, nbytes);
 #endif
 	pv->pv_pa = free_pv->pv_pa;
 	pv->pv_va = free_pv->pv_va;

Index: src/sys/arch/evbarm/conf/files.fdt
diff -u src/sys/arch/evbarm/conf/files.fdt:1.6 src/sys/arch/evbarm/conf/files.fdt:1.7
--- src/sys/arch/evbarm/conf/files.fdt:1.6	Thu Feb 20 01:35:55 2020
+++ src/sys/arch/evbarm/conf/files.fdt	Sat Dec 12 09:27:31 2020
@@ -1,10 +1,9 @@
-#	$NetBSD: files.fdt,v 1.6 2020/02/20 01:35:55 jmcneill Exp $
+#	$NetBSD: files.fdt,v 1.7 2020/12/12 09:27:31 skrll Exp $
 #
 # FDT-based kernel configuration info
 #
 
 file	arch/evbarm/fdt/fdt_dma_machdep.c	fdt
 file	arch/evbarm/fdt/fdt_machdep.c		fdt
-file	arch/evbarm/fdt/fdt_memory.c		fdt
 
 include "arch/arm/fdt/files.fdt"

Index: src/sys/arch/evbarm/fdt/fdt_machdep.c
diff -u src/sys/arch/evbarm/fdt/fdt_machdep.c:1.82 src/sys/arch/evbarm/fdt/fdt_machdep.c:1.83
--- src/sys/arch/evbarm/fdt/fdt_machdep.c:1.82	Sat Nov 28 22:16:23 2020
+++ src/sys/arch/evbarm/fdt/fdt_machdep.c	Sat Dec 12 09:27:31 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: fdt_machdep.c,v 1.82 2020/11/28 22:16:23 riastradh Exp $ */
+/* $NetBSD: fdt_machdep.c,v 1.83 2020/12/12 09:27:31 skrll Exp $ */
 
 /*-
  * Copyright (c) 2015-2017 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.82 2020/11/28 22:16:23 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.83 2020/12/12 09:27:31 skrll Exp $");
 
 #include "opt_machdep.h"
 #include "opt_bootconfig.h"
@@ -89,10 +89,10 @@ __KERNEL_RCSID(0, "$NetBSD: fdt_machdep.
 #include <evbarm/include/autoconf.h>
 #include <evbarm/fdt/machdep.h>
 #include <evbarm/fdt/platform.h>
-#include <evbarm/fdt/fdt_memory.h>
 
 #include <arm/fdt/arm_fdtvar.h>
 #include <dev/fdt/fdt_private.h>
+#include <dev/fdt/fdt_memory.h>
 
 #ifdef EFI_RUNTIME
 #include <arm/arm/efi_runtime.h>
@@ -172,81 +172,6 @@ static struct consdev earlycons = {
 #define VPRINTF(...)	__nothing
 #endif
 
-/*
- * Get all of physical memory, including holes.
- */
-static void
-fdt_get_memory(uint64_t *pstart, uint64_t *pend)
-{
-	const int memory = OF_finddevice("/memory");
-	uint64_t cur_addr, cur_size;
-	int index;
-
-	/* Assume the first entry is the start of memory */
-	if (fdtbus_get_reg64(memory, 0, &cur_addr, &cur_size) != 0)
-		panic("Cannot determine memory size");
-
-	*pstart = cur_addr;
-	*pend = cur_addr + cur_size;
-
-	VPRINTF("FDT /memory [%d] @ 0x%" PRIx64 " size 0x%" PRIx64 "\n",
-	    0, *pstart, *pend - *pstart);
-
-	for (index = 1;
-	     fdtbus_get_reg64(memory, index, &cur_addr, &cur_size) == 0;
-	     index++) {
-		VPRINTF("FDT /memory [%d] @ 0x%" PRIx64 " size 0x%" PRIx64 "\n",
-		    index, cur_addr, cur_size);
-
-		if (cur_addr + cur_size > *pend)
-			*pend = cur_addr + cur_size;
-	}
-}
-
-void
-fdt_add_reserved_memory_range(uint64_t addr, uint64_t size)
-{
-	fdt_memory_remove_range(addr, size);
-}
-
-/*
- * Exclude memory ranges from memory config from the device tree
- */
-static void
-fdt_add_reserved_memory(uint64_t min_addr, uint64_t max_addr)
-{
-	uint64_t lstart = 0, lend = 0;
-	uint64_t addr, size;
-	int index, error;
-
-	const int num = fdt_num_mem_rsv(fdtbus_get_data());
-	for (index = 0; index <= num; index++) {
-		error = fdt_get_mem_rsv(fdtbus_get_data(), index,
-		    &addr, &size);
-		if (error != 0)
-			continue;
-		if (lstart <= addr && addr <= lend) {
-			size -= (lend - addr);
-			addr = lend;
-		}
-		if (size == 0)
-			continue;
-		if (addr + size <= min_addr)
-			continue;
-		if (addr >= max_addr)
-			continue;
-		if (addr < min_addr) {
-			size -= (min_addr - addr);
-			addr = min_addr;
-		}
-		if (addr + size > max_addr)
-			size = max_addr - addr;
-		fdt_add_reserved_memory_range(addr, size);
-		lstart = addr;
-		lend = addr + size;
-	}
-}
-
 static void
 fdt_add_dram_blocks(const struct fdt_memory *m, void *arg)
 {
@@ -293,29 +218,28 @@ fdt_add_boot_physmem(const struct fdt_me
 #endif
 }
 
+
+static void
+fdt_print_memory(const struct fdt_memory *m, void *arg)
+{
+
+	VPRINTF("FDT /memory @ 0x%" PRIx64 " size 0x%" PRIx64 "\n",
+	    m->start, m->end - m->start);
+}
+
+
 /*
  * Define usable memory regions.
  */
 static void
 fdt_build_bootconfig(uint64_t mem_start, uint64_t mem_end)
 {
-	const int memory = OF_finddevice("/memory");
 	BootConfig *bc = &bootconfig;
+
 	uint64_t addr, size;
 	int index;
 
-	for (index = 0;
-	     fdtbus_get_reg64(memory, index, &addr, &size) == 0;
-	     index++) {
-		if (addr >= mem_end || size == 0)
-			continue;
-		if (addr + size > mem_end)
-			size = mem_end - addr;
-
-		fdt_memory_add_range(addr, size);
-	}
-
-	fdt_add_reserved_memory(mem_start, mem_end);
+	fdt_memory_remove_reserved(mem_start, mem_end);
 
 	const uint64_t initrd_size =
 	    round_page(initrd_end) - trunc_page(initrd_start);
@@ -338,7 +262,7 @@ fdt_build_bootconfig(uint64_t mem_start,
 		for (index = 0;
 		     fdtbus_get_reg64(framebuffer, index, &addr, &size) == 0;
 		     index++) {
-			fdt_add_reserved_memory_range(addr, size);
+			fdt_memory_remove_range(addr, size);
 		}
 	}
 
@@ -576,6 +500,7 @@ initarm(void *arg)
 	/* If the DTB is too big, try to pack it in place first. */
 	if (fdt_totalsize(fdt_addr_r) > sizeof(fdt_data))
 		(void)fdt_pack(__UNCONST(fdt_addr_r));
+
 	error = fdt_open_into(fdt_addr_r, fdt_data, sizeof(fdt_data));
 	if (error != 0)
 		panic("fdt_move failed: %s", fdt_strerror(error));
@@ -656,13 +581,17 @@ initarm(void *arg)
 	parse_mi_bootargs(mi_bootargs);
 #endif
 
-	fdt_get_memory(&memory_start, &memory_end);
+	fdt_memory_get(&memory_start, &memory_end);
+
+	fdt_memory_foreach(fdt_print_memory, NULL);
 
 #if !defined(_LP64)
 	/* Cannot map memory above 4GB (remove last page as well) */
 	const uint64_t memory_limit = 0x100000000ULL - PAGE_SIZE;
-	if (memory_end > memory_limit)
+	if (memory_end > memory_limit) {
+		fdt_memory_remove_range(memory_limit , memory_end);
 		memory_end = memory_limit;
+	}
 #endif
 	uint64_t memory_size = memory_end - memory_start;
 

Index: src/sys/arch/evbarm/fdt/platform.h
diff -u src/sys/arch/evbarm/fdt/platform.h:1.9 src/sys/arch/evbarm/fdt/platform.h:1.10
--- src/sys/arch/evbarm/fdt/platform.h:1.9	Sat Sep 19 16:31:40 2020
+++ src/sys/arch/evbarm/fdt/platform.h	Sat Dec 12 09:27:31 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: platform.h,v 1.9 2020/09/19 16:31:40 skrll Exp $ */
+/* $NetBSD: platform.h,v 1.10 2020/12/12 09:27:31 skrll Exp $ */
 
 /*-
  * Copyright (c) 2015-2017 Jared McNeill <jmcne...@invisible.ca>
@@ -29,10 +29,6 @@
 #ifndef _EVBARM_FDT_PLATFORM_H
 #define _EVBARM_FDT_PLATFORM_H
 
-#ifndef _LOCORE
-void fdt_add_reserved_memory_range(uint64_t, uint64_t);
-#endif
-
 #define KERNEL_IO_VBASE		VM_KERNEL_IO_ADDRESS
 #define KERNEL_IO_VSIZE		VM_KERNEL_IO_SIZE
 

Index: src/sys/dev/fdt/files.fdt
diff -u src/sys/dev/fdt/files.fdt:1.56 src/sys/dev/fdt/files.fdt:1.57
--- src/sys/dev/fdt/files.fdt:1.56	Fri Oct 30 16:08:45 2020
+++ src/sys/dev/fdt/files.fdt	Sat Dec 12 09:27:31 2020
@@ -1,9 +1,10 @@
-# $NetBSD: files.fdt,v 1.56 2020/10/30 16:08:45 skrll Exp $
+# $NetBSD: files.fdt,v 1.57 2020/12/12 09:27:31 skrll Exp $
 
 include	"external/bsd/libfdt/conf/files.libfdt"
 
 defflag	opt_fdt.h				FDTBASE : libfdt, ofw_subr
 defflag	opt_fdt.h				FDT: FDTBASE
+defparam opt_fdt.h				FDT_MEMORY_RANGES
 defparam opt_fdt.h				FDT_DEFAULT_STDOUT_PATH
 
 define	fdt { [pass = 10] } : clk, pwm
@@ -53,8 +54,10 @@ device	dispcon: fdt_port, drmkms, ddc_re
 attach	dispcon at fdt with dispcon_hdmi
 file	dev/fdt/hdmi_connector.c		dispcon_hdmi
 
+file	dev/fdt/fdt_memory.c			fdtbase
 file	dev/fdt/fdt_openfirm.c			fdtbase
 file	dev/fdt/fdt_subr.c			fdtbase
+
 file	dev/fdt/fdt_clock.c			fdt
 file	dev/fdt/fdt_dai.c			fdt
 file	dev/fdt/fdt_dma.c			fdt

Added files:

Index: src/sys/dev/fdt/fdt_memory.c
diff -u /dev/null src/sys/dev/fdt/fdt_memory.c:1.1
--- /dev/null	Sat Dec 12 09:27:32 2020
+++ src/sys/dev/fdt/fdt_memory.c	Sat Dec 12 09:27:31 2020
@@ -0,0 +1,244 @@
+/* $NetBSD: fdt_memory.c,v 1.1 2020/12/12 09:27:31 skrll Exp $ */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jared McNeill <jmcne...@invisible.ca>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_fdt.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: fdt_memory.c,v 1.1 2020/12/12 09:27:31 skrll Exp $");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+
+#include <libfdt.h>
+#include <dev/fdt/fdtvar.h>
+#include <dev/fdt/fdt_memory.h>
+
+#ifndef FDT_MEMORY_RANGES
+#define FDT_MEMORY_RANGES	256
+#endif
+
+struct fdt_memory_range {
+	struct fdt_memory               mr_mem;
+	bool                            mr_used;
+	TAILQ_ENTRY(fdt_memory_range)   mr_list;
+};
+
+static TAILQ_HEAD(fdt_memory_rangehead, fdt_memory_range) fdt_memory_ranges =
+    TAILQ_HEAD_INITIALIZER(fdt_memory_ranges);
+
+static struct fdt_memory_range fdt_memory_range_pool[FDT_MEMORY_RANGES];
+
+static struct fdt_memory_range *
+fdt_memory_range_alloc(void)
+{
+	for (size_t n = 0; n < FDT_MEMORY_RANGES; n++)
+		if (!fdt_memory_range_pool[n].mr_used) {
+			fdt_memory_range_pool[n].mr_used = true;
+			return &fdt_memory_range_pool[n];
+		}
+
+	printf("%s: no free memory ranges, increase FDT_MEMORY_RANGES!\n", __func__);
+	return NULL;
+}
+
+static void
+fdt_memory_range_free(struct fdt_memory_range *mr)
+{
+	mr->mr_used = false;
+}
+
+/*
+ * Get all of physical memory, including holes.
+ */
+void
+fdt_memory_get(uint64_t *pstart, uint64_t *pend)
+{
+	const int memory = OF_finddevice("/memory");
+	uint64_t cur_addr, cur_size;
+	int index;
+
+	for (index = 0;
+	     fdtbus_get_reg64(memory, index, &cur_addr, &cur_size) == 0;
+	     index++) {
+		fdt_memory_add_range(cur_addr, cur_size);
+
+		/* Assume the first entry is the start of memory */
+		if (index == 0) {
+			*pstart = cur_addr;
+			*pend = cur_addr + cur_size;
+			continue;
+		}
+		if (cur_addr + cur_size > *pend)
+			*pend = cur_addr + cur_size;
+	}
+	if (index == 0)
+		panic("Cannot determine memory size");
+}
+
+/*
+ * Exclude memory ranges from memory config from the device tree
+ */
+void
+fdt_memory_remove_reserved(uint64_t min_addr, uint64_t max_addr)
+{
+	uint64_t lstart = 0, lend = 0;
+	uint64_t addr, size;
+	int index, error;
+
+	const int num = fdt_num_mem_rsv(fdtbus_get_data());
+	for (index = 0; index <= num; index++) {
+		error = fdt_get_mem_rsv(fdtbus_get_data(), index,
+		    &addr, &size);
+		if (error != 0)
+			continue;
+		if (lstart <= addr && addr <= lend) {
+			size -= (lend - addr);
+			addr = lend;
+		}
+		if (size == 0)
+			continue;
+		if (addr + size <= min_addr)
+			continue;
+		if (addr >= max_addr)
+			continue;
+		if (addr < min_addr) {
+			size -= (min_addr - addr);
+			addr = min_addr;
+		}
+		if (addr + size > max_addr)
+			size = max_addr - addr;
+		fdt_memory_remove_range(addr, size);
+		lstart = addr;
+		lend = addr + size;
+	}
+}
+
+void
+fdt_memory_add_range(uint64_t start, uint64_t size)
+{
+	struct fdt_memory_range *mr, *prev, *cur, *tmp;
+	bool inserted = false;
+
+	mr = fdt_memory_range_alloc();
+	if (mr == NULL)
+		return;
+
+	mr->mr_mem.start = start;
+	mr->mr_mem.end = start + size;
+
+	/*
+	 * Add the new range to the list of sorted ranges.
+	 */
+	TAILQ_FOREACH(cur, &fdt_memory_ranges, mr_list)
+		if (mr->mr_mem.start <= cur->mr_mem.start) {
+			TAILQ_INSERT_BEFORE(cur, mr, mr_list);
+			inserted = true;
+			break;
+		}
+	if (!inserted)
+		TAILQ_INSERT_TAIL(&fdt_memory_ranges, mr, mr_list);
+
+	/*
+	 * Remove overlaps.
+	 */
+	TAILQ_FOREACH_SAFE(mr, &fdt_memory_ranges, mr_list, tmp) {
+		prev = TAILQ_PREV(mr, fdt_memory_rangehead, mr_list);
+		if (prev && prev->mr_mem.end > mr->mr_mem.start) {
+			mr->mr_mem.start = prev->mr_mem.end;
+			if (mr->mr_mem.start >= mr->mr_mem.end) {
+				TAILQ_REMOVE(&fdt_memory_ranges, mr, mr_list);
+				fdt_memory_range_free(mr);
+			}
+		}
+	}
+
+	/*
+	 * Combine adjacent ranges.
+	 */
+	TAILQ_FOREACH_SAFE(mr, &fdt_memory_ranges, mr_list, tmp) {
+		prev = TAILQ_PREV(mr, fdt_memory_rangehead, mr_list);
+		if (prev && prev->mr_mem.end == mr->mr_mem.start) {
+			prev->mr_mem.end = mr->mr_mem.end;
+			TAILQ_REMOVE(&fdt_memory_ranges, mr, mr_list);
+			fdt_memory_range_free(mr);
+		}
+	}
+}
+
+void
+fdt_memory_remove_range(uint64_t start, uint64_t size)
+{
+	struct fdt_memory_range *mr, *next, *tmp;
+	const uint64_t end = start + size;
+
+	TAILQ_FOREACH_SAFE(mr, &fdt_memory_ranges, mr_list, tmp) {
+		if (start <= mr->mr_mem.start && end >= mr->mr_mem.end) {
+			/*
+			 * Removed range completely covers this range,
+			 * just remove it.
+			 */
+			TAILQ_REMOVE(&fdt_memory_ranges, mr, mr_list);
+			fdt_memory_range_free(mr);
+		} else if (start > mr->mr_mem.start && end < mr->mr_mem.end) {
+			/*
+			 * Removed range is completely contained by this range,
+			 * split it.
+			 */
+			next = fdt_memory_range_alloc();
+			if (next == NULL)
+				panic("fdt_memory_remove_range");
+			next->mr_mem.start = end;
+			next->mr_mem.end = mr->mr_mem.end;
+			mr->mr_mem.end = start;
+			TAILQ_INSERT_AFTER(&fdt_memory_ranges, mr, next, mr_list);
+		} else if (start <= mr->mr_mem.start && end > mr->mr_mem.start && end < mr->mr_mem.end) {
+			/*
+			 * Partial overlap at the beginning of the range.
+			 */
+			mr->mr_mem.start = end;
+		} else if (start > mr->mr_mem.start && start < mr->mr_mem.end && end >= mr->mr_mem.end) {
+			/*
+			 * Partial overlap at the end of the range.
+			 */
+			mr->mr_mem.end = start;
+		}
+		KASSERT(mr->mr_mem.start < mr->mr_mem.end);
+	}
+}
+
+void
+fdt_memory_foreach(void (*fn)(const struct fdt_memory *, void *), void *arg)
+{
+	struct fdt_memory_range *mr;
+
+	TAILQ_FOREACH(mr, &fdt_memory_ranges, mr_list)
+		fn(&mr->mr_mem, arg);
+}
Index: src/sys/dev/fdt/fdt_memory.h
diff -u /dev/null src/sys/dev/fdt/fdt_memory.h:1.1
--- /dev/null	Sat Dec 12 09:27:32 2020
+++ src/sys/dev/fdt/fdt_memory.h	Sat Dec 12 09:27:31 2020
@@ -0,0 +1,48 @@
+/* $NetBSD: fdt_memory.h,v 1.1 2020/12/12 09:27:31 skrll Exp $ */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jared McNeill <jmcne...@invisible.ca>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_FDT_FDT_MEMORY_H_
+#define _DEV_FDT_FDT_MEMORY_H_
+
+struct fdt_memory {
+	uint64_t	start;
+	uint64_t	end;
+};
+
+void	fdt_memory_init(void);
+void	fdt_memory_get(uint64_t *, uint64_t *);
+void	fdt_memory_add_range(uint64_t, uint64_t);
+void	fdt_memory_remove_range(uint64_t, uint64_t);
+void	fdt_memory_remove_reserved(uint64_t, uint64_t);
+
+void	fdt_memory_foreach(void (*)(const struct fdt_memory *, void *), void *);
+
+#endif /* _DEV_FDT_FDT_MEMORY_H_ */

Reply via email to