qemu/semihosting/uaccess.c
Philippe Mathieu-Daudé d2f28a0ce8 semihosting/uaccess: Include missing 'exec/cpu-all.h' header
TLB_INVALID_MASK is defined in "exec/cpu-all.h".
Include it in order to avoid when refactoring:

  ../semihosting/uaccess.c:41:21: error: use of undeclared identifier 'TLB_INVALID_MASK'
     41 |         if (flags & TLB_INVALID_MASK) {
        |                     ^

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20250103171037.11265-3-philmd@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20250116160306.1709518-5-alex.bennee@linaro.org>
2025-01-17 10:43:54 +00:00

92 lines
2.4 KiB
C

/*
* Helper routines to provide target memory access for semihosting
* syscalls in system emulation mode.
*
* Copyright (c) 2007 CodeSourcery.
*
* This code is licensed under the GPL
*/
#include "qemu/osdep.h"
#include "exec/cpu-all.h"
#include "exec/exec-all.h"
#include "semihosting/uaccess.h"
void *uaccess_lock_user(CPUArchState *env, target_ulong addr,
target_ulong len, bool copy)
{
void *p = malloc(len);
if (p && copy) {
if (cpu_memory_rw_debug(env_cpu(env), addr, p, len, 0)) {
free(p);
p = NULL;
}
}
return p;
}
ssize_t uaccess_strlen_user(CPUArchState *env, target_ulong addr)
{
int mmu_idx = cpu_mmu_index(env_cpu(env), false);
size_t len = 0;
while (1) {
size_t left_in_page;
int flags;
void *h;
/* Find the number of bytes remaining in the page. */
left_in_page = TARGET_PAGE_SIZE - (addr & ~TARGET_PAGE_MASK);
flags = probe_access_flags(env, addr, 0, MMU_DATA_LOAD,
mmu_idx, true, &h, 0);
if (flags & TLB_INVALID_MASK) {
return -1;
}
if (flags & TLB_MMIO) {
do {
uint8_t c;
if (cpu_memory_rw_debug(env_cpu(env), addr, &c, 1, 0)) {
return -1;
}
if (c == 0) {
return len;
}
addr++;
len++;
if (len > INT32_MAX) {
return -1;
}
} while (--left_in_page != 0);
} else {
char *p = memchr(h, 0, left_in_page);
if (p) {
len += p - (char *)h;
return len <= INT32_MAX ? (ssize_t)len : -1;
}
addr += left_in_page;
len += left_in_page;
if (len > INT32_MAX) {
return -1;
}
}
}
}
char *uaccess_lock_user_string(CPUArchState *env, target_ulong addr)
{
ssize_t len = uaccess_strlen_user(env, addr);
if (len < 0) {
return NULL;
}
return uaccess_lock_user(env, addr, len + 1, true);
}
void uaccess_unlock_user(CPUArchState *env, void *p,
target_ulong addr, target_ulong len)
{
if (len) {
cpu_memory_rw_debug(env_cpu(env), addr, p, len, 1);
}
free(p);
}