From 02324a475c7df4223d63d631d0cead61f0efeb03 Mon Sep 17 00:00:00 2001 From: "Emilio G. Cota" Date: Fri, 5 Jun 2020 16:49:16 +0100 Subject: [PATCH 01/17] qemu-plugin.h: add missing include to define size_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Emilio G. Cota Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Alex Bennée Message-Id: <20200524202427.951784-1-cota@braap.org> Message-Id: <20200605154929.26910-2-alex.bennee@linaro.org> --- include/qemu/qemu-plugin.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index 89ed579f55..bab8b0d4b3 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -12,6 +12,7 @@ #include #include +#include /* * For best performance, build the plugin with -fvisibility=hidden so that From a6703e65ecfe3a57f122abdf1f8353fb60927a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 5 Jun 2020 16:49:17 +0100 Subject: [PATCH 02/17] scripts/clean-includes: Mark 'qemu/qemu-plugin.h' as special header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "qemu/qemu-plugin.h" isn't meant to be include by QEMU codebase, but by 3rd party plugins that QEMU can use. These plugins can be built out of QEMU and don't include "qemu/osdep.h". Mark "qemu/qemu-plugin.h" as a special header that doesn't need to be cleaned for "qemu/osdep.h". Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Emilio G. Cota Signed-off-by: Alex Bennée Message-Id: <20200524215654.13256-1-f4bug@amsat.org> Message-Id: <20200605154929.26910-3-alex.bennee@linaro.org> --- scripts/clean-includes | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/clean-includes b/scripts/clean-includes index dd938daa3e..795b3bea31 100755 --- a/scripts/clean-includes +++ b/scripts/clean-includes @@ -123,6 +123,7 @@ for f in "$@"; do ;; *include/qemu/osdep.h | \ *include/qemu/compiler.h | \ + *include/qemu/qemu-plugin.h | \ *include/glib-compat.h | \ *include/sysemu/os-posix.h | \ *include/sysemu/os-win32.h | \ From 4e62bfa9ee54d071c656d12057b7d293ca22d423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 5 Jun 2020 16:49:18 +0100 Subject: [PATCH 03/17] tests/plugin: correctly honour io_count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200605154929.26910-4-alex.bennee@linaro.org> --- tests/plugin/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/plugin/mem.c b/tests/plugin/mem.c index 878abf09d1..4725bd851d 100644 --- a/tests/plugin/mem.c +++ b/tests/plugin/mem.c @@ -28,7 +28,7 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) g_string_printf(out, "mem accesses: %" PRIu64 "\n", mem_count); if (do_haddr) { - g_string_append_printf(out, "io accesses: %" PRIu64 "\n", mem_count); + g_string_append_printf(out, "io accesses: %" PRIu64 "\n", io_count); } qemu_plugin_outs(out->str); } From 2e886a242cf540d716d431a55071a717d562eb69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 5 Jun 2020 16:49:19 +0100 Subject: [PATCH 04/17] exec: flush the whole TLB if a watchpoint crosses a page boundary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no particular reason why you can't have a watchpoint in TCG that covers a large chunk of the address space. We could be clever about it but these cases are pretty rare and we can assume the user will expect a little performance degradation. NB: In my testing gdb will silently squash a watchpoint like: watch (char[0x7fffffffff]) *0x0 to a 4 byte watchpoint. Practically it will limit the maximum size based on max-value-size. However given enough of a tweak the sky is the limit. Reported-by: Alexander Bulekov Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Message-Id: <20200605154929.26910-5-alex.bennee@linaro.org> --- exec.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index be4be2df3a..a0bf9d61c8 100644 --- a/exec.c +++ b/exec.c @@ -1038,6 +1038,7 @@ int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, int flags, CPUWatchpoint **watchpoint) { CPUWatchpoint *wp; + vaddr in_page; /* forbid ranges which are empty or run off the end of the address space */ if (len == 0 || (addr + len - 1) < addr) { @@ -1058,7 +1059,12 @@ int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry); } - tlb_flush_page(cpu, addr); + in_page = -(addr | TARGET_PAGE_MASK); + if (len <= in_page) { + tlb_flush_page(cpu, addr); + } else { + tlb_flush(cpu); + } if (watchpoint) *watchpoint = wp; From 1de8e4c4dcf2af8e1c7d95f1d3c42d0c35b96295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 5 Jun 2020 16:49:20 +0100 Subject: [PATCH 05/17] .travis.yml: allow failure for unreliable hosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They will still run but they won't get in the way of the result. Signed-off-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20200605154929.26910-6-alex.bennee@linaro.org> --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 564be50a3c..ec6367af1f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -429,6 +429,7 @@ jobs: env: - TEST_CMD="make check check-tcg V=1" - CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS}" + - UNRELIABLE=true - name: "[ppc64] GCC check-tcg" arch: ppc64le @@ -493,6 +494,7 @@ jobs: env: - TEST_CMD="make check check-tcg V=1" - CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user" + - UNRELIABLE=true script: - ( cd ${SRC_DIR} ; git submodule update --init roms/SLOF ) - BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$? @@ -535,6 +537,7 @@ jobs: - TEST_CMD="make check-unit" - CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools --host-cc=clang --cxx=clang++" + - UNRELIABLE=true # Release builds # The make-release script expect a QEMU version, so our tag must start with a 'v'. @@ -556,3 +559,5 @@ jobs: - mkdir -p release-build && cd release-build - ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; } - make install + allow_failures: + - env: UNRELIABLE=true From 12d43b5ae916809aad9ccf8aa2a0a06260527340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 5 Jun 2020 16:49:21 +0100 Subject: [PATCH 06/17] .shippable: temporaily disable some cross builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These currently fail due to Debian bug #960271 as the linux-libc-library has a user-space build breaking symbol in it. Signed-off-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20200605154929.26910-7-alex.bennee@linaro.org> --- .shippable.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.shippable.yml b/.shippable.yml index 2cce7b5689..10cf219bff 100644 --- a/.shippable.yml +++ b/.shippable.yml @@ -5,8 +5,8 @@ env: global: - LC_ALL=C matrix: - - IMAGE=debian-amd64 - TARGET_LIST=x86_64-softmmu,x86_64-linux-user + # - IMAGE=debian-amd64 + # TARGET_LIST=x86_64-softmmu,x86_64-linux-user - IMAGE=debian-win32-cross TARGET_LIST=arm-softmmu,i386-softmmu,lm32-softmmu - IMAGE=debian-win64-cross @@ -19,10 +19,10 @@ env: TARGET_LIST=aarch64-softmmu,aarch64-linux-user - IMAGE=debian-s390x-cross TARGET_LIST=s390x-softmmu,s390x-linux-user - - IMAGE=debian-mips-cross - TARGET_LIST=mips-softmmu,mipsel-linux-user - - IMAGE=debian-mips64el-cross - TARGET_LIST=mips64el-softmmu,mips64el-linux-user + # - IMAGE=debian-mips-cross + # TARGET_LIST=mips-softmmu,mipsel-linux-user + # - IMAGE=debian-mips64el-cross + # TARGET_LIST=mips64el-softmmu,mips64el-linux-user - IMAGE=debian-ppc64el-cross TARGET_LIST=ppc64-softmmu,ppc64-linux-user,ppc64abi32-linux-user build: From e035e6ffed3e3943920c93b19ca1d92444add4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 5 Jun 2020 16:49:23 +0100 Subject: [PATCH 07/17] tests/docker: fix pre-requisite for debian-tricore-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Bastian Koppelmann Signed-off-by: Alex Bennée Message-Id: <20200605154929.26910-9-alex.bennee@linaro.org> --- tests/docker/Makefile.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index ed46bd98eb..981b7fcf2a 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -130,7 +130,7 @@ docker-image-debian-sparc64-cross: docker-image-debian10 docker-image-travis: NOUSER=1 # Specialist build images, sometimes very limited tools -docker-image-tricore-cross: docker-image-debian9 +docker-image-debian-tricore-cross: docker-image-debian9 docker-image-debian-arm64-test-cross: docker-image-debian11 # These images may be good enough for building tests but not for test builds From a97098844b9e4d2d1c3a24f66b8e2c7f97b3a795 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 5 Jun 2020 16:49:24 +0100 Subject: [PATCH 08/17] docker: update Ubuntu to 20.04 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paolo Bonzini Tested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Alex Bennée Message-Id: <20200604231716.11354-1-pbonzini@redhat.com> Message-Id: <20200605154929.26910-10-alex.bennee@linaro.org> --- tests/docker/dockerfiles/ubuntu.docker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker index eeb3b22bf2..43872417de 100644 --- a/tests/docker/dockerfiles/ubuntu.docker +++ b/tests/docker/dockerfiles/ubuntu.docker @@ -9,7 +9,7 @@ # system won't pick up that it has changed. # -FROM ubuntu:19.04 +FROM ubuntu:20.04 ENV PACKAGES flex bison \ ccache \ clang \ From 083b9bd7a1c526d57ec17b23dd6eca414e808886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 5 Jun 2020 16:49:25 +0100 Subject: [PATCH 09/17] hw/virtio/vhost: re-factor vhost-section and allow DIRTY_MEMORY_CODE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The purpose of vhost_section is to identify RAM regions that need to be made available to a vhost client. However when running under TCG all RAM sections have DIRTY_MEMORY_CODE set which leads to problems down the line. Re-factor the code so: - steps are clearer to follow - reason for rejection is recorded in the trace point - we allow DIRTY_MEMORY_CODE We expand the comment to explain that kernel based vhost has specific support for migration tracking. Signed-off-by: Alex Bennée Tested-by: Fabiano Rosas Cc: Michael S. Tsirkin Cc: Dr. David Alan Gilbert Cc: Stefan Hajnoczi Message-Id: <20200605154929.26910-11-alex.bennee@linaro.org> --- hw/virtio/trace-events | 3 ++- hw/virtio/vhost.c | 55 ++++++++++++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index e83500bee9..6427a0047d 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -5,7 +5,8 @@ vhost_commit(bool started, bool changed) "Started: %d Changed: %d" vhost_region_add_section(const char *name, uint64_t gpa, uint64_t size, uint64_t host) "%s: 0x%"PRIx64"+0x%"PRIx64" @ 0x%"PRIx64 vhost_region_add_section_merge(const char *name, uint64_t new_size, uint64_t gpa, uint64_t owr) "%s: size: 0x%"PRIx64 " gpa: 0x%"PRIx64 " owr: 0x%"PRIx64 vhost_region_add_section_aligned(const char *name, uint64_t gpa, uint64_t size, uint64_t host) "%s: 0x%"PRIx64"+0x%"PRIx64" @ 0x%"PRIx64 -vhost_section(const char *name, int r) "%s:%d" +vhost_section(const char *name) "%s" +vhost_reject_section(const char *name, int d) "%s:%d" vhost_iotlb_miss(void *dev, int step) "%p step %d" # vhost-user.c diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index aff98a0ede..e3e2181290 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -27,6 +27,7 @@ #include "migration/blocker.h" #include "migration/qemu-file-types.h" #include "sysemu/dma.h" +#include "sysemu/tcg.h" #include "trace.h" /* enabled until disconnected backend stabilizes */ @@ -403,26 +404,50 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev, return r; } +/* + * vhost_section: identify sections needed for vhost access + * + * We only care about RAM sections here (where virtqueue and guest + * internals accessed by virtio might live). If we find one we still + * allow the backend to potentially filter it out of our list. + */ static bool vhost_section(struct vhost_dev *dev, MemoryRegionSection *section) { - bool result; - bool log_dirty = memory_region_get_dirty_log_mask(section->mr) & - ~(1 << DIRTY_MEMORY_MIGRATION); - result = memory_region_is_ram(section->mr) && - !memory_region_is_rom(section->mr); + MemoryRegion *mr = section->mr; - /* Vhost doesn't handle any block which is doing dirty-tracking other - * than migration; this typically fires on VGA areas. - */ - result &= !log_dirty; + if (memory_region_is_ram(mr) && !memory_region_is_rom(mr)) { + uint8_t dirty_mask = memory_region_get_dirty_log_mask(mr); + uint8_t handled_dirty; - if (result && dev->vhost_ops->vhost_backend_mem_section_filter) { - result &= - dev->vhost_ops->vhost_backend_mem_section_filter(dev, section); + /* + * Kernel based vhost doesn't handle any block which is doing + * dirty-tracking other than migration for which it has + * specific logging support. However for TCG the kernel never + * gets involved anyway so we can also ignore it's + * self-modiying code detection flags. However a vhost-user + * client could still confuse a TCG guest if it re-writes + * executable memory that has already been translated. + */ + handled_dirty = (1 << DIRTY_MEMORY_MIGRATION) | + (1 << DIRTY_MEMORY_CODE); + + if (dirty_mask & ~handled_dirty) { + trace_vhost_reject_section(mr->name, 1); + return false; + } + + if (dev->vhost_ops->vhost_backend_mem_section_filter && + !dev->vhost_ops->vhost_backend_mem_section_filter(dev, section)) { + trace_vhost_reject_section(mr->name, 2); + return false; + } + + trace_vhost_section(mr->name); + return true; + } else { + trace_vhost_reject_section(mr->name, 3); + return false; } - - trace_vhost_section(section->mr->name, result); - return result; } static void vhost_begin(MemoryListener *listener) From ad592e37dfccf730378a44c5fa79acb603a7678d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 5 Jun 2020 16:49:26 +0100 Subject: [PATCH 10/17] linux-user: provide fallback pgd_find_hole for bare chroots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When running QEMU out of a chroot environment we may not have access to /proc/self/maps. As there is no other "official" way to introspect our memory map we need to fall back to the original technique of repeatedly trying to mmap an address range until we find one that works. Fortunately it's not quite as ugly as the original code given we already re-factored the complications of dealing with the ARM_COMMPAGE. We do make an attempt to skip over brk() which is about the only concrete piece of information we have about the address map at this moment. Fixes: ee9474303 Reported-by: Peter Maydell Signed-off-by: Alex Bennée Message-Id: <20200605154929.26910-12-alex.bennee@linaro.org> --- linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index ebc663ea0b..475d243f3b 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2101,6 +2101,50 @@ static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr, } } +/** + * pgd_find_hole_fallback: potential mmap address + * @guest_size: size of available space + * @brk: location of break + * @align: memory alignment + * + * This is a fallback method for finding a hole in the host address + * space if we don't have the benefit of being able to access + * /proc/self/map. It can potentially take a very long time as we can + * only dumbly iterate up the host address space seeing if the + * allocation would work. + */ +static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk, long align) +{ + uintptr_t base; + + /* Start (aligned) at the bottom and work our way up */ + base = ROUND_UP(mmap_min_addr, align); + + while (true) { + uintptr_t align_start, end; + align_start = ROUND_UP(base, align); + end = align_start + guest_size; + + /* if brk is anywhere in the range give ourselves some room to grow. */ + if (align_start <= brk && brk < end) { + base = brk + (16 * MiB); + continue; + } else if (align_start + guest_size < align_start) { + /* we have run out of space */ + return -1; + } else { + int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE | MAP_FIXED; + void * mmap_start = mmap((void *) align_start, guest_size, + PROT_NONE, flags, -1, 0); + if (mmap_start != MAP_FAILED) { + munmap((void *) align_start, guest_size); + return (uintptr_t) mmap_start; + } + base += qemu_host_page_size; + } + } +} + /* Return value for guest_base, or -1 if no hole found. */ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, long align) @@ -2116,6 +2160,10 @@ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, /* Read brk after we've read the maps, which will malloc. */ brk = (uintptr_t)sbrk(0); + if (!maps) { + return pgd_find_hole_fallback(guest_size, brk, align); + } + /* The first hole is before the first map entry. */ this_start = mmap_min_addr; From 5c3e87f345ac93de9260f12c408d2afd87a6ab3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 5 Jun 2020 16:49:27 +0100 Subject: [PATCH 11/17] linux-user: deal with address wrap for ARM_COMMPAGE on 32 bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We rely on the pointer to wrap when accessing the high address of the COMMPAGE so it lands somewhere reasonable. However on 32 bit hosts we cannot afford just to map the entire 4gb address range. The old mmap trial and error code handled this by just checking we could map both the guest_base and the computed COMMPAGE address. We can't just manipulate loadaddr to get what we want so we introduce an offset which pgb_find_hole can apply when looking for a gap for guest_base that ensures there is space left to map the COMMPAGE afterwards. This is arguably a little inefficient for the one 32 bit value (kuser_helper_version) we need to keep there given all the actual code entries are picked up during the translation phase. Fixes: ee94743034b Bug: https://bugs.launchpad.net/qemu/+bug/1880225 Cc: Bug 1880225 <1880225@bugs.launchpad.net> Signed-off-by: Alex Bennée Tested-by: Aleksandar Markovic Cc: Richard Henderson Cc: Peter Maydell Message-Id: <20200605154929.26910-13-alex.bennee@linaro.org> --- linux-user/elfload.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 475d243f3b..b5cb21384a 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -389,7 +389,7 @@ static bool init_guest_commpage(void) { void *want = g2h(ARM_COMMPAGE & -qemu_host_page_size); void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); if (addr == MAP_FAILED) { perror("Allocating guest commpage"); @@ -2113,7 +2113,8 @@ static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr, * only dumbly iterate up the host address space seeing if the * allocation would work. */ -static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk, long align) +static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk, + long align, uintptr_t offset) { uintptr_t base; @@ -2123,7 +2124,7 @@ static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk, lon while (true) { uintptr_t align_start, end; align_start = ROUND_UP(base, align); - end = align_start + guest_size; + end = align_start + guest_size + offset; /* if brk is anywhere in the range give ourselves some room to grow. */ if (align_start <= brk && brk < end) { @@ -2138,7 +2139,7 @@ static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk, lon PROT_NONE, flags, -1, 0); if (mmap_start != MAP_FAILED) { munmap((void *) align_start, guest_size); - return (uintptr_t) mmap_start; + return (uintptr_t) mmap_start + offset; } base += qemu_host_page_size; } @@ -2147,7 +2148,7 @@ static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk, lon /* Return value for guest_base, or -1 if no hole found. */ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, - long align) + long align, uintptr_t offset) { GSList *maps, *iter; uintptr_t this_start, this_end, next_start, brk; @@ -2161,7 +2162,7 @@ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, brk = (uintptr_t)sbrk(0); if (!maps) { - return pgd_find_hole_fallback(guest_size, brk, align); + return pgd_find_hole_fallback(guest_size, brk, align, offset); } /* The first hole is before the first map entry. */ @@ -2173,7 +2174,7 @@ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, this_end = ((MapInfo *)iter->data)->start; next_start = ((MapInfo *)iter->data)->end; - align_start = ROUND_UP(this_start, align); + align_start = ROUND_UP(this_start + offset, align); /* Skip holes that are too small. */ if (align_start >= this_end) { @@ -2223,6 +2224,7 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, { uintptr_t loaddr = orig_loaddr; uintptr_t hiaddr = orig_hiaddr; + uintptr_t offset = 0; uintptr_t addr; if (hiaddr != orig_hiaddr) { @@ -2236,18 +2238,19 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, if (ARM_COMMPAGE) { /* * Extend the allocation to include the commpage. - * For a 64-bit host, this is just 4GiB; for a 32-bit host, - * the address arithmetic will wrap around, but the difference - * will produce the correct allocation size. + * For a 64-bit host, this is just 4GiB; for a 32-bit host we + * need to ensure there is space bellow the guest_base so we + * can map the commpage in the place needed when the address + * arithmetic wraps around. */ if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) { - hiaddr = (uintptr_t)4 << 30; + hiaddr = (uintptr_t) 4 << 30; } else { - loaddr = ARM_COMMPAGE & -align; + offset = -(ARM_COMMPAGE & -align); } } - addr = pgb_find_hole(loaddr, hiaddr - loaddr, align); + addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset); if (addr == -1) { /* * If ARM_COMMPAGE, there *might* be a non-consecutive allocation @@ -2282,7 +2285,7 @@ static void pgb_dynamic(const char *image_name, long align) * just above that, and maximises the positive guest addresses. */ commpage = ARM_COMMPAGE & -align; - addr = pgb_find_hole(commpage, -commpage, align); + addr = pgb_find_hole(commpage, -commpage, align, 0); assert(addr != -1); guest_base = addr; } From b6771210b5bba543628b8eeacfea9f994372f880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 5 Jun 2020 16:49:28 +0100 Subject: [PATCH 12/17] tests/tcg: add simple commpage test case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The COMMPAGE are a number of kernel provided user-space routines for 32 bit ARM systems. Add a basic series of smoke tests to ensure it is working as it should. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Message-Id: <20200605154929.26910-14-alex.bennee@linaro.org> --- tests/tcg/arm/Makefile.target | 2 ++ tests/tcg/arm/commpage.c | 61 +++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 tests/tcg/arm/commpage.c diff --git a/tests/tcg/arm/Makefile.target b/tests/tcg/arm/Makefile.target index 11c39c601e..3da09a38be 100644 --- a/tests/tcg/arm/Makefile.target +++ b/tests/tcg/arm/Makefile.target @@ -68,6 +68,8 @@ run-semiconsole-arm: semiconsole-arm run-plugin-semiconsole-arm-with-%: $(call skip-test, $<, "MANUAL ONLY") +ARM_TESTS += commpage + TESTS += $(ARM_TESTS) # On ARM Linux only supports 4k pages diff --git a/tests/tcg/arm/commpage.c b/tests/tcg/arm/commpage.c new file mode 100644 index 0000000000..c76e70cb8b --- /dev/null +++ b/tests/tcg/arm/commpage.c @@ -0,0 +1,61 @@ +/* + * Verify the COMMPAGE emulation + * + * The ARM commpage is a set of user space helper functions provided + * by the kernel in an effort to ease portability of user space code + * between different CPUs with potentially different capabilities. It + * is a 32 bit invention and similar to the vdso segment in many ways. + * + * The ABI is documented in the Linux kernel: + * Documentation/arm/kernel_userspace_helpers.rst + * + * Copyright (c) 2020 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include +#include + +#define ARM_COMMPAGE (0xffff0f00u) +#define ARM_KUSER_VERSION (*(int32_t *)(ARM_COMMPAGE + 0xfc)) +typedef void * (get_tls_fn)(void); +#define ARM_KUSER_GET_TLS (*(get_tls_fn *)(ARM_COMMPAGE + 0xe0)) +typedef int (cmpxchg_fn)(int oldval, int newval, volatile int *ptr); +#define ARM_KUSER_CMPXCHG (*(cmpxchg_fn *)(ARM_COMMPAGE + 0xc0)) +typedef void (dmb_fn)(void); +#define ARM_KUSER_DMB (*(dmb_fn *)(ARM_COMMPAGE + 0xa0)) +typedef int (cmpxchg64_fn)(const int64_t *oldval, + const int64_t *newval, + volatile int64_t *ptr); +#define ARM_KUSER_CMPXCHG64 (*(cmpxchg64_fn *)(ARM_COMMPAGE + 0x60)) + +#define fail_unless(x) \ + do { \ + if (!(x)) { \ + fprintf(stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \ + exit(EXIT_FAILURE); \ + } \ + } while (0) + + +int main(int argc, char *argv[argc]) +{ + void *kuser_tls; + int val = 1; + const int64_t oldval = 1, newval = 2; + int64_t val64 = 1; + + fail_unless(ARM_KUSER_VERSION == 0x5); + kuser_tls = ARM_KUSER_GET_TLS(); + printf("TLS = %p\n", kuser_tls); + fail_unless(kuser_tls != 0); + fail_unless(ARM_KUSER_CMPXCHG(1, 2, &val) == 0); + printf("val = %d\n", val); + /* this is a crash test, not checking an actual barrier occurs */ + ARM_KUSER_DMB(); + fail_unless(ARM_KUSER_CMPXCHG64(&oldval, &newval, &val64) == 0); + printf("val64 = %lld\n", val64); + return 0; +} From 8ef618859c379fdce81c91bc93e0574e36ea76ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 5 Jun 2020 16:49:29 +0100 Subject: [PATCH 13/17] linux-user: detect overflow of MAP_FIXED mmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Relaxing the restrictions on 64 bit guests leads to the user being able to attempt to map right at the edge of addressable memory. This in turn lead to address overflow tripping the assert in page_set_flags when the end address wrapped around. Detect the wrap earlier and correctly -ENOMEM the guest (in the reported case LTP mmap15). Fixes: 7d8cbbabcb Signed-off-by: Alex Bennée Reported-by: Laurent Vivier Message-Id: <20200605154929.26910-15-alex.bennee@linaro.org> --- linux-user/mmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index caab62909e..0019447892 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -467,7 +467,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, * It can fail only on 64-bit host with 32-bit target. * On any other target/host host mmap() handles this error correctly. */ - if (!guest_range_valid(start, len)) { + if (end < start || !guest_range_valid(start, len)) { errno = ENOMEM; goto fail; } From c6dd82e8a6348096cf7c66a9c1b8a5815aa4ff91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 15 May 2020 18:30:25 +0200 Subject: [PATCH 14/17] tests/docker: Remove flex/bison packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU does not use flex/bison packages. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Claudio Fontana Signed-off-by: Alex Bennée Message-Id: <20200515163029.12917-2-philmd@redhat.com> --- tests/docker/dockerfiles/centos7.docker | 2 -- tests/docker/dockerfiles/centos8.docker | 2 -- tests/docker/dockerfiles/debian-xtensa-cross.docker | 2 -- tests/docker/dockerfiles/debian10.docker | 2 -- tests/docker/dockerfiles/debian9.docker | 2 -- tests/docker/dockerfiles/fedora.docker | 2 -- tests/docker/dockerfiles/ubuntu.docker | 2 +- tests/docker/dockerfiles/ubuntu1804.docker | 2 +- 8 files changed, 2 insertions(+), 14 deletions(-) diff --git a/tests/docker/dockerfiles/centos7.docker b/tests/docker/dockerfiles/centos7.docker index 9a2a2e515d..e197acdc3c 100644 --- a/tests/docker/dockerfiles/centos7.docker +++ b/tests/docker/dockerfiles/centos7.docker @@ -5,13 +5,11 @@ RUN yum -y update # Please keep this list sorted alphabetically ENV PACKAGES \ - bison \ bzip2 \ bzip2-devel \ ccache \ csnappy-devel \ dbus-daemon \ - flex \ gcc-c++ \ gcc \ gettext \ diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker index bfa0d33c9c..9852c5b9ee 100644 --- a/tests/docker/dockerfiles/centos8.docker +++ b/tests/docker/dockerfiles/centos8.docker @@ -3,11 +3,9 @@ FROM centos:8.1.1911 RUN dnf -y update ENV PACKAGES \ SDL-devel \ - bison \ bzip2 \ bzip2-devel \ dbus-daemon \ - flex \ gcc \ gcc-c++ \ gettext \ diff --git a/tests/docker/dockerfiles/debian-xtensa-cross.docker b/tests/docker/dockerfiles/debian-xtensa-cross.docker index e6f93f65ee..beb73f46ba 100644 --- a/tests/docker/dockerfiles/debian-xtensa-cross.docker +++ b/tests/docker/dockerfiles/debian-xtensa-cross.docker @@ -11,11 +11,9 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \ DEBIAN_FRONTEND=noninteractive eatmydata \ apt-get install -y --no-install-recommends \ - bison \ build-essential \ ca-certificates \ curl \ - flex \ gettext \ git \ python3-minimal diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/dockerfiles/debian10.docker index 0769700a41..bcdff04ddf 100644 --- a/tests/docker/dockerfiles/debian10.docker +++ b/tests/docker/dockerfiles/debian10.docker @@ -18,12 +18,10 @@ RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ apt install -y --no-install-recommends \ bc \ - bison \ build-essential \ ca-certificates \ clang \ dbus \ - flex \ gdb-multiarch \ gettext \ git \ diff --git a/tests/docker/dockerfiles/debian9.docker b/tests/docker/dockerfiles/debian9.docker index 08cc970feb..0f0ebe530a 100644 --- a/tests/docker/dockerfiles/debian9.docker +++ b/tests/docker/dockerfiles/debian9.docker @@ -18,11 +18,9 @@ RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ apt install -y --no-install-recommends \ bc \ - bison \ build-essential \ ca-certificates \ clang \ - flex \ gdb-multiarch \ gettext \ git \ diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker index 179575ecaa..92b6e11c8a 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -3,7 +3,6 @@ FROM fedora:30 # Please keep this list sorted alphabetically ENV PACKAGES \ bc \ - bison \ brlapi-devel \ bzip2 \ bzip2-devel \ @@ -13,7 +12,6 @@ ENV PACKAGES \ dbus-daemon \ device-mapper-multipath-devel \ findutils \ - flex \ gcc \ gcc-c++ \ gettext \ diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker index 43872417de..161806e6b8 100644 --- a/tests/docker/dockerfiles/ubuntu.docker +++ b/tests/docker/dockerfiles/ubuntu.docker @@ -10,7 +10,7 @@ # FROM ubuntu:20.04 -ENV PACKAGES flex bison \ +ENV PACKAGES \ ccache \ clang \ dbus \ diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dockerfiles/ubuntu1804.docker index f66b06f4cf..a10ea2850b 100644 --- a/tests/docker/dockerfiles/ubuntu1804.docker +++ b/tests/docker/dockerfiles/ubuntu1804.docker @@ -1,5 +1,5 @@ FROM ubuntu:18.04 -ENV PACKAGES flex bison \ +ENV PACKAGES \ ccache \ clang \ gcc \ From e661e9580cb78b04bc2b843cee8ed23fbef1f311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 15 May 2020 18:30:26 +0200 Subject: [PATCH 15/17] tests/vm: Remove flex/bison packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU does not use flex/bison packages. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Claudio Fontana Signed-off-by: Alex Bennée Message-Id: <20200515163029.12917-3-philmd@redhat.com> --- tests/vm/fedora | 1 - tests/vm/freebsd | 1 - tests/vm/netbsd | 1 - tests/vm/openbsd | 1 - tests/vm/ubuntu.i386 | 2 +- 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/vm/fedora b/tests/vm/fedora index bd9c6cf295..a9195670f4 100755 --- a/tests/vm/fedora +++ b/tests/vm/fedora @@ -32,7 +32,6 @@ class FedoraVM(basevm.BaseVM): pkgs = [ # tools 'git-core', - 'flex', 'bison', 'gcc', 'binutils', 'make', # perl diff --git a/tests/vm/freebsd b/tests/vm/freebsd index 298967fe9c..f87db2b126 100755 --- a/tests/vm/freebsd +++ b/tests/vm/freebsd @@ -38,7 +38,6 @@ class FreeBSDVM(basevm.BaseVM): "bash", "gmake", "gsed", - "flex", "bison", # libs: crypto "gnutls", diff --git a/tests/vm/netbsd b/tests/vm/netbsd index b10c9d429d..cdac502dad 100755 --- a/tests/vm/netbsd +++ b/tests/vm/netbsd @@ -36,7 +36,6 @@ class NetBSDVM(basevm.BaseVM): "bash", "gmake", "gsed", - "flex", "bison", # libs: crypto "gnutls", diff --git a/tests/vm/openbsd b/tests/vm/openbsd index 0b705f4945..13e7f9a6d5 100755 --- a/tests/vm/openbsd +++ b/tests/vm/openbsd @@ -35,7 +35,6 @@ class OpenBSDVM(basevm.BaseVM): "bash", "gmake", "gsed", - "bison", # libs: usb "libusb1", diff --git a/tests/vm/ubuntu.i386 b/tests/vm/ubuntu.i386 index 1570775335..24527cc78c 100755 --- a/tests/vm/ubuntu.i386 +++ b/tests/vm/ubuntu.i386 @@ -52,7 +52,7 @@ class UbuntuX86VM(basevm.BaseVM): self.ssh_root_check("sed -ie s/^#\ deb-src/deb-src/g /etc/apt/sources.list") self.ssh_root_check("apt-get update") self.ssh_root_check("apt-get build-dep -y qemu") - self.ssh_root_check("apt-get install -y libfdt-dev flex bison language-pack-en") + self.ssh_root_check("apt-get install -y libfdt-dev language-pack-en") self.ssh_root("poweroff") self.wait() os.rename(img_tmp, img) From 48ba32e62210fde35c1d0dc6164233bcc8bb331d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 15 May 2020 18:30:28 +0200 Subject: [PATCH 16/17] cirrus-ci: Remove flex/bison packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU does not use flex/bison packages. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Li-Wen Hsu Signed-off-by: Alex Bennée Message-Id: <20200515163029.12917-5-philmd@redhat.com> --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index de0727cb09..ce7850a320 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -7,7 +7,7 @@ freebsd_12_task: cpu: 8 memory: 8G install_script: ASSUME_ALWAYS_YES=yes pkg bootstrap -f ; pkg install -y - bash bison curl cyrus-sasl git glib gmake gnutls gsed + bash curl cyrus-sasl git glib gmake gnutls gsed nettle perl5 pixman pkgconf png usbredir script: - mkdir build From a5b04ccd742f6c58a1d305530d9e07ad9731b8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 15 May 2020 18:30:29 +0200 Subject: [PATCH 17/17] scripts/coverity-scan: Remove flex/bison packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU does not use flex/bison packages. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Claudio Fontana Signed-off-by: Alex Bennée Message-Id: <20200515163029.12917-6-philmd@redhat.com> --- scripts/coverity-scan/coverity-scan.docker | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/coverity-scan/coverity-scan.docker b/scripts/coverity-scan/coverity-scan.docker index a4f64d1283..ad4d64c0f8 100644 --- a/scripts/coverity-scan/coverity-scan.docker +++ b/scripts/coverity-scan/coverity-scan.docker @@ -19,7 +19,6 @@ FROM fedora:30 ENV PACKAGES \ alsa-lib-devel \ bc \ - bison \ brlapi-devel \ bzip2 \ bzip2-devel \ @@ -30,7 +29,6 @@ ENV PACKAGES \ dbus-daemon \ device-mapper-multipath-devel \ findutils \ - flex \ gcc \ gcc-c++ \ gettext \