aboutsummaryrefslogtreecommitdiff
path: root/softmmu
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2023-09-07 10:29:06 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2023-09-07 10:29:06 -0400
commit03a3a62fbd0aa5227e978eef3c67d3978aec9e5f (patch)
tree0979b98ba5a0610cae753a05153714f45b90389b /softmmu
parent13d9f6dca08a38e9258b6328f3ad61bdb8e19619 (diff)
parent34e8182053c065e5e99017f798fb79259e26f583 (diff)
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
* only build util/async-teardown.c when system build is requested * target/i386: fix BQL handling of the legacy FERR interrupts * target/i386: fix memory operand size for CVTPS2PD * target/i386: Add support for AMX-COMPLEX in CPUID enumeration * compile plugins on Darwin * configure and meson cleanups * drop mkvenv support for Python 3.7 and Debian10 * add wrap file for libblkio * tweak KVM stubs # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmT5t6UUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroMmjwf+MpvVuq+nn+3PqGUXgnzJx5ccA5ne # O9Xy8+1GdlQPzBw/tPovxXDSKn3HQtBfxObn2CCE1tu/4uHWpBA1Vksn++NHdUf2 # P0yoHxGskJu5iYYTtIcNw5cH2i+AizdiXuEjhfNjqD5Y234cFoHnUApt9e3zBvVO # cwGD7WpPuSb4g38hHkV6nKcx72o7b4ejDToqUVZJ2N+RkddSqB03fSdrOru0hR7x # V+lay0DYdFszNDFm05LJzfDbcrHuSryGA91wtty7Fzj6QhR/HBHQCUZJxMB5PI7F # Zy4Zdpu60zxtSxUqeKgIi7UhNFgMcax2Hf9QEqdc/B4ARoBbboh4q4u8kQ== # =dH7/ # -----END PGP SIGNATURE----- # gpg: Signature made Thu 07 Sep 2023 07:44:37 EDT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (51 commits) docs/system/replay: do not show removed command line option subprojects: add wrap file for libblkio sysemu/kvm: Restrict kvm_pc_setup_irq_routing() to x86 targets sysemu/kvm: Restrict kvm_has_pit_state2() to x86 targets sysemu/kvm: Restrict kvm_get_apic_state() to x86 targets sysemu/kvm: Restrict kvm_arch_get_supported_cpuid/msr() to x86 targets target/i386: Restrict declarations specific to CONFIG_KVM target/i386: Allow elision of kvm_hv_vpindex_settable() target/i386: Allow elision of kvm_enable_x2apic() target/i386: Remove unused KVM stubs target/i386/cpu-sysemu: Inline kvm_apic_in_kernel() target/i386/helper: Restrict KVM declarations to system emulation hw/i386/fw_cfg: Include missing 'cpu.h' header hw/i386/pc: Include missing 'cpu.h' header hw/i386/pc: Include missing 'sysemu/tcg.h' header Revert "mkvenv: work around broken pip installations on Debian 10" mkvenv: assume presence of importlib.metadata Python: Drop support for Python 3.7 configure: remove dead code meson: list leftover CONFIG_* symbols ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'softmmu')
-rw-r--r--softmmu/async-teardown.c146
-rw-r--r--softmmu/meson.build1
-rw-r--r--softmmu/vl.c87
3 files changed, 230 insertions, 4 deletions
diff --git a/softmmu/async-teardown.c b/softmmu/async-teardown.c
new file mode 100644
index 0000000000..62cdeb0f20
--- /dev/null
+++ b/softmmu/async-teardown.c
@@ -0,0 +1,146 @@
+/*
+ * Asynchronous teardown
+ *
+ * Copyright IBM, Corp. 2022
+ *
+ * Authors:
+ * Claudio Imbrenda <imbrenda@linux.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version. See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include <dirent.h>
+#include <sys/prctl.h>
+#include <sched.h>
+
+#include "qemu/async-teardown.h"
+
+#ifdef _SC_THREAD_STACK_MIN
+#define CLONE_STACK_SIZE sysconf(_SC_THREAD_STACK_MIN)
+#else
+#define CLONE_STACK_SIZE 16384
+#endif
+
+static pid_t the_ppid;
+
+/*
+ * Close all open file descriptors.
+ */
+static void close_all_open_fd(void)
+{
+ struct dirent *de;
+ int fd, dfd;
+ DIR *dir;
+
+#ifdef CONFIG_CLOSE_RANGE
+ int r = close_range(0, ~0U, 0);
+ if (!r) {
+ /* Success, no need to try other ways. */
+ return;
+ }
+#endif
+
+ dir = opendir("/proc/self/fd");
+ if (!dir) {
+ /* If /proc is not mounted, there is nothing that can be done. */
+ return;
+ }
+ /* Avoid closing the directory. */
+ dfd = dirfd(dir);
+
+ for (de = readdir(dir); de; de = readdir(dir)) {
+ fd = atoi(de->d_name);
+ if (fd != dfd) {
+ close(fd);
+ }
+ }
+ closedir(dir);
+}
+
+static void hup_handler(int signal)
+{
+ /* Check every second if this process has been reparented. */
+ while (the_ppid == getppid()) {
+ /* sleep() is safe to use in a signal handler. */
+ sleep(1);
+ }
+
+ /* At this point the parent process has terminated completely. */
+ _exit(0);
+}
+
+static int async_teardown_fn(void *arg)
+{
+ struct sigaction sa = { .sa_handler = hup_handler };
+ sigset_t hup_signal;
+ char name[16];
+
+ /* Set a meaningful name for this process. */
+ snprintf(name, 16, "cleanup/%d", the_ppid);
+ prctl(PR_SET_NAME, (unsigned long)name);
+
+ /*
+ * Close all file descriptors that might have been inherited from the
+ * main qemu process when doing clone, needed to make libvirt happy.
+ * Not using close_range for increased compatibility with older kernels.
+ */
+ close_all_open_fd();
+
+ /* Set up a handler for SIGHUP and unblock SIGHUP. */
+ sigaction(SIGHUP, &sa, NULL);
+ sigemptyset(&hup_signal);
+ sigaddset(&hup_signal, SIGHUP);
+ sigprocmask(SIG_UNBLOCK, &hup_signal, NULL);
+
+ /* Ask to receive SIGHUP when the parent dies. */
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+
+ /*
+ * Sleep forever, unless the parent process has already terminated. The
+ * only interruption can come from the SIGHUP signal, which in normal
+ * operation is received when the parent process dies.
+ */
+ if (the_ppid == getppid()) {
+ pause();
+ }
+
+ /* At this point the parent process has terminated completely. */
+ _exit(0);
+}
+
+/*
+ * Allocate a new stack of a reasonable size, and return a pointer to its top.
+ */
+static void *new_stack_for_clone(void)
+{
+ size_t stack_size = CLONE_STACK_SIZE;
+ char *stack_ptr;
+
+ /* Allocate a new stack and get a pointer to its top. */
+ stack_ptr = qemu_alloc_stack(&stack_size);
+#if !defined(HOST_HPPA)
+ /* The top is at the end of the area, except on HPPA. */
+ stack_ptr += stack_size;
+#endif
+
+ return stack_ptr;
+}
+
+/*
+ * Block all signals, start (clone) a new process sharing the address space
+ * with qemu (CLONE_VM), then restore signals.
+ */
+void init_async_teardown(void)
+{
+ sigset_t all_signals, old_signals;
+
+ the_ppid = getpid();
+
+ sigfillset(&all_signals);
+ sigprocmask(SIG_BLOCK, &all_signals, &old_signals);
+ clone(async_teardown_fn, new_stack_for_clone(), CLONE_VM, NULL);
+ sigprocmask(SIG_SETMASK, &old_signals, NULL);
+}
diff --git a/softmmu/meson.build b/softmmu/meson.build
index ea5603f021..c18b7ad738 100644
--- a/softmmu/meson.build
+++ b/softmmu/meson.build
@@ -37,3 +37,4 @@ endif
system_ss.add(when: seccomp, if_true: files('qemu-seccomp.c'))
system_ss.add(when: fdt, if_true: files('device_tree.c'))
+system_ss.add(when: 'CONFIG_LINUX', if_true: files('async-teardown.c'))
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 5a10b3c309..3db4fd2680 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -49,6 +49,7 @@
#include "qemu/error-report.h"
#include "qemu/sockets.h"
#include "qemu/accel.h"
+#include "qemu/async-teardown.h"
#include "hw/usb.h"
#include "hw/isa/isa.h"
#include "hw/scsi/scsi.h"
@@ -89,7 +90,6 @@
#include "qapi/qobject-input-visitor.h"
#include "qemu/option.h"
#include "qemu/config-file.h"
-#include "qemu/qemu-options.h"
#include "qemu/main-loop.h"
#ifdef CONFIG_VIRTFS
#include "fsdev/qemu-fsdev.h"
@@ -747,6 +747,33 @@ static QemuOptsList qemu_smp_opts = {
},
};
+#if defined(CONFIG_POSIX)
+static QemuOptsList qemu_run_with_opts = {
+ .name = "run-with",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_run_with_opts.head),
+ .desc = {
+#if defined(CONFIG_LINUX)
+ {
+ .name = "async-teardown",
+ .type = QEMU_OPT_BOOL,
+ },
+#endif
+ {
+ .name = "chroot",
+ .type = QEMU_OPT_STRING,
+ },
+ { /* end of list */ }
+ },
+};
+
+#define qemu_add_run_with_opts() qemu_add_opts(&qemu_run_with_opts)
+
+#else
+
+#define qemu_add_run_with_opts()
+
+#endif /* CONFIG_POSIX */
+
static void realtime_init(void)
{
if (enable_mlock) {
@@ -865,6 +892,16 @@ static void help(int exitcode)
exit(exitcode);
}
+enum {
+
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
+ opt_enum,
+#define DEFHEADING(text)
+#define ARCHHEADING(text, arch_mask)
+
+#include "qemu-options.def"
+};
+
#define HAS_ARG 0x0001
typedef struct QEMUOption {
@@ -2698,6 +2735,7 @@ void qemu_init(int argc, char **argv)
qemu_add_opts(&qemu_semihosting_config_opts);
qemu_add_opts(&qemu_fw_cfg_opts);
qemu_add_opts(&qemu_action_opts);
+ qemu_add_run_with_opts();
module_call_init(MODULE_INIT_OPTS);
error_init(argv[0]);
@@ -3516,11 +3554,52 @@ void qemu_init(int argc, char **argv)
case QEMU_OPTION_nouserconfig:
/* Nothing to be parsed here. Especially, do not error out below. */
break;
- default:
- if (os_parse_cmd_args(popt->index, optarg)) {
- error_report("Option not supported in this build");
+#if defined(CONFIG_POSIX)
+ case QEMU_OPTION_runas:
+ if (!os_set_runas(optarg)) {
+ error_report("User \"%s\" doesn't exist"
+ " (and is not <uid>:<gid>)",
+ optarg);
exit(1);
}
+ break;
+ case QEMU_OPTION_chroot:
+ warn_report("option is deprecated,"
+ " use '-run-with chroot=...' instead");
+ os_set_chroot(optarg);
+ break;
+ case QEMU_OPTION_daemonize:
+ os_set_daemonize(true);
+ break;
+#if defined(CONFIG_LINUX)
+ /* deprecated */
+ case QEMU_OPTION_asyncteardown:
+ init_async_teardown();
+ break;
+#endif
+ case QEMU_OPTION_run_with: {
+ const char *str;
+ opts = qemu_opts_parse_noisily(qemu_find_opts("run-with"),
+ optarg, false);
+ if (!opts) {
+ exit(1);
+ }
+#if defined(CONFIG_LINUX)
+ if (qemu_opt_get_bool(opts, "async-teardown", false)) {
+ init_async_teardown();
+ }
+#endif
+ str = qemu_opt_get(opts, "chroot");
+ if (str) {
+ os_set_chroot(str);
+ }
+ break;
+ }
+#endif /* CONFIG_POSIX */
+
+ default:
+ error_report("Option not supported in this build");
+ exit(1);
}
}
}