
From: Simon Glass <sjg@chromium.org> Add a new mem.c file and move memory-related functions to it. Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/sandbox/cpu/Makefile | 2 +- arch/sandbox/cpu/cpu.c | 274 +----------------------------------- arch/sandbox/cpu/mem.c | 288 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 290 insertions(+), 274 deletions(-) create mode 100644 arch/sandbox/cpu/mem.c diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile index bfcdc335d32..aac65e48675 100644 --- a/arch/sandbox/cpu/Makefile +++ b/arch/sandbox/cpu/Makefile @@ -5,7 +5,7 @@ # (C) Copyright 2000-2003 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -obj-y := cache.o cpu.o state.o +obj-y := cache.o cpu.o mem.o state.o extra-y := start.o os.o extra-$(CONFIG_SANDBOX_SDL) += sdl.o obj-$(CONFIG_XPL_BUILD) += spl.o diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index 6db8739e66b..218057b94ad 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -9,27 +9,16 @@ #include <cpu_func.h> #include <errno.h> #include <log.h> +#include <mapmem.h> #include <os.h> -#include <setjmp.h> #include <asm/global_data.h> -#include <asm/io.h> #include <asm/malloc.h> #include <asm/state.h> -#include <dm/ofnode.h> #include <linux/delay.h> #include <linux/libfdt.h> DECLARE_GLOBAL_DATA_PTR; -/* Enable access to PCI memory with map_sysmem() */ -static bool enable_pci_map; - -#ifdef CONFIG_PCI -/* Last device that was mapped into memory, and length of mapping */ -static struct udevice *map_dev; -unsigned long map_len; -#endif - void __noreturn sandbox_exit(void) { /* Do this here while it still has an effect */ @@ -61,267 +50,6 @@ int cleanup_before_linux_select(int flags) return 0; } -/** - * is_in_sandbox_mem() - Checks if a pointer is within sandbox's emulated DRAM - * - * This provides a way to check if a pointer is owned by sandbox (and is within - * its RAM) or not. Sometimes pointers come from a test which conceptually runs - * output sandbox, potentially with direct access to the C-library malloc() - * function, or the sandbox stack (which is not actually within the emulated - * DRAM. - * - * Such pointers obviously cannot be mapped into sandbox's DRAM, so we must - * detect them an process them separately, by recording a mapping to a tag, - * which we can use to map back to the pointer later. - * - * @ptr: Pointer to check - * Return: true if this is within sandbox emulated DRAM, false if not - */ -static bool is_in_sandbox_mem(const void *ptr) -{ - return (const uint8_t *)ptr >= gd->arch.ram_buf && - (const uint8_t *)ptr < gd->arch.ram_buf + gd->ram_size; -} - -/** - * phys_to_virt() - Converts a sandbox RAM address to a pointer - * - * Sandbox uses U-Boot addresses from 0 to the size of DRAM. These index into - * the emulated DRAM buffer used by sandbox. This function converts such an - * address to a pointer into this buffer, which can be used to access the - * memory. - * - * If the address is outside this range, it is assumed to be a tag - */ -void *phys_to_virt(phys_addr_t paddr) -{ - struct sandbox_mapmem_entry *mentry; - struct sandbox_state *state; - - /* If the address is within emulated DRAM, calculate the value */ - if (paddr < gd->ram_size) - return (void *)(gd->arch.ram_buf + paddr); - - /* - * Otherwise search out list of tags for the correct pointer previously - * created by map_to_sysmem() - */ - state = state_get_current(); - list_for_each_entry(mentry, &state->mapmem_head, sibling_node) { - if (mentry->tag == paddr) { - log_debug("Used map from %lx to %p\n", (ulong)paddr, - mentry->ptr); - mentry->refcnt++; - return mentry->ptr; - } - } - - printf("%s: Cannot map sandbox address %lx (SDRAM from 0 to %lx)\n", - __func__, (ulong)paddr, (ulong)gd->ram_size); - os_abort(); - - /* Not reached */ - return NULL; -} - -struct sandbox_mapmem_entry *find_tag(const void *ptr) -{ - struct sandbox_mapmem_entry *mentry; - struct sandbox_state *state = state_get_current(); - - list_for_each_entry(mentry, &state->mapmem_head, sibling_node) { - if (mentry->ptr == ptr) { - log_debug("Used map from %p to %lx\n", ptr, - mentry->tag); - return mentry; - } - } - - return NULL; -} - -phys_addr_t virt_to_phys(void *ptr) -{ - struct sandbox_mapmem_entry *mentry; - - /* - * If it is in emulated RAM, don't bother looking for a tag. Just - * calculate the pointer using the provides offset into the RAM buffer. - */ - if (is_in_sandbox_mem(ptr)) - return (phys_addr_t)((uint8_t *)ptr - gd->arch.ram_buf); - - mentry = find_tag(ptr); - if (!mentry) { - /* Abort so that gdb can be used here */ - printf("%s: Cannot map sandbox address %p (SDRAM from 0 to %lx)\n", - __func__, ptr, (ulong)gd->ram_size); - os_abort(); - } - log_debug("Used map from %p to %lx\n", ptr, mentry->tag); - - return mentry->tag; -} - -void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) -{ -#if defined(CONFIG_PCI) && !defined(CONFIG_XPL_BUILD) - unsigned long plen = len; - void *ptr; - - map_dev = NULL; - if (enable_pci_map && !pci_map_physmem(paddr, &len, &map_dev, &ptr)) { - if (plen != len) { - printf("%s: Warning: partial map at %x, wanted %lx, got %lx\n", - __func__, (uint)paddr, len, plen); - } - map_len = len; - log_debug("pci map %lx -> %p\n", (ulong)paddr, ptr); - return ptr; - } -#endif - - return phys_to_virt(paddr); -} - -void unmap_physmem(const void *ptr, unsigned long flags) -{ - struct sandbox_mapmem_entry *mentry; - -#ifdef CONFIG_PCI - if (map_dev) { - pci_unmap_physmem(ptr, map_len, map_dev); - map_dev = NULL; - } -#endif - - /* If it is in emulated RAM, we didn't create a tag, so nothing to do */ - if (is_in_sandbox_mem(ptr)) - return; - - mentry = find_tag(ptr); - if (mentry) { - if (!--mentry->refcnt) { - list_del(&mentry->sibling_node); - log_debug("Removed map from %p to %lx\n", ptr, - (ulong)mentry->tag); - free(mentry); - } - } else { - log_warning("Address not mapped: %p\n", ptr); - } -} - -phys_addr_t map_to_sysmem(const void *ptr) -{ - struct sandbox_mapmem_entry *mentry; - - /* - * If it is in emulated RAM, don't bother creating a tag. Just return - * the offset into the RAM buffer. - */ - if (is_in_sandbox_mem(ptr)) - return (u8 *)ptr - gd->arch.ram_buf; - - /* - * See if there is an existing tag with this pointer. If not, set up a - * new one. - */ - mentry = find_tag(ptr); - if (!mentry) { - struct sandbox_state *state = state_get_current(); - - mentry = malloc(sizeof(*mentry)); - if (!mentry) { - printf("%s: Error: Out of memory\n", __func__); - os_exit(ENOMEM); - } - mentry->tag = state->next_tag++; - mentry->ptr = (void *)ptr; - mentry->refcnt = 0; - list_add_tail(&mentry->sibling_node, &state->mapmem_head); - log_debug("Added map from %p to %lx\n", ptr, - (ulong)mentry->tag); - } - - mentry->refcnt++; - - /* - * Return the tag as the address to use. A later call to map_sysmem() - * will return ptr - */ - return mentry->tag; -} - -void sandbox_map_list(void) -{ - struct sandbox_mapmem_entry *mentry; - struct sandbox_state *state = state_get_current(); - - printf("Sandbox memory-mapping\n"); - printf("%8s %16s %6s\n", "Addr", "Mapping", "Refcnt"); - list_for_each_entry(mentry, &state->mapmem_head, sibling_node) { - printf("%8lx %p %6d\n", mentry->tag, mentry->ptr, - mentry->refcnt); - } -} - -unsigned long sandbox_read(const void *addr, enum sandboxio_size_t size) -{ - struct sandbox_state *state = state_get_current(); - - if (!state->allow_memio) - return 0; - - switch (size) { - case SB_SIZE_8: - return *(u8 *)addr; - case SB_SIZE_16: - return *(u16 *)addr; - case SB_SIZE_32: - return *(u32 *)addr; - case SB_SIZE_64: - return *(u64 *)addr; - } - - return 0; -} - -void sandbox_write(void *addr, unsigned int val, enum sandboxio_size_t size) -{ - struct sandbox_state *state = state_get_current(); - - if (!state->allow_memio) - return; - - switch (size) { - case SB_SIZE_8: - *(u8 *)addr = val; - break; - case SB_SIZE_16: - *(u16 *)addr = val; - break; - case SB_SIZE_32: - *(u32 *)addr = val; - break; - case SB_SIZE_64: - *(u64 *)addr = val; - break; - } -} - -void sandbox_set_enable_memio(bool enable) -{ - struct sandbox_state *state = state_get_current(); - - state->allow_memio = enable; -} - -void sandbox_set_enable_pci_map(int enable) -{ - enable_pci_map = enable; -} - void dcache_enable(void) { } diff --git a/arch/sandbox/cpu/mem.c b/arch/sandbox/cpu/mem.c new file mode 100644 index 00000000000..54a55c1558c --- /dev/null +++ b/arch/sandbox/cpu/mem.c @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * Copyright 2025 Simon Glass <sjg@chromium.org> + */ + +#define LOG_CATEGORY LOGC_SANDBOX + +#include <errno.h> +#include <log.h> +#include <malloc.h> +#include <os.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/state.h> +#include <linux/list.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Enable access to PCI memory with map_sysmem() */ +static bool enable_pci_map; + +#ifdef CONFIG_PCI +/* Last device that was mapped into memory, and length of mapping */ +static struct udevice *map_dev; +unsigned long map_len; +#endif + +/** + * is_in_sandbox_mem() - Checks if a pointer is within sandbox's emulated DRAM + * + * This provides a way to check if a pointer is owned by sandbox (and is within + * its RAM) or not. Sometimes pointers come from a test which conceptually runs + * output sandbox, potentially with direct access to the C-library malloc() + * function, or the sandbox stack (which is not actually within the emulated + * DRAM. + * + * Such pointers obviously cannot be mapped into sandbox's DRAM, so we must + * detect them an process them separately, by recording a mapping to a tag, + * which we can use to map back to the pointer later. + * + * @ptr: Pointer to check + * Return: true if this is within sandbox emulated DRAM, false if not + */ +static bool is_in_sandbox_mem(const void *ptr) +{ + return (const uint8_t *)ptr >= gd->arch.ram_buf && + (const uint8_t *)ptr < gd->arch.ram_buf + gd->ram_size; +} + +/** + * phys_to_virt() - Converts a sandbox RAM address to a pointer + * + * Sandbox uses U-Boot addresses from 0 to the size of DRAM. These index into + * the emulated DRAM buffer used by sandbox. This function converts such an + * address to a pointer into this buffer, which can be used to access the + * memory. + * + * If the address is outside this range, it is assumed to be a tag + */ +void *phys_to_virt(phys_addr_t paddr) +{ + struct sandbox_mapmem_entry *mentry; + struct sandbox_state *state; + + /* If the address is within emulated DRAM, calculate the value */ + if (paddr < gd->ram_size) + return (void *)(gd->arch.ram_buf + paddr); + + /* + * Otherwise search out list of tags for the correct pointer previously + * created by map_to_sysmem() + */ + state = state_get_current(); + list_for_each_entry(mentry, &state->mapmem_head, sibling_node) { + if (mentry->tag == paddr) { + log_debug("Used map from %lx to %p\n", (ulong)paddr, + mentry->ptr); + mentry->refcnt++; + return mentry->ptr; + } + } + + printf("%s: Cannot map sandbox address %lx (SDRAM from 0 to %lx)\n", + __func__, (ulong)paddr, (ulong)gd->ram_size); + os_abort(); + + /* Not reached */ + return NULL; +} + +struct sandbox_mapmem_entry *find_tag(const void *ptr) +{ + struct sandbox_mapmem_entry *mentry; + struct sandbox_state *state = state_get_current(); + + list_for_each_entry(mentry, &state->mapmem_head, sibling_node) { + if (mentry->ptr == ptr) { + log_debug("Used map from %p to %lx\n", ptr, + mentry->tag); + return mentry; + } + } + + return NULL; +} + +phys_addr_t virt_to_phys(void *ptr) +{ + struct sandbox_mapmem_entry *mentry; + + /* + * If it is in emulated RAM, don't bother looking for a tag. Just + * calculate the pointer using the provides offset into the RAM buffer. + */ + if (is_in_sandbox_mem(ptr)) + return (phys_addr_t)((uint8_t *)ptr - gd->arch.ram_buf); + + mentry = find_tag(ptr); + if (!mentry) { + /* Abort so that gdb can be used here */ + printf("%s: Cannot map sandbox address %p (SDRAM from 0 to %lx)\n", + __func__, ptr, (ulong)gd->ram_size); + os_abort(); + } + log_debug("Used map from %p to %lx\n", ptr, mentry->tag); + + return mentry->tag; +} + +void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) +{ +#if defined(CONFIG_PCI) && !defined(CONFIG_XPL_BUILD) + unsigned long plen = len; + void *ptr; + + map_dev = NULL; + if (enable_pci_map && !pci_map_physmem(paddr, &len, &map_dev, &ptr)) { + if (plen != len) { + printf("%s: Warning: partial map at %x, wanted %lx, got %lx\n", + __func__, (uint)paddr, len, plen); + } + map_len = len; + log_debug("pci map %lx -> %p\n", (ulong)paddr, ptr); + return ptr; + } +#endif + + return phys_to_virt(paddr); +} + +void unmap_physmem(const void *ptr, unsigned long flags) +{ + struct sandbox_mapmem_entry *mentry; + +#ifdef CONFIG_PCI + if (map_dev) { + pci_unmap_physmem(ptr, map_len, map_dev); + map_dev = NULL; + } +#endif + + /* If it is in emulated RAM, we didn't create a tag, so nothing to do */ + if (is_in_sandbox_mem(ptr)) + return; + + mentry = find_tag(ptr); + if (mentry) { + if (!--mentry->refcnt) { + list_del(&mentry->sibling_node); + log_debug("Removed map from %p to %lx\n", ptr, + (ulong)mentry->tag); + free(mentry); + } + } else { + log_warning("Address not mapped: %p\n", ptr); + } +} + +phys_addr_t map_to_sysmem(const void *ptr) +{ + struct sandbox_mapmem_entry *mentry; + + /* + * If it is in emulated RAM, don't bother creating a tag. Just return + * the offset into the RAM buffer. + */ + if (is_in_sandbox_mem(ptr)) + return (u8 *)ptr - gd->arch.ram_buf; + + /* + * See if there is an existing tag with this pointer. If not, set up a + * new one. + */ + mentry = find_tag(ptr); + if (!mentry) { + struct sandbox_state *state = state_get_current(); + + mentry = malloc(sizeof(*mentry)); + if (!mentry) { + printf("%s: Error: Out of memory\n", __func__); + os_exit(ENOMEM); + } + mentry->tag = state->next_tag++; + mentry->ptr = (void *)ptr; + mentry->refcnt = 0; + list_add_tail(&mentry->sibling_node, &state->mapmem_head); + log_debug("Added map from %p to %lx\n", ptr, + (ulong)mentry->tag); + } + + mentry->refcnt++; + + /* + * Return the tag as the address to use. A later call to map_sysmem() + * will return ptr + */ + return mentry->tag; +} + +void sandbox_map_list(void) +{ + struct sandbox_mapmem_entry *mentry; + struct sandbox_state *state = state_get_current(); + + printf("Sandbox memory-mapping\n"); + printf("%8s %16s %6s\n", "Addr", "Mapping", "Refcnt"); + list_for_each_entry(mentry, &state->mapmem_head, sibling_node) { + printf("%8lx %p %6d\n", mentry->tag, mentry->ptr, + mentry->refcnt); + } +} + +unsigned long sandbox_read(const void *addr, enum sandboxio_size_t size) +{ + struct sandbox_state *state = state_get_current(); + + if (!state->allow_memio) + return 0; + + switch (size) { + case SB_SIZE_8: + return *(u8 *)addr; + case SB_SIZE_16: + return *(u16 *)addr; + case SB_SIZE_32: + return *(u32 *)addr; + case SB_SIZE_64: + return *(u64 *)addr; + } + + return 0; +} + +void sandbox_write(void *addr, unsigned int val, enum sandboxio_size_t size) +{ + struct sandbox_state *state = state_get_current(); + + if (!state->allow_memio) + return; + + switch (size) { + case SB_SIZE_8: + *(u8 *)addr = val; + break; + case SB_SIZE_16: + *(u16 *)addr = val; + break; + case SB_SIZE_32: + *(u32 *)addr = val; + break; + case SB_SIZE_64: + *(u64 *)addr = val; + break; + } +} + +void sandbox_set_enable_memio(bool enable) +{ + struct sandbox_state *state = state_get_current(); + + state->allow_memio = enable; +} + +void sandbox_set_enable_pci_map(int enable) +{ + enable_pci_map = enable; +} -- 2.43.0