From 1c6c3b764d992ecd9cb44f8646d74935269d20a6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 26 Feb 2022 18:07:16 +0000 Subject: [PATCH 01/18] util: Make qemu_oom_check() a static function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The qemu_oom_check() function, which we define in both oslib-posix.c and oslib-win32.c, is now used only locally in that file; make it static. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-id: 20220226180723.1706285-3-peter.maydell@linaro.org --- include/qemu-common.h | 2 -- util/oslib-posix.c | 2 +- util/oslib-win32.c | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/qemu-common.h b/include/qemu-common.h index 68b2e3bc10..8c0d9ab0f7 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -26,8 +26,6 @@ int qemu_main(int argc, char **argv, char **envp); #endif -void *qemu_oom_check(void *ptr); - ssize_t qemu_write_full(int fd, const void *buf, size_t count) QEMU_WARN_UNUSED_RESULT; diff --git a/util/oslib-posix.c b/util/oslib-posix.c index f2be7321c5..ed5974d384 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -199,7 +199,7 @@ fail_close: return false; } -void *qemu_oom_check(void *ptr) +static void *qemu_oom_check(void *ptr) { if (ptr == NULL) { fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); diff --git a/util/oslib-win32.c b/util/oslib-win32.c index af559ef339..c87e697724 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -44,7 +44,7 @@ /* this must come after including "trace.h" */ #include -void *qemu_oom_check(void *ptr) +static void *qemu_oom_check(void *ptr) { if (ptr == NULL) { fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError()); From ac8057a11b81195f22602e2f0fa720baed79a41e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 26 Feb 2022 18:07:17 +0000 Subject: [PATCH 02/18] util: Unify implementations of qemu_memalign() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We implement qemu_memalign() in both oslib-posix.c and oslib-win32.c, but the two versions are essentially the same: they call qemu_try_memalign(), and abort() after printing an error message if it fails. The only difference is that the win32 version prints the GetLastError() value whereas the POSIX version prints strerror(errno). However, this is a bug in the win32 version: in commit dfbd0b873a85021 in 2020 we changed the implementation of qemu_try_memalign() from using VirtualAlloc() (which sets the GetLastError() value) to using _aligned_malloc() (which sets errno), but didn't update the error message to match. Replace the two separate functions with a single version in a new memalign.c file, which drops the unnecessary extra qemu_oom_check() function and instead prints a more useful message including the requested size and alignment as well as the errno string. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220226180723.1706285-4-peter.maydell@linaro.org Reviewed-by: Philippe Mathieu-Daudé --- util/memalign.c | 39 +++++++++++++++++++++++++++++++++++++++ util/meson.build | 1 + util/oslib-posix.c | 14 -------------- util/oslib-win32.c | 14 -------------- 4 files changed, 40 insertions(+), 28 deletions(-) create mode 100644 util/memalign.c diff --git a/util/memalign.c b/util/memalign.c new file mode 100644 index 0000000000..6dfc20abbb --- /dev/null +++ b/util/memalign.c @@ -0,0 +1,39 @@ +/* + * memalign.c: Allocate an aligned memory region + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2010-2016 Red Hat, Inc. + * Copyright (c) 2022 Linaro Ltd + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" + +void *qemu_memalign(size_t alignment, size_t size) +{ + void *p = qemu_try_memalign(alignment, size); + if (p) { + return p; + } + fprintf(stderr, + "qemu_memalign: failed to allocate %zu bytes at alignment %zu: %s\n", + size, alignment, strerror(errno)); + abort(); +} diff --git a/util/meson.build b/util/meson.build index 3736988b9f..f6ee74ad0c 100644 --- a/util/meson.build +++ b/util/meson.build @@ -51,6 +51,7 @@ util_ss.add(when: 'CONFIG_POSIX', if_true: files('drm.c')) util_ss.add(files('guest-random.c')) util_ss.add(files('yank.c')) util_ss.add(files('int128.c')) +util_ss.add(files('memalign.c')) if have_user util_ss.add(files('selfmap.c')) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index ed5974d384..0278902ee7 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -199,15 +199,6 @@ fail_close: return false; } -static void *qemu_oom_check(void *ptr) -{ - if (ptr == NULL) { - fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); - abort(); - } - return ptr; -} - void *qemu_try_memalign(size_t alignment, size_t size) { void *ptr; @@ -234,11 +225,6 @@ void *qemu_try_memalign(size_t alignment, size_t size) return ptr; } -void *qemu_memalign(size_t alignment, size_t size) -{ - return qemu_oom_check(qemu_try_memalign(alignment, size)); -} - /* alloc shared memory pages */ void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared, bool noreserve) diff --git a/util/oslib-win32.c b/util/oslib-win32.c index c87e697724..0585741469 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -44,15 +44,6 @@ /* this must come after including "trace.h" */ #include -static void *qemu_oom_check(void *ptr) -{ - if (ptr == NULL) { - fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError()); - abort(); - } - return ptr; -} - void *qemu_try_memalign(size_t alignment, size_t size) { void *ptr; @@ -68,11 +59,6 @@ void *qemu_try_memalign(size_t alignment, size_t size) return ptr; } -void *qemu_memalign(size_t alignment, size_t size) -{ - return qemu_oom_check(qemu_try_memalign(alignment, size)); -} - static int get_allocation_granularity(void) { SYSTEM_INFO system_info; From bc0fecc1c2f2c70780e38b3f821dc5b89eed0716 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 26 Feb 2022 18:07:18 +0000 Subject: [PATCH 03/18] util: Return valid allocation for qemu_try_memalign() with zero size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently qemu_try_memalign()'s behaviour if asked to allocate 0 bytes is rather variable: * on Windows, we will assert * on POSIX platforms, we get the underlying behaviour of the posix_memalign() or equivalent function, which may be either "return a valid non-NULL pointer" or "return NULL" Explictly check for 0 byte allocations, so we get consistent behaviour across platforms. We handle them by incrementing the size so that we return a valid non-NULL pointer that can later be passed to qemu_vfree(). This is permitted behaviour for the posix_memalign() API and is the most usual way that underlying malloc() etc implementations handle a zero-sized allocation request, because it won't trip up calling code that assumes NULL means an error. (This includes our own qemu_memalign(), which will abort on NULL.) This change is a preparation for sharing the qemu_try_memalign() code between Windows and POSIX. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé --- util/oslib-posix.c | 3 +++ util/oslib-win32.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 0278902ee7..f7e22f4ff9 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -209,6 +209,9 @@ void *qemu_try_memalign(size_t alignment, size_t size) g_assert(is_power_of_2(alignment)); } + if (size == 0) { + size++; + } #if defined(CONFIG_POSIX_MEMALIGN) int ret; ret = posix_memalign(&ptr, alignment, size); diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 0585741469..8c28d70904 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -48,12 +48,14 @@ void *qemu_try_memalign(size_t alignment, size_t size) { void *ptr; - g_assert(size != 0); if (alignment < sizeof(void *)) { alignment = sizeof(void *); } else { g_assert(is_power_of_2(alignment)); } + if (size == 0) { + size++; + } ptr = _aligned_malloc(size, alignment); trace_qemu_memalign(alignment, size, ptr); return ptr; From 8698343b867224c1742d75dfdc276061c5839dc8 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 26 Feb 2022 18:07:19 +0000 Subject: [PATCH 04/18] meson.build: Don't misdetect posix_memalign() on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we incorrectly think that posix_memalign() exists on Windows. This is because of a combination of: * the msys2/mingw toolchain/libc claim to have a __builtin_posix_memalign when there isn't a builtin of that name * meson will assume that if you have a __builtin_foo that counts for has_function('foo') Specifying a specific include file via prefix: causes meson to not treat builtins as sufficient and actually look for the function itself; see this meson pull request which added that as the official way to get the right answer: https://github.com/mesonbuild/meson/pull/1150 Currently this misdectection doesn't cause problems because we only use CONFIG_POSIX_MEMALIGN in oslib-posix.c; however that will change in a following commit. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220226180723.1706285-6-peter.maydell@linaro.org Reviewed-by: Philippe Mathieu-Daudé --- meson.build | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 038502714a..b541506c1c 100644 --- a/meson.build +++ b/meson.build @@ -1619,7 +1619,9 @@ config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime')) config_host_data.set('CONFIG_DUP3', cc.has_function('dup3')) config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate')) config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate')) -config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign')) +# Note that we need to specify prefix: here to avoid incorrectly +# thinking that Windows has posix_memalign() +config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include ')) config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll')) config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include ')) config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads)) From 5c8c714a0a78dfd0bb7b04e796b96eb5d41f1292 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 26 Feb 2022 18:07:20 +0000 Subject: [PATCH 05/18] util: Share qemu_try_memalign() implementation between POSIX and Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The qemu_try_memalign() functions for POSIX and Windows used to be significantly different, but these days they are identical except for the actual allocation function called, and the POSIX version already has to have ifdeffery for different allocation functions. Move to a single implementation in memalign.c, which uses the Windows _aligned_malloc if we detect that function in meson. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220226180723.1706285-7-peter.maydell@linaro.org Reviewed-by: Philippe Mathieu-Daudé --- meson.build | 1 + util/memalign.c | 39 +++++++++++++++++++++++++++++++++++++++ util/oslib-posix.c | 29 ----------------------------- util/oslib-win32.c | 17 ----------------- 4 files changed, 40 insertions(+), 46 deletions(-) diff --git a/meson.build b/meson.build index b541506c1c..bc0ac931e1 100644 --- a/meson.build +++ b/meson.build @@ -1622,6 +1622,7 @@ config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate' # Note that we need to specify prefix: here to avoid incorrectly # thinking that Windows has posix_memalign() config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include ')) +config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc')) config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll')) config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include ')) config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads)) diff --git a/util/memalign.c b/util/memalign.c index 6dfc20abbb..22b405700e 100644 --- a/util/memalign.c +++ b/util/memalign.c @@ -25,6 +25,45 @@ */ #include "qemu/osdep.h" +#include "qemu/host-utils.h" +#include "trace.h" + +void *qemu_try_memalign(size_t alignment, size_t size) +{ + void *ptr; + + if (alignment < sizeof(void*)) { + alignment = sizeof(void*); + } else { + g_assert(is_power_of_2(alignment)); + } + + /* + * Handling of 0 allocations varies among the different + * platform APIs (for instance _aligned_malloc() will + * fail) -- ensure that we always return a valid non-NULL + * pointer that can be freed by qemu_vfree(). + */ + if (size == 0) { + size++; + } +#if defined(CONFIG_POSIX_MEMALIGN) + int ret; + ret = posix_memalign(&ptr, alignment, size); + if (ret != 0) { + errno = ret; + ptr = NULL; + } +#elif defined(CONFIG_ALIGNED_MALLOC) + ptr = _aligned_malloc(size, alignment); +#elif defined(CONFIG_BSD) + ptr = valloc(size); +#else + ptr = memalign(alignment, size); +#endif + trace_qemu_memalign(alignment, size, ptr); + return ptr; +} void *qemu_memalign(size_t alignment, size_t size) { diff --git a/util/oslib-posix.c b/util/oslib-posix.c index f7e22f4ff9..91798f7e50 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -199,35 +199,6 @@ fail_close: return false; } -void *qemu_try_memalign(size_t alignment, size_t size) -{ - void *ptr; - - if (alignment < sizeof(void*)) { - alignment = sizeof(void*); - } else { - g_assert(is_power_of_2(alignment)); - } - - if (size == 0) { - size++; - } -#if defined(CONFIG_POSIX_MEMALIGN) - int ret; - ret = posix_memalign(&ptr, alignment, size); - if (ret != 0) { - errno = ret; - ptr = NULL; - } -#elif defined(CONFIG_BSD) - ptr = valloc(size); -#else - ptr = memalign(alignment, size); -#endif - trace_qemu_memalign(alignment, size, ptr); - return ptr; -} - /* alloc shared memory pages */ void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared, bool noreserve) diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 8c28d70904..d9768532be 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -44,23 +44,6 @@ /* this must come after including "trace.h" */ #include -void *qemu_try_memalign(size_t alignment, size_t size) -{ - void *ptr; - - if (alignment < sizeof(void *)) { - alignment = sizeof(void *); - } else { - g_assert(is_power_of_2(alignment)); - } - if (size == 0) { - size++; - } - ptr = _aligned_malloc(size, alignment); - trace_qemu_memalign(alignment, size, ptr); - return ptr; -} - static int get_allocation_granularity(void) { SYSTEM_INFO system_info; From 88454f844efe26ea8ac7f394a72b1e6620dccf7e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 26 Feb 2022 18:07:21 +0000 Subject: [PATCH 06/18] util: Use meson checks for valloc() and memalign() presence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of assuming that all CONFIG_BSD have valloc() and anything else is memalign(), explicitly check for those functions in meson.build and use the "is the function present" define. Tests for specific functionality are better than which-OS checks; this also lets us give a helpful error message if somehow there's no usable function present. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-id: 20220226180723.1706285-8-peter.maydell@linaro.org --- meson.build | 2 ++ util/memalign.c | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index bc0ac931e1..774d0248a6 100644 --- a/meson.build +++ b/meson.build @@ -1623,6 +1623,8 @@ config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate' # thinking that Windows has posix_memalign() config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include ')) config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc')) +config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc')) +config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign')) config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll')) config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include ')) config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads)) diff --git a/util/memalign.c b/util/memalign.c index 22b405700e..083aaae619 100644 --- a/util/memalign.c +++ b/util/memalign.c @@ -56,10 +56,12 @@ void *qemu_try_memalign(size_t alignment, size_t size) } #elif defined(CONFIG_ALIGNED_MALLOC) ptr = _aligned_malloc(size, alignment); -#elif defined(CONFIG_BSD) +#elif defined(CONFIG_VALLOC) ptr = valloc(size); -#else +#elif defined(CONFIG_MEMALIGN) ptr = memalign(alignment, size); +#else + #error No function to allocate aligned memory available #endif trace_qemu_memalign(alignment, size, ptr); return ptr; From 1a11265d7e854203652606b671a0e02ba100a249 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 26 Feb 2022 18:07:22 +0000 Subject: [PATCH 07/18] util: Put qemu_vfree() in memalign.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qemu_vfree() is the companion free function to qemu_memalign(); put it in memalign.c so the allocation and free functions are together. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220226180723.1706285-9-peter.maydell@linaro.org Reviewed-by: Philippe Mathieu-Daudé --- util/memalign.c | 11 +++++++++++ util/oslib-posix.c | 6 ------ util/oslib-win32.c | 6 ------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/util/memalign.c b/util/memalign.c index 083aaae619..440b8fd9a7 100644 --- a/util/memalign.c +++ b/util/memalign.c @@ -78,3 +78,14 @@ void *qemu_memalign(size_t alignment, size_t size) size, alignment, strerror(errno)); abort(); } + +void qemu_vfree(void *ptr) +{ + trace_qemu_vfree(ptr); +#if !defined(CONFIG_POSIX_MEMALIGN) && defined(CONFIG_ALIGNED_MALLOC) + /* Only Windows _aligned_malloc needs a special free function */ + _aligned_free(ptr); +#else + free(ptr); +#endif +} diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 91798f7e50..2ebfb75057 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -220,12 +220,6 @@ void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared, return ptr; } -void qemu_vfree(void *ptr) -{ - trace_qemu_vfree(ptr); - free(ptr); -} - void qemu_anon_ram_free(void *ptr, size_t size) { trace_qemu_anon_ram_free(ptr, size); diff --git a/util/oslib-win32.c b/util/oslib-win32.c index d9768532be..4b1ce0be4b 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -75,12 +75,6 @@ void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared, return ptr; } -void qemu_vfree(void *ptr) -{ - trace_qemu_vfree(ptr); - _aligned_free(ptr); -} - void qemu_anon_ram_free(void *ptr, size_t size) { trace_qemu_anon_ram_free(ptr, size); From 5df022cf2e5e24910a7d579d5780ae78bc24f247 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 26 Feb 2022 18:07:23 +0000 Subject: [PATCH 08/18] osdep: Move memalign-related functions to their own header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the various memalign-related functions out of osdep.h and into their own header, which we include only where they are used. While we're doing this, add some brief documentation comments. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-id: 20220226180723.1706285-10-peter.maydell@linaro.org --- block/blkverify.c | 1 + block/block-copy.c | 1 + block/commit.c | 1 + block/crypto.c | 1 + block/dmg.c | 1 + block/export/fuse.c | 1 + block/file-posix.c | 1 + block/io.c | 1 + block/mirror.c | 1 + block/nvme.c | 1 + block/parallels-ext.c | 1 + block/parallels.c | 1 + block/qcow.c | 1 + block/qcow2-cache.c | 1 + block/qcow2-cluster.c | 1 + block/qcow2-refcount.c | 1 + block/qcow2-snapshot.c | 1 + block/qcow2.c | 1 + block/qed-l2-cache.c | 1 + block/qed-table.c | 1 + block/qed.c | 1 + block/quorum.c | 1 + block/raw-format.c | 1 + block/vdi.c | 1 + block/vhdx-log.c | 1 + block/vhdx.c | 1 + block/vmdk.c | 1 + block/vpc.c | 1 + block/win32-aio.c | 1 + hw/block/dataplane/xen-block.c | 1 + hw/block/fdc.c | 1 + hw/ide/core.c | 1 + hw/ppc/spapr.c | 1 + hw/ppc/spapr_softmmu.c | 1 + hw/scsi/scsi-disk.c | 1 + hw/tpm/tpm_ppi.c | 2 +- include/qemu/memalign.h | 61 ++++++++++++++++++++++++++++++++++ include/qemu/osdep.h | 18 ---------- nbd/server.c | 1 + net/l2tpv3.c | 2 +- plugins/loader.c | 1 + qemu-img.c | 1 + qemu-io-cmds.c | 1 + qom/object.c | 1 + softmmu/physmem.c | 1 + target/i386/hvf/hvf.c | 1 + target/i386/kvm/kvm.c | 1 + tcg/region.c | 1 + tests/bench/atomic_add-bench.c | 1 + tests/bench/qht-bench.c | 1 + util/atomic64.c | 1 + util/memalign.c | 1 + util/qht.c | 1 + 53 files changed, 112 insertions(+), 20 deletions(-) create mode 100644 include/qemu/memalign.h diff --git a/block/blkverify.c b/block/blkverify.c index d1facf5ba9..53ba1c9195 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -16,6 +16,7 @@ #include "qemu/cutils.h" #include "qemu/module.h" #include "qemu/option.h" +#include "qemu/memalign.h" typedef struct { BdrvChild *test_file; diff --git a/block/block-copy.c b/block/block-copy.c index ce116318b5..619e5580fa 100644 --- a/block/block-copy.c +++ b/block/block-copy.c @@ -22,6 +22,7 @@ #include "qemu/coroutine.h" #include "block/aio_task.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #define BLOCK_COPY_MAX_COPY_RANGE (16 * MiB) #define BLOCK_COPY_MAX_BUFFER (1 * MiB) diff --git a/block/commit.c b/block/commit.c index c76899f640..851d1c557a 100644 --- a/block/commit.c +++ b/block/commit.c @@ -20,6 +20,7 @@ #include "qapi/error.h" #include "qapi/qmp/qerror.h" #include "qemu/ratelimit.h" +#include "qemu/memalign.h" #include "sysemu/block-backend.h" enum { diff --git a/block/crypto.c b/block/crypto.c index 9d5fecbef8..1ba82984ef 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -31,6 +31,7 @@ #include "qemu/module.h" #include "qemu/option.h" #include "qemu/cutils.h" +#include "qemu/memalign.h" #include "crypto.h" typedef struct BlockCrypto BlockCrypto; diff --git a/block/dmg.c b/block/dmg.c index 447901fbb8..c626587f9c 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -27,6 +27,7 @@ #include "qemu/bswap.h" #include "qemu/error-report.h" #include "qemu/module.h" +#include "qemu/memalign.h" #include "dmg.h" int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in, diff --git a/block/export/fuse.c b/block/export/fuse.c index 5029e70f84..e80b24a867 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -19,6 +19,7 @@ #define FUSE_USE_VERSION 31 #include "qemu/osdep.h" +#include "qemu/memalign.h" #include "block/aio.h" #include "block/block.h" #include "block/export.h" diff --git a/block/file-posix.c b/block/file-posix.c index 1f1756e192..c000a61db2 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -31,6 +31,7 @@ #include "qemu/module.h" #include "qemu/option.h" #include "qemu/units.h" +#include "qemu/memalign.h" #include "trace.h" #include "block/thread-pool.h" #include "qemu/iov.h" diff --git a/block/io.c b/block/io.c index efc011ce65..8e621a4946 100644 --- a/block/io.c +++ b/block/io.c @@ -32,6 +32,7 @@ #include "block/coroutines.h" #include "block/write-threshold.h" #include "qemu/cutils.h" +#include "qemu/memalign.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" diff --git a/block/mirror.c b/block/mirror.c index ce6bc58d1f..d8ecb9efa2 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -23,6 +23,7 @@ #include "qapi/qmp/qerror.h" #include "qemu/ratelimit.h" #include "qemu/bitmap.h" +#include "qemu/memalign.h" #define MAX_IN_FLIGHT 16 #define MAX_IO_BYTES (1 << 20) /* 1 Mb */ diff --git a/block/nvme.c b/block/nvme.c index dd20de3865..552029931d 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -21,6 +21,7 @@ #include "qemu/module.h" #include "qemu/cutils.h" #include "qemu/option.h" +#include "qemu/memalign.h" #include "qemu/vfio-helpers.h" #include "block/block_int.h" #include "sysemu/replay.h" diff --git a/block/parallels-ext.c b/block/parallels-ext.c index e0dd0975c6..cb22a427d7 100644 --- a/block/parallels-ext.c +++ b/block/parallels-ext.c @@ -29,6 +29,7 @@ #include "parallels.h" #include "crypto/hash.h" #include "qemu/uuid.h" +#include "qemu/memalign.h" #define PARALLELS_FORMAT_EXTENSION_MAGIC 0xAB234CEF23DCEA87ULL diff --git a/block/parallels.c b/block/parallels.c index e58c828422..cd23e02d06 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -41,6 +41,7 @@ #include "qapi/qapi-visit-block-core.h" #include "qemu/bswap.h" #include "qemu/bitmap.h" +#include "qemu/memalign.h" #include "migration/blocker.h" #include "parallels.h" diff --git a/block/qcow.c b/block/qcow.c index c39940f33e..4fba1b9e36 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -32,6 +32,7 @@ #include "qemu/option.h" #include "qemu/bswap.h" #include "qemu/cutils.h" +#include "qemu/memalign.h" #include #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c index 7444b9c4ab..8a0105911f 100644 --- a/block/qcow2-cache.c +++ b/block/qcow2-cache.c @@ -23,6 +23,7 @@ */ #include "qemu/osdep.h" +#include "qemu/memalign.h" #include "qcow2.h" #include "trace.h" diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 21884a1ab9..20a16ba6ee 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -28,6 +28,7 @@ #include "qapi/error.h" #include "qcow2.h" #include "qemu/bswap.h" +#include "qemu/memalign.h" #include "trace.h" int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 4614572252..94033972be 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -28,6 +28,7 @@ #include "qemu/range.h" #include "qemu/bswap.h" #include "qemu/cutils.h" +#include "qemu/memalign.h" #include "trace.h" static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size, diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 71ddb08c21..075269a023 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -29,6 +29,7 @@ #include "qemu/bswap.h" #include "qemu/error-report.h" #include "qemu/cutils.h" +#include "qemu/memalign.h" static void qcow2_free_single_snapshot(BlockDriverState *bs, int i) { diff --git a/block/qcow2.c b/block/qcow2.c index c8115e1cba..b5c47931ef 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -38,6 +38,7 @@ #include "qemu/option_int.h" #include "qemu/cutils.h" #include "qemu/bswap.h" +#include "qemu/memalign.h" #include "qapi/qobject-input-visitor.h" #include "qapi/qapi-visit-block-core.h" #include "crypto.h" diff --git a/block/qed-l2-cache.c b/block/qed-l2-cache.c index b548362398..caf2c024c2 100644 --- a/block/qed-l2-cache.c +++ b/block/qed-l2-cache.c @@ -51,6 +51,7 @@ */ #include "qemu/osdep.h" +#include "qemu/memalign.h" #include "trace.h" #include "qed.h" diff --git a/block/qed-table.c b/block/qed-table.c index 405d446cbe..1cc844b1a5 100644 --- a/block/qed-table.c +++ b/block/qed-table.c @@ -17,6 +17,7 @@ #include "qemu/sockets.h" /* for EINPROGRESS on Windows */ #include "qed.h" #include "qemu/bswap.h" +#include "qemu/memalign.h" /* Called with table_lock held. */ static int coroutine_fn qed_read_table(BDRVQEDState *s, uint64_t offset, diff --git a/block/qed.c b/block/qed.c index 558d3646c4..f34d9a3ac1 100644 --- a/block/qed.c +++ b/block/qed.c @@ -20,6 +20,7 @@ #include "qemu/main-loop.h" #include "qemu/module.h" #include "qemu/option.h" +#include "qemu/memalign.h" #include "trace.h" #include "qed.h" #include "sysemu/block-backend.h" diff --git a/block/quorum.c b/block/quorum.c index c28dda7baa..f33f30d36b 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -17,6 +17,7 @@ #include "qemu/cutils.h" #include "qemu/module.h" #include "qemu/option.h" +#include "qemu/memalign.h" #include "block/block_int.h" #include "block/coroutines.h" #include "block/qdict.h" diff --git a/block/raw-format.c b/block/raw-format.c index bda757fd19..69fd650eaf 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -31,6 +31,7 @@ #include "qapi/error.h" #include "qemu/module.h" #include "qemu/option.h" +#include "qemu/memalign.h" typedef struct BDRVRawState { uint64_t offset; diff --git a/block/vdi.c b/block/vdi.c index bdc58d726e..cca3a3a356 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -64,6 +64,7 @@ #include "qemu/coroutine.h" #include "qemu/cutils.h" #include "qemu/uuid.h" +#include "qemu/memalign.h" /* Code configuration options. */ diff --git a/block/vhdx-log.c b/block/vhdx-log.c index 7672161d95..ff0d4e0da0 100644 --- a/block/vhdx-log.c +++ b/block/vhdx-log.c @@ -23,6 +23,7 @@ #include "block/block_int.h" #include "qemu/error-report.h" #include "qemu/bswap.h" +#include "qemu/memalign.h" #include "vhdx.h" diff --git a/block/vhdx.c b/block/vhdx.c index 356ec4c455..410c6f9610 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -25,6 +25,7 @@ #include "qemu/crc32c.h" #include "qemu/bswap.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "vhdx.h" #include "migration/blocker.h" #include "qemu/uuid.h" diff --git a/block/vmdk.c b/block/vmdk.c index 0dfab6e941..37c0946066 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -33,6 +33,7 @@ #include "qemu/module.h" #include "qemu/option.h" #include "qemu/bswap.h" +#include "qemu/memalign.h" #include "migration/blocker.h" #include "qemu/cutils.h" #include diff --git a/block/vpc.c b/block/vpc.c index 297a26262a..4d8f16e199 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -33,6 +33,7 @@ #include "migration/blocker.h" #include "qemu/bswap.h" #include "qemu/uuid.h" +#include "qemu/memalign.h" #include "qapi/qmp/qdict.h" #include "qapi/qobject-input-visitor.h" #include "qapi/qapi-visit-block-core.h" diff --git a/block/win32-aio.c b/block/win32-aio.c index c57e10c997..aadc7b1bc3 100644 --- a/block/win32-aio.c +++ b/block/win32-aio.c @@ -29,6 +29,7 @@ #include "block/raw-aio.h" #include "qemu/event_notifier.h" #include "qemu/iov.h" +#include "qemu/memalign.h" #include #include diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index 860787580a..2785b9e849 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -21,6 +21,7 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" +#include "qemu/memalign.h" #include "qapi/error.h" #include "hw/xen/xen_common.h" #include "hw/block/xen_blkif.h" diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 21d18ac2e3..347875a0cd 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -32,6 +32,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/timer.h" +#include "qemu/memalign.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" diff --git a/hw/ide/core.c b/hw/ide/core.c index 33463d9b8f..a7ac4de18a 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -30,6 +30,7 @@ #include "qemu/main-loop.h" #include "qemu/timer.h" #include "qemu/hw-version.h" +#include "qemu/memalign.h" #include "sysemu/sysemu.h" #include "sysemu/blockdev.h" #include "sysemu/dma.h" diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 4cc204f90d..953fc65fa8 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -27,6 +27,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/datadir.h" +#include "qemu/memalign.h" #include "qapi/error.h" #include "qapi/qapi-events-machine.h" #include "qapi/qapi-events-qdev.h" diff --git a/hw/ppc/spapr_softmmu.c b/hw/ppc/spapr_softmmu.c index 4ee03c83e4..5170a33369 100644 --- a/hw/ppc/spapr_softmmu.c +++ b/hw/ppc/spapr_softmmu.c @@ -1,5 +1,6 @@ #include "qemu/osdep.h" #include "qemu/cutils.h" +#include "qemu/memalign.h" #include "cpu.h" #include "helper_regs.h" #include "hw/ppc/spapr.h" diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 3666b8d946..072686ed58 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -26,6 +26,7 @@ #include "qemu/main-loop.h" #include "qemu/module.h" #include "qemu/hw-version.h" +#include "qemu/memalign.h" #include "hw/scsi/scsi.h" #include "migration/qemu-file-types.h" #include "migration/vmstate.h" diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c index 6dbb9f41e4..c89ac53e65 100644 --- a/hw/tpm/tpm_ppi.c +++ b/hw/tpm/tpm_ppi.c @@ -12,7 +12,7 @@ */ #include "qemu/osdep.h" - +#include "qemu/memalign.h" #include "qapi/error.h" #include "sysemu/memory_mapping.h" #include "migration/vmstate.h" diff --git a/include/qemu/memalign.h b/include/qemu/memalign.h new file mode 100644 index 0000000000..fa299f3bf6 --- /dev/null +++ b/include/qemu/memalign.h @@ -0,0 +1,61 @@ +/* + * Allocation and free functions for aligned memory + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef QEMU_MEMALIGN_H +#define QEMU_MEMALIGN_H + +/** + * qemu_try_memalign: Allocate aligned memory + * @alignment: required alignment, in bytes + * @size: size of allocation, in bytes + * + * Allocate memory on an aligned boundary (i.e. the returned + * address will be an exact multiple of @alignment). + * @alignment must be a power of 2, or the function will assert(). + * On success, returns allocated memory; on failure, returns NULL. + * + * The memory allocated through this function must be freed via + * qemu_vfree() (and not via free()). + */ +void *qemu_try_memalign(size_t alignment, size_t size); +/** + * qemu_memalign: Allocate aligned memory, without failing + * @alignment: required alignment, in bytes + * @size: size of allocation, in bytes + * + * Allocate memory in the same way as qemu_try_memalign(), but + * abort() with an error message if the memory allocation fails. + * + * The memory allocated through this function must be freed via + * qemu_vfree() (and not via free()). + */ +void *qemu_memalign(size_t alignment, size_t size); +/** + * qemu_vfree: Free memory allocated through qemu_memalign + * @ptr: memory to free + * + * This function must be used to free memory allocated via qemu_memalign() + * or qemu_try_memalign(). (Using the wrong free function will cause + * subtle bugs on Windows hosts.) + */ +void qemu_vfree(void *ptr); +/* + * It's an analog of GLIB's g_autoptr_cleanup_generic_gfree(), used to define + * g_autofree macro. + */ +static inline void qemu_cleanup_generic_vfree(void *p) +{ + void **pp = (void **)p; + qemu_vfree(*pp); +} + +/* + * Analog of g_autofree, but qemu_vfree is called on cleanup instead of g_free. + */ +#define QEMU_AUTO_VFREE __attribute__((cleanup(qemu_cleanup_generic_vfree))) + +#endif diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 7bcce3bceb..bc3df26da3 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -379,28 +379,10 @@ extern "C" { #endif int qemu_daemon(int nochdir, int noclose); -void *qemu_try_memalign(size_t alignment, size_t size); -void *qemu_memalign(size_t alignment, size_t size); void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared, bool noreserve); -void qemu_vfree(void *ptr); void qemu_anon_ram_free(void *ptr, size_t size); -/* - * It's an analog of GLIB's g_autoptr_cleanup_generic_gfree(), used to define - * g_autofree macro. - */ -static inline void qemu_cleanup_generic_vfree(void *p) -{ - void **pp = (void **)p; - qemu_vfree(*pp); -} - -/* - * Analog of g_autofree, but qemu_vfree is called on cleanup instead of g_free. - */ -#define QEMU_AUTO_VFREE __attribute__((cleanup(qemu_cleanup_generic_vfree))) - #ifdef _WIN32 #define HAVE_CHARDEV_SERIAL 1 #elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ diff --git a/nbd/server.c b/nbd/server.c index 9fb2f26402..53e68cf027 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -25,6 +25,7 @@ #include "trace.h" #include "nbd-internal.h" #include "qemu/units.h" +#include "qemu/memalign.h" #define NBD_META_ID_BASE_ALLOCATION 0 #define NBD_META_ID_ALLOCATION_DEPTH 1 diff --git a/net/l2tpv3.c b/net/l2tpv3.c index e4d4218db6..b8faa8796c 100644 --- a/net/l2tpv3.c +++ b/net/l2tpv3.c @@ -34,7 +34,7 @@ #include "qemu/sockets.h" #include "qemu/iov.h" #include "qemu/main-loop.h" - +#include "qemu/memalign.h" /* The buffer size needs to be investigated for optimum numbers and * optimum means of paging in on different systems. This size is diff --git a/plugins/loader.c b/plugins/loader.c index 4883b0a1cb..88c30bde2d 100644 --- a/plugins/loader.c +++ b/plugins/loader.c @@ -27,6 +27,7 @@ #include "qemu/cacheinfo.h" #include "qemu/xxhash.h" #include "qemu/plugin.h" +#include "qemu/memalign.h" #include "hw/core/cpu.h" #include "exec/exec-all.h" #ifndef CONFIG_USER_ONLY diff --git a/qemu-img.c b/qemu-img.c index 6fe2466032..5dffb3e616 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -42,6 +42,7 @@ #include "qemu/module.h" #include "qemu/sockets.h" #include "qemu/units.h" +#include "qemu/memalign.h" #include "qom/object_interfaces.h" #include "sysemu/block-backend.h" #include "block/block_int.h" diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 46593d632d..633b46cdb2 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -21,6 +21,7 @@ #include "qemu/option.h" #include "qemu/timer.h" #include "qemu/cutils.h" +#include "qemu/memalign.h" #define CMD_NOFILE_OK 0x01 diff --git a/qom/object.c b/qom/object.c index 9f7a33139d..4048a2fef1 100644 --- a/qom/object.c +++ b/qom/object.c @@ -16,6 +16,7 @@ #include "qom/object.h" #include "qom/object_interfaces.h" #include "qemu/cutils.h" +#include "qemu/memalign.h" #include "qapi/visitor.h" #include "qapi/string-input-visitor.h" #include "qapi/string-output-visitor.h" diff --git a/softmmu/physmem.c b/softmmu/physmem.c index a13289a594..59dcf13faf 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -42,6 +42,7 @@ #include "qemu/config-file.h" #include "qemu/error-report.h" #include "qemu/qemu-print.h" +#include "qemu/memalign.h" #include "exec/memory.h" #include "exec/ioport.h" #include "sysemu/dma.h" diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 4ba6e82fab..fc12c02fb2 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -49,6 +49,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "sysemu/hvf.h" #include "sysemu/hvf_int.h" diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 2c8feb4a6f..83d0988302 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -37,6 +37,7 @@ #include "qemu/main-loop.h" #include "qemu/config-file.h" #include "qemu/error-report.h" +#include "qemu/memalign.h" #include "hw/i386/x86.h" #include "hw/i386/apic.h" #include "hw/i386/apic_internal.h" diff --git a/tcg/region.c b/tcg/region.c index 72afb35738..97ca5291d5 100644 --- a/tcg/region.c +++ b/tcg/region.c @@ -26,6 +26,7 @@ #include "qemu/units.h" #include "qemu/madvise.h" #include "qemu/mprotect.h" +#include "qemu/memalign.h" #include "qemu/cacheinfo.h" #include "qapi/error.h" #include "exec/exec-all.h" diff --git a/tests/bench/atomic_add-bench.c b/tests/bench/atomic_add-bench.c index f05471ab45..8a6faad6ec 100644 --- a/tests/bench/atomic_add-bench.c +++ b/tests/bench/atomic_add-bench.c @@ -2,6 +2,7 @@ #include "qemu/thread.h" #include "qemu/host-utils.h" #include "qemu/processor.h" +#include "qemu/memalign.h" struct thread_info { uint64_t r; diff --git a/tests/bench/qht-bench.c b/tests/bench/qht-bench.c index 2e5b70ccd0..8afe161d10 100644 --- a/tests/bench/qht-bench.c +++ b/tests/bench/qht-bench.c @@ -10,6 +10,7 @@ #include "qemu/qht.h" #include "qemu/rcu.h" #include "qemu/xxhash.h" +#include "qemu/memalign.h" struct thread_stats { size_t rd; diff --git a/util/atomic64.c b/util/atomic64.c index 22983a970f..c20d071d8e 100644 --- a/util/atomic64.c +++ b/util/atomic64.c @@ -8,6 +8,7 @@ #include "qemu/atomic.h" #include "qemu/thread.h" #include "qemu/cacheinfo.h" +#include "qemu/memalign.h" #ifdef CONFIG_ATOMIC64 #error This file must only be compiled if !CONFIG_ATOMIC64 diff --git a/util/memalign.c b/util/memalign.c index 440b8fd9a7..c199ae7073 100644 --- a/util/memalign.c +++ b/util/memalign.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qemu/host-utils.h" +#include "qemu/memalign.h" #include "trace.h" void *qemu_try_memalign(size_t alignment, size_t size) diff --git a/util/qht.c b/util/qht.c index 079605121b..065fc501f4 100644 --- a/util/qht.c +++ b/util/qht.c @@ -69,6 +69,7 @@ #include "qemu/qht.h" #include "qemu/atomic.h" #include "qemu/rcu.h" +#include "qemu/memalign.h" //#define QHT_DEBUG From c64ee036ac215f970a76e8c51cb1cfaaef70feb5 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 3 Mar 2022 11:37:40 +0000 Subject: [PATCH 09/18] target/arm/translate-neon: UNDEF if VLD1/VST1 stride bits are non-zero For VLD1/VST1 (single element to one lane) we are only accessing one register, and so the 'stride' is meaningless. The bits that would specify stride (insn bit [4] for size=1, bit [6] for size=2) are specified to be zero in the encoding (which would correspond to a stride of 1 for VLD2/VLD3/VLD4 etc), and we must UNDEF if they are not. We failed to make this check, which meant that we would incorrectly handle some instruction patterns as loads or stores instead of UNDEFing them. Enforce that stride == 1 for the nregs == 1 case. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/890 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Tested-by: Richard Henderson Message-id: 20220303113741.2156877-2-peter.maydell@linaro.org --- target/arm/translate-neon.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c index 3854dd3516..072fdc1e6e 100644 --- a/target/arm/translate-neon.c +++ b/target/arm/translate-neon.c @@ -657,6 +657,9 @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a) /* Catch the UNDEF cases. This is unavoidably a bit messy. */ switch (nregs) { case 1: + if (a->stride != 1) { + return false; + } if (((a->align & (1 << a->size)) != 0) || (a->size == 2 && (a->align == 1 || a->align == 2))) { return false; From 41c5a0f791ef4d9377ec5b952931a1c75df7a815 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 3 Mar 2022 11:37:41 +0000 Subject: [PATCH 10/18] target/arm/translate-neon: Simplify align field check for VLD3 For VLD3 (single 3-element structure to one lane), there is no alignment specification and the alignment bits in the instruction must be zero. This is bit [4] for the size=0 and size=1 cases, and bits [5:4] for the size=2 case. We do this check correctly in VLDST_single(), but we write it a bit oddly: in the 'case 3' code we check for bit 0 of a->align (bit [4] of the insn), and then we fall through to the 'case 2' code which checks bit 1 of a->align (bit [5] of the insn) in the size 2 case. Replace this with just checking "is a->align non-zero" for VLD3, which lets us drop the fall-through and put the cases in this switch in numerical order. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Tested-by: Richard Henderson Message-id: 20220303113741.2156877-3-peter.maydell@linaro.org --- target/arm/translate-neon.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c index 072fdc1e6e..384604c009 100644 --- a/target/arm/translate-neon.c +++ b/target/arm/translate-neon.c @@ -665,16 +665,16 @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a) return false; } break; - case 3: - if ((a->align & 1) != 0) { - return false; - } - /* fall through */ case 2: if (a->size == 2 && (a->align & 2) != 0) { return false; } break; + case 3: + if (a->align != 0) { + return false; + } + break; case 4: if (a->size == 2 && a->align == 3) { return false; From e40509801d4f0b17fac641a07696ecb41421b3dc Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 3 Mar 2022 20:23:37 +0000 Subject: [PATCH 11/18] hw/intc/arm_gicv3_its: Add trace events for commands When debugging code that's using the ITS, it's helpful to see tracing of the ITS commands that the guest executes. Add suitable trace events. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220303202341.2232284-2-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 28 ++++++++++++++++++++++++++-- hw/intc/trace-events | 12 ++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 4f598d3c14..77dc702734 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -366,6 +366,19 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, const uint64_t *cmdpkt, devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT; eventid = cmdpkt[1] & EVENTID_MASK; + switch (cmd) { + case INTERRUPT: + trace_gicv3_its_cmd_int(devid, eventid); + break; + case CLEAR: + trace_gicv3_its_cmd_clear(devid, eventid); + break; + case DISCARD: + trace_gicv3_its_cmd_discard(devid, eventid); + break; + default: + g_assert_not_reached(); + } return do_process_its_cmd(s, devid, eventid, cmd); } @@ -382,15 +395,16 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt, devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT; eventid = cmdpkt[1] & EVENTID_MASK; + icid = cmdpkt[2] & ICID_MASK; if (ignore_pInt) { pIntid = eventid; + trace_gicv3_its_cmd_mapi(devid, eventid, icid); } else { pIntid = (cmdpkt[1] & pINTID_MASK) >> pINTID_SHIFT; + trace_gicv3_its_cmd_mapti(devid, eventid, icid, pIntid); } - icid = cmdpkt[2] & ICID_MASK; - if (devid >= s->dt.num_entries) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes: devid %d>=%d", @@ -484,6 +498,7 @@ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt) } else { cte.rdbase = 0; } + trace_gicv3_its_cmd_mapc(icid, cte.rdbase, cte.valid); if (icid >= s->ct.num_entries) { qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPC: invalid ICID 0x%d", icid); @@ -539,6 +554,8 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt) dte.ittaddr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT; dte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK; + trace_gicv3_its_cmd_mapd(devid, dte.size, dte.ittaddr, dte.valid); + if (devid >= s->dt.num_entries) { qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPD: invalid device ID field 0x%x >= 0x%x\n", @@ -562,6 +579,8 @@ static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt) rd1 = FIELD_EX64(cmdpkt[2], MOVALL_2, RDBASE1); rd2 = FIELD_EX64(cmdpkt[3], MOVALL_3, RDBASE2); + trace_gicv3_its_cmd_movall(rd1, rd2); + if (rd1 >= s->gicv3->num_cpu) { qemu_log_mask(LOG_GUEST_ERROR, "%s: RDBASE1 %" PRId64 @@ -601,6 +620,8 @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt) eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID); new_icid = FIELD_EX64(cmdpkt[2], MOVI_2, ICID); + trace_gicv3_its_cmd_movi(devid, eventid, new_icid); + if (devid >= s->dt.num_entries) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes: devid %d>=%d", @@ -779,6 +800,7 @@ static void process_cmdq(GICv3ITSState *s) * is already consistent by the time SYNC command is executed. * Hence no further processing is required for SYNC command. */ + trace_gicv3_its_cmd_sync(); break; case GITS_CMD_MAPD: result = process_mapd(s, cmdpkt); @@ -803,6 +825,7 @@ static void process_cmdq(GICv3ITSState *s) * need to trigger lpi priority re-calculation to be in * sync with LPI config table or pending table changes. */ + trace_gicv3_its_cmd_inv(); for (i = 0; i < s->gicv3->num_cpu; i++) { gicv3_redist_update_lpi(&s->gicv3->cpu[i]); } @@ -814,6 +837,7 @@ static void process_cmdq(GICv3ITSState *s) result = process_movall(s, cmdpkt); break; default: + trace_gicv3_its_cmd_unknown(cmd); break; } if (result == CMD_CONTINUE) { diff --git a/hw/intc/trace-events b/hw/intc/trace-events index b28cda4e08..e92662b405 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -176,6 +176,18 @@ gicv3_its_write(uint64_t offset, uint64_t data, unsigned size) "GICv3 ITS write: gicv3_its_badwrite(uint64_t offset, uint64_t data, unsigned size) "GICv3 ITS write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u: error" gicv3_its_translation_write(uint64_t offset, uint64_t data, unsigned size, uint32_t requester_id) "GICv3 ITS TRANSLATER write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u requester_id 0x%x" gicv3_its_process_command(uint32_t rd_offset, uint8_t cmd) "GICv3 ITS: processing command at offset 0x%x: 0x%x" +gicv3_its_cmd_int(uint32_t devid, uint32_t eventid) "GICv3 ITS: command INT DeviceID 0x%x EventID 0x%x" +gicv3_its_cmd_clear(uint32_t devid, uint32_t eventid) "GICv3 ITS: command CLEAR DeviceID 0x%x EventID 0x%x" +gicv3_its_cmd_discard(uint32_t devid, uint32_t eventid) "GICv3 ITS: command DISCARD DeviceID 0x%x EventID 0x%x" +gicv3_its_cmd_sync(void) "GICv3 ITS: command SYNC" +gicv3_its_cmd_mapd(uint32_t devid, uint32_t size, uint64_t ittaddr, int valid) "GICv3 ITS: command MAPD DeviceID 0x%x Size 0x%x ITT_addr 0x%" PRIx64 " V %d" +gicv3_its_cmd_mapc(uint32_t icid, uint64_t rdbase, int valid) "GICv3 ITS: command MAPC ICID 0x%x RDbase 0x%" PRIx64 " V %d" +gicv3_its_cmd_mapi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS: command MAPI DeviceID 0x%x EventID 0x%x ICID 0x%x" +gicv3_its_cmd_mapti(uint32_t devid, uint32_t eventid, uint32_t icid, uint32_t intid) "GICv3 ITS: command MAPTI DeviceID 0x%x EventID 0x%x ICID 0x%x pINTID 0x%x" +gicv3_its_cmd_inv(void) "GICv3 ITS: command INV or INVALL" +gicv3_its_cmd_movall(uint64_t rd1, uint64_t rd2) "GICv3 ITS: command MOVALL RDbase1 0x%" PRIx64 " RDbase2 0x%" PRIx64 +gicv3_its_cmd_movi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS: command MOVI DeviceID 0x%x EventID 0x%x ICID 0x%x" +gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x" # armv7m_nvic.c nvic_recompute_state(int vectpending, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d vectpending_prio %d exception_prio %d" From 930f40e90bbc9f8f3818219cc8a17c3afe84d719 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 3 Mar 2022 20:23:38 +0000 Subject: [PATCH 12/18] hw/intc/arm_gicv3_its: Add trace events for table reads and writes For debugging guest use of the ITS, it can be helpful to trace when the ITS reads and writes the in-memory tables. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220303202341.2232284-3-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 37 +++++++++++++++++++++++++++++++------ hw/intc/trace-events | 9 +++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 77dc702734..9f4df6a8cb 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -161,16 +161,22 @@ static MemTxResult get_cte(GICv3ITSState *s, uint16_t icid, CTEntry *cte) if (entry_addr == -1) { /* No L2 table entry, i.e. no valid CTE, or a memory error */ cte->valid = false; - return res; + goto out; } cteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res); if (res != MEMTX_OK) { - return res; + goto out; } cte->valid = FIELD_EX64(cteval, CTE, VALID); cte->rdbase = FIELD_EX64(cteval, CTE, RDBASE); - return MEMTX_OK; +out: + if (res != MEMTX_OK) { + trace_gicv3_its_cte_read_fault(icid); + } else { + trace_gicv3_its_cte_read(icid, cte->valid, cte->rdbase); + } + return res; } /* @@ -187,6 +193,10 @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte, uint64_t itel = 0; uint32_t iteh = 0; + trace_gicv3_its_ite_write(dte->ittaddr, eventid, ite->valid, + ite->inttype, ite->intid, ite->icid, + ite->vpeid, ite->doorbell); + if (ite->valid) { itel = FIELD_DP64(itel, ITE_L, VALID, 1); itel = FIELD_DP64(itel, ITE_L, INTTYPE, ite->inttype); @@ -221,11 +231,13 @@ static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid, itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, &res); if (res != MEMTX_OK) { + trace_gicv3_its_ite_read_fault(dte->ittaddr, eventid); return res; } iteh = address_space_ldl_le(as, iteaddr + 8, MEMTXATTRS_UNSPECIFIED, &res); if (res != MEMTX_OK) { + trace_gicv3_its_ite_read_fault(dte->ittaddr, eventid); return res; } @@ -235,6 +247,9 @@ static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid, ite->icid = FIELD_EX64(itel, ITE_L, ICID); ite->vpeid = FIELD_EX64(itel, ITE_L, VPEID); ite->doorbell = FIELD_EX64(iteh, ITE_H, DOORBELL); + trace_gicv3_its_ite_read(dte->ittaddr, eventid, ite->valid, + ite->inttype, ite->intid, ite->icid, + ite->vpeid, ite->doorbell); return MEMTX_OK; } @@ -254,17 +269,23 @@ static MemTxResult get_dte(GICv3ITSState *s, uint32_t devid, DTEntry *dte) if (entry_addr == -1) { /* No L2 table entry, i.e. no valid DTE, or a memory error */ dte->valid = false; - return res; + goto out; } dteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res); if (res != MEMTX_OK) { - return res; + goto out; } dte->valid = FIELD_EX64(dteval, DTE, VALID); dte->size = FIELD_EX64(dteval, DTE, SIZE); /* DTE word field stores bits [51:8] of the ITT address */ dte->ittaddr = FIELD_EX64(dteval, DTE, ITTADDR) << ITTADDR_SHIFT; - return MEMTX_OK; +out: + if (res != MEMTX_OK) { + trace_gicv3_its_dte_read_fault(devid); + } else { + trace_gicv3_its_dte_read(devid, dte->valid, dte->size, dte->ittaddr); + } + return res; } /* @@ -465,6 +486,8 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte) uint64_t cteval = 0; MemTxResult res = MEMTX_OK; + trace_gicv3_its_cte_write(icid, cte->valid, cte->rdbase); + if (cte->valid) { /* add mapping entry to collection table */ cteval = FIELD_DP64(cteval, CTE, VALID, 1); @@ -524,6 +547,8 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte) uint64_t dteval = 0; MemTxResult res = MEMTX_OK; + trace_gicv3_its_dte_write(devid, dte->valid, dte->size, dte->ittaddr); + if (dte->valid) { /* add mapping entry to device table */ dteval = FIELD_DP64(dteval, DTE, VALID, 1); diff --git a/hw/intc/trace-events b/hw/intc/trace-events index e92662b405..53414aa197 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -188,6 +188,15 @@ gicv3_its_cmd_inv(void) "GICv3 ITS: command INV or INVALL" gicv3_its_cmd_movall(uint64_t rd1, uint64_t rd2) "GICv3 ITS: command MOVALL RDbase1 0x%" PRIx64 " RDbase2 0x%" PRIx64 gicv3_its_cmd_movi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS: command MOVI DeviceID 0x%x EventID 0x%x ICID 0x%x" gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x" +gicv3_its_cte_read(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table read for ICID 0x%x: valid %d RDBase 0x%x" +gicv3_its_cte_write(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table write for ICID 0x%x: valid %d RDBase 0x%x" +gicv3_its_cte_read_fault(uint32_t icid) "GICv3 ITS: Collection Table read for ICID 0x%x: faulted" +gicv3_its_ite_read(uint64_t ittaddr, uint32_t eventid, int valid, int inttype, uint32_t intid, uint32_t icid, uint32_t vpeid, uint32_t doorbell) "GICv3 ITS: Interrupt Table read for ITTaddr 0x%" PRIx64 " EventID 0x%x: valid %d inttype %d intid 0x%x ICID 0x%x vPEID 0x%x doorbell 0x%x" +gicv3_its_ite_read_fault(uint64_t ittaddr, uint32_t eventid) "GICv3 ITS: Interrupt Table read for ITTaddr 0x%" PRIx64 " EventID 0x%x: faulted" +gicv3_its_ite_write(uint64_t ittaddr, uint32_t eventid, int valid, int inttype, uint32_t intid, uint32_t icid, uint32_t vpeid, uint32_t doorbell) "GICv3 ITS: Interrupt Table write for ITTaddr 0x%" PRIx64 " EventID 0x%x: valid %d inttype %d intid 0x%x ICID 0x%x vPEID 0x%x doorbell 0x%x" +gicv3_its_dte_read(uint32_t devid, int valid, uint32_t size, uint64_t ittaddr) "GICv3 ITS: Device Table read for DeviceID 0x%x: valid %d size 0x%x ITTaddr 0x%" PRIx64 +gicv3_its_dte_write(uint32_t devid, int valid, uint32_t size, uint64_t ittaddr) "GICv3 ITS: Device Table write for DeviceID 0x%x: valid %d size 0x%x ITTaddr 0x%" PRIx64 +gicv3_its_dte_read_fault(uint32_t devid) "GICv3 ITS: Device Table read for DeviceID 0x%x: faulted" # armv7m_nvic.c nvic_recompute_state(int vectpending, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d vectpending_prio %d exception_prio %d" From 31164ebf08d87b59c570af5b2c80e91940a70968 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 3 Mar 2022 20:23:39 +0000 Subject: [PATCH 13/18] hw/intc/arm_gicv3: Specify valid and impl in MemoryRegionOps The GICv3 has some registers that support byte accesses, and some that support 8-byte accesses. Our TCG implementation implements all of this, switching on the 'size' argument and handling the registers that must support reads of that size while logging an error for attempted accesses to registers that do not support that size access. However we forgot to tell the core memory subsystem about this by specifying the .impl and .valid fields in the MemoryRegionOps struct, so the core was happily simulating 8 byte accesses by combining two 4 byte accesses. This doesn't have much guest-visible effect, since there aren't many 8 byte registers and they all support being written in two 4 byte parts. Set the .impl and .valid fields to say that all sizes from 1 to 8 bytes are both valid and implemented by the device. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220303202341.2232284-4-peter.maydell@linaro.org --- hw/intc/arm_gicv3.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c index 6d3c8ee231..0b8f79a122 100644 --- a/hw/intc/arm_gicv3.c +++ b/hw/intc/arm_gicv3.c @@ -369,11 +369,19 @@ static const MemoryRegionOps gic_ops[] = { .read_with_attrs = gicv3_dist_read, .write_with_attrs = gicv3_dist_write, .endianness = DEVICE_NATIVE_ENDIAN, + .valid.min_access_size = 1, + .valid.max_access_size = 8, + .impl.min_access_size = 1, + .impl.max_access_size = 8, }, { .read_with_attrs = gicv3_redist_read, .write_with_attrs = gicv3_redist_write, .endianness = DEVICE_NATIVE_ENDIAN, + .valid.min_access_size = 1, + .valid.max_access_size = 8, + .impl.min_access_size = 1, + .impl.max_access_size = 8, } }; From b45f91e1a70e70f482ed75b50e24850591db2e5e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 3 Mar 2022 20:23:40 +0000 Subject: [PATCH 14/18] hw/intc/arm_gicv3: Fix missing spaces in error log messages We forgot a space in some log messages, so the output ended up looking like gicv3_dist_write: invalid guest write at offset 0000000000008000size 8 with a missing space before "size". Add the missing spaces. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220303202341.2232284-5-peter.maydell@linaro.org --- hw/intc/arm_gicv3_dist.c | 4 ++-- hw/intc/arm_gicv3_its.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c index 4164500ea9..28d913b211 100644 --- a/hw/intc/arm_gicv3_dist.c +++ b/hw/intc/arm_gicv3_dist.c @@ -838,7 +838,7 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data, if (!r) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid guest read at offset " TARGET_FMT_plx - "size %u\n", __func__, offset, size); + " size %u\n", __func__, offset, size); trace_gicv3_dist_badread(offset, size, attrs.secure); /* The spec requires that reserved registers are RAZ/WI; * so use MEMTX_ERROR returns from leaf functions as a way to @@ -879,7 +879,7 @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data, if (!r) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid guest write at offset " TARGET_FMT_plx - "size %u\n", __func__, offset, size); + " size %u\n", __func__, offset, size); trace_gicv3_dist_badwrite(offset, data, size, attrs.secure); /* The spec requires that reserved registers are RAZ/WI; * so use MEMTX_ERROR returns from leaf functions as a way to diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 9f4df6a8cb..b96b874afd 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -1313,7 +1313,7 @@ static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data, if (!result) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid guest read at offset " TARGET_FMT_plx - "size %u\n", __func__, offset, size); + " size %u\n", __func__, offset, size); trace_gicv3_its_badread(offset, size); /* * The spec requires that reserved registers are RAZ/WI; @@ -1349,7 +1349,7 @@ static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data, if (!result) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid guest write at offset " TARGET_FMT_plx - "size %u\n", __func__, offset, size); + " size %u\n", __func__, offset, size); trace_gicv3_its_badwrite(offset, data, size); /* * The spec requires that reserved registers are RAZ/WI; From cf734c2a0f6a61dd22639416a5295d0e0fd8a7cd Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 3 Mar 2022 20:23:41 +0000 Subject: [PATCH 15/18] hw/intc/arm_gicv3_cpuif: Fix register names in ICV_HPPIR read trace event The trace_gicv3_icv_hppir_read trace event takes an integer value which it uses to form the register name, which should be either ICV_HPPIR0 or ICV_HPPIR1. We were passing in the 'grp' variable for this, but that is either GICV3_G0 or GICV3_G1NS, which happen to be 0 and 2, which meant that tracing for the ICV_HPPIR1 register was incorrectly printed as ICV_HPPIR2. Use the same approach we do for all the other similar trace events, and pass in 'ri->crm == 8 ? 0 : 1', deriving the index value directly from the ARMCPRegInfo struct. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220303202341.2232284-6-peter.maydell@linaro.org --- hw/intc/arm_gicv3_cpuif.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index d7e03d0cab..1a3d440a54 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -612,7 +612,8 @@ static uint64_t icv_hppir_read(CPUARMState *env, const ARMCPRegInfo *ri) } } - trace_gicv3_icv_hppir_read(grp, gicv3_redist_affid(cs), value); + trace_gicv3_icv_hppir_read(ri->crm == 8 ? 0 : 1, + gicv3_redist_affid(cs), value); return value; } From 99eb313ddbbcf73c1adcdadceba1423b691c6d05 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sun, 27 Feb 2022 13:22:41 +0900 Subject: [PATCH 16/18] ui/cocoa: Use the standard about panel This provides standard look and feel for the about panel and reduces code. Signed-off-by: Akihiko Odaki Message-id: 20220227042241.1543-1-akihiko.odaki@gmail.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- ui/cocoa.m | 112 +++++++++++------------------------------------------ 1 file changed, 23 insertions(+), 89 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 8ab9ab5e84..c88149852b 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -83,7 +83,7 @@ static void cocoa_switch(DisplayChangeListener *dcl, static void cocoa_refresh(DisplayChangeListener *dcl); -static NSWindow *normalWindow, *about_window; +static NSWindow *normalWindow; static const DisplayChangeListenerOps dcl_ops = { .dpy_name = "cocoa", .dpy_gfx_update = cocoa_update, @@ -1140,7 +1140,6 @@ QemuCocoaView *cocoaView; - (BOOL)verifyQuit; - (void)openDocumentation:(NSString *)filename; - (IBAction) do_about_menu_item: (id) sender; -- (void)make_about_window; - (void)adjustSpeed:(id)sender; @end @@ -1186,8 +1185,6 @@ QemuCocoaView *cocoaView; [pauseLabel setFont: [NSFont fontWithName: @"Helvetica" size: 90]]; [pauseLabel setTextColor: [NSColor blackColor]]; [pauseLabel sizeToFit]; - - [self make_about_window]; } return self; } @@ -1471,92 +1468,29 @@ QemuCocoaView *cocoaView; /* The action method for the About menu item */ - (IBAction) do_about_menu_item: (id) sender { - [about_window makeKeyAndOrderFront: nil]; -} - -/* Create and display the about dialog */ -- (void)make_about_window -{ - /* Make the window */ - int x = 0, y = 0, about_width = 400, about_height = 200; - NSRect window_rect = NSMakeRect(x, y, about_width, about_height); - about_window = [[NSWindow alloc] initWithContentRect:window_rect - styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | - NSWindowStyleMaskMiniaturizable - backing:NSBackingStoreBuffered - defer:NO]; - [about_window setTitle: @"About"]; - [about_window setReleasedWhenClosed: NO]; - [about_window center]; - NSView *superView = [about_window contentView]; - - /* Create the dimensions of the picture */ - int picture_width = 80, picture_height = 80; - x = (about_width - picture_width)/2; - y = about_height - picture_height - 10; - NSRect picture_rect = NSMakeRect(x, y, picture_width, picture_height); - - /* Make the picture of QEMU */ - NSImageView *picture_view = [[NSImageView alloc] initWithFrame: - picture_rect]; - char *qemu_image_path_c = get_relocated_path(CONFIG_QEMU_ICONDIR "/hicolor/512x512/apps/qemu.png"); - NSString *qemu_image_path = [NSString stringWithUTF8String:qemu_image_path_c]; - g_free(qemu_image_path_c); - NSImage *qemu_image = [[NSImage alloc] initWithContentsOfFile:qemu_image_path]; - [picture_view setImage: qemu_image]; - [picture_view setImageScaling: NSImageScaleProportionallyUpOrDown]; - [superView addSubview: picture_view]; - - /* Make the name label */ - NSBundle *bundle = [NSBundle mainBundle]; - if (bundle) { - x = 0; - y = y - 25; - int name_width = about_width, name_height = 20; - NSRect name_rect = NSMakeRect(x, y, name_width, name_height); - NSTextField *name_label = [[NSTextField alloc] initWithFrame: name_rect]; - [name_label setEditable: NO]; - [name_label setBezeled: NO]; - [name_label setDrawsBackground: NO]; - [name_label setAlignment: NSTextAlignmentCenter]; - NSString *qemu_name = [[bundle executablePath] lastPathComponent]; - [name_label setStringValue: qemu_name]; - [superView addSubview: name_label]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + char *icon_path_c = get_relocated_path(CONFIG_QEMU_ICONDIR "/hicolor/512x512/apps/qemu.png"); + NSString *icon_path = [NSString stringWithUTF8String:icon_path_c]; + g_free(icon_path_c); + NSImage *icon = [[NSImage alloc] initWithContentsOfFile:icon_path]; + NSString *version = @"QEMU emulator version " QEMU_FULL_VERSION; + NSString *copyright = @QEMU_COPYRIGHT; + NSDictionary *options; + if (icon) { + options = @{ + NSAboutPanelOptionApplicationIcon : icon, + NSAboutPanelOptionApplicationVersion : version, + @"Copyright" : copyright, + }; + [icon release]; + } else { + options = @{ + NSAboutPanelOptionApplicationVersion : version, + @"Copyright" : copyright, + }; } - - /* Set the version label's attributes */ - x = 0; - y = 50; - int version_width = about_width, version_height = 20; - NSRect version_rect = NSMakeRect(x, y, version_width, version_height); - NSTextField *version_label = [[NSTextField alloc] initWithFrame: - version_rect]; - [version_label setEditable: NO]; - [version_label setBezeled: NO]; - [version_label setAlignment: NSTextAlignmentCenter]; - [version_label setDrawsBackground: NO]; - - /* Create the version string*/ - NSString *version_string; - version_string = [[NSString alloc] initWithFormat: - @"QEMU emulator version %s", QEMU_FULL_VERSION]; - [version_label setStringValue: version_string]; - [superView addSubview: version_label]; - - /* Make copyright label */ - x = 0; - y = 35; - int copyright_width = about_width, copyright_height = 20; - NSRect copyright_rect = NSMakeRect(x, y, copyright_width, copyright_height); - NSTextField *copyright_label = [[NSTextField alloc] initWithFrame: - copyright_rect]; - [copyright_label setEditable: NO]; - [copyright_label setBezeled: NO]; - [copyright_label setDrawsBackground: NO]; - [copyright_label setAlignment: NSTextAlignmentCenter]; - [copyright_label setStringValue: [NSString stringWithFormat: @"%s", - QEMU_COPYRIGHT]]; - [superView addSubview: copyright_label]; + [NSApp orderFrontStandardAboutPanelWithOptions:options]; + [pool release]; } /* Used by the Speed menu items */ From 69b2265d5fe8e0f401d75e175e0a243a7d505e53 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 1 Mar 2022 11:59:57 -1000 Subject: [PATCH 17/18] target/arm: Provide cpu property for controling FEAT_LPA2 There is a Linux kernel bug present until v5.12 that prevents booting with FEAT_LPA2 enabled. As a workaround for TCG, allow the feature to be disabled from -cpu max. Since this kernel bug is present in the Fedora 31 image that we test in avocado, disable lpa2 on the command-line. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/cpu.c | 6 ++++++ target/arm/cpu.h | 5 ++++- target/arm/cpu64.c | 24 ++++++++++++++++++++++++ tests/avocado/boot_linux.py | 2 ++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 7091684a16..185d4e774d 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1392,6 +1392,12 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp) error_propagate(errp, local_err); return; } + + arm_cpu_lpa2_finalize(cpu, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } } if (kvm_enabled()) { diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 24d9fff170..4aa70ceca1 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -204,10 +204,12 @@ typedef struct { # define ARM_MAX_VQ 16 void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp); void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp); +void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp); #else # define ARM_MAX_VQ 1 static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { } static inline void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) { } +static inline void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) { } #endif typedef struct ARMVectorReg { @@ -975,10 +977,11 @@ struct ARMCPU { /* * Intermediate values used during property parsing. - * Once finalized, the values should be read from ID_AA64ISAR1. + * Once finalized, the values should be read from ID_AA64*. */ bool prop_pauth; bool prop_pauth_impdef; + bool prop_lpa2; /* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */ uint32_t dcz_blocksize; diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 2fdc16bf18..eb44c05822 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -688,6 +688,29 @@ void aarch64_add_pauth_properties(Object *obj) } } +static Property arm_cpu_lpa2_property = + DEFINE_PROP_BOOL("lpa2", ARMCPU, prop_lpa2, true); + +void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) +{ + uint64_t t; + + /* + * We only install the property for tcg -cpu max; this is the + * only situation in which the cpu field can be true. + */ + if (!cpu->prop_lpa2) { + return; + } + + t = cpu->isar.id_aa64mmfr0; + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 2); /* 16k pages w/ LPA2 */ + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4, 1); /* 4k pages w/ LPA2 */ + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 3); /* 16k stage2 w/ LPA2 */ + t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 3); /* 4k stage2 w/ LPA2 */ + cpu->isar.id_aa64mmfr0 = t; +} + static void aarch64_host_initfn(Object *obj) { #if defined(CONFIG_KVM) @@ -897,6 +920,7 @@ static void aarch64_max_initfn(Object *obj) aarch64_add_sve_properties(obj); object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq, cpu_max_set_sve_max_vq, NULL, NULL); + qdev_property_add_static(DEVICE(obj), &arm_cpu_lpa2_property); } static void aarch64_a64fx_initfn(Object *obj) diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py index ab19146d1e..ee584d2fdf 100644 --- a/tests/avocado/boot_linux.py +++ b/tests/avocado/boot_linux.py @@ -79,6 +79,7 @@ class BootLinuxAarch64(LinuxTest): """ self.require_accelerator("tcg") self.vm.add_args("-accel", "tcg") + self.vm.add_args("-cpu", "max,lpa2=off") self.vm.add_args("-machine", "virt,gic-version=2") self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) @@ -91,6 +92,7 @@ class BootLinuxAarch64(LinuxTest): """ self.require_accelerator("tcg") self.vm.add_args("-accel", "tcg") + self.vm.add_args("-cpu", "max,lpa2=off") self.vm.add_args("-machine", "virt,gic-version=3") self.add_common_args() self.launch_and_wait(set_up_ssh_connection=False) From 0942820408dc788560f6968e9b5f011803b846c2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 1 Mar 2022 11:59:58 -1000 Subject: [PATCH 18/18] hw/arm/virt: Disable LPA2 for -machine virt-6.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a Linux kernel bug present until v5.12 that prevents booting with FEAT_LPA2 enabled. As a workaround for TCG, disable this feature for machine versions prior to 7.0. Cc: Daniel P. Berrangé Signed-off-by: Richard Henderson Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- hw/arm/virt.c | 7 +++++++ include/hw/arm/virt.h | 1 + 2 files changed, 8 insertions(+) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 46bf7ceddf..46a42502bc 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2102,6 +2102,10 @@ static void machvirt_init(MachineState *machine) object_property_set_bool(cpuobj, "pmu", false, NULL); } + if (vmc->no_tcg_lpa2 && object_property_find(cpuobj, "lpa2")) { + object_property_set_bool(cpuobj, "lpa2", false, NULL); + } + if (object_property_find(cpuobj, "reset-cbar")) { object_property_set_int(cpuobj, "reset-cbar", vms->memmap[VIRT_CPUPERIPHS].base, @@ -3020,8 +3024,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(7, 0) static void virt_machine_6_2_options(MachineClass *mc) { + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); + virt_machine_7_0_options(mc); compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len); + vmc->no_tcg_lpa2 = true; } DEFINE_VIRT_MACHINE(6, 2) diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index c1ea17d0de..7e76ee2619 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -132,6 +132,7 @@ struct VirtMachineClass { bool no_secure_gpio; /* Machines < 6.2 have no support for describing cpu topology to guest */ bool no_cpu_topology; + bool no_tcg_lpa2; }; struct VirtMachineState {