[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL v3 35/55] util/oslib-posix: Forward SIGBUS to MCE handler under Li
From: |
Michael S. Tsirkin |
Subject: |
[PULL v3 35/55] util/oslib-posix: Forward SIGBUS to MCE handler under Linux |
Date: |
Fri, 7 Jan 2022 20:05:27 -0500 |
From: David Hildenbrand <david@redhat.com>
Temporarily modifying the SIGBUS handler is really nasty, as we might be
unlucky and receive an MCE SIGBUS while having our handler registered.
Unfortunately, there is no way around messing with SIGBUS when
MADV_POPULATE_WRITE is not applicable or not around.
Let's forward SIGBUS that don't belong to us to the already registered
handler and document the situation.
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20211217134611.31172-8-david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
softmmu/cpus.c | 4 ++++
util/oslib-posix.c | 37 ++++++++++++++++++++++++++++++++++---
2 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/softmmu/cpus.c b/softmmu/cpus.c
index 071085f840..23bca46b07 100644
--- a/softmmu/cpus.c
+++ b/softmmu/cpus.c
@@ -352,6 +352,10 @@ static void qemu_init_sigbus(void)
{
struct sigaction action;
+ /*
+ * ALERT: when modifying this, take care that SIGBUS forwarding in
+ * os_mem_prealloc() will continue working as expected.
+ */
memset(&action, 0, sizeof(action));
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = sigbus_handler;
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 9829149e4b..9efdc74bba 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -35,6 +35,7 @@
#include "sysemu/sysemu.h"
#include "trace.h"
#include "qapi/error.h"
+#include "qemu/error-report.h"
#include "qemu/sockets.h"
#include "qemu/thread.h"
#include <libgen.h>
@@ -95,6 +96,7 @@ typedef struct MemsetThread MemsetThread;
/* used by sigbus_handler() */
static MemsetContext *sigbus_memset_context;
+struct sigaction sigbus_oldact;
static QemuMutex sigbus_mutex;
static QemuMutex page_mutex;
@@ -446,7 +448,11 @@ const char *qemu_get_exec_dir(void)
return exec_dir;
}
+#ifdef CONFIG_LINUX
+static void sigbus_handler(int signal, siginfo_t *siginfo, void *ctx)
+#else /* CONFIG_LINUX */
static void sigbus_handler(int signal)
+#endif /* CONFIG_LINUX */
{
int i;
@@ -459,6 +465,26 @@ static void sigbus_handler(int signal)
}
}
}
+
+#ifdef CONFIG_LINUX
+ /*
+ * We assume that the MCE SIGBUS handler could have been registered. We
+ * should never receive BUS_MCEERR_AO on any of our threads, but only on
+ * the main thread registered for PR_MCE_KILL_EARLY. Further, we should not
+ * receive BUS_MCEERR_AR triggered by action of other threads on one of
+ * our threads. So, no need to check for unrelated SIGBUS when seeing one
+ * for our threads.
+ *
+ * We will forward to the MCE handler, which will either handle the SIGBUS
+ * or reinstall the default SIGBUS handler and reraise the SIGBUS. The
+ * default SIGBUS handler will crash the process, so we don't care.
+ */
+ if (sigbus_oldact.sa_flags & SA_SIGINFO) {
+ sigbus_oldact.sa_sigaction(signal, siginfo, ctx);
+ return;
+ }
+#endif /* CONFIG_LINUX */
+ warn_report("os_mem_prealloc: unrelated SIGBUS detected and ignored");
}
static void *do_touch_pages(void *arg)
@@ -628,10 +654,10 @@ void os_mem_prealloc(int fd, char *area, size_t memory,
int smp_cpus,
{
static gsize initialized;
int ret;
- struct sigaction act, oldact;
size_t hpagesize = qemu_fd_getpagesize(fd);
size_t numpages = DIV_ROUND_UP(memory, hpagesize);
bool use_madv_populate_write;
+ struct sigaction act;
/*
* Sense on every invocation, as MADV_POPULATE_WRITE cannot be used for
@@ -647,10 +673,15 @@ void os_mem_prealloc(int fd, char *area, size_t memory,
int smp_cpus,
qemu_mutex_lock(&sigbus_mutex);
memset(&act, 0, sizeof(act));
+#ifdef CONFIG_LINUX
+ act.sa_sigaction = &sigbus_handler;
+ act.sa_flags = SA_SIGINFO;
+#else /* CONFIG_LINUX */
act.sa_handler = &sigbus_handler;
act.sa_flags = 0;
+#endif /* CONFIG_LINUX */
- ret = sigaction(SIGBUS, &act, &oldact);
+ ret = sigaction(SIGBUS, &act, &sigbus_oldact);
if (ret) {
error_setg_errno(errp, errno,
"os_mem_prealloc: failed to install signal handler");
@@ -667,7 +698,7 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int
smp_cpus,
}
if (!use_madv_populate_write) {
- ret = sigaction(SIGBUS, &oldact, NULL);
+ ret = sigaction(SIGBUS, &sigbus_oldact, NULL);
if (ret) {
/* Terminate QEMU since it can't recover from error */
perror("os_mem_prealloc: failed to reinstall signal handler");
--
MST
- [PULL v3 25/55] smbios: Rename SMBIOS_ENTRY_POINT_* enums, (continued)
- [PULL v3 25/55] smbios: Rename SMBIOS_ENTRY_POINT_* enums, Michael S. Tsirkin, 2022/01/07
- [PULL v3 27/55] hw/i386: expose a "smbios-entry-point-type" PC machine property, Michael S. Tsirkin, 2022/01/07
- [PULL v3 31/55] util/oslib-posix: Introduce and use MemsetContext for touch_all_pages(), Michael S. Tsirkin, 2022/01/07
- [PULL v3 28/55] hw/vhost-user-blk: turn on VIRTIO_BLK_F_SIZE_MAX feature for virtio blk device, Michael S. Tsirkin, 2022/01/07
- [PULL v3 29/55] util/oslib-posix: Let touch_all_pages() return an error, Michael S. Tsirkin, 2022/01/07
- [PULL v3 32/55] util/oslib-posix: Don't create too many threads with small memory or little pages, Michael S. Tsirkin, 2022/01/07
- [PULL v3 33/55] util/oslib-posix: Avoid creating a single thread with MADV_POPULATE_WRITE, Michael S. Tsirkin, 2022/01/07
- [PULL v3 30/55] util/oslib-posix: Support MADV_POPULATE_WRITE for os_mem_prealloc(), Michael S. Tsirkin, 2022/01/07
- [PULL v3 36/55] virtio-mem: Support "prealloc=on" option, Michael S. Tsirkin, 2022/01/07
- [PULL v3 34/55] util/oslib-posix: Support concurrent os_mem_prealloc() invocation, Michael S. Tsirkin, 2022/01/07
- [PULL v3 35/55] util/oslib-posix: Forward SIGBUS to MCE handler under Linux,
Michael S. Tsirkin <=
- [PULL v3 37/55] virtio: signal after wrapping packed used_idx, Michael S. Tsirkin, 2022/01/07
- [PULL v3 38/55] MAINTAINERS: Add a separate entry for acpi/VIOT tables, Michael S. Tsirkin, 2022/01/07
- [PULL v3 39/55] linux-headers: sync VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, Michael S. Tsirkin, 2022/01/07
- [PULL v3 40/55] virtio-mem: Support VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, Michael S. Tsirkin, 2022/01/07
- [PULL v3 41/55] virtio-mem: Set "unplugged-inaccessible=auto" for the 7.0 machine on x86, Michael S. Tsirkin, 2022/01/07
- [PULL v3 42/55] intel-iommu: correctly check passthrough during translation, Michael S. Tsirkin, 2022/01/07
- [PULL v3 43/55] acpi: fix QEMU crash when started with SLIC table, Michael S. Tsirkin, 2022/01/07
- [PULL v3 44/55] tests: acpi: whitelist expected blobs before changing them, Michael S. Tsirkin, 2022/01/07
- [PULL v3 45/55] tests: acpi: add SLIC table test, Michael S. Tsirkin, 2022/01/07
- [PULL v3 46/55] tests: acpi: SLIC: update expected blobs, Michael S. Tsirkin, 2022/01/07