semihosting: Support SYS_HEAPINFO when env->boot_info is not set

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 <keithp@keithp.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20210107170717.2098982-5-keithp@keithp.com>
Message-Id: <20210108224256.2321-16-alex.bennee@linaro.org>
This commit is contained in:
Keith Packard 2021-01-08 22:42:51 +00:00 committed by Alex Bennée
parent 3c37cfe0b1
commit 095f8c0293

View File

@ -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