Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge tag 'pull-tcg-20230805' of https://gitlab.com/rth7680/qemu into…
… 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: Adjust task_unmapped_base for reserved_va
linux-user: Use ELF_ET_DYN_BASE for ET_DYN with interpreter
linux-user: Remove host != guest page size workarounds in brk and image load
linux-user: Set V in ELF_HWCAP for RISC-V
*-user: Remove last_brk as unused

# -----BEGIN PGP SIGNATURE-----
#
# iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmTPFQkdHHJpY2hhcmQu
# aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV9B/ggAlYHsJAJdQaGXYTZD
# 8ycXAUAKSovIxLbI0nGDgr9qjFeoMLYB0FYlN3Xur9yY3olOcQYIdL81Cog/RAti
# RooQt1U3VaXIXwSb+fniM9yqu0vP8KrBlH5HgU3dViNa9AYkRXHypmo1j1vRKWL9
# C1GGoY9pehlvLvWweA5BuW1f8cMPX4xG1WJBX1nl3/JMRHCOerUnw0Q6cGqlmFAI
# IV32lkXnbLh9zkSeuizi2F+zZP1MuYOjR7nzqlfU/R4E6bKCdPl/FfCQNkA4VjUM
# SRHWljjKwk3/MbYi4PSs9aS1fKKv+fLdzeAzrMJhGri72CsAHXennaJ3rqk2Bu3U
# you+9g==
# =rI/G
# -----END PGP SIGNATURE-----
# gpg: Signature made Sat 05 Aug 2023 08:35:37 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-20230805' of https://gitlab.com/rth7680/qemu: (24 commits)
  linux-user/elfload: Set V in ELF_HWCAP for RISC-V
  accel/tcg: Call save_iotlb_data from io_readx as well.
  linux-user: Use zero_bss for PT_LOAD with no file contents too
  linux-user: Do not adjust zero_bss for host page size
  linux-user: Do not adjust image mapping for host page size
  linux-user: Properly set image_info.brk in flatload
  linux-user: Adjust initial brk when interpreter is close to executable
  linux-user: Use elf_et_dyn_base for ET_DYN with interpreter
  linux-user: Use MAP_FIXED_NOREPLACE for initial image mmap
  linux-user: Define ELF_ET_DYN_BASE in $guest/target_mman.h
  linux-user: Define TASK_UNMAPPED_BASE in $guest/target_mman.h
  linux-user: Adjust task_unmapped_base for reserved_va
  bsd-user: Remove last_brk
  linux-user: Remove last_brk
  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
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed Aug 6, 2023
2 parents 6db03cc + 8432466 commit d7fd7f9
Show file tree
Hide file tree
Showing 31 changed files with 624 additions and 296 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
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
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
2 changes: 1 addition & 1 deletion gdbstub/gdbstub.c
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
13 changes: 13 additions & 0 deletions linux-user/aarch64/target_mman.h
Expand Up @@ -4,6 +4,19 @@
#define TARGET_PROT_BTI 0x10
#define TARGET_PROT_MTE 0x20

/*
* arch/arm64/include/asm/processor.h:
*
* TASK_UNMAPPED_BASE DEFAULT_MAP_WINDOW / 4
* DEFAULT_MAP_WINDOW DEFAULT_MAP_WINDOW_64
* DEFAULT_MAP_WINDOW_64 UL(1) << VA_BITS_MIN
* VA_BITS_MIN 48 (unless explicitly configured smaller)
*/
#define TASK_UNMAPPED_BASE (1ull << (48 - 2))

/* arch/arm64/include/asm/elf.h */
#define ELF_ET_DYN_BASE TARGET_PAGE_ALIGN((1ull << 48) / 3 * 2)

#include "../generic/target_mman.h"

#endif
11 changes: 11 additions & 0 deletions linux-user/alpha/target_mman.h
Expand Up @@ -20,6 +20,17 @@
#define TARGET_MS_SYNC 2
#define TARGET_MS_INVALIDATE 4

/*
* arch/alpha/include/asm/processor.h:
*
* TASK_UNMAPPED_BASE TASK_SIZE / 2
* TASK_SIZE 0x40000000000UL
*/
#define TASK_UNMAPPED_BASE 0x20000000000ull

/* arch/alpha/include/asm/elf.h */
#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)

#include "../generic/target_mman.h"

#endif
11 changes: 11 additions & 0 deletions linux-user/arm/target_mman.h
@@ -1 +1,12 @@
/*
* arch/arm/include/asm/memory.h
* TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M)
* TASK_SIZE CONFIG_PAGE_OFFSET
* CONFIG_PAGE_OFFSET 0xC0000000 (default in Kconfig)
*/
#define TASK_UNMAPPED_BASE 0x40000000

/* arch/arm/include/asm/elf.h */
#define ELF_ET_DYN_BASE 0x00400000

#include "../generic/target_mman.h"
12 changes: 12 additions & 0 deletions linux-user/cris/target_mman.h
@@ -1 +1,13 @@
/*
* arch/cris/include/asm/processor.h:
* TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
*
* arch/cris/include/arch-v32/arch/processor.h
* TASK_SIZE 0xb0000000
*/
#define TASK_UNMAPPED_BASE TARGET_PAGE_ALIGN(0xb0000000 / 3)

/* arch/cris/include/uapi/asm/elf.h */
#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE * 2)

#include "../generic/target_mman.h"
190 changes: 83 additions & 107 deletions linux-user/elfload.c
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 @@ -1959,15 +1960,6 @@ struct exec
#define ZMAGIC 0413
#define QMAGIC 0314

/* Necessary parameters */
#define TARGET_ELF_EXEC_PAGESIZE \
(((eppnt->p_align & ~qemu_host_page_mask) != 0) ? \
TARGET_PAGE_SIZE : MAX(qemu_host_page_size, TARGET_PAGE_SIZE))
#define TARGET_ELF_PAGELENGTH(_v) ROUND_UP((_v), TARGET_ELF_EXEC_PAGESIZE)
#define TARGET_ELF_PAGESTART(_v) ((_v) & \
~(abi_ulong)(TARGET_ELF_EXEC_PAGESIZE-1))
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))

#define DLINFO_ITEMS 16

static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
Expand Down Expand Up @@ -2221,44 +2213,36 @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,

/* Map and zero the bss. We need to explicitly zero any fractional pages
after the data section (i.e. bss). */
static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
static void zero_bss(abi_ulong start_bss, abi_ulong end_bss, int prot)
{
uintptr_t host_start, host_map_start, host_end;

last_bss = TARGET_PAGE_ALIGN(last_bss);

/* ??? There is confusion between qemu_real_host_page_size and
qemu_host_page_size here and elsewhere in target_mmap, which
may lead to the end of the data section mapping from the file
not being mapped. At least there was an explicit test and
comment for that here, suggesting that "the file size must
be known". The comment probably pre-dates the introduction
of the fstat system call in target_mmap which does in fact
find out the size. What isn't clear is if the workaround
here is still actually needed. For now, continue with it,
but merge it with the "normal" mmap that would allocate the bss. */

host_start = (uintptr_t) g2h_untagged(elf_bss);
host_end = (uintptr_t) g2h_untagged(last_bss);
host_map_start = REAL_HOST_PAGE_ALIGN(host_start);

if (host_map_start < host_end) {
void *p = mmap((void *)host_map_start, host_end - host_map_start,
prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (p == MAP_FAILED) {
perror("cannot mmap brk");
exit(-1);
}
}
abi_ulong align_bss;

align_bss = TARGET_PAGE_ALIGN(start_bss);
end_bss = TARGET_PAGE_ALIGN(end_bss);

/* Ensure that the bss page(s) are valid */
if ((page_get_flags(last_bss-1) & prot) != prot) {
page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss - 1,
prot | PAGE_VALID);
if (start_bss < align_bss) {
int flags = page_get_flags(start_bss);

if (!(flags & PAGE_VALID)) {
/* Map the start of the bss. */
align_bss -= TARGET_PAGE_SIZE;
} else if (flags & PAGE_WRITE) {
/* The page is already mapped writable. */
memset(g2h_untagged(start_bss), 0, align_bss - start_bss);
} else {
/* Read-only zeros? */
g_assert_not_reached();
}
}

if (host_start < host_map_start) {
memset((void *)host_start, 0, host_map_start - host_start);
if (align_bss < end_bss) {
abi_long err = target_mmap(align_bss, end_bss - align_bss, prot,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if (err == -1) {
perror("cannot mmap brk");
exit(-1);
}
}
}

Expand Down Expand Up @@ -3106,60 +3090,65 @@ static void load_elf_image(const char *image_name, int image_fd,
}
}

if (pinterp_name != NULL) {
/*
* This is the main executable.
*
* Reserve extra space for brk.
* We hold on to this space while placing the interpreter
* and the stack, lest they be placed immediately after
* the data segment and block allocation from the brk.
*
* 16MB is chosen as "large enough" without being so large as
* to allow the result to not fit with a 32-bit guest on a
* 32-bit host. However some 64 bit guests (e.g. s390x)
* attempt to place their heap further ahead and currently
* nothing stops them smashing into QEMUs address space.
*/
#if TARGET_LONG_BITS == 64
info->reserve_brk = 32 * MiB;
#else
info->reserve_brk = 16 * MiB;
#endif
hiaddr += info->reserve_brk;
load_addr = loaddr;

if (pinterp_name != NULL) {
if (ehdr->e_type == ET_EXEC) {
/*
* Make sure that the low address does not conflict with
* MMAP_MIN_ADDR or the QEMU application itself.
*/
probe_guest_base(image_name, loaddr, hiaddr);
} else {
abi_ulong align;

/*
* The binary is dynamic, but we still need to
* select guest_base. In this case we pass a size.
*/
probe_guest_base(image_name, 0, hiaddr - loaddr);

/*
* Avoid collision with the loader by providing a different
* default load address.
*/
load_addr += elf_et_dyn_base;

/*
* TODO: Better support for mmap alignment is desirable.
* Since we do not have complete control over the guest
* address space, we prefer the kernel to choose some address
* rather than force the use of LOAD_ADDR via MAP_FIXED.
* But without MAP_FIXED we cannot guarantee alignment,
* only suggest it.
*/
align = pow2ceil(info->alignment);
if (align) {
load_addr &= -align;
}
}
}

/*
* Reserve address space for all of this.
*
* In the case of ET_EXEC, we supply MAP_FIXED so that we get
* exactly the address range that is required.
* In the case of ET_EXEC, we supply MAP_FIXED_NOREPLACE so that we get
* exactly the address range that is required. Without reserved_va,
* the guest address space is not isolated. We have attempted to avoid
* conflict with the host program itself via probe_guest_base, but using
* MAP_FIXED_NOREPLACE instead of MAP_FIXED provides an extra check.
*
* Otherwise this is ET_DYN, and we are searching for a location
* that can hold the memory space required. If the image is
* pre-linked, LOADDR will be non-zero, and the kernel should
* pre-linked, LOAD_ADDR will be non-zero, and the kernel should
* honor that address if it happens to be free.
*
* In both cases, we will overwrite pages in this range with mappings
* from the executable.
*/
load_addr = target_mmap(loaddr, (size_t)hiaddr - loaddr + 1, PROT_NONE,
load_addr = target_mmap(load_addr, (size_t)hiaddr - loaddr + 1, PROT_NONE,
MAP_PRIVATE | MAP_ANON | MAP_NORESERVE |
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
(ehdr->e_type == ET_EXEC ? MAP_FIXED_NOREPLACE : 0),
-1, 0);
if (load_addr == -1) {
goto exit_mmap;
Expand Down Expand Up @@ -3194,7 +3183,8 @@ static void load_elf_image(const char *image_name, int image_fd,
info->end_code = 0;
info->start_data = -1;
info->end_data = 0;
info->brk = 0;
/* Usual start for brk is after all sections of the main executable. */
info->brk = TARGET_PAGE_ALIGN(hiaddr);
info->elf_flags = ehdr->e_flags;

prot_exec = PROT_EXEC;
Expand All @@ -3220,7 +3210,7 @@ static void load_elf_image(const char *image_name, int image_fd,
for (i = 0; i < ehdr->e_phnum; i++) {
struct elf_phdr *eppnt = phdr + i;
if (eppnt->p_type == PT_LOAD) {
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
int elf_prot = 0;

if (eppnt->p_flags & PF_R) {
Expand All @@ -3234,8 +3224,8 @@ static void load_elf_image(const char *image_name, int image_fd,
}

vaddr = load_bias + eppnt->p_vaddr;
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
vaddr_po = vaddr & ~TARGET_PAGE_MASK;
vaddr_ps = vaddr & TARGET_PAGE_MASK;

vaddr_ef = vaddr + eppnt->p_filesz;
vaddr_em = vaddr + eppnt->p_memsz;
Expand All @@ -3245,30 +3235,17 @@ static void load_elf_image(const char *image_name, int image_fd,
* but no backing file segment.
*/
if (eppnt->p_filesz != 0) {
vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_filesz + vaddr_po);
error = target_mmap(vaddr_ps, vaddr_len, elf_prot,
MAP_PRIVATE | MAP_FIXED,
error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
elf_prot, MAP_PRIVATE | MAP_FIXED,
image_fd, eppnt->p_offset - vaddr_po);

if (error == -1) {
goto exit_mmap;
}
}

/*
* If the load segment requests extra zeros (e.g. bss), map it.
*/
if (eppnt->p_filesz < eppnt->p_memsz) {
zero_bss(vaddr_ef, vaddr_em, elf_prot);
}
} else if (eppnt->p_memsz != 0) {
vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_memsz + vaddr_po);
error = target_mmap(vaddr_ps, vaddr_len, elf_prot,
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
-1, 0);

if (error == -1) {
goto exit_mmap;
}
/* If the load segment requests extra zeros (e.g. bss), map it. */
if (vaddr_ef < vaddr_em) {
zero_bss(vaddr_ef, vaddr_em, elf_prot);
}

/* Find the full program boundaries. */
Expand All @@ -3288,9 +3265,6 @@ static void load_elf_image(const char *image_name, int image_fd,
info->end_data = vaddr_ef;
}
}
if (vaddr_em > info->brk) {
info->brk = vaddr_em;
}
#ifdef TARGET_MIPS
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
Mips_elf_abiflags_v0 abiflags;
Expand Down Expand Up @@ -3619,6 +3593,19 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
if (elf_interpreter) {
load_elf_interp(elf_interpreter, &interp_info, bprm->buf);

/*
* While unusual because of ELF_ET_DYN_BASE, if we are unlucky
* with the mappings the interpreter can be loaded above but
* near the main executable, which can leave very little room
* for the heap.
* If the current brk has less than 16MB, use the end of the
* interpreter.
*/
if (interp_info.brk > info->brk &&
interp_info.load_bias - info->brk < 16 * MiB) {
info->brk = interp_info.brk;
}

/* If the program interpreter is one of these two, then assume
an iBCS2 image. Otherwise assume a native linux image. */

Expand Down Expand Up @@ -3672,17 +3659,6 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
bprm->core_dump = &elf_core_dump;
#endif

/*
* If we reserved extra space for brk, release it now.
* The implementation of do_brk in syscalls.c expects to be able
* 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);
target_munmap(start_brk, end_brk - start_brk);
}

return 0;
}

Expand Down

0 comments on commit d7fd7f9

Please sign in to comment.