qemu/semihosting/uaccess.c
Philippe Mathieu-Daudé f14eced5ac semihosting: Rename softmmu_FOO_user() -> uaccess_FOO_user()
Add a check in 'softmmu-uaccess.h' that the header is only
include in system emulation, and rename it as 'uaccess.h'.

Rename the API methods:

  - softmmu_[un]lock_user*() -> uaccess_[un]lock_user*()
  - softmmu_strlen_user() -> uaccess_strlen_user().

Update a pair of comments.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20231004090629.37473-9-philmd@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2023-10-07 19:02:59 +02:00

92 lines
2.3 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/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, 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);
}