diff options
Diffstat (limited to 'common/memory.c')
-rw-r--r-- | common/memory.c | 128 |
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); |