summaryrefslogtreecommitdiffstats
path: root/common/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/memory.c')
-rw-r--r--common/memory.c128
1 files changed, 101 insertions, 27 deletions
diff --git a/common/memory.c b/common/memory.c
index 114958fbcf..583843cc34 100644
--- a/common/memory.c
+++ b/common/memory.c
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
- * memory.c
- *
* Copyright (c) 2011 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
*/
+#define pr_fmt(fmt) "memory: " fmt
+
#include <common.h>
#include <memory.h>
#include <of.h>
@@ -23,6 +14,8 @@
#include <asm-generic/memory_layout.h>
#include <asm/sections.h>
#include <malloc.h>
+#include <of.h>
+#include <mmu.h>
/*
* Begin and End of memory area for malloc(), and current "brk"
@@ -43,7 +36,7 @@ unsigned long mem_malloc_end(void)
#ifdef CONFIG_MALLOC_TLSF
#include <tlsf.h>
-tlsf_pool tlsf_mem_pool;
+tlsf_t tlsf_mem_pool;
#endif
int mem_malloc_initialized;
@@ -59,14 +52,14 @@ void mem_malloc_init(void *start, void *end)
malloc_end = (unsigned long)end;
malloc_brk = malloc_start;
#ifdef CONFIG_MALLOC_TLSF
- tlsf_mem_pool = tlsf_create(start, end - start + 1);
+ tlsf_mem_pool = tlsf_create_with_pool(start, end - start + 1);
#endif
mem_malloc_initialized = 1;
}
-#if !defined __SANDBOX__ && !defined CONFIG_EFI_BOOTUP
static int mem_malloc_resource(void)
{
+#if !defined __SANDBOX__
/*
* Normally it's a bug when one of these fails,
* but we have some setups where some of these
@@ -88,13 +81,14 @@ static int mem_malloc_resource(void)
(unsigned long)&__bss_start,
(unsigned long)&__bss_stop -
(unsigned long)&__bss_start);
+#endif
#ifdef STACK_BASE
request_sdram_region("stack", STACK_BASE, STACK_SIZE);
#endif
+
return 0;
}
coredevice_initcall(mem_malloc_resource);
-#endif
static void *sbrk_no_zero(ptrdiff_t increment)
{
@@ -122,19 +116,59 @@ void *sbrk(ptrdiff_t increment)
LIST_HEAD(memory_banks);
+static int barebox_grow_memory_bank(struct memory_bank *bank, const char *name,
+ const struct resource *newres)
+{
+ struct resource *res;
+ resource_size_t bank_end = bank->res->end;
+
+ if (newres->start < bank->start) {
+ res = request_iomem_region(name, newres->start, bank->start - 1);
+ if (IS_ERR(res))
+ return PTR_ERR(res);
+ __merge_regions(name, bank->res, res);
+ }
+
+ if (bank_end < newres->end) {
+ res = request_iomem_region(name, bank_end + 1, newres->end);
+ if (IS_ERR(res))
+ return PTR_ERR(res);
+ __merge_regions(name, bank->res, res);
+ }
+
+ bank->start = newres->start;
+ bank->size = resource_size(bank->res);
+
+ return 0;
+}
+
int barebox_add_memory_bank(const char *name, resource_size_t start,
resource_size_t size)
{
- struct memory_bank *bank = xzalloc(sizeof(*bank));
- struct device_d *dev;
+ struct memory_bank *bank;
+ struct resource *res;
+ struct resource newres = {
+ .start = start,
+ .end = start + size - 1,
+ .flags = IORESOURCE_MEM,
+ };
- bank->res = request_iomem_region(name, start, start + size - 1);
- if (IS_ERR(bank->res))
- return PTR_ERR(bank->res);
+ for_each_memory_bank(bank) {
+ if (resource_contains(bank->res, &newres))
+ return 0;
+ if (resource_contains(&newres, bank->res))
+ return barebox_grow_memory_bank(bank, name, &newres);
+ }
+
+ res = request_iomem_region(name, start, start + size - 1);
+ if (IS_ERR(res))
+ return PTR_ERR(res);
- dev = add_mem_device(name, start, size, IORESOURCE_MEM_WRITEABLE);
+ res->flags = IORESOURCE_MEM;
- bank->dev = dev;
+ bank = xzalloc(sizeof(*bank));
+
+ bank->res = res;
bank->start = start;
bank->size = size;
@@ -143,19 +177,34 @@ int barebox_add_memory_bank(const char *name, resource_size_t start,
return 0;
}
+static int add_mem_devices(void)
+{
+ struct memory_bank *bank;
+
+ for_each_memory_bank(bank) {
+ add_mem_device(bank->res->name, bank->start, bank->size,
+ IORESOURCE_MEM_WRITEABLE);
+ }
+
+ return 0;
+}
+postmem_initcall(add_mem_devices);
+
/*
* Request a region from the registered sdram
*/
-struct resource *request_sdram_region(const char *name, resource_size_t start,
- resource_size_t size)
+struct resource *__request_sdram_region(const char *name, unsigned flags,
+ resource_size_t start, resource_size_t size)
{
struct memory_bank *bank;
+ flags |= IORESOURCE_MEM;
+
for_each_memory_bank(bank) {
struct resource *res;
- res = __request_region(bank->res, name, start,
- start + size - 1);
+ res = __request_region(bank->res, start, start + size - 1,
+ name, flags);
if (!IS_ERR(res))
return res;
}
@@ -163,6 +212,31 @@ struct resource *request_sdram_region(const char *name, resource_size_t start,
return NULL;
}
+/* use for secure firmware to inhibit speculation */
+struct resource *reserve_sdram_region(const char *name, resource_size_t start,
+ resource_size_t size)
+{
+ struct resource *res;
+
+ if (!IS_ALIGNED(start, PAGE_SIZE)) {
+ pr_err("%s: %s start is not page aligned\n", __func__, name);
+ start = ALIGN_DOWN(start, PAGE_SIZE);
+ }
+
+ if (!IS_ALIGNED(size, PAGE_SIZE)) {
+ pr_err("%s: %s size is not page aligned\n", __func__, name);
+ size = ALIGN(size, PAGE_SIZE);
+ }
+
+ res = __request_sdram_region(name, IORESOURCE_BUSY, start, size);
+ if (!res)
+ return NULL;
+
+ remap_range((void *)start, size, MAP_UNCACHED);
+
+ return res;
+}
+
int release_sdram_region(struct resource *res)
{
return release_region(res);