From 6063d3fedb2767f1a4d668828f49ef8505fa54f3 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 10 Jun 2025 13:36:40 +0100 Subject: [PATCH 10/43] hw/virtio/virtio: avoid cost of -ftrivial-auto-var-init in hot path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Stefan Hajnoczi RH-MergeRequest: 381: Solve -ftrivial-auto-var-init performance regression with QEMU_UNINITIALIZED RH-Jira: RHEL-95479 RH-Acked-by: Miroslav Rezanina RH-Commit: [2/31] 12f251ba363203812e46f268a6f46ccfdbf21b41 (stefanha/centos-stream-qemu-kvm) Since commit 7ff9ff039380 ("meson: mitigate against use of uninitialize stack for exploits") the -ftrivial-auto-var-init=zero compiler option is used to zero local variables. While this reduces security risks associated with uninitialized stack data, it introduced a measurable bottleneck in the virtqueue_split_pop() and virtqueue_packed_pop() functions. These virtqueue functions are in the hot path. They are called for each element (request) that is popped from a VIRTIO device's virtqueue. Using __attribute__((uninitialized)) on large stack variables in these functions improves fio randread bs=4k iodepth=64 performance from 304k to 332k IOPS (+9%). This issue was found using perf-top(1). virtqueue_split_pop() was one of the top CPU consumers and the "annotate" feature showed that the memory zeroing instructions at the beginning of the functions were hot. Fixes: 7ff9ff039380 ("meson: mitigate against use of uninitialize stack for exploits") Cc: Daniel P. Berrangé Signed-off-by: Stefan Hajnoczi Reviewed-by: Stefan Hajnoczi Message-id: 20250610123709.835102-3-berrange@redhat.com Signed-off-by: Stefan Hajnoczi (cherry picked from commit ba2868ce091cd4abe4be6de4b7e44b3be303b352) Signed-off-by: Stefan Hajnoczi --- hw/virtio/virtio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 85110bce37..f41a418da3 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1680,8 +1680,8 @@ static void *virtqueue_split_pop(VirtQueue *vq, size_t sz) VirtIODevice *vdev = vq->vdev; VirtQueueElement *elem = NULL; unsigned out_num, in_num, elem_entries; - hwaddr addr[VIRTQUEUE_MAX_SIZE]; - struct iovec iov[VIRTQUEUE_MAX_SIZE]; + hwaddr QEMU_UNINITIALIZED addr[VIRTQUEUE_MAX_SIZE]; + struct iovec QEMU_UNINITIALIZED iov[VIRTQUEUE_MAX_SIZE]; VRingDesc desc; int rc; @@ -1826,8 +1826,8 @@ static void *virtqueue_packed_pop(VirtQueue *vq, size_t sz) VirtIODevice *vdev = vq->vdev; VirtQueueElement *elem = NULL; unsigned out_num, in_num, elem_entries; - hwaddr addr[VIRTQUEUE_MAX_SIZE]; - struct iovec iov[VIRTQUEUE_MAX_SIZE]; + hwaddr QEMU_UNINITIALIZED addr[VIRTQUEUE_MAX_SIZE]; + struct iovec QEMU_UNINITIALIZED iov[VIRTQUEUE_MAX_SIZE]; VRingPackedDesc desc; uint16_t id; int rc; -- 2.39.3