Skip to content

Commit

Permalink
Merge tag 'pull-tcg-20230806' of https://gitlab.com/rth7680/qemu into…
Browse files Browse the repository at this point in the history
… staging

accel/tcg: Do not issue misaligned i/o
accel/tcg: Call save_iotlb_data from io_readx
gdbstub: use 0 ("any process") on packets with no PID
linux-user: Fixes for MAP_FIXED_NOREPLACE
linux-user: Fixes for brk
linux-user: Set V in ELF_HWCAP for RISC-V
*-user: Remove last_brk as unused

# -----BEGIN PGP SIGNATURE-----
#
# iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmTP/ygdHHJpY2hhcmQu
# aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV+YIAf+OGaSuBJgVIT12VIX
# ZRVOAUMNnHBPYFiOgv8m7oS3ZgbCXMga0rLyumLaXnI4/bp8ifbLCE7rcZOMUb2G
# aRRllcppYku0Qp19kiPJoYl5iWCaNq7S5kO/8ysh4sC7+/t98YLYBDtZBKcR21mv
# bYtJ7qrhmlXPpv2LEOTPbWh0NKO+zkwZArnqrBUWM+tCxOcjHzXx6MVpp8PaZTal
# iXU5L20YcjqdRxpDHPT+rshf8yFPbQpmuNpj1JdRQ/LxXWgsY/jNVeJXbLbQ+zvx
# nFE94GWeKg/KhqzoXiqmmFgmDsQUzeoUM8OTubJlvBNIrabDZp2RGMgABLAciGKM
# 5Uj7xQ==
# =+mjA
# -----END PGP SIGNATURE-----
# gpg: Signature made Sun 06 Aug 2023 01:14:32 PM PDT
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate]

* tag 'pull-tcg-20230806' of https://gitlab.com/rth7680/qemu:
  bsd-user: Remove last_brk
  linux-user: Remove last_brk
  linux-user: Properly set image_info.brk in flatload
  linux-user: Do not align brk with host page size
  linux-user: Do nothing if too small brk is specified
  linux-user: Use MAP_FIXED_NOREPLACE for do_brk()
  linux-user: Do not call get_errno() in do_brk()
  linux-user: Fix MAP_FIXED_NOREPLACE on old kernels
  linux-user: Unset MAP_FIXED_NOREPLACE for host
  linux-user/elfload: Set V in ELF_HWCAP for RISC-V
  configure: Fix linux-user host detection for riscv64
  gdbstub: use 0 ("any process") on packets with no PID
  accel/tcg: Call save_iotlb_data from io_readx as well
  accel/tcg: Do not issue misaligned i/o
  accel/tcg: Issue wider aligned i/o in do_{ld,st}_mmio_*
  accel/tcg: Adjust parameters and locking with do_{ld,st}_mmio_*

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed Aug 6, 2023
2 parents 6db03cc + f0ef272 commit d7ebbfc
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 176 deletions.
289 changes: 192 additions & 97 deletions accel/tcg/cputlb.c

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions bsd-user/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,6 @@ static int mmap_frag(abi_ulong real_start,
#endif
abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;

unsigned long last_brk;

/*
* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk of guest
* address space.
Expand Down
1 change: 0 additions & 1 deletion bsd-user/qemu.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_size, unsigned long flags,
abi_ulong new_addr);
int target_msync(abi_ulong start, abi_ulong len, int flags);
extern unsigned long last_brk;
extern abi_ulong mmap_next_start;
abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
void TSA_NO_TSA mmap_fork_start(void);
Expand Down
9 changes: 8 additions & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,13 @@ else
echo "WARNING: unrecognized host CPU, proceeding with 'uname -m' output '$cpu'"
fi

case "$cpu" in
riscv*)
host_arch=riscv ;;
*)
host_arch="$cpu" ;;
esac

# Normalise host CPU name and set multilib cflags. The canonicalization
# isn't really necessary, because the architectures that we check for
# should not hit the 'uname -m' case, but better safe than sorry.
Expand Down Expand Up @@ -803,7 +810,7 @@ default_target_list=""
mak_wilds=""

if [ "$linux_user" != no ]; then
if [ "$targetos" = linux ] && [ -d "$source_path/linux-user/include/host/$cpu" ]; then
if [ "$targetos" = linux ] && [ -d "$source_path/linux-user/include/host/$host_arch" ]; then
linux_user=yes
elif [ "$linux_user" = yes ]; then
error_exit "linux-user not supported on this architecture"
Expand Down
2 changes: 1 addition & 1 deletion gdbstub/gdbstub.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ static GDBThreadIdKind read_thread_id(const char *buf, const char **end_buf,
/* Skip '.' */
buf++;
} else {
p = 1;
p = 0;
}

ret = qemu_strtoul(buf, &buf, 16, &t);
Expand Down
7 changes: 4 additions & 3 deletions linux-user/elfload.c
Original file line number Diff line number Diff line change
Expand Up @@ -1710,7 +1710,8 @@ static uint32_t get_elf_hwcap(void)
#define MISA_BIT(EXT) (1 << (EXT - 'A'))
RISCVCPU *cpu = RISCV_CPU(thread_cpu);
uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A')
| MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C');
| MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C')
| MISA_BIT('V');

return cpu->env.misa_ext & mask;
#undef MISA_BIT
Expand Down Expand Up @@ -3678,8 +3679,8 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
* to mmap pages in this space.
*/
if (info->reserve_brk) {
abi_ulong start_brk = HOST_PAGE_ALIGN(info->brk);
abi_ulong end_brk = HOST_PAGE_ALIGN(info->brk + info->reserve_brk);
abi_ulong start_brk = TARGET_PAGE_ALIGN(info->brk);
abi_ulong end_brk = TARGET_PAGE_ALIGN(info->brk + info->reserve_brk);
target_munmap(start_brk, end_brk - start_brk);
}

Expand Down
2 changes: 1 addition & 1 deletion linux-user/flatload.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info)
info->end_code = libinfo[0].start_code + libinfo[0].text_len;
info->start_data = libinfo[0].start_data;
info->end_data = libinfo[0].end_data;
info->start_brk = libinfo[0].start_brk;
info->brk = libinfo[0].start_brk;
info->start_stack = sp;
info->stack_limit = libinfo[0].start_brk;
info->entry = start_addr;
Expand Down
2 changes: 0 additions & 2 deletions linux-user/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -920,8 +920,6 @@ int main(int argc, char **argv, char **envp)
fprintf(f, "page layout changed following binary load\n");
page_dump(f);

fprintf(f, "start_brk 0x" TARGET_ABI_FMT_lx "\n",
info->start_brk);
fprintf(f, "end_code 0x" TARGET_ABI_FMT_lx "\n",
info->end_code);
fprintf(f, "start_code 0x" TARGET_ABI_FMT_lx "\n",
Expand Down
49 changes: 37 additions & 12 deletions linux-user/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,11 @@ static bool mmap_frag(abi_ulong real_start, abi_ulong start, abi_ulong last,
void *p = mmap(host_start, qemu_host_page_size,
target_to_host_prot(prot),
flags | MAP_ANONYMOUS, -1, 0);
if (p == MAP_FAILED) {
if (p != host_start) {
if (p != MAP_FAILED) {
munmap(p, qemu_host_page_size);
errno = EEXIST;
}
return false;
}
prot_old = prot;
Expand Down Expand Up @@ -310,8 +314,6 @@ static bool mmap_frag(abi_ulong real_start, abi_ulong start, abi_ulong last,
#endif
abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;

unsigned long last_brk;

/*
* Subroutine of mmap_find_vma, used when we have pre-allocated
* a chunk of guest address space.
Expand Down Expand Up @@ -603,11 +605,26 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
goto fail;
}

/* Validate that the chosen range is empty. */
if ((flags & MAP_FIXED_NOREPLACE)
&& !page_check_range_empty(start, last)) {
errno = EEXIST;
goto fail;
if (flags & MAP_FIXED_NOREPLACE) {
/* Validate that the chosen range is empty. */
if (!page_check_range_empty(start, last)) {
errno = EEXIST;
goto fail;
}

/*
* With reserved_va, the entire address space is mmaped in the
* host to ensure it isn't accidentally used for something else.
* We have just checked that the guest address is not mapped
* within the guest, but need to replace the host reservation.
*
* Without reserved_va, despite the guest address check above,
* keep MAP_FIXED_NOREPLACE so that the guest does not overwrite
* any host address mappings.
*/
if (reserved_va) {
flags = (flags & ~MAP_FIXED_NOREPLACE) | MAP_FIXED;
}
}

/*
Expand Down Expand Up @@ -672,17 +689,25 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,

/* map the middle (easier) */
if (real_start < real_last) {
void *p;
void *p, *want_p;
off_t offset1;
size_t len1;

if (flags & MAP_ANONYMOUS) {
offset1 = 0;
} else {
offset1 = offset + real_start - start;
}
p = mmap(g2h_untagged(real_start), real_last - real_start + 1,
target_to_host_prot(target_prot), flags, fd, offset1);
if (p == MAP_FAILED) {
len1 = real_last - real_start + 1;
want_p = g2h_untagged(real_start);

p = mmap(want_p, len1, target_to_host_prot(target_prot),
flags, fd, offset1);
if (p != want_p) {
if (p != MAP_FAILED) {
munmap(p, len1);
errno = EEXIST;
}
goto fail;
}
passthrough_start = real_start;
Expand Down
1 change: 0 additions & 1 deletion linux-user/qemu.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ struct image_info {
abi_ulong end_code;
abi_ulong start_data;
abi_ulong end_data;
abi_ulong start_brk;
abi_ulong brk;
abi_ulong reserve_brk;
abi_ulong start_mmap;
Expand Down
67 changes: 13 additions & 54 deletions linux-user/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -802,93 +802,52 @@ static inline int host_to_target_sock_type(int host_type)
}

static abi_ulong target_brk, initial_target_brk;
static abi_ulong brk_page;

void target_set_brk(abi_ulong new_brk)
{
target_brk = TARGET_PAGE_ALIGN(new_brk);
initial_target_brk = target_brk;
brk_page = HOST_PAGE_ALIGN(target_brk);
}

/* do_brk() must return target values and target errnos. */
abi_long do_brk(abi_ulong brk_val)
{
abi_long mapped_addr;
abi_ulong new_alloc_size;
abi_ulong new_brk, new_host_brk_page;
abi_ulong new_brk;
abi_ulong old_brk;

/* brk pointers are always untagged */

/* return old brk value if brk_val unchanged or zero */
if (!brk_val || brk_val == target_brk) {
return target_brk;
}

/* do not allow to shrink below initial brk value */
if (brk_val < initial_target_brk) {
brk_val = initial_target_brk;
return target_brk;
}

new_brk = TARGET_PAGE_ALIGN(brk_val);
new_host_brk_page = HOST_PAGE_ALIGN(brk_val);
old_brk = TARGET_PAGE_ALIGN(target_brk);

/* brk_val and old target_brk might be on the same page */
if (new_brk == TARGET_PAGE_ALIGN(target_brk)) {
/* empty remaining bytes in (possibly larger) host page */
memset(g2h_untagged(new_brk), 0, new_host_brk_page - new_brk);
/* new and old target_brk might be on the same page */
if (new_brk == old_brk) {
target_brk = brk_val;
return target_brk;
}

/* Release heap if necesary */
if (new_brk < target_brk) {
/* empty remaining bytes in (possibly larger) host page */
memset(g2h_untagged(new_brk), 0, new_host_brk_page - new_brk);

/* free unused host pages and set new brk_page */
target_munmap(new_host_brk_page, brk_page - new_host_brk_page);
brk_page = new_host_brk_page;
if (new_brk < old_brk) {
target_munmap(new_brk, old_brk - new_brk);

target_brk = brk_val;
return target_brk;
}

/* We need to allocate more memory after the brk... Note that
* we don't use MAP_FIXED because that will map over the top of
* any existing mapping (like the one with the host libc or qemu
* itself); instead we treat "mapped but at wrong address" as
* a failure and unmap again.
*/
if (new_host_brk_page > brk_page) {
new_alloc_size = new_host_brk_page - brk_page;
mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, 0, 0));
} else {
new_alloc_size = 0;
mapped_addr = brk_page;
}

if (mapped_addr == brk_page) {
/* Heap contents are initialized to zero, as for anonymous
* mapped pages. Technically the new pages are already
* initialized to zero since they *are* anonymous mapped
* pages, however we have to take care with the contents that
* come from the remaining part of the previous page: it may
* contains garbage data due to a previous heap usage (grown
* then shrunken). */
memset(g2h_untagged(brk_page), 0, HOST_PAGE_ALIGN(brk_page) - brk_page);
mapped_addr = target_mmap(old_brk, new_brk - old_brk,
PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_ANON | MAP_PRIVATE,
-1, 0);

if (mapped_addr == old_brk) {
target_brk = brk_val;
brk_page = new_host_brk_page;
return target_brk;
} else if (mapped_addr != -1) {
/* Mapped but at wrong address, meaning there wasn't actually
* enough space for this brk.
*/
target_munmap(mapped_addr, new_alloc_size);
mapped_addr = -1;
}

#if defined(TARGET_ALPHA)
Expand Down
1 change: 0 additions & 1 deletion linux-user/user-mmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_size, unsigned long flags,
abi_ulong new_addr);
abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice);
extern unsigned long last_brk;
extern abi_ulong mmap_next_start;
abi_ulong mmap_find_vma(abi_ulong, abi_ulong, abi_ulong);
void mmap_fork_start(void);
Expand Down

0 comments on commit d7ebbfc

Please sign in to comment.