From 095f8c029319b79cce487e3b566cd826b93da3e6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 8 Jan 2021 22:42:51 +0000 Subject: [PATCH] semihosting: Support SYS_HEAPINFO when env->boot_info is not set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit env->boot_info is only set in some ARM startup paths, so we cannot rely on it to support the SYS_HEAPINFO semihosting function. When not available, fallback to finding a RAM memory region containing the current stack and use the base of that. Signed-off-by: Keith Packard Signed-off-by: Alex Bennée Message-Id: <20210107170717.2098982-5-keithp@keithp.com> Message-Id: <20210108224256.2321-16-alex.bennee@linaro.org> --- hw/semihosting/arm-compat-semi.c | 43 +++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/hw/semihosting/arm-compat-semi.c b/hw/semihosting/arm-compat-semi.c index ac1271545e..293791f721 100644 --- a/hw/semihosting/arm-compat-semi.c +++ b/hw/semihosting/arm-compat-semi.c @@ -137,6 +137,36 @@ typedef struct GuestFD { static GArray *guestfd_array; +#ifndef CONFIG_USER_ONLY +#include "exec/address-spaces.h" +/* + * Find the base of a RAM region containing the specified address + */ +static inline hwaddr +common_semi_find_region_base(hwaddr addr) +{ + MemoryRegion *subregion; + + /* + * Find the chunk of R/W memory containing the address. This is + * used for the SYS_HEAPINFO semihosting call, which should + * probably be using information from the loaded application. + */ + QTAILQ_FOREACH(subregion, &get_system_memory()->subregions, + subregions_link) { + if (subregion->ram && !subregion->readonly) { + Int128 top128 = int128_add(int128_make64(subregion->addr), + subregion->size); + Int128 addr128 = int128_make64(addr); + if (subregion->addr <= addr && int128_lt(addr128, top128)) { + return subregion->addr; + } + } + } + return 0; +} +#endif + #ifdef TARGET_ARM static inline target_ulong common_semi_arg(CPUState *cs, int argno) @@ -175,7 +205,18 @@ common_semi_rambase(CPUState *cs) { CPUArchState *env = cs->env_ptr; const struct arm_boot_info *info = env->boot_info; - return info->loader_start; + target_ulong sp; + + if (info) { + return info->loader_start; + } + + if (is_a64(env)) { + sp = env->xregs[31]; + } else { + sp = env->regs[13]; + } + return common_semi_find_region_base(sp); } #endif