* bug fixes

* reduced memory footprint for IPI virtualization on Intel processors
 * asynchronous teardown support (Linux only)
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmNiVykUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroN0Swf/YxjphCtFgYYSO14WP+7jAnfRZLhm
 0xWChWP8rco5I352OBFeFU64Av5XoLGNn6SZLl8lcg86lQ/G0D27jxu6wOcDDHgw
 0yTDO1gevj51UKsbxoC66OWSZwKTEo398/BHPDcI2W41yOFycSdtrPgspOrFRVvf
 7M3nNjuNPsQorZeuu8NGr3jakqbt99ZDXcyDEWbrEAcmy2JBRMbGgT0Kdnc6aZfW
 CvL+1ljxzldNwGeNBbQW2QgODbfHx5cFZcy4Daze35l5Ra7K/FrgAzr6o/HXptya
 9fEs5LJQ1JWI6JtpaWwFy7fcIIOsJ0YW/hWWQZSDt9JdAJFE5/+vF+Kz5Q==
 =CgrO
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* bug fixes
* reduced memory footprint for IPI virtualization on Intel processors
* asynchronous teardown support (Linux only)

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmNiVykUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroN0Swf/YxjphCtFgYYSO14WP+7jAnfRZLhm
# 0xWChWP8rco5I352OBFeFU64Av5XoLGNn6SZLl8lcg86lQ/G0D27jxu6wOcDDHgw
# 0yTDO1gevj51UKsbxoC66OWSZwKTEo398/BHPDcI2W41yOFycSdtrPgspOrFRVvf
# 7M3nNjuNPsQorZeuu8NGr3jakqbt99ZDXcyDEWbrEAcmy2JBRMbGgT0Kdnc6aZfW
# CvL+1ljxzldNwGeNBbQW2QgODbfHx5cFZcy4Daze35l5Ra7K/FrgAzr6o/HXptya
# 9fEs5LJQ1JWI6JtpaWwFy7fcIIOsJ0YW/hWWQZSDt9JdAJFE5/+vF+Kz5Q==
# =CgrO
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 02 Nov 2022 07:40:25 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:
  target/i386: Fix test for paging enabled
  util/log: Close per-thread log file on thread termination
  target/i386: Set maximum APIC ID to KVM prior to vCPU creation
  os-posix: asynchronous teardown for shutdown on Linux
  target/i386: Fix calculation of LOCK NEG eflags

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2022-11-03 10:54:37 -04:00
commit 7f5acfcb66
13 changed files with 230 additions and 6 deletions

150
util/async-teardown.c Normal file
View file

@ -0,0 +1,150 @@
/*
* 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 <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/prctl.h>
#include <signal.h>
#include <sched.h>
#include <unistd.h>
#include "qemu/osdep.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);
}

View file

@ -42,6 +42,7 @@ static QemuMutex global_mutex;
static char *global_filename;
static FILE *global_file;
static __thread FILE *thread_file;
static __thread Notifier qemu_log_thread_cleanup_notifier;
int qemu_loglevel;
static bool log_append;
@ -77,6 +78,12 @@ static int log_thread_id(void)
#endif
}
static void qemu_log_thread_cleanup(Notifier *n, void *unused)
{
fclose(thread_file);
thread_file = NULL;
}
/* Lock/unlock output. */
FILE *qemu_log_trylock(void)
@ -93,6 +100,8 @@ FILE *qemu_log_trylock(void)
return NULL;
}
thread_file = logfile;
qemu_log_thread_cleanup_notifier.notify = qemu_log_thread_cleanup;
qemu_thread_atexit_add(&qemu_log_thread_cleanup_notifier);
} else {
rcu_read_lock();
/*

View file

@ -3,6 +3,7 @@ util_ss.add(files('thread-context.c'), numa)
if not config_host_data.get('CONFIG_ATOMIC64')
util_ss.add(files('atomic64.c'))
endif
util_ss.add(when: 'CONFIG_LINUX', if_true: files('async-teardown.c'))
util_ss.add(when: 'CONFIG_POSIX', if_true: files('aio-posix.c'))
util_ss.add(when: 'CONFIG_POSIX', if_true: files('fdmon-poll.c'))
if config_host_data.get('CONFIG_EPOLL_CREATE1')