From 1f546b709d6121d1a3e629e482ba14fb7bf10ce2 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Tue, 15 Jun 2021 13:55:23 -0400 Subject: [PATCH 01/76] tests: migration-test: Add dirty ring test Add dirty ring test if kernel supports it. Add the dirty ring parameter on source should be mostly enough, but let's change the dest too to make them match always. Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Peter Xu Message-Id: <20210615175523.439830-3-peterx@redhat.com> Reviewed-by: Juan Quintela Signed-off-by: Dr. David Alan Gilbert --- tests/qtest/migration-test.c | 58 ++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 2b028df687..328d6dbe97 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -27,6 +27,10 @@ #include "migration-helpers.h" #include "tests/migration/migration-test.h" +#if defined(__linux__) +#include "linux/kvm.h" +#endif + /* TODO actually test the results and get rid of this */ #define qtest_qmp_discard_response(...) qobject_unref(qtest_qmp(__VA_ARGS__)) @@ -467,6 +471,8 @@ typedef struct { bool use_shmem; /* only launch the target process */ bool only_target; + /* Use dirty ring if true; dirty logging otherwise */ + bool use_dirty_ring; char *opts_source; char *opts_target; } MigrateStart; @@ -573,11 +579,13 @@ static int test_migrate_start(QTestState **from, QTestState **to, shmem_opts = g_strdup(""); } - cmd_source = g_strdup_printf("-accel kvm -accel tcg%s%s " + cmd_source = g_strdup_printf("-accel kvm%s -accel tcg%s%s " "-name source,debug-threads=on " "-m %s " "-serial file:%s/src_serial " "%s %s %s %s", + args->use_dirty_ring ? + ",dirty-ring-size=4096" : "", machine_opts ? " -machine " : "", machine_opts ? machine_opts : "", memory_size, tmpfs, @@ -587,12 +595,14 @@ static int test_migrate_start(QTestState **from, QTestState **to, *from = qtest_init(cmd_source); } - cmd_target = g_strdup_printf("-accel kvm -accel tcg%s%s " + cmd_target = g_strdup_printf("-accel kvm%s -accel tcg%s%s " "-name target,debug-threads=on " "-m %s " "-serial file:%s/dest_serial " "-incoming %s " "%s %s %s %s", + args->use_dirty_ring ? + ",dirty-ring-size=4096" : "", machine_opts ? " -machine " : "", machine_opts ? machine_opts : "", memory_size, tmpfs, uri, @@ -785,12 +795,14 @@ static void test_baddest(void) test_migrate_end(from, to, false); } -static void test_precopy_unix(void) +static void test_precopy_unix_common(bool dirty_ring) { g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); MigrateStart *args = migrate_start_new(); QTestState *from, *to; + args->use_dirty_ring = dirty_ring; + if (test_migrate_start(&from, &to, uri, args)) { return; } @@ -825,6 +837,18 @@ static void test_precopy_unix(void) test_migrate_end(from, to, true); } +static void test_precopy_unix(void) +{ + /* Using default dirty logging */ + test_precopy_unix_common(false); +} + +static void test_precopy_unix_dirty_ring(void) +{ + /* Using dirty ring tracking */ + test_precopy_unix_common(true); +} + #if 0 /* Currently upset on aarch64 TCG */ static void test_ignore_shared(void) @@ -1369,6 +1393,29 @@ static void test_multifd_tcp_cancel(void) test_migrate_end(from, to2, true); } +static bool kvm_dirty_ring_supported(void) +{ +#if defined(__linux__) + int ret, kvm_fd = open("/dev/kvm", O_RDONLY); + + if (kvm_fd < 0) { + return false; + } + + ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_DIRTY_LOG_RING); + close(kvm_fd); + + /* We test with 4096 slots */ + if (ret < 4096) { + return false; + } + + return true; +#else + return false; +#endif +} + int main(int argc, char **argv) { char template[] = "/tmp/migration-test-XXXXXX"; @@ -1439,6 +1486,11 @@ int main(int argc, char **argv) qtest_add_func("/migration/multifd/tcp/zstd", test_multifd_tcp_zstd); #endif + if (kvm_dirty_ring_supported()) { + qtest_add_func("/migration/dirty_ring", + test_precopy_unix_dirty_ring); + } + ret = g_test_run(); g_assert_cmpint(ret, ==, 0); From c00d434ac6f202b1e81aa52f3385bd9c22ac1599 Mon Sep 17 00:00:00 2001 From: Feng Lin Date: Fri, 25 Jun 2021 14:21:38 +0800 Subject: [PATCH 02/76] migration: fix the memory overwriting risk in add_to_iovec When testing migration, a Segmentation fault qemu core is generated. 0 error_free (err=0x1) 1 0x00007f8b862df647 in qemu_fclose (f=f@entry=0x55e06c247640) 2 0x00007f8b8516d59a in migrate_fd_cleanup (s=s@entry=0x55e06c0e1ef0) 3 0x00007f8b8516d66c in migrate_fd_cleanup_bh (opaque=0x55e06c0e1ef0) 4 0x00007f8b8626a47f in aio_bh_poll (ctx=ctx@entry=0x55e06b5a16d0) 5 0x00007f8b8626e71f in aio_dispatch (ctx=0x55e06b5a16d0) 6 0x00007f8b8626a33d in aio_ctx_dispatch (source=, callback=, user_data=) 7 0x00007f8b866bdba4 in g_main_context_dispatch () 8 0x00007f8b8626cde9 in glib_pollfds_poll () 9 0x00007f8b8626ce62 in os_host_main_loop_wait (timeout=) 10 0x00007f8b8626cffd in main_loop_wait (nonblocking=nonblocking@entry=0) 11 0x00007f8b862ef01f in main_loop () Using gdb print the struct QEMUFile f = { ..., iovcnt = 65, last_error = 21984, last_error_obj = 0x1, shutdown = true } Well iovcnt is overflow, because the max size of MAX_IOV_SIZE is 64. struct QEMUFile { ...; struct iovec iov[MAX_IOV_SIZE]; unsigned int iovcnt; int last_error; Error *last_error_obj; bool shutdown; }; iovcnt and last_error is overwrited by add_to_iovec(). Right now, add_to_iovec() increase iovcnt before check the limit. And it seems that add_to_iovec() assumes that iovcnt will set to zero in qemu_fflush(). But qemu_fflush() will directly return when f->shutdown is true. The situation may occur when libvirtd restart during migration, after f->shutdown is set, before calling qemu_file_set_error() in qemu_file_shutdown(). So the safiest way is checking the iovcnt before increasing it. Signed-off-by: Feng Lin Message-Id: <20210625062138.1899-1-linfeng23@huawei.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert Fix typo in 'writeable' which is actually misnamed 'writable' --- migration/qemu-file.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/migration/qemu-file.c b/migration/qemu-file.c index d6e03dbc0e..1eacf9e831 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -416,6 +416,11 @@ static int add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size, { f->iov[f->iovcnt - 1].iov_len += size; } else { + if (f->iovcnt >= MAX_IOV_SIZE) { + /* Should only happen if a previous fflush failed */ + assert(f->shutdown || !qemu_file_is_writable(f)); + return 1; + } if (may_free) { set_bit(f->iovcnt, f->may_free); } From cc48c587d25ff5dd7dddb4e5072de9ca8464c832 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Tue, 29 Jun 2021 14:13:55 -0400 Subject: [PATCH 03/76] migration: Move yank outside qemu_start_incoming_migration() Starting from commit b5eea99ec2f5c, qmp_migrate_recover() calls unregister before calling qemu_start_incoming_migration(). I believe it wanted to mitigate the next call to yank_register_instance(), but I think that's wrong. Firstly, if during recover, we should keep the yank instance there, not "quickly removing and adding it back". Meanwhile, calling qmp_migrate_recover() twice with b5eea99ec2f5c will directly crash the dest qemu (right now it can't; but it'll start to work right after the next patch) because the 1st call of qmp_migrate_recover() will unregister permanently when the channel failed to establish, then the 2nd call of qmp_migrate_recover() crashes at yank_unregister_instance(). This patch fixes it by moving yank ops out of qemu_start_incoming_migration() into qmp_migrate_incoming. For qmp_migrate_recover(), drop the unregister of yank instance too since we keep it there during the recovery phase. Signed-off-by: Peter Xu Reviewed-by: Dr. David Alan Gilbert Message-Id: <20210629181356.217312-2-peterx@redhat.com> Signed-off-by: Dr. David Alan Gilbert --- migration/migration.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 4228635d18..1bb03d1eca 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -456,10 +456,6 @@ static void qemu_start_incoming_migration(const char *uri, Error **errp) { const char *p = NULL; - if (!yank_register_instance(MIGRATION_YANK_INSTANCE, errp)) { - return; - } - qapi_event_send_migration(MIGRATION_STATUS_SETUP); if (strstart(uri, "tcp:", &p) || strstart(uri, "unix:", NULL) || @@ -474,7 +470,6 @@ static void qemu_start_incoming_migration(const char *uri, Error **errp) } else if (strstart(uri, "fd:", &p)) { fd_start_incoming_migration(p, errp); } else { - yank_unregister_instance(MIGRATION_YANK_INSTANCE); error_setg(errp, "unknown migration protocol: %s", uri); } } @@ -2083,9 +2078,14 @@ void qmp_migrate_incoming(const char *uri, Error **errp) return; } + if (!yank_register_instance(MIGRATION_YANK_INSTANCE, errp)) { + return; + } + qemu_start_incoming_migration(uri, &local_err); if (local_err) { + yank_unregister_instance(MIGRATION_YANK_INSTANCE); error_propagate(errp, local_err); return; } @@ -2114,7 +2114,6 @@ void qmp_migrate_recover(const char *uri, Error **errp) * only re-setup the migration stream and poke existing migration * to continue using that newly established channel. */ - yank_unregister_instance(MIGRATION_YANK_INSTANCE); qemu_start_incoming_migration(uri, errp); } From b7f9afd48e7bc5c341e55348f2c2eed08314be7d Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Tue, 29 Jun 2021 14:13:56 -0400 Subject: [PATCH 04/76] migration: Allow reset of postcopy_recover_triggered when failed It's possible qemu_start_incoming_migration() failed at any point, when it happens we should reset postcopy_recover_triggered to false so that the user can still retry with a saner incoming port. Signed-off-by: Peter Xu Message-Id: <20210629181356.217312-3-peterx@redhat.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- migration/migration.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/migration/migration.c b/migration/migration.c index 1bb03d1eca..fcca289ef7 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2097,6 +2097,13 @@ void qmp_migrate_recover(const char *uri, Error **errp) { MigrationIncomingState *mis = migration_incoming_get_current(); + /* + * Don't even bother to use ERRP_GUARD() as it _must_ always be set by + * callers (no one should ignore a recover failure); if there is, it's a + * programming error. + */ + assert(errp); + if (mis->state != MIGRATION_STATUS_POSTCOPY_PAUSED) { error_setg(errp, "Migrate recover can only be run " "when postcopy is paused."); @@ -2115,6 +2122,12 @@ void qmp_migrate_recover(const char *uri, Error **errp) * to continue using that newly established channel. */ qemu_start_incoming_migration(uri, errp); + + /* Safe to dereference with the assert above */ + if (*errp) { + /* Reset the flag so user could still retry */ + qatomic_set(&mis->postcopy_recover_triggered, false); + } } void qmp_migrate_pause(Error **errp) From fde93d99d9c208c07e2dcc24cd04e824d2b65b35 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Tue, 29 Jun 2021 17:50:06 +0200 Subject: [PATCH 05/76] migration: move wait-unplug loop to its own function The loop is used in migration_thread() and bg_migration_thread(), so we can move it to its own function and call it from these both places. Moreover, in migration_thread() we have a wrong state transition from SETUP to ACTIVE while state could be WAIT_UNPLUG. This is correctly managed in bg_migration_thread() so use this code instead. Signed-off-by: Laurent Vivier Message-Id: <20210629155007.629086-2-lvivier@redhat.com> Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Juan Quintela Signed-off-by: Dr. David Alan Gilbert --- migration/migration.c | 54 +++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index fcca289ef7..dbc484c802 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -3676,6 +3676,28 @@ bool migration_rate_limit(void) return urgent; } +/* + * if failover devices are present, wait they are completely + * unplugged + */ + +static void qemu_savevm_wait_unplug(MigrationState *s, int old_state, + int new_state) +{ + if (qemu_savevm_state_guest_unplug_pending()) { + migrate_set_state(&s->state, old_state, MIGRATION_STATUS_WAIT_UNPLUG); + + while (s->state == MIGRATION_STATUS_WAIT_UNPLUG && + qemu_savevm_state_guest_unplug_pending()) { + qemu_sem_timedwait(&s->wait_unplug_sem, 250); + } + + migrate_set_state(&s->state, MIGRATION_STATUS_WAIT_UNPLUG, new_state); + } else { + migrate_set_state(&s->state, old_state, new_state); + } +} + /* * Master migration thread on the source VM. * It drives the migration and pumps the data down the outgoing channel. @@ -3722,22 +3744,10 @@ static void *migration_thread(void *opaque) qemu_savevm_state_setup(s->to_dst_file); - if (qemu_savevm_state_guest_unplug_pending()) { - migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, - MIGRATION_STATUS_WAIT_UNPLUG); - - while (s->state == MIGRATION_STATUS_WAIT_UNPLUG && - qemu_savevm_state_guest_unplug_pending()) { - qemu_sem_timedwait(&s->wait_unplug_sem, 250); - } - - migrate_set_state(&s->state, MIGRATION_STATUS_WAIT_UNPLUG, - MIGRATION_STATUS_ACTIVE); - } + qemu_savevm_wait_unplug(s, MIGRATION_STATUS_SETUP, + MIGRATION_STATUS_ACTIVE); s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start; - migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, - MIGRATION_STATUS_ACTIVE); trace_migration_thread_setup_complete(); @@ -3845,21 +3855,9 @@ static void *bg_migration_thread(void *opaque) qemu_savevm_state_header(s->to_dst_file); qemu_savevm_state_setup(s->to_dst_file); - if (qemu_savevm_state_guest_unplug_pending()) { - migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, - MIGRATION_STATUS_WAIT_UNPLUG); + qemu_savevm_wait_unplug(s, MIGRATION_STATUS_SETUP, + MIGRATION_STATUS_ACTIVE); - while (s->state == MIGRATION_STATUS_WAIT_UNPLUG && - qemu_savevm_state_guest_unplug_pending()) { - qemu_sem_timedwait(&s->wait_unplug_sem, 250); - } - - migrate_set_state(&s->state, MIGRATION_STATUS_WAIT_UNPLUG, - MIGRATION_STATUS_ACTIVE); - } else { - migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, - MIGRATION_STATUS_ACTIVE); - } s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start; trace_migration_thread_setup_complete(); From 944bc528421aa848ca218ee535ea923a4147a525 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Tue, 29 Jun 2021 17:50:07 +0200 Subject: [PATCH 06/76] migration: failover: continue to wait card unplug on error If the user cancels the migration in the unplug-wait state, QEMU will try to plug back the card and this fails because the card is partially unplugged. To avoid the problem, continue to wait the card unplug, but to allow the migration to be canceled if the card never finishes to unplug use a timeout. Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1976852 Signed-off-by: Laurent Vivier Reviewed-by: Dr. David Alan Gilbert Message-Id: <20210629155007.629086-3-lvivier@redhat.com> Signed-off-by: Dr. David Alan Gilbert --- migration/migration.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/migration/migration.c b/migration/migration.c index dbc484c802..5ff7ba9d5c 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -3691,6 +3691,17 @@ static void qemu_savevm_wait_unplug(MigrationState *s, int old_state, qemu_savevm_state_guest_unplug_pending()) { qemu_sem_timedwait(&s->wait_unplug_sem, 250); } + if (s->state != MIGRATION_STATUS_WAIT_UNPLUG) { + int timeout = 120; /* 30 seconds */ + /* + * migration has been canceled + * but as we have started an unplug we must wait the end + * to be able to plug back the card + */ + while (timeout-- && qemu_savevm_state_guest_unplug_pending()) { + qemu_sem_timedwait(&s->wait_unplug_sem, 250); + } + } migrate_set_state(&s->state, MIGRATION_STATUS_WAIT_UNPLUG, new_state); } else { From d9a801f7e9fd18ce96a0bfff73b785f0a1f8e6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Fri, 11 Jun 2021 17:43:20 +0100 Subject: [PATCH 07/76] virtiofsd: use GDateTime for formatting timestamp for debug messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GDateTime APIs provided by GLib avoid portability pitfalls, such as some platforms where 'struct timeval.tv_sec' field is still 'long' instead of 'time_t'. When combined with automatic cleanup, GDateTime often results in simpler code too. Localtime is changed to UTC to avoid the need to grant extra seccomp permissions for GLib's access of the timezone database. Signed-off-by: Daniel P. Berrangé Reviewed-by: Dr. David Alan Gilbert Message-Id: <20210611164319.67762-1-berrange@redhat.com> Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/passthrough_ll.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 49c21fd855..9858e961d9 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -3559,10 +3559,6 @@ static void setup_nofile_rlimit(unsigned long rlimit_nofile) static void log_func(enum fuse_log_level level, const char *fmt, va_list ap) { g_autofree char *localfmt = NULL; - struct timespec ts; - struct tm tm; - char sec_fmt[sizeof "2020-12-07 18:17:54"]; - char zone_fmt[sizeof "+0100"]; if (current_log_level < level) { return; @@ -3574,23 +3570,10 @@ static void log_func(enum fuse_log_level level, const char *fmt, va_list ap) localfmt = g_strdup_printf("[ID: %08ld] %s", syscall(__NR_gettid), fmt); } else { - /* try formatting a broken-down timestamp */ - if (clock_gettime(CLOCK_REALTIME, &ts) != -1 && - localtime_r(&ts.tv_sec, &tm) != NULL && - strftime(sec_fmt, sizeof sec_fmt, "%Y-%m-%d %H:%M:%S", - &tm) != 0 && - strftime(zone_fmt, sizeof zone_fmt, "%z", &tm) != 0) { - localfmt = g_strdup_printf("[%s.%02ld%s] [ID: %08ld] %s", - sec_fmt, - ts.tv_nsec / (10L * 1000 * 1000), - zone_fmt, syscall(__NR_gettid), - fmt); - } else { - /* fall back to a flat timestamp */ - localfmt = g_strdup_printf("[%" PRId64 "] [ID: %08ld] %s", - get_clock(), syscall(__NR_gettid), - fmt); - } + g_autoptr(GDateTime) now = g_date_time_new_now_utc(); + g_autofree char *nowstr = g_date_time_format(now, "%Y-%m-%d %H:%M:%S.%f%z"); + localfmt = g_strdup_printf("[%s] [ID: %08ld] %s", + nowstr, syscall(__NR_gettid), fmt); } fmt = localfmt; } From 3399bca4514b5c8d513a88fa3e472756468cb4c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Fri, 11 Jun 2021 13:04:27 +0100 Subject: [PATCH 08/76] docs: describe the security considerations with virtiofsd xattr mapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Different guest xattr prefixes have distinct access control rules applied by the guest. When remapping a guest xattr care must be taken that the remapping does not allow the a guest user to bypass guest kernel access control rules. For example if 'trusted.*' which requires CAP_SYS_ADMIN is remapped to 'user.virtiofs.trusted.*', an unprivileged guest user which can write to 'user.*' can bypass the CAP_SYS_ADMIN control. Thus the target of any remapping must be explicitly blocked from read/writes by the guest, to prevent access control bypass. The examples shown in the virtiofsd man page already do the right thing and ensure safety, but the security implications of getting this wrong were not made explicit. This could lead to host admins and apps unwittingly creating insecure configurations. Signed-off-by: Daniel P. Berrangé Message-Id: <20210611120427.49736-1-berrange@redhat.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- docs/tools/virtiofsd.rst | 55 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst index 4911e797cb..a6c3502710 100644 --- a/docs/tools/virtiofsd.rst +++ b/docs/tools/virtiofsd.rst @@ -127,8 +127,8 @@ Options timeout. ``always`` sets a long cache lifetime at the expense of coherency. The default is ``auto``. -xattr-mapping -------------- +Extended attribute (xattr) mapping +---------------------------------- By default the name of xattr's used by the client are passed through to the server file system. This can be a problem where either those xattr names are used @@ -136,6 +136,9 @@ by something on the server (e.g. selinux client/server confusion) or if the virtiofsd is running in a container with restricted privileges where it cannot access some attributes. +Mapping syntax +~~~~~~~~~~~~~~ + A mapping of xattr names can be made using -o xattrmap=mapping where the ``mapping`` string consists of a series of rules. @@ -232,8 +235,48 @@ Note: When the 'security.capability' xattr is remapped, the daemon has to do extra work to remove it during many operations, which the host kernel normally does itself. -xattr-mapping Examples ----------------------- +Security considerations +~~~~~~~~~~~~~~~~~~~~~~~ + +Operating systems typically partition the xattr namespace using +well defined name prefixes. Each partition may have different +access controls applied. For example, on Linux there are multiple +partitions + + * ``system.*`` - access varies depending on attribute & filesystem + * ``security.*`` - only processes with CAP_SYS_ADMIN + * ``trusted.*`` - only processes with CAP_SYS_ADMIN + * ``user.*`` - any process granted by file permissions / ownership + +While other OS such as FreeBSD have different name prefixes +and access control rules. + +When remapping attributes on the host, it is important to +ensure that the remapping does not allow a guest user to +evade the guest access control rules. + +Consider if ``trusted.*`` from the guest was remapped to +``user.virtiofs.trusted*`` in the host. An unprivileged +user in a Linux guest has the ability to write to xattrs +under ``user.*``. Thus the user can evade the access +control restriction on ``trusted.*`` by instead writing +to ``user.virtiofs.trusted.*``. + +As noted above, the partitions used and access controls +applied, will vary across guest OS, so it is not wise to +try to predict what the guest OS will use. + +The simplest way to avoid an insecure configuration is +to remap all xattrs at once, to a given fixed prefix. +This is shown in example (1) below. + +If selectively mapping only a subset of xattr prefixes, +then rules must be added to explicitly block direct +access to the target of the remapping. This is shown +in example (2) below. + +Mapping examples +~~~~~~~~~~~~~~~~ 1) Prefix all attributes with 'user.virtiofs.' @@ -271,7 +314,9 @@ stripping of 'user.virtiofs.'. The second rule hides unprefixed 'trusted.' attributes on the host. The third rule stops a guest from explicitly setting -the 'user.virtiofs.' path directly. +the 'user.virtiofs.' path directly to prevent access +control bypass on the target of the earlier prefix +remapping. Finally, the fourth rule lets all remaining attributes through. From 1d03e5660711c40f79917054328e0dc6bcb879a3 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Thu, 24 Jun 2021 12:18:09 +0200 Subject: [PATCH 09/76] virtiofsd: Don't allow file creation with FUSE_OPEN A well behaved FUSE client uses FUSE_CREATE to create files. It isn't supposed to pass O_CREAT along a FUSE_OPEN request, as documented in the "fuse_lowlevel.h" header : /** * Open a file * * Open flags are available in fi->flags. The following rules * apply. * * - Creation (O_CREAT, O_EXCL, O_NOCTTY) flags will be * filtered out / handled by the kernel. But if the client happens to do it anyway, the server ends up passing this flag to open() without the mandatory mode_t 4th argument. Since open() is a variadic function, glibc will happily pass whatever it finds on the stack to the syscall. If this file is compiled with -D_FORTIFY_SOURCE=2, glibc will even detect that and abort: *** invalid openat64 call: O_CREAT or O_TMPFILE without mode ***: terminated Specifying O_CREAT with FUSE_OPEN is a protocol violation. Check this in do_open(), print out a message and return an error to the client, EINVAL like we already do when fuse_mbuf_iter_advance() fails. The FUSE filesystem doesn't currently support O_TMPFILE, but the very same would happen if O_TMPFILE was passed in a FUSE_OPEN request. Check that as well. Signed-off-by: Greg Kurz Message-Id: <20210624101809.48032-1-groug@kaod.org> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/fuse_lowlevel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c index 7fe2cef1eb..3d725bcba2 100644 --- a/tools/virtiofsd/fuse_lowlevel.c +++ b/tools/virtiofsd/fuse_lowlevel.c @@ -1084,6 +1084,12 @@ static void do_open(fuse_req_t req, fuse_ino_t nodeid, return; } + /* File creation is handled by do_create() or do_mknod() */ + if (arg->flags & (O_CREAT | O_TMPFILE)) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.flags = arg->flags; fi.kill_priv = arg->open_flags & FUSE_OPEN_KILL_SUIDGID; From 061624455fc3e4a19caeba321b284548127d858e Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 22 Jun 2021 11:08:46 -0400 Subject: [PATCH 10/76] virtiofsd: Fix fuse setxattr() API change issue With kernel header updates fuse_setxattr_in struct has grown in size. But this new struct size only takes affect if user has opted in for fuse feature FUSE_SETXATTR_EXT otherwise fuse continues to send "fuse_setxattr_in" of older size. Older size is determined by FUSE_COMPAT_SETXATTR_IN_SIZE. Fix this. If we have not opted in for FUSE_SETXATTR_EXT, then expect that we will get fuse_setxattr_in of size FUSE_COMPAT_SETXATTR_IN_SIZE and not sizeof(struct fuse_sexattr_in). Fixes: 278f064e4524 ("Update Linux headers to 5.13-rc4") Signed-off-by: Vivek Goyal Message-Id: <20210622150852.1507204-2-vgoyal@redhat.com> Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Greg Kurz Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/fuse_common.h | 5 +++++ tools/virtiofsd/fuse_lowlevel.c | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h index fa9671872e..0c2665b977 100644 --- a/tools/virtiofsd/fuse_common.h +++ b/tools/virtiofsd/fuse_common.h @@ -372,6 +372,11 @@ struct fuse_file_info { */ #define FUSE_CAP_HANDLE_KILLPRIV_V2 (1 << 28) +/** + * Indicates that file server supports extended struct fuse_setxattr_in + */ +#define FUSE_CAP_SETXATTR_EXT (1 << 29) + /** * Ioctl flags * diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c index 3d725bcba2..2028677907 100644 --- a/tools/virtiofsd/fuse_lowlevel.c +++ b/tools/virtiofsd/fuse_lowlevel.c @@ -1425,8 +1425,13 @@ static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, struct fuse_setxattr_in *arg; const char *name; const char *value; + bool setxattr_ext = req->se->conn.want & FUSE_CAP_SETXATTR_EXT; - arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (setxattr_ext) { + arg = fuse_mbuf_iter_advance(iter, sizeof(*arg)); + } else { + arg = fuse_mbuf_iter_advance(iter, FUSE_COMPAT_SETXATTR_IN_SIZE); + } name = fuse_mbuf_iter_advance_str(iter); if (!arg || !name) { fuse_reply_err(req, EINVAL); From 5290fb625d1bf692306ee958efc67c8620866f67 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 22 Jun 2021 11:08:47 -0400 Subject: [PATCH 11/76] virtiofsd: Fix xattr operations overwriting errno getxattr/setxattr/removexattr/listxattr operations handle regualar and non-regular files differently. For the case of non-regular files we do fchdir(/proc/self/fd) and the xattr operation and then revert back to original working directory. After this we are saving errno and that's buggy because fchdir() will overwrite the errno. FCHDIR_NOFAIL(lo->proc_self_fd); ret = getxattr(procname, name, value, size); FCHDIR_NOFAIL(lo->root.fd); if (ret == -1) saverr = errno In above example, if getxattr() failed, we will still return 0 to caller as errno must have been written by FCHDIR_NOFAIL(lo->root.fd) call. Fix all such instances and capture "errno" early and save in "saverr" variable. Signed-off-by: Vivek Goyal Message-Id: <20210622150852.1507204-3-vgoyal@redhat.com> Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Greg Kurz Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/passthrough_ll.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 9858e961d9..ccbda98c5a 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -2791,15 +2791,17 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, goto out_err; } ret = fgetxattr(fd, name, value, size); + saverr = ret == -1 ? errno : 0; } else { /* fchdir should not fail here */ FCHDIR_NOFAIL(lo->proc_self_fd); ret = getxattr(procname, name, value, size); + saverr = ret == -1 ? errno : 0; FCHDIR_NOFAIL(lo->root.fd); } if (ret == -1) { - goto out_err; + goto out; } if (size) { saverr = 0; @@ -2864,15 +2866,17 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) goto out_err; } ret = flistxattr(fd, value, size); + saverr = ret == -1 ? errno : 0; } else { /* fchdir should not fail here */ FCHDIR_NOFAIL(lo->proc_self_fd); ret = listxattr(procname, value, size); + saverr = ret == -1 ? errno : 0; FCHDIR_NOFAIL(lo->root.fd); } if (ret == -1) { - goto out_err; + goto out; } if (size) { saverr = 0; @@ -2998,15 +3002,15 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, goto out; } ret = fsetxattr(fd, name, value, size, flags); + saverr = ret == -1 ? errno : 0; } else { /* fchdir should not fail here */ FCHDIR_NOFAIL(lo->proc_self_fd); ret = setxattr(procname, name, value, size, flags); + saverr = ret == -1 ? errno : 0; FCHDIR_NOFAIL(lo->root.fd); } - saverr = ret == -1 ? errno : 0; - out: if (fd >= 0) { close(fd); @@ -3064,15 +3068,15 @@ static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char *in_name) goto out; } ret = fremovexattr(fd, name); + saverr = ret == -1 ? errno : 0; } else { /* fchdir should not fail here */ FCHDIR_NOFAIL(lo->proc_self_fd); ret = removexattr(procname, name); + saverr = ret == -1 ? errno : 0; FCHDIR_NOFAIL(lo->root.fd); } - saverr = ret == -1 ? errno : 0; - out: if (fd >= 0) { close(fd); From c46ef954fa33f5a409144c5395f8b23d22f42cab Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 22 Jun 2021 11:08:48 -0400 Subject: [PATCH 12/76] virtiofsd: Add support for extended setxattr Add the bits to enable support for setxattr_ext if fuse offers it. Do not enable it by default yet. Let passthrough_ll opt-in. Enabling it by deafult kind of automatically means that you are taking responsibility of clearing SGID if ACL is set. Signed-off-by: Vivek Goyal Message-Id: <20210622150852.1507204-4-vgoyal@redhat.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert Fixed up double def in fuse_common.h --- tools/virtiofsd/fuse_lowlevel.c | 11 ++++++++++- tools/virtiofsd/fuse_lowlevel.h | 3 ++- tools/virtiofsd/passthrough_ll.c | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c index 2028677907..e4679c73ab 100644 --- a/tools/virtiofsd/fuse_lowlevel.c +++ b/tools/virtiofsd/fuse_lowlevel.c @@ -1445,7 +1445,9 @@ static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, } if (req->se->op.setxattr) { - req->se->op.setxattr(req, nodeid, name, value, arg->size, arg->flags); + uint32_t setxattr_flags = setxattr_ext ? arg->setxattr_flags : 0; + req->se->op.setxattr(req, nodeid, name, value, arg->size, arg->flags, + setxattr_flags); } else { fuse_reply_err(req, ENOSYS); } @@ -1992,6 +1994,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, if (arg->flags & FUSE_HANDLE_KILLPRIV_V2) { se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV_V2; } + if (arg->flags & FUSE_SETXATTR_EXT) { + se->conn.capable |= FUSE_CAP_SETXATTR_EXT; + } #ifdef HAVE_SPLICE #ifdef HAVE_VMSPLICE se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE; @@ -2127,6 +2132,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, outarg.flags |= FUSE_HANDLE_KILLPRIV_V2; } + if (se->conn.want & FUSE_CAP_SETXATTR_EXT) { + outarg.flags |= FUSE_SETXATTR_EXT; + } + fuse_log(FUSE_LOG_DEBUG, " INIT: %u.%u\n", outarg.major, outarg.minor); fuse_log(FUSE_LOG_DEBUG, " flags=0x%08x\n", outarg.flags); fuse_log(FUSE_LOG_DEBUG, " max_readahead=0x%08x\n", outarg.max_readahead); diff --git a/tools/virtiofsd/fuse_lowlevel.h b/tools/virtiofsd/fuse_lowlevel.h index 3bf786b034..4b4e8c9724 100644 --- a/tools/virtiofsd/fuse_lowlevel.h +++ b/tools/virtiofsd/fuse_lowlevel.h @@ -798,7 +798,8 @@ struct fuse_lowlevel_ops { * fuse_reply_err */ void (*setxattr)(fuse_req_t req, fuse_ino_t ino, const char *name, - const char *value, size_t size, int flags); + const char *value, size_t size, int flags, + uint32_t setxattr_flags); /** * Get an extended attribute diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index ccbda98c5a..4dec087bd4 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -2955,7 +2955,8 @@ out: } static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, - const char *value, size_t size, int flags) + const char *value, size_t size, int flags, + uint32_t extra_flags) { char procname[64]; const char *name; From 6d0028b94797157477ddc759209f3e523e186ad9 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 22 Jun 2021 11:08:49 -0400 Subject: [PATCH 13/76] virtiofsd: Add umask to seccom allow list Patches in this series are going to make use of "umask" syscall. So allow it. Signed-off-by: Vivek Goyal Reviewed-by: Stefan Hajnoczi Message-Id: <20210622150852.1507204-5-vgoyal@redhat.com> Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/passthrough_seccomp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/virtiofsd/passthrough_seccomp.c b/tools/virtiofsd/passthrough_seccomp.c index 62441cfcdb..f49ed94b5e 100644 --- a/tools/virtiofsd/passthrough_seccomp.c +++ b/tools/virtiofsd/passthrough_seccomp.c @@ -114,6 +114,7 @@ static const int syscall_allowlist[] = { SCMP_SYS(utimensat), SCMP_SYS(write), SCMP_SYS(writev), + SCMP_SYS(umask), }; /* Syscalls used when --syslog is enabled */ From 227e5d7fd57b94e36fd754099308969b1373c4ef Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 22 Jun 2021 11:08:50 -0400 Subject: [PATCH 14/76] virtiofsd: Add capability to change/restore umask When parent directory has default acl and a file is created in that directory, then umask is ignored and final file permissions are determined using default acl instead. (man 2 umask). Currently, fuse applies the umask and sends modified mode in create request accordingly. fuse server can set FUSE_DONT_MASK and tell fuse client to not apply umask and fuse server will take care of it as needed. With posix acls enabled, requirement will be that we want umask to determine final file mode if parent directory does not have default acl. So if posix acls are enabled, opt in for FUSE_DONT_MASK. virtiofsd will set umask of the thread doing file creation. And host kernel should use that umask if parent directory does not have default acls, otherwise umask does not take affect. Miklos mentioned that we already call unshare(CLONE_FS) for every thread. That means umask has now become property of per thread and it should be ok to manipulate it in file creation path. This patch only adds capability to change umask and restore it. It does not enable it yet. Next few patches will add capability to enable it based on if user enabled posix_acl or not. This should fix fstest generic/099. Reported-by: Luis Henriques Signed-off-by: Vivek Goyal Reviewed-by: Stefan Hajnoczi Reviewed-by: Dr. David Alan Gilbert Message-Id: <20210622150852.1507204-6-vgoyal@redhat.com> Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/passthrough_ll.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 4dec087bd4..65b2c6fd74 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -122,6 +122,7 @@ struct lo_inode { struct lo_cred { uid_t euid; gid_t egid; + mode_t umask; }; enum { @@ -172,6 +173,8 @@ struct lo_data { /* An O_PATH file descriptor to /proc/self/fd/ */ int proc_self_fd; int user_killpriv_v2, killpriv_v2; + /* If set, virtiofsd is responsible for setting umask during creation */ + bool change_umask; }; static const struct fuse_opt lo_opts[] = { @@ -1134,7 +1137,8 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) * ownership of caller. * TODO: What about selinux context? */ -static int lo_change_cred(fuse_req_t req, struct lo_cred *old) +static int lo_change_cred(fuse_req_t req, struct lo_cred *old, + bool change_umask) { int res; @@ -1154,11 +1158,14 @@ static int lo_change_cred(fuse_req_t req, struct lo_cred *old) return errno_save; } + if (change_umask) { + old->umask = umask(req->ctx.umask); + } return 0; } /* Regain Privileges */ -static void lo_restore_cred(struct lo_cred *old) +static void lo_restore_cred(struct lo_cred *old, bool restore_umask) { int res; @@ -1173,6 +1180,9 @@ static void lo_restore_cred(struct lo_cred *old) fuse_log(FUSE_LOG_ERR, "setegid(%u): %m\n", old->egid); exit(1); } + + if (restore_umask) + umask(old->umask); } static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent, @@ -1202,7 +1212,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent, return; } - saverr = lo_change_cred(req, &old); + saverr = lo_change_cred(req, &old, lo->change_umask && !S_ISLNK(mode)); if (saverr) { goto out; } @@ -1211,7 +1221,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent, saverr = errno; - lo_restore_cred(&old); + lo_restore_cred(&old, lo->change_umask && !S_ISLNK(mode)); if (res == -1) { goto out; @@ -1917,7 +1927,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, return; } - err = lo_change_cred(req, &old); + err = lo_change_cred(req, &old, lo->change_umask); if (err) { goto out; } @@ -1928,7 +1938,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, fd = openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mode); err = fd == -1 ? errno : 0; - lo_restore_cred(&old); + lo_restore_cred(&old, lo->change_umask); /* Ignore the error if file exists and O_EXCL was not given */ if (err && (err != EEXIST || (fi->flags & O_EXCL))) { From f1aa1774dfb79ce0546d9fbc1ce05cb00550c600 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 22 Jun 2021 11:08:51 -0400 Subject: [PATCH 15/76] virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr When posix access acls are set on a file, it can lead to adjusting file permissions (mode) as well. If caller does not have CAP_FSETID and it also does not have membership of owner group, this will lead to clearing SGID bit in mode. Current fuse code is written in such a way that it expects file server to take care of chaning file mode (permission), if there is a need. Right now, host kernel does not clear SGID bit because virtiofsd is running as root and has CAP_FSETID. For host kernel to clear SGID, virtiofsd need to switch to gid of caller in guest and also drop CAP_FSETID (if caller did not have it to begin with). If SGID needs to be cleared, client will set the flag FUSE_SETXATTR_ACL_KILL_SGID in setxattr request. In that case server should kill sgid. Currently just switch to uid/gid of the caller and drop CAP_FSETID and that should do it. This should fix the xfstest generic/375 test case. We don't have to switch uid for this to work. That could be one optimization that pass a parameter to lo_change_cred() to only switch gid and not uid. Also this will not work whenever (if ever) we support idmapped mounts. In that case it is possible that uid/gid in request are 0/0 but still we need to clear SGID. So we will have to pick a non-root sgid and switch to that instead. That's an TODO item for future when idmapped mount support is introduced. This patch only adds the capability to switch creds and drop FSETID when acl xattr is set. This does not take affect yet. It can take affect when next patch adds the capability to enable posix_acl. Reported-by: Luis Henriques Signed-off-by: Vivek Goyal Message-Id: <20210622150852.1507204-7-vgoyal@redhat.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/passthrough_ll.c | 75 ++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 65b2c6fd74..6e30fd9113 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -175,6 +175,7 @@ struct lo_data { int user_killpriv_v2, killpriv_v2; /* If set, virtiofsd is responsible for setting umask during creation */ bool change_umask; + int posix_acl; }; static const struct fuse_opt lo_opts[] = { @@ -1185,6 +1186,51 @@ static void lo_restore_cred(struct lo_cred *old, bool restore_umask) umask(old->umask); } +/* + * A helper to change cred and drop capability. Returns 0 on success and + * errno on error + */ +static int lo_drop_cap_change_cred(fuse_req_t req, struct lo_cred *old, + bool change_umask, const char *cap_name, + bool *cap_dropped) +{ + int ret; + bool __cap_dropped; + + assert(cap_name); + + ret = drop_effective_cap(cap_name, &__cap_dropped); + if (ret) { + return ret; + } + + ret = lo_change_cred(req, old, change_umask); + if (ret) { + if (__cap_dropped) { + if (gain_effective_cap(cap_name)) { + fuse_log(FUSE_LOG_ERR, "Failed to gain CAP_%s\n", cap_name); + } + } + } + + if (cap_dropped) { + *cap_dropped = __cap_dropped; + } + return ret; +} + +static void lo_restore_cred_gain_cap(struct lo_cred *old, bool restore_umask, + const char *cap_name) +{ + assert(cap_name); + + lo_restore_cred(old, restore_umask); + + if (gain_effective_cap(cap_name)) { + fuse_log(FUSE_LOG_ERR, "Failed to gain CAP_%s\n", cap_name); + } +} + static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev, const char *link) @@ -2976,6 +3022,9 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, ssize_t ret; int saverr; int fd = -1; + bool switched_creds = false; + bool cap_fsetid_dropped = false; + struct lo_cred old = {}; mapped_name = NULL; name = in_name; @@ -3006,6 +3055,26 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, ", name=%s value=%s size=%zd)\n", ino, name, value, size); sprintf(procname, "%i", inode->fd); + /* + * If we are setting posix access acl and if SGID needs to be + * cleared, then switch to caller's gid and drop CAP_FSETID + * and that should make sure host kernel clears SGID. + * + * This probably will not work when we support idmapped mounts. + * In that case we will need to find a non-root gid and switch + * to it. (Instead of gid in request). Fix it when we support + * idmapped mounts. + */ + if (lo->posix_acl && !strcmp(name, "system.posix_acl_access") + && (extra_flags & FUSE_SETXATTR_ACL_KILL_SGID)) { + ret = lo_drop_cap_change_cred(req, &old, false, "FSETID", + &cap_fsetid_dropped); + if (ret) { + saverr = ret; + goto out; + } + switched_creds = true; + } if (S_ISREG(inode->filetype) || S_ISDIR(inode->filetype)) { fd = openat(lo->proc_self_fd, procname, O_RDONLY); if (fd < 0) { @@ -3021,6 +3090,12 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, saverr = ret == -1 ? errno : 0; FCHDIR_NOFAIL(lo->root.fd); } + if (switched_creds) { + if (cap_fsetid_dropped) + lo_restore_cred_gain_cap(&old, false, "FSETID"); + else + lo_restore_cred(&old, false); + } out: if (fd >= 0) { From 65a820d292622fd2c3e1e5cd49455adc7f90faf0 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 22 Jun 2021 11:08:52 -0400 Subject: [PATCH 16/76] virtiofsd: Add an option to enable/disable posix acls fuse has an option FUSE_POSIX_ACL which needs to be opted in by fuse server to enable posix acls. As of now we are not opting in for this, so posix acls are disabled on virtiofs by default. Add virtiofsd option "-o posix_acl/no_posix_acl" to let users enable/disable posix acl support. By default it is disabled as of now due to performance concerns with cache=none. Currently even if file server has not opted in for FUSE_POSIX_ACL, user can still query acl and set acl, and system.posix_acl_access and system.posix_acl_default xattrs show up listxattr response. Miklos said this is confusing. So he said lets block and filter system.posix_acl_access and system.posix_acl_default xattrs in getxattr/setxattr/listxattr if user has explicitly disabled posix acls using -o no_posix_acl. As of now continuing to keeping the existing behavior if user did not specify any option to disable acl support due to concerns about backward compatibility. Signed-off-by: Vivek Goyal Message-Id: <20210622150852.1507204-8-vgoyal@redhat.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- docs/tools/virtiofsd.rst | 3 + tools/virtiofsd/helper.c | 1 + tools/virtiofsd/passthrough_ll.c | 115 ++++++++++++++++++++++++++++++- 3 files changed, 118 insertions(+), 1 deletion(-) diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst index a6c3502710..c4ac7fdf38 100644 --- a/docs/tools/virtiofsd.rst +++ b/docs/tools/virtiofsd.rst @@ -101,6 +101,9 @@ Options Enable/disable extended attributes (xattr) on files and directories. The default is ``no_xattr``. + * posix_acl|no_posix_acl - + Enable/disable posix acl support. Posix ACLs are disabled by default`. + .. option:: --socket-path=PATH Listen on vhost-user UNIX domain socket at PATH. diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c index 5e98ed702b..a8295d975a 100644 --- a/tools/virtiofsd/helper.c +++ b/tools/virtiofsd/helper.c @@ -186,6 +186,7 @@ void fuse_cmdline_help(void) " to virtiofsd from guest applications.\n" " default: no_allow_direct_io\n" " -o announce_submounts Announce sub-mount points to the guest\n" + " -o posix_acl/no_posix_acl Enable/Disable posix_acl. (default: disabled)\n" ); } diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 6e30fd9113..38b2af8599 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -175,7 +175,7 @@ struct lo_data { int user_killpriv_v2, killpriv_v2; /* If set, virtiofsd is responsible for setting umask during creation */ bool change_umask; - int posix_acl; + int user_posix_acl, posix_acl; }; static const struct fuse_opt lo_opts[] = { @@ -208,6 +208,8 @@ static const struct fuse_opt lo_opts[] = { { "announce_submounts", offsetof(struct lo_data, announce_submounts), 1 }, { "killpriv_v2", offsetof(struct lo_data, user_killpriv_v2), 1 }, { "no_killpriv_v2", offsetof(struct lo_data, user_killpriv_v2), 0 }, + { "posix_acl", offsetof(struct lo_data, user_posix_acl), 1 }, + { "no_posix_acl", offsetof(struct lo_data, user_posix_acl), 0 }, FUSE_OPT_END }; static bool use_syslog = false; @@ -706,6 +708,32 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn) conn->want &= ~FUSE_CAP_HANDLE_KILLPRIV_V2; lo->killpriv_v2 = 0; } + + if (lo->user_posix_acl == 1) { + /* + * User explicitly asked for this option. Enable it unconditionally. + * If connection does not have this capability, print error message + * now. It will fail later in fuse_lowlevel.c + */ + if (!(conn->capable & FUSE_CAP_POSIX_ACL) || + !(conn->capable & FUSE_CAP_DONT_MASK) || + !(conn->capable & FUSE_CAP_SETXATTR_EXT)) { + fuse_log(FUSE_LOG_ERR, "lo_init: Can not enable posix acl." + " kernel does not support FUSE_POSIX_ACL, FUSE_DONT_MASK" + " or FUSE_SETXATTR_EXT capability.\n"); + } else { + fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling posix acl\n"); + } + + conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK | + FUSE_CAP_SETXATTR_EXT; + lo->change_umask = true; + lo->posix_acl = true; + } else { + /* User either did not specify anything or wants it disabled */ + fuse_log(FUSE_LOG_DEBUG, "lo_init: disabling posix_acl\n"); + conn->want &= ~FUSE_CAP_POSIX_ACL; + } } static void lo_getattr(fuse_req_t req, fuse_ino_t ino, @@ -2783,6 +2811,63 @@ static int xattr_map_server(const struct lo_data *lo, const char *server_name, assert(fchdir_res == 0); \ } while (0) +static bool block_xattr(struct lo_data *lo, const char *name) +{ + /* + * If user explicitly enabled posix_acl or did not provide any option, + * do not block acl. Otherwise block system.posix_acl_access and + * system.posix_acl_default xattrs. + */ + if (lo->user_posix_acl) { + return false; + } + if (!strcmp(name, "system.posix_acl_access") || + !strcmp(name, "system.posix_acl_default")) + return true; + + return false; +} + +/* + * Returns number of bytes in xattr_list after filtering on success. This + * could be zero as well if nothing is left after filtering. + * + * Returns negative error code on failure. + * xattr_list is modified in place. + */ +static int remove_blocked_xattrs(struct lo_data *lo, char *xattr_list, + unsigned in_size) +{ + size_t out_index, in_index; + + /* + * As of now we only filter out acl xattrs. If acls are enabled or + * they have not been explicitly disabled, there is nothing to + * filter. + */ + if (lo->user_posix_acl) { + return in_size; + } + + out_index = 0; + in_index = 0; + while (in_index < in_size) { + char *in_ptr = xattr_list + in_index; + + /* Length of current attribute name */ + size_t in_len = strlen(xattr_list + in_index) + 1; + + if (!block_xattr(lo, in_ptr)) { + if (in_index != out_index) { + memmove(xattr_list + out_index, xattr_list + in_index, in_len); + } + out_index += in_len; + } + in_index += in_len; + } + return out_index; +} + static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, size_t size) { @@ -2796,6 +2881,11 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, int saverr; int fd = -1; + if (block_xattr(lo, in_name)) { + fuse_reply_err(req, EOPNOTSUPP); + return; + } + mapped_name = NULL; name = in_name; if (lo->xattrmap) { @@ -2986,6 +3076,12 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) goto out; } } + + ret = remove_blocked_xattrs(lo, value, ret); + if (ret <= 0) { + saverr = -ret; + goto out; + } fuse_reply_buf(req, value, ret); } else { /* @@ -3026,6 +3122,11 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name, bool cap_fsetid_dropped = false; struct lo_cred old = {}; + if (block_xattr(lo, in_name)) { + fuse_reply_err(req, EOPNOTSUPP); + return; + } + mapped_name = NULL; name = in_name; if (lo->xattrmap) { @@ -3118,6 +3219,11 @@ static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char *in_name) int saverr; int fd = -1; + if (block_xattr(lo, in_name)) { + fuse_reply_err(req, EOPNOTSUPP); + return; + } + mapped_name = NULL; name = in_name; if (lo->xattrmap) { @@ -3795,6 +3901,7 @@ int main(int argc, char *argv[]) .allow_direct_io = 0, .proc_self_fd = -1, .user_killpriv_v2 = -1, + .user_posix_acl = -1, }; struct lo_map_elem *root_elem; struct lo_map_elem *reserve_elem; @@ -3923,6 +4030,12 @@ int main(int argc, char *argv[]) exit(1); } + if (lo.user_posix_acl == 1 && !lo.xattr) { + fuse_log(FUSE_LOG_ERR, "Can't enable posix ACLs. xattrs are disabled." + "\n"); + exit(1); + } + lo.use_statx = true; se = fuse_session_new(&args, &lo_oper, sizeof(lo_oper), &lo); From c99fb3a50db983402e85423139e5d4449cda9111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hyman=20Huang=28=E9=BB=84=E5=8B=87=29?= Date: Thu, 3 Jun 2021 22:19:53 +0800 Subject: [PATCH 17/76] tests/migration: parse the thread-id key of CpuInfoFast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit thread_id in CpuInfoFast is deprecated, parse thread-id instead after execute qmp query-cpus-fast. fix this so that test can go smoothly. Signed-off-by: Hyman Huang(黄勇) Message-Id: <584578c0a0dd781cee45f72ddf517f6e6a41c504.1622729934.git.huangy81@chinatelecom.cn> Reviewed-by: Daniel P. Berrangé Signed-off-by: Dr. David Alan Gilbert --- tests/migration/guestperf/engine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/migration/guestperf/engine.py b/tests/migration/guestperf/engine.py index 208e095794..9e16fa92d2 100644 --- a/tests/migration/guestperf/engine.py +++ b/tests/migration/guestperf/engine.py @@ -113,7 +113,7 @@ class Engine(object): vcpus = src.command("query-cpus-fast") src_threads = [] for vcpu in vcpus: - src_threads.append(vcpu["thread_id"]) + src_threads.append(vcpu["thread-id"]) # XXX how to get dst timings on remote host ? From fa264f426642245eb623e9f86cf57022d854dc69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hyman=20Huang=28=E9=BB=84=E5=8B=87=29?= Date: Thu, 3 Jun 2021 22:20:37 +0800 Subject: [PATCH 18/76] tests/migration: fix "downtime_limit" type when "migrate-set-parameters" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit migrate-set-parameters parse "downtime_limit" as integer type when execute "migrate-set-parameters" before migration, and, the unit dowtime_limit is milliseconds, fix this two so that test can go smoothly. Signed-off-by: Hyman Huang(黄勇) Message-Id: <31d82df24cc0c468dbe4d2d86730158ebf248071.1622729934.git.huangy81@chinatelecom.cn> Reviewed-by: Daniel P. Berrangé Signed-off-by: Dr. David Alan Gilbert --- tests/migration/guestperf/engine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/migration/guestperf/engine.py b/tests/migration/guestperf/engine.py index 9e16fa92d2..7c991c4407 100644 --- a/tests/migration/guestperf/engine.py +++ b/tests/migration/guestperf/engine.py @@ -153,7 +153,7 @@ class Engine(object): max_bandwidth=scenario._bandwidth * 1024 * 1024) resp = src.command("migrate-set-parameters", - downtime_limit=scenario._downtime / 1024.0) + downtime_limit=scenario._downtime) if scenario._compression_mt: resp = src.command("migrate-set-capabilities", From e5f607913cee3f3b486eb024dbc7079b51f6da57 Mon Sep 17 00:00:00 2001 From: Li Zhijian Date: Mon, 28 Jun 2021 15:19:59 +0800 Subject: [PATCH 19/76] migration/rdma: Use error_report to suppress errno message Since the prior calls are successful, in this case a errno doesn't indicate a real error which would just make us confused. before: (qemu) migrate -d rdma:192.168.22.23:8888 source_resolve_host RDMA Device opened: kernel name rxe_eth0 uverbs device name uverbs2, infiniband_verbs class device path /sys/class/infiniband_verbs/uverbs2, infiniband class device path /sys/class/infiniband/rxe_eth0, transport: (2) Ethernet rdma_get_cm_event != EVENT_ESTABLISHED after rdma_connect: No space left on device Signed-off-by: Li Zhijian Message-Id: <20210628071959.23455-1-lizhijian@cn.fujitsu.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- migration/rdma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migration/rdma.c b/migration/rdma.c index d90b29a4b5..b6cc4bef4a 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -1006,7 +1006,7 @@ route: if (cm_event->event != RDMA_CM_EVENT_ADDR_RESOLVED) { ERROR(errp, "result not equal to event_addr_resolved %s", rdma_event_str(cm_event->event)); - perror("rdma_resolve_addr"); + error_report("rdma_resolve_addr"); rdma_ack_cm_event(cm_event); ret = -EINVAL; goto err_resolve_get_addr; @@ -2544,7 +2544,7 @@ static int qemu_rdma_connect(RDMAContext *rdma, Error **errp, bool return_path) } if (cm_event->event != RDMA_CM_EVENT_ESTABLISHED) { - perror("rdma_get_cm_event != EVENT_ESTABLISHED after rdma_connect"); + error_report("rdma_get_cm_event != EVENT_ESTABLISHED after rdma_connect"); ERROR(errp, "connecting to destination!"); rdma_ack_cm_event(cm_event); goto err_rdma_source_connect; From 6f569084277dc7ae351141cfa6ad3649e92a1390 Mon Sep 17 00:00:00 2001 From: Christian Schoenebeck Date: Thu, 6 May 2021 15:12:23 +0200 Subject: [PATCH 20/76] 9pfs: add link to 9p developer docs To lower the entry level for new developers, add a link to the 9p developer docs (i.e. qemu wiki) to MAINTAINERS and to the beginning of 9p source files, that is to: https://wiki.qemu.org/Documentation/9p Signed-off-by: Christian Schoenebeck Acked-by: Greg Kurz Message-Id: --- MAINTAINERS | 1 + hw/9pfs/9p-local.c | 5 +++++ hw/9pfs/9p-posix-acl.c | 5 +++++ hw/9pfs/9p-proxy.c | 5 +++++ hw/9pfs/9p-synth.c | 5 +++++ hw/9pfs/9p-util.c | 5 +++++ hw/9pfs/9p-xattr-user.c | 5 +++++ hw/9pfs/9p-xattr.c | 5 +++++ hw/9pfs/9p.c | 5 +++++ hw/9pfs/codir.c | 5 +++++ hw/9pfs/cofile.c | 5 +++++ hw/9pfs/cofs.c | 5 +++++ hw/9pfs/coth.c | 5 +++++ hw/9pfs/coxattr.c | 5 +++++ hw/9pfs/virtio-9p-device.c | 5 +++++ hw/9pfs/xen-9p-backend.c | 5 +++++ tests/qtest/libqos/virtio-9p.c | 5 +++++ tests/qtest/virtio-9p-test.c | 5 +++++ 18 files changed, 86 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index cb8f3ea2c2..684142e12e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1881,6 +1881,7 @@ virtio-9p M: Greg Kurz M: Christian Schoenebeck S: Odd Fixes +W: https://wiki.qemu.org/Documentation/9p F: hw/9pfs/ X: hw/9pfs/xen-9p* F: fsdev/ diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index af52c1daac..210d9e7705 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -10,6 +10,11 @@ * the COPYING file in the top-level directory. */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "9p.h" #include "9p-local.h" diff --git a/hw/9pfs/9p-posix-acl.c b/hw/9pfs/9p-posix-acl.c index bbf89064f7..eadae270dd 100644 --- a/hw/9pfs/9p-posix-acl.c +++ b/hw/9pfs/9p-posix-acl.c @@ -11,6 +11,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "qemu/xattr.h" #include "9p.h" diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c index 4aa4e0a3ba..09bd9f1464 100644 --- a/hw/9pfs/9p-proxy.c +++ b/hw/9pfs/9p-proxy.c @@ -10,6 +10,11 @@ * the COPYING file in the top-level directory. */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include #include diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c index 473ef914b0..b38088e066 100644 --- a/hw/9pfs/9p-synth.c +++ b/hw/9pfs/9p-synth.c @@ -12,6 +12,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "9p.h" #include "fsdev/qemu-fsdev.h" diff --git a/hw/9pfs/9p-util.c b/hw/9pfs/9p-util.c index 614b7fc34d..3221d9b498 100644 --- a/hw/9pfs/9p-util.c +++ b/hw/9pfs/9p-util.c @@ -10,6 +10,11 @@ * See the COPYING file in the top-level directory. */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "qemu/xattr.h" #include "9p-util.h" diff --git a/hw/9pfs/9p-xattr-user.c b/hw/9pfs/9p-xattr-user.c index 2c90817b75..f2ae9582e6 100644 --- a/hw/9pfs/9p-xattr-user.c +++ b/hw/9pfs/9p-xattr-user.c @@ -11,6 +11,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "9p.h" #include "fsdev/file-op-9p.h" diff --git a/hw/9pfs/9p-xattr.c b/hw/9pfs/9p-xattr.c index c696d8f846..9ae69dd8db 100644 --- a/hw/9pfs/9p-xattr.c +++ b/hw/9pfs/9p-xattr.c @@ -11,6 +11,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "9p.h" #include "fsdev/file-op-9p.h" diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 134806db52..0fa776af09 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -11,6 +11,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include #include "hw/virtio/virtio.h" diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 1f70a58df5..032cce04c4 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -11,6 +11,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index 83bb6c14e0..20f93a90e7 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -11,6 +11,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 0b321b456e..9d0adc2e78 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -11,6 +11,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" diff --git a/hw/9pfs/coth.c b/hw/9pfs/coth.c index 9778f24b00..2802d41cce 100644 --- a/hw/9pfs/coth.c +++ b/hw/9pfs/coth.c @@ -12,6 +12,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "block/thread-pool.h" #include "qemu/coroutine.h" diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c index 0e00ffaa0d..dbcd09e0fd 100644 --- a/hw/9pfs/coxattr.c +++ b/hw/9pfs/coxattr.c @@ -11,6 +11,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 14371a78ef..54ee93b71f 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -11,6 +11,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "hw/virtio/virtio.h" #include "qemu/sockets.h" diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c index a969fcc54c..65c4979c3c 100644 --- a/hw/9pfs/xen-9p-backend.c +++ b/hw/9pfs/xen-9p-backend.c @@ -8,6 +8,11 @@ * */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "hw/9pfs/9p.h" diff --git a/tests/qtest/libqos/virtio-9p.c b/tests/qtest/libqos/virtio-9p.c index be91662c6f..b4e1143288 100644 --- a/tests/qtest/libqos/virtio-9p.c +++ b/tests/qtest/libqos/virtio-9p.c @@ -16,6 +16,11 @@ * License along with this library; if not, see */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "libqtest.h" #include "qemu/module.h" diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c index 92a498f249..41fed41de1 100644 --- a/tests/qtest/virtio-9p-test.c +++ b/tests/qtest/virtio-9p-test.c @@ -7,6 +7,11 @@ * See the COPYING file in the top-level directory. */ +/* + * Not so fast! You might want to read the 9p developer docs first: + * https://wiki.qemu.org/Documentation/9p + */ + #include "qemu/osdep.h" #include "libqtest-single.h" #include "qemu/module.h" From 232a4d2c25c3a83e148116a15f992f728c3579e6 Mon Sep 17 00:00:00 2001 From: Christian Schoenebeck Date: Sun, 16 May 2021 17:55:34 +0200 Subject: [PATCH 21/76] 9pfs: simplify v9fs_walk() There is only one comparison between nwnames and P9_MAXWELEM required. Signed-off-by: Christian Schoenebeck Reviewed-by: Greg Kurz Message-Id: --- hw/9pfs/9p.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 0fa776af09..89aa07db78 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -1739,7 +1739,11 @@ static void coroutine_fn v9fs_walk(void *opaque) trace_v9fs_walk(pdu->tag, pdu->id, fid, newfid, nwnames); - if (nwnames && nwnames <= P9_MAXWELEM) { + if (nwnames > P9_MAXWELEM) { + err = -EINVAL; + goto out_nofid; + } + if (nwnames) { wnames = g_new0(V9fsString, nwnames); qids = g_new0(V9fsQID, nwnames); for (i = 0; i < nwnames; i++) { @@ -1753,9 +1757,6 @@ static void coroutine_fn v9fs_walk(void *opaque) } offset += err; } - } else if (nwnames > P9_MAXWELEM) { - err = -EINVAL; - goto out_nofid; } fidp = get_fid(pdu, fid); if (fidp == NULL) { From 8bf27550effb124221100c3c6f5d513dd29ec37d Mon Sep 17 00:00:00 2001 From: Christian Schoenebeck Date: Fri, 4 Jun 2021 16:46:45 +0200 Subject: [PATCH 22/76] 9pfs: fix not_same_qid() There is only one user of not_same_qid() which is v9fs_walk() and the latter is using it for comparing a client supplied path with the 9p export root path, for the sole purpose to prevent a Twalk request from escaping from the exported 9p tree via "..". However for that specific purpose the implementation of not_same_qid() is wrong; if mtime of the 9p export root path changed between Tattach and Twalk then not_same_qid() returns true when actually comparing against the export root path. To fix for the actual semantic being used, only compare QID path members, but do not compare version or type members. Signed-off-by: Christian Schoenebeck Reviewed-by: Greg Kurz Message-Id: --- hw/9pfs/9p.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 89aa07db78..e10a02f71d 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -1707,10 +1707,7 @@ static bool name_is_illegal(const char *name) static bool not_same_qid(const V9fsQID *qid1, const V9fsQID *qid2) { - return - qid1->type != qid2->type || - qid1->version != qid2->version || - qid1->path != qid2->path; + return qid1->path != qid2->path; } static void coroutine_fn v9fs_walk(void *opaque) From 110243750dc4389fe8715c1db87a6ce6c2b9e645 Mon Sep 17 00:00:00 2001 From: Christian Schoenebeck Date: Fri, 4 Jun 2021 19:52:18 +0200 Subject: [PATCH 23/76] 9pfs: capture root stat We already capture the QID of the exported 9p root path, i.e. to prevent client access outside the defined, exported filesystem's tree. This is currently checked by comparing the root QID with another FID's QID. The problem with the latter is that resolving a QID of any given 9p path can only be done on 9p server's main thread, that's because it might mutate the server's state if inode remapping is enabled. For that reason also capture the POSIX stat info of the root path for being able to identify on any (e.g. worker) thread whether an arbitrary given path is identical to the export root. Signed-off-by: Christian Schoenebeck Reviewed-by: Greg Kurz Message-Id: --- hw/9pfs/9p.c | 10 +++++++++- hw/9pfs/9p.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index e10a02f71d..eb15ec2082 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -1400,6 +1400,7 @@ static void coroutine_fn v9fs_attach(void *opaque) size_t offset = 7; V9fsQID qid; ssize_t err; + struct stat stbuf; v9fs_string_init(&uname); v9fs_string_init(&aname); @@ -1422,7 +1423,13 @@ static void coroutine_fn v9fs_attach(void *opaque) clunk_fid(s, fid); goto out; } - err = fid_to_qid(pdu, fidp, &qid); + err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); + if (err < 0) { + err = -EINVAL; + clunk_fid(s, fid); + goto out; + } + err = stat_to_qid(pdu, &stbuf, &qid); if (err < 0) { err = -EINVAL; clunk_fid(s, fid); @@ -1455,6 +1462,7 @@ static void coroutine_fn v9fs_attach(void *opaque) err += offset; memcpy(&s->root_qid, &qid, sizeof(qid)); + memcpy(&s->root_st, &stbuf, sizeof(stbuf)); trace_v9fs_attach_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path); out: diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index 00381591ff..6f0b4c78c0 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -356,6 +356,7 @@ struct V9fsState { Error *migration_blocker; V9fsConf fsconf; V9fsQID root_qid; + struct stat root_st; dev_t dev_id; struct qht qpd_table; struct qht qpp_table; From 1d0fc0d0eef057dc02055f531907188d19a83cb2 Mon Sep 17 00:00:00 2001 From: Christian Schoenebeck Date: Fri, 4 Jun 2021 19:54:57 +0200 Subject: [PATCH 24/76] 9pfs: drop fid_to_qid() There is only one user of fid_to_qid() which is v9fs_walk(). Let's open-code fid_to_qid() directly within v9fs_walk(), because fid_to_qid() hides the POSIX stat buffer which we are going to need in the subsequent patch. Signed-off-by: Christian Schoenebeck Reviewed-by: Greg Kurz Message-Id: --- hw/9pfs/9p.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index eb15ec2082..0e3857798d 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -971,23 +971,6 @@ static int stat_to_qid(V9fsPDU *pdu, const struct stat *stbuf, V9fsQID *qidp) return 0; } -static int coroutine_fn fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, - V9fsQID *qidp) -{ - struct stat stbuf; - int err; - - err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); - if (err < 0) { - return err; - } - err = stat_to_qid(pdu, &stbuf, qidp); - if (err < 0) { - return err; - } - return 0; -} - V9fsPDU *pdu_alloc(V9fsState *s) { V9fsPDU *pdu = NULL; @@ -1772,7 +1755,11 @@ static void coroutine_fn v9fs_walk(void *opaque) v9fs_path_init(&dpath); v9fs_path_init(&path); - err = fid_to_qid(pdu, fidp, &qid); + err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); + if (err < 0) { + goto out; + } + err = stat_to_qid(pdu, &stbuf, &qid); if (err < 0) { goto out; } From f22cad42281621f86a0756a7cff382f90a33ec8c Mon Sep 17 00:00:00 2001 From: Christian Schoenebeck Date: Fri, 4 Jun 2021 19:57:21 +0200 Subject: [PATCH 25/76] 9pfs: replace not_same_qid() by same_stat_id() As we are actually only comparing the filesystem ID (i.e. device number and inode number pair) let's use the POSIX stat buffer instead of QIDs, because resolving QIDs requires to be done on 9p server's main thread only as it might mutate the server state if inode remapping is enabled. Signed-off-by: Christian Schoenebeck Reviewed-by: Greg Kurz Message-Id: <26aa465ff9cc9c07e053331554a02fdae3994417.1622821729.git.qemu_oss@crudebyte.com> --- hw/9pfs/9p.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 0e3857798d..47b000d3a9 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -1696,9 +1696,9 @@ static bool name_is_illegal(const char *name) return !*name || strchr(name, '/') != NULL; } -static bool not_same_qid(const V9fsQID *qid1, const V9fsQID *qid2) +static bool same_stat_id(const struct stat *a, const struct stat *b) { - return qid1->path != qid2->path; + return a->st_dev == b->st_dev && a->st_ino == b->st_ino; } static void coroutine_fn v9fs_walk(void *opaque) @@ -1771,7 +1771,7 @@ static void coroutine_fn v9fs_walk(void *opaque) v9fs_path_copy(&dpath, &fidp->path); v9fs_path_copy(&path, &fidp->path); for (name_idx = 0; name_idx < nwnames; name_idx++) { - if (not_same_qid(&pdu->s->root_qid, &qid) || + if (!same_stat_id(&pdu->s->root_st, &stbuf) || strcmp("..", wnames[name_idx].data)) { err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data, &path); From 66550339b77410212c7a99f0f80021721541b742 Mon Sep 17 00:00:00 2001 From: Christian Schoenebeck Date: Fri, 4 Jun 2021 19:59:16 +0200 Subject: [PATCH 26/76] 9pfs: drop root_qid There is no longer a user of root_qid, so drop it. Signed-off-by: Christian Schoenebeck Reviewed-by: Greg Kurz Message-Id: <6896dd161d3257db6b0513842a14f87ca191fdf6.1622821729.git.qemu_oss@crudebyte.com> --- hw/9pfs/9p.c | 1 - hw/9pfs/9p.h | 1 - 2 files changed, 2 deletions(-) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 47b000d3a9..7be07f2d68 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -1444,7 +1444,6 @@ static void coroutine_fn v9fs_attach(void *opaque) } err += offset; - memcpy(&s->root_qid, &qid, sizeof(qid)); memcpy(&s->root_st, &stbuf, sizeof(stbuf)); trace_v9fs_attach_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path); diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index 6f0b4c78c0..1567b67841 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -355,7 +355,6 @@ struct V9fsState { int32_t root_fid; Error *migration_blocker; V9fsConf fsconf; - V9fsQID root_qid; struct stat root_st; dev_t dev_id; struct qht qpd_table; From 8d6cb100731c4d28535adbf2a3c2d1f29be3fef4 Mon Sep 17 00:00:00 2001 From: Christian Schoenebeck Date: Fri, 2 Jul 2021 17:16:32 +0200 Subject: [PATCH 27/76] 9pfs: reduce latency of Twalk As with previous performance optimization on Treaddir handling; reduce the overall latency, i.e. overall time spent on processing a Twalk request by reducing the amount of thread hops between the 9p server's main thread and fs worker thread(s). In fact this patch even reduces the thread hops for Twalk handling to its theoritical minimum of exactly 2 thread hops: main thread -> fs worker thread -> main thread This is achieved by doing all the required fs driver tasks altogether in a single v9fs_co_run_in_worker({ ... }); code block. Signed-off-by: Christian Schoenebeck Reviewed-by: Greg Kurz Message-Id: <1a6701674afc4f08d40396e3aa2631e18a4dbb33.1622821729.git.qemu_oss@crudebyte.com> --- hw/9pfs/9p.c | 99 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 24 deletions(-) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 7be07f2d68..2815257f42 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -1705,9 +1705,9 @@ static void coroutine_fn v9fs_walk(void *opaque) int name_idx; V9fsQID *qids = NULL; int i, err = 0; - V9fsPath dpath, path; + V9fsPath dpath, path, *pathes = NULL; uint16_t nwnames; - struct stat stbuf; + struct stat stbuf, fidst, *stbufs = NULL; size_t offset = 7; int32_t fid, newfid; V9fsString *wnames = NULL; @@ -1733,6 +1733,8 @@ static void coroutine_fn v9fs_walk(void *opaque) if (nwnames) { wnames = g_new0(V9fsString, nwnames); qids = g_new0(V9fsQID, nwnames); + stbufs = g_new0(struct stat, nwnames); + pathes = g_new0(V9fsPath, nwnames); for (i = 0; i < nwnames; i++) { err = pdu_unmarshal(pdu, offset, "s", &wnames[i]); if (err < 0) { @@ -1753,39 +1755,85 @@ static void coroutine_fn v9fs_walk(void *opaque) v9fs_path_init(&dpath); v9fs_path_init(&path); - - err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); - if (err < 0) { - goto out; - } - err = stat_to_qid(pdu, &stbuf, &qid); - if (err < 0) { - goto out; - } - /* - * Both dpath and path initially poin to fidp. + * Both dpath and path initially point to fidp. * Needed to handle request with nwnames == 0 */ v9fs_path_copy(&dpath, &fidp->path); v9fs_path_copy(&path, &fidp->path); + + /* + * To keep latency (i.e. overall execution time for processing this + * Twalk client request) as small as possible, run all the required fs + * driver code altogether inside the following block. + */ + v9fs_co_run_in_worker({ + if (v9fs_request_cancelled(pdu)) { + err = -EINTR; + break; + } + err = s->ops->lstat(&s->ctx, &dpath, &fidst); + if (err < 0) { + err = -errno; + break; + } + stbuf = fidst; + for (name_idx = 0; name_idx < nwnames; name_idx++) { + if (v9fs_request_cancelled(pdu)) { + err = -EINTR; + break; + } + if (!same_stat_id(&pdu->s->root_st, &stbuf) || + strcmp("..", wnames[name_idx].data)) + { + err = s->ops->name_to_path(&s->ctx, &dpath, + wnames[name_idx].data, &path); + if (err < 0) { + err = -errno; + break; + } + if (v9fs_request_cancelled(pdu)) { + err = -EINTR; + break; + } + err = s->ops->lstat(&s->ctx, &path, &stbuf); + if (err < 0) { + err = -errno; + break; + } + stbufs[name_idx] = stbuf; + v9fs_path_copy(&dpath, &path); + v9fs_path_copy(&pathes[name_idx], &path); + } + } + }); + /* + * Handle all the rest of this Twalk request on main thread ... + */ + if (err < 0) { + goto out; + } + + err = stat_to_qid(pdu, &fidst, &qid); + if (err < 0) { + goto out; + } + stbuf = fidst; + + /* reset dpath and path */ + v9fs_path_copy(&dpath, &fidp->path); + v9fs_path_copy(&path, &fidp->path); + for (name_idx = 0; name_idx < nwnames; name_idx++) { if (!same_stat_id(&pdu->s->root_st, &stbuf) || - strcmp("..", wnames[name_idx].data)) { - err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data, - &path); - if (err < 0) { - goto out; - } - - err = v9fs_co_lstat(pdu, &path, &stbuf); - if (err < 0) { - goto out; - } + strcmp("..", wnames[name_idx].data)) + { + stbuf = stbufs[name_idx]; err = stat_to_qid(pdu, &stbuf, &qid); if (err < 0) { goto out; } + v9fs_path_copy(&path, &pathes[name_idx]); v9fs_path_copy(&dpath, &path); } memcpy(&qids[name_idx], &qid, sizeof(qid)); @@ -1821,9 +1869,12 @@ out_nofid: if (nwnames && nwnames <= P9_MAXWELEM) { for (name_idx = 0; name_idx < nwnames; name_idx++) { v9fs_string_free(&wnames[name_idx]); + v9fs_path_free(&pathes[name_idx]); } g_free(wnames); g_free(qids); + g_free(stbufs); + g_free(pathes); } } From bc05439334061f6adc04e4a044d490f961e7e0c3 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 5 Jul 2021 10:25:42 +0200 Subject: [PATCH 28/76] Makefile: Remove /usr/bin/env wrapper from the SHELL variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wrapper should not be needed here (it's not the shebang line of a shell script), and it is causing trouble on Haiku where "env" resides in a different directory. Reported-by: Richard Zak Signed-off-by: Thomas Huth Reviewed-by: Daniel P. Berrangé Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20210705082542.936856-1-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 30f19d33bb..6c36330eef 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ SRC_PATH=. # we have explicit rules for everything MAKEFLAGS += -rR -SHELL = /usr/bin/env bash -o pipefail +SHELL = bash -o pipefail # Usage: $(call quiet-command,command and args,"NAME","args to print") # This will run "command and args", and either: From f6b560bbc1b0120d7737c0efb53f691828d82faa Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 30 Jun 2021 18:32:28 +0200 Subject: [PATCH 29/76] softmmu/vl: Remove obsolete comment about the "frame" parameter The frame parameter has been removed along with the support for SDL 1.2. Fixes: 09bd7ba9f5 ("Remove deprecated -no-frame option") Signed-off-by: Thomas Huth Message-Id: <20210630163231.467987-2-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index d99e2cbdbf..cee6339580 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1062,8 +1062,6 @@ static void parse_display(const char *p) * sdl DisplayType needs hand-crafted parser instead of * parse_display_qapi() due to some options not in * DisplayOptions, specifically: - * - frame - * Already deprecated. * - ctrl_grab + alt_grab * Not clear yet what happens to them long-term. Should * replaced by something better or deprecated and dropped. From bb20b86db9acb7a6f653fd40c45d46a9df6b2a75 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 30 Jun 2021 18:32:29 +0200 Subject: [PATCH 30/76] ui: Fix the "-display sdl,window_close=..." parameter According to the QAPI schema, there is a "-" and not a "_" between "window" and "close", and we're also talking about "window-close" in the long parameter description in qemu-options.hx, so we should make sure that we rather use the variant with the "-" by default instead of only allowing the one with the "_" here. The old way still stays enabled for compatibility, but we deprecate it, so that we can switch to a QAPIfied parameter one day more easily. Signed-off-by: Thomas Huth Message-Id: <20210630163231.467987-3-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- docs/system/deprecated.rst | 6 ++++++ qemu-options.hx | 2 +- softmmu/vl.c | 7 ++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index e2e0090878..bb624d3170 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -126,6 +126,12 @@ other options have been processed. This will either have no effect (if if they were not given. The property is therefore useless and should not be specified. +``-display sdl,window_close=...`` (since 6.1) +''''''''''''''''''''''''''''''''''''''''''''' + +Use ``-display sdl,window-close=...`` instead (i.e. with a minus instead of +an underscore between "window" and "close"). + QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/qemu-options.hx b/qemu-options.hx index ba3ca9da1d..ae56fa4f28 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1784,7 +1784,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, #endif #if defined(CONFIG_SDL) "-display sdl[,alt_grab=on|off][,ctrl_grab=on|off]\n" - " [,window_close=on|off][,gl=on|core|es|off]\n" + " [,window-close=on|off][,gl=on|core|es|off]\n" #endif #if defined(CONFIG_GTK) "-display gtk[,grab_on_hover=on|off][,gl=on|off]|\n" diff --git a/softmmu/vl.c b/softmmu/vl.c index cee6339580..36b761677d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1089,7 +1089,12 @@ static void parse_display(const char *p) } else { goto invalid_sdl_args; } - } else if (strstart(opts, ",window_close=", &nextopt)) { + } else if (strstart(opts, ",window_close=", &nextopt) || + strstart(opts, ",window-close=", &nextopt)) { + if (strstart(opts, ",window_close=", NULL)) { + warn_report("window_close with an underscore is deprecated," + " please use window-close instead."); + } opts = nextopt; dpy.has_window_close = true; if (strstart(opts, "on", &nextopt)) { From b6ddc6a2b2b8c32dc2db12d5848eadde10e30136 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 30 Jun 2021 18:32:30 +0200 Subject: [PATCH 31/76] ui: Mark the '-no-quit' option as deprecated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's just a wrapper around the -display ...,window-close=off parameter, and the name "no-quit" is rather confusing compared to "window-close" (since there are still other means to quit the emulator), so we should rather tell our users to use the "window-close" parameter instead. While we're at it, update the documentation to state that "-no-quit" is available for GTK, too, not only for SDL. Reviewed-by: Daniel P. Berrangé Signed-off-by: Thomas Huth Message-Id: <20210630163231.467987-4-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- docs/system/deprecated.rst | 6 ++++++ qemu-options.hx | 5 +++-- softmmu/vl.c | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index bb624d3170..70e08baff6 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -132,6 +132,12 @@ specified. Use ``-display sdl,window-close=...`` instead (i.e. with a minus instead of an underscore between "window" and "close"). +``-no-quit`` (since 6.1) +'''''''''''''''''''''''' + +The ``-no-quit`` is a synonym for ``-display ...,window-close=off`` which +should be used instead. + QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/qemu-options.hx b/qemu-options.hx index ae56fa4f28..c862f1fa57 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1910,10 +1910,11 @@ SRST ERST DEF("no-quit", 0, QEMU_OPTION_no_quit, - "-no-quit disable SDL window close capability\n", QEMU_ARCH_ALL) + "-no-quit disable SDL/GTK window close capability (deprecated)\n", QEMU_ARCH_ALL) SRST ``-no-quit`` - Disable SDL window close capability. + Disable window close capability (SDL and GTK only). This option is + deprecated, please use ``-display ...,window-close=off`` instead. ERST DEF("sdl", 0, QEMU_OPTION_sdl, diff --git a/softmmu/vl.c b/softmmu/vl.c index 36b761677d..7dd2d72d0b 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3237,6 +3237,8 @@ void qemu_init(int argc, char **argv, char **envp) case QEMU_OPTION_no_quit: dpy.has_window_close = true; dpy.window_close = false; + warn_report("-no-quit is deprecated, please use " + "-display ...,window-close=off instead."); break; case QEMU_OPTION_sdl: #ifdef CONFIG_SDL From 95f439bd115efacb8593ca26e14303116f7ca988 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 30 Jun 2021 18:32:31 +0200 Subject: [PATCH 32/76] qemu-options: Improve the documentation of the -display options The sdl and gtk display options support more parameters than currently documented. Also the "vnc" option got lost during a recent commit, add it again. Fixes: ddc717581c ("Add display suboptions to man pages") Signed-off-by: Thomas Huth Message-Id: <20210630163231.467987-5-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- qemu-options.hx | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index c862f1fa57..8965dabc83 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1783,11 +1783,12 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, "-display spice-app[,gl=on|off]\n" #endif #if defined(CONFIG_SDL) - "-display sdl[,alt_grab=on|off][,ctrl_grab=on|off]\n" - " [,window-close=on|off][,gl=on|core|es|off]\n" + "-display sdl[,alt_grab=on|off][,ctrl_grab=on|off][,gl=on|core|es|off]\n" + " [,show-cursor=on|off][,window-close=on|off]\n" #endif #if defined(CONFIG_GTK) - "-display gtk[,grab_on_hover=on|off][,gl=on|off]|\n" + "-display gtk[,full-screen=on|off][,gl=on|off][,grab-on-hover=on|off]\n" + " [,show-cursor=on|off][,window-close=on|off]\n" #endif #if defined(CONFIG_VNC) "-display vnc=[,]\n" @@ -1824,17 +1825,37 @@ SRST application. The Spice server will redirect the serial consoles and QEMU monitors. (Since 4.0) - ``sdl[,window-close=on|off][,gl=on|core|es|off]`` - + ``sdl`` Display video output via SDL (usually in a separate graphics window; see the SDL documentation for other possibilities). + Valid parameters are: - ``gtk[,grab-on-hover=on|off][,gl=on|off]`` + ``alt_grab=on|off`` : Use Control+Alt+Shift-g to toggle mouse grabbing + + ``ctrl_grab=on|off`` : Use Right-Control-g to toggle mouse grabbing + + ``gl=on|off|core|es`` : Use OpenGL for displaying + + ``show-cursor=on|off`` : Force showing the mouse cursor + + ``window-close=on|off`` : Allow to quit qemu with window close button + + ``gtk`` Display video output in a GTK window. This interface provides drop-down menus and other UI elements to configure and control - the VM during runtime. + the VM during runtime. Valid parameters are: - ``curses [,charset=]`` + ``full-screen=on|off`` : Start in fullscreen mode + + ``gl=on|off`` : Use OpenGL for displaying + + ``grab-on-hover=on|off`` : Grab keyboard input on mouse hover + + ``show-cursor=on|off`` : Force showing the mouse cursor + + ``window-close=on|off`` : Allow to quit qemu with window close button + + ``curses[,charset=]`` Display video output via curses. For graphics device models which support a text mode, QEMU can display this output using a curses/ncurses interface. Nothing is displayed when the graphics @@ -1845,11 +1866,14 @@ SRST ``charset=CP850`` for IBM CP850 encoding. The default is ``CP437``. - ``egl-headless[,rendernode]`` + ``egl-headless[,rendernode=]`` Offload all OpenGL operations to a local DRI device. For any graphical display, this display needs to be paired with either VNC or SPICE displays. + ``vnc=`` + Start a VNC server on display + ``none`` Do not display video output. The guest will still see an emulated graphics card, but its output will not be displayed to @@ -1857,9 +1881,6 @@ SRST that it only affects what is done with video output; -nographic also changes the destination of the serial and parallel port data. - - - ERST DEF("nographic", 0, QEMU_OPTION_nographic, From dff5f68224505926762c9609b7fb120a2adc6aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 19 Jun 2021 11:13:41 +0200 Subject: [PATCH 33/76] coverity-scan: Remove lm32 / unicore32 targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lm32 has been removed in commit 9d49bcf6992 ("Drop the deprecated lm32 target"), and unicore32 in 4369223902a ("Drop the deprecated unicore32 target"). Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20210619091342.3660495-2-f4bug@amsat.org> Signed-off-by: Paolo Bonzini --- scripts/coverity-scan/COMPONENTS.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/coverity-scan/COMPONENTS.md b/scripts/coverity-scan/COMPONENTS.md index 02a3447dab..183f26a32c 100644 --- a/scripts/coverity-scan/COMPONENTS.md +++ b/scripts/coverity-scan/COMPONENTS.md @@ -21,9 +21,6 @@ hppa i386 ~ (/qemu)?((/include)?/hw/i386/.*|/target/i386/.*|/hw/intc/[^/]*apic[^/]*\.c) -lm32 - ~ (/qemu)?((/include)?/hw/lm32/.*|/target/lm32/.*|/hw/.*/(milkymist|lm32).*) - m68k ~ (/qemu)?((/include)?/hw/m68k/.*|/target/m68k/.*|(/include)?/hw(/.*)?/mcf.*) @@ -60,9 +57,6 @@ tilegx tricore ~ (/qemu)?((/include)?/hw/tricore/.*|/target/tricore/.*) -unicore32 - ~ (/qemu)?((/include)?/hw/unicore32/.*|/target/unicore32/.*) - 9pfs ~ (/qemu)?(/hw/9pfs/.*|/fsdev/.*) From dd52af17ec947332dfe45bd5f098c94c6ec0baa3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 20 Aug 2020 09:15:08 -0400 Subject: [PATCH 34/76] coverity-scan: switch to vpath build This is the patch that has been running on the coverity cronjob for a few weeks now. Signed-off-by: Paolo Bonzini --- scripts/coverity-scan/run-coverity-scan | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/coverity-scan/run-coverity-scan b/scripts/coverity-scan/run-coverity-scan index 6eefb4b558..7395bbfad4 100755 --- a/scripts/coverity-scan/run-coverity-scan +++ b/scripts/coverity-scan/run-coverity-scan @@ -380,15 +380,17 @@ export PATH="$TOOLBIN:$PATH" cd "$SRCDIR" -echo "Doing make distclean..." -make distclean +echo "Nuking build directory..." +rm -rf +build +mkdir +build +cd +build echo "Configuring..." # We configure with a fixed set of enables here to ensure that we don't # accidentally reduce the scope of the analysis by doing the build on # the system that's missing a dependency that we need to build part of # the codebase. -./configure --disable-modules --enable-sdl --enable-gtk \ +../configure --disable-modules --enable-sdl --enable-gtk \ --enable-opengl --enable-vte --enable-gnutls \ --enable-nettle --enable-curses --enable-curl \ --audio-drv-list=oss,alsa,sdl,pa --enable-virtfs \ From ac7b7cae4e8598359a2a7557899904c9563a776a Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Mon, 5 Jul 2021 11:46:25 +0100 Subject: [PATCH 35/76] target/i386: Declare constants for XSAVE offsets Declare and use manifest constants for the XSAVE state component offsets. Signed-off-by: David Edmondson Message-Id: <20210705104632.2902400-2-david.edmondson@oracle.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index f7fa5870b1..aedb8f2e01 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1305,6 +1305,22 @@ typedef struct XSavePKRU { uint32_t padding; } XSavePKRU; +#define XSAVE_FCW_FSW_OFFSET 0x000 +#define XSAVE_FTW_FOP_OFFSET 0x004 +#define XSAVE_CWD_RIP_OFFSET 0x008 +#define XSAVE_CWD_RDP_OFFSET 0x010 +#define XSAVE_MXCSR_OFFSET 0x018 +#define XSAVE_ST_SPACE_OFFSET 0x020 +#define XSAVE_XMM_SPACE_OFFSET 0x0a0 +#define XSAVE_XSTATE_BV_OFFSET 0x200 +#define XSAVE_AVX_OFFSET 0x240 +#define XSAVE_BNDREG_OFFSET 0x3c0 +#define XSAVE_BNDCSR_OFFSET 0x400 +#define XSAVE_OPMASK_OFFSET 0x440 +#define XSAVE_ZMM_HI256_OFFSET 0x480 +#define XSAVE_HI16_ZMM_OFFSET 0x680 +#define XSAVE_PKRU_OFFSET 0xa80 + typedef struct X86XSaveArea { X86LegacyXSaveArea legacy; X86XSaveHeader header; @@ -1325,19 +1341,19 @@ typedef struct X86XSaveArea { XSavePKRU pkru_state; } X86XSaveArea; -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != 0x240); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != XSAVE_AVX_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveAVX) != 0x100); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndreg_state) != 0x3c0); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndreg_state) != XSAVE_BNDREG_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveBNDREG) != 0x40); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndcsr_state) != 0x400); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndcsr_state) != XSAVE_BNDCSR_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveBNDCSR) != 0x40); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, opmask_state) != 0x440); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, opmask_state) != XSAVE_OPMASK_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveOpmask) != 0x40); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, zmm_hi256_state) != 0x480); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, zmm_hi256_state) != XSAVE_ZMM_HI256_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveZMM_Hi256) != 0x200); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, hi16_zmm_state) != 0x680); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, hi16_zmm_state) != XSAVE_HI16_ZMM_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveHi16_ZMM) != 0x400); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, pkru_state) != 0xA80); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, pkru_state) != XSAVE_PKRU_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8); typedef enum TPRAccess { From 436463b84b75fad6ff962e45a2220a7d1d17557e Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Mon, 5 Jul 2021 11:46:26 +0100 Subject: [PATCH 36/76] target/i386: Consolidate the X86XSaveArea offset checks Rather than having similar but different checks in cpu.h and kvm.c, move them all to cpu.h. Message-Id: <20210705104632.2902400-3-david.edmondson@oracle.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 22 +++++++++++++++------- target/i386/kvm/kvm.c | 39 --------------------------------------- 2 files changed, 15 insertions(+), 46 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index aedb8f2e01..6590ad6391 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1341,21 +1341,29 @@ typedef struct X86XSaveArea { XSavePKRU pkru_state; } X86XSaveArea; -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != XSAVE_AVX_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveAVX) != 0x100); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndreg_state) != XSAVE_BNDREG_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveBNDREG) != 0x40); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndcsr_state) != XSAVE_BNDCSR_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveBNDCSR) != 0x40); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, opmask_state) != XSAVE_OPMASK_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveOpmask) != 0x40); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, zmm_hi256_state) != XSAVE_ZMM_HI256_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveZMM_Hi256) != 0x200); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, hi16_zmm_state) != XSAVE_HI16_ZMM_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSaveHi16_ZMM) != 0x400); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, pkru_state) != XSAVE_PKRU_OFFSET); QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fcw) != XSAVE_FCW_FSW_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.ftw) != XSAVE_FTW_FOP_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fpip) != XSAVE_CWD_RIP_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fpdp) != XSAVE_CWD_RDP_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.mxcsr) != XSAVE_MXCSR_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fpregs) != XSAVE_ST_SPACE_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.xmm_regs) != XSAVE_XMM_SPACE_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != XSAVE_AVX_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndreg_state) != XSAVE_BNDREG_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndcsr_state) != XSAVE_BNDCSR_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, opmask_state) != XSAVE_OPMASK_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, zmm_hi256_state) != XSAVE_ZMM_HI256_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, hi16_zmm_state) != XSAVE_HI16_ZMM_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, pkru_state) != XSAVE_PKRU_OFFSET); + typedef enum TPRAccess { TPR_ACCESS_READ, TPR_ACCESS_WRITE, diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 04e4ec063f..3ab1d71775 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -2466,45 +2466,6 @@ static int kvm_put_fpu(X86CPU *cpu) return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_FPU, &fpu); } -#define XSAVE_FCW_FSW 0 -#define XSAVE_FTW_FOP 1 -#define XSAVE_CWD_RIP 2 -#define XSAVE_CWD_RDP 4 -#define XSAVE_MXCSR 6 -#define XSAVE_ST_SPACE 8 -#define XSAVE_XMM_SPACE 40 -#define XSAVE_XSTATE_BV 128 -#define XSAVE_YMMH_SPACE 144 -#define XSAVE_BNDREGS 240 -#define XSAVE_BNDCSR 256 -#define XSAVE_OPMASK 272 -#define XSAVE_ZMM_Hi256 288 -#define XSAVE_Hi16_ZMM 416 -#define XSAVE_PKRU 672 - -#define XSAVE_BYTE_OFFSET(word_offset) \ - ((word_offset) * sizeof_field(struct kvm_xsave, region[0])) - -#define ASSERT_OFFSET(word_offset, field) \ - QEMU_BUILD_BUG_ON(XSAVE_BYTE_OFFSET(word_offset) != \ - offsetof(X86XSaveArea, field)) - -ASSERT_OFFSET(XSAVE_FCW_FSW, legacy.fcw); -ASSERT_OFFSET(XSAVE_FTW_FOP, legacy.ftw); -ASSERT_OFFSET(XSAVE_CWD_RIP, legacy.fpip); -ASSERT_OFFSET(XSAVE_CWD_RDP, legacy.fpdp); -ASSERT_OFFSET(XSAVE_MXCSR, legacy.mxcsr); -ASSERT_OFFSET(XSAVE_ST_SPACE, legacy.fpregs); -ASSERT_OFFSET(XSAVE_XMM_SPACE, legacy.xmm_regs); -ASSERT_OFFSET(XSAVE_XSTATE_BV, header.xstate_bv); -ASSERT_OFFSET(XSAVE_YMMH_SPACE, avx_state); -ASSERT_OFFSET(XSAVE_BNDREGS, bndreg_state); -ASSERT_OFFSET(XSAVE_BNDCSR, bndcsr_state); -ASSERT_OFFSET(XSAVE_OPMASK, opmask_state); -ASSERT_OFFSET(XSAVE_ZMM_Hi256, zmm_hi256_state); -ASSERT_OFFSET(XSAVE_Hi16_ZMM, hi16_zmm_state); -ASSERT_OFFSET(XSAVE_PKRU, pkru_state); - static int kvm_put_xsave(X86CPU *cpu) { CPUX86State *env = &cpu->env; From fde74821006472f40fee9a094e6da86cd39b5623 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Mon, 5 Jul 2021 11:46:27 +0100 Subject: [PATCH 37/76] target/i386: Clarify the padding requirements of X86XSaveArea Replace the hard-coded size of offsets or structure elements with defined constants or sizeof(). Signed-off-by: David Edmondson Message-Id: <20210705104632.2902400-4-david.edmondson@oracle.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 6590ad6391..92f9ca264c 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1329,7 +1329,13 @@ typedef struct X86XSaveArea { /* AVX State: */ XSaveAVX avx_state; - uint8_t padding[960 - 576 - sizeof(XSaveAVX)]; + + /* Ensure that XSaveBNDREG is properly aligned. */ + uint8_t padding[XSAVE_BNDREG_OFFSET + - sizeof(X86LegacyXSaveArea) + - sizeof(X86XSaveHeader) + - sizeof(XSaveAVX)]; + /* MPX State: */ XSaveBNDREG bndreg_state; XSaveBNDCSR bndcsr_state; From c0198c5f87b6db25712672292e01ab710d6ef631 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Mon, 5 Jul 2021 11:46:28 +0100 Subject: [PATCH 38/76] target/i386: Pass buffer and length to XSAVE helper In preparation for removing assumptions about XSAVE area offsets, pass a buffer pointer and buffer length to the XSAVE helper functions. Signed-off-by: David Edmondson Message-Id: <20210705104632.2902400-5-david.edmondson@oracle.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 5 +++-- target/i386/hvf/hvf.c | 3 ++- target/i386/hvf/x86hvf.c | 19 ++++++++----------- target/i386/kvm/kvm.c | 13 +++++++------ target/i386/xsave_helper.c | 17 +++++++++-------- 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 92f9ca264c..ada2941c6e 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1667,6 +1667,7 @@ typedef struct CPUX86State { uint64_t apic_bus_freq; #if defined(CONFIG_KVM) || defined(CONFIG_HVF) void *xsave_buf; + uint32_t xsave_buf_len; #endif #if defined(CONFIG_KVM) struct kvm_nested_state *nested_state; @@ -2227,8 +2228,8 @@ void x86_cpu_dump_local_apic_state(CPUState *cs, int flags); /* cpu.c */ bool cpu_is_bsp(X86CPU *cpu); -void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf); -void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf); +void x86_cpu_xrstor_all_areas(X86CPU *cpu, const void *buf, uint32_t buflen); +void x86_cpu_xsave_all_areas(X86CPU *cpu, void *buf, uint32_t buflen); void x86_update_hflags(CPUX86State* env); static inline bool hyperv_feat_enabled(X86CPU *cpu, int feat) diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 346dbcc26f..e62e8df028 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -267,7 +267,8 @@ int hvf_arch_init_vcpu(CPUState *cpu) wvmcs(cpu->hvf->fd, VMCS_TPR_THRESHOLD, 0); x86cpu = X86_CPU(cpu); - x86cpu->env.xsave_buf = qemu_memalign(4096, 4096); + x86cpu->env.xsave_buf_len = 4096; + x86cpu->env.xsave_buf = qemu_memalign(4096, x86cpu->env.xsave_buf_len); hv_vcpu_enable_native_msr(cpu->hvf->fd, MSR_STAR, 1); hv_vcpu_enable_native_msr(cpu->hvf->fd, MSR_LSTAR, 1); diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index 2ced2c2478..05ec1bddc4 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -73,14 +73,12 @@ void hvf_get_segment(SegmentCache *qseg, struct vmx_segment *vmx_seg) void hvf_put_xsave(CPUState *cpu_state) { + void *xsave = X86_CPU(cpu_state)->env.xsave_buf; + uint32_t xsave_len = X86_CPU(cpu_state)->env.xsave_buf_len; - struct X86XSaveArea *xsave; + x86_cpu_xsave_all_areas(X86_CPU(cpu_state), xsave, xsave_len); - xsave = X86_CPU(cpu_state)->env.xsave_buf; - - x86_cpu_xsave_all_areas(X86_CPU(cpu_state), xsave); - - if (hv_vcpu_write_fpstate(cpu_state->hvf->fd, (void*)xsave, 4096)) { + if (hv_vcpu_write_fpstate(cpu_state->hvf->fd, xsave, xsave_len)) { abort(); } } @@ -158,15 +156,14 @@ void hvf_put_msrs(CPUState *cpu_state) void hvf_get_xsave(CPUState *cpu_state) { - struct X86XSaveArea *xsave; + void *xsave = X86_CPU(cpu_state)->env.xsave_buf; + uint32_t xsave_len = X86_CPU(cpu_state)->env.xsave_buf_len; - xsave = X86_CPU(cpu_state)->env.xsave_buf; - - if (hv_vcpu_read_fpstate(cpu_state->hvf->fd, (void*)xsave, 4096)) { + if (hv_vcpu_read_fpstate(cpu_state->hvf->fd, xsave, xsave_len)) { abort(); } - x86_cpu_xrstor_all_areas(X86_CPU(cpu_state), xsave); + x86_cpu_xrstor_all_areas(X86_CPU(cpu_state), xsave, xsave_len); } void hvf_get_segments(CPUState *cpu_state) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 3ab1d71775..41b0764ab7 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -1888,8 +1888,9 @@ int kvm_arch_init_vcpu(CPUState *cs) } if (has_xsave) { - env->xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); - memset(env->xsave_buf, 0, sizeof(struct kvm_xsave)); + env->xsave_buf_len = sizeof(struct kvm_xsave); + env->xsave_buf = qemu_memalign(4096, env->xsave_buf_len); + memset(env->xsave_buf, 0, env->xsave_buf_len); } max_nested_state_len = kvm_max_nested_state_length(); @@ -2469,12 +2470,12 @@ static int kvm_put_fpu(X86CPU *cpu) static int kvm_put_xsave(X86CPU *cpu) { CPUX86State *env = &cpu->env; - X86XSaveArea *xsave = env->xsave_buf; + void *xsave = env->xsave_buf; if (!has_xsave) { return kvm_put_fpu(cpu); } - x86_cpu_xsave_all_areas(cpu, xsave); + x86_cpu_xsave_all_areas(cpu, xsave, env->xsave_buf_len); return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave); } @@ -3119,7 +3120,7 @@ static int kvm_get_fpu(X86CPU *cpu) static int kvm_get_xsave(X86CPU *cpu) { CPUX86State *env = &cpu->env; - X86XSaveArea *xsave = env->xsave_buf; + void *xsave = env->xsave_buf; int ret; if (!has_xsave) { @@ -3130,7 +3131,7 @@ static int kvm_get_xsave(X86CPU *cpu) if (ret < 0) { return ret; } - x86_cpu_xrstor_all_areas(cpu, xsave); + x86_cpu_xrstor_all_areas(cpu, xsave, env->xsave_buf_len); return 0; } diff --git a/target/i386/xsave_helper.c b/target/i386/xsave_helper.c index 818115e7d2..b16c6ac0fe 100644 --- a/target/i386/xsave_helper.c +++ b/target/i386/xsave_helper.c @@ -6,14 +6,16 @@ #include "cpu.h" -void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf) +void x86_cpu_xsave_all_areas(X86CPU *cpu, void *buf, uint32_t buflen) { CPUX86State *env = &cpu->env; X86XSaveArea *xsave = buf; - uint16_t cwd, swd, twd; int i; - memset(xsave, 0, sizeof(X86XSaveArea)); + + assert(buflen >= sizeof(*xsave)); + + memset(xsave, 0, buflen); twd = 0; swd = env->fpus & ~(7 << 11); swd |= (env->fpstt & 7) << 11; @@ -56,17 +58,17 @@ void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf) 16 * sizeof env->xmm_regs[16]); memcpy(&xsave->pkru_state, &env->pkru, sizeof env->pkru); #endif - } -void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf) +void x86_cpu_xrstor_all_areas(X86CPU *cpu, const void *buf, uint32_t buflen) { - CPUX86State *env = &cpu->env; const X86XSaveArea *xsave = buf; - int i; uint16_t cwd, swd, twd; + + assert(buflen >= sizeof(*xsave)); + cwd = xsave->legacy.fcw; swd = xsave->legacy.fsw; twd = xsave->legacy.ftw; @@ -108,5 +110,4 @@ void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf) 16 * sizeof env->xmm_regs[16]); memcpy(&env->pkru, &xsave->pkru_state, sizeof env->pkru); #endif - } From 5aa10ab1a08e4123dee214a2f854909efb07b45b Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Mon, 5 Jul 2021 11:46:29 +0100 Subject: [PATCH 39/76] target/i386: Make x86_ext_save_areas visible outside cpu.c Provide visibility of the x86_ext_save_areas array and associated type outside of cpu.c. Signed-off-by: David Edmondson Message-Id: <20210705104632.2902400-6-david.edmondson@oracle.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 7 +------ target/i386/cpu.h | 9 +++++++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index d8f3ab3192..13caa0de50 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1304,12 +1304,7 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { }; #undef REGISTER -typedef struct ExtSaveArea { - uint32_t feature, bits; - uint32_t offset, size; -} ExtSaveArea; - -static const ExtSaveArea x86_ext_save_areas[] = { +const ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { [XSTATE_FP_BIT] = { /* x87 FP state component is always enabled if XSAVE is supported */ .feature = FEAT_1_ECX, .bits = CPUID_EXT_XSAVE, diff --git a/target/i386/cpu.h b/target/i386/cpu.h index ada2941c6e..c9c0a34330 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1370,6 +1370,15 @@ QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, zmm_hi256_state) != XSAVE_ZMM_HI256_OFF QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, hi16_zmm_state) != XSAVE_HI16_ZMM_OFFSET); QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, pkru_state) != XSAVE_PKRU_OFFSET); +typedef struct ExtSaveArea { + uint32_t feature, bits; + uint32_t offset, size; +} ExtSaveArea; + +#define XSAVE_STATE_AREA_COUNT (XSTATE_PKRU_BIT + 1) + +extern const ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT]; + typedef enum TPRAccess { TPR_ACCESS_READ, TPR_ACCESS_WRITE, From 3568987f78faff90829ea6c885bbdd5b083dc86c Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Mon, 5 Jul 2021 11:46:30 +0100 Subject: [PATCH 40/76] target/i386: Observe XSAVE state area offsets Rather than relying on the X86XSaveArea structure definition directly, the routines that manipulate the XSAVE state area should observe the offsets declared in the x86_ext_save_areas array. Currently the offsets declared in the array are derived from the structure definition, resulting in no functional change. Signed-off-by: David Edmondson Message-Id: <20210705104632.2902400-7-david.edmondson@oracle.com> Signed-off-by: Paolo Bonzini --- target/i386/xsave_helper.c | 262 ++++++++++++++++++++++++++++--------- 1 file changed, 200 insertions(+), 62 deletions(-) diff --git a/target/i386/xsave_helper.c b/target/i386/xsave_helper.c index b16c6ac0fe..ac61a96344 100644 --- a/target/i386/xsave_helper.c +++ b/target/i386/xsave_helper.c @@ -9,13 +9,20 @@ void x86_cpu_xsave_all_areas(X86CPU *cpu, void *buf, uint32_t buflen) { CPUX86State *env = &cpu->env; - X86XSaveArea *xsave = buf; - uint16_t cwd, swd, twd; + const ExtSaveArea *e, *f; int i; - assert(buflen >= sizeof(*xsave)); + X86LegacyXSaveArea *legacy; + X86XSaveHeader *header; + uint16_t cwd, swd, twd; + + memset(buf, 0, buflen); + + e = &x86_ext_save_areas[XSTATE_FP_BIT]; + + legacy = buf + e->offset; + header = buf + e->offset + sizeof(*legacy); - memset(xsave, 0, buflen); twd = 0; swd = env->fpus & ~(7 << 11); swd |= (env->fpstt & 7) << 11; @@ -23,91 +30,222 @@ void x86_cpu_xsave_all_areas(X86CPU *cpu, void *buf, uint32_t buflen) for (i = 0; i < 8; ++i) { twd |= (!env->fptags[i]) << i; } - xsave->legacy.fcw = cwd; - xsave->legacy.fsw = swd; - xsave->legacy.ftw = twd; - xsave->legacy.fpop = env->fpop; - xsave->legacy.fpip = env->fpip; - xsave->legacy.fpdp = env->fpdp; - memcpy(&xsave->legacy.fpregs, env->fpregs, - sizeof env->fpregs); - xsave->legacy.mxcsr = env->mxcsr; - xsave->header.xstate_bv = env->xstate_bv; - memcpy(&xsave->bndreg_state.bnd_regs, env->bnd_regs, - sizeof env->bnd_regs); - xsave->bndcsr_state.bndcsr = env->bndcs_regs; - memcpy(&xsave->opmask_state.opmask_regs, env->opmask_regs, - sizeof env->opmask_regs); + legacy->fcw = cwd; + legacy->fsw = swd; + legacy->ftw = twd; + legacy->fpop = env->fpop; + legacy->fpip = env->fpip; + legacy->fpdp = env->fpdp; + memcpy(&legacy->fpregs, env->fpregs, + sizeof(env->fpregs)); + legacy->mxcsr = env->mxcsr; for (i = 0; i < CPU_NB_REGS; i++) { - uint8_t *xmm = xsave->legacy.xmm_regs[i]; - uint8_t *ymmh = xsave->avx_state.ymmh[i]; - uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i]; + uint8_t *xmm = legacy->xmm_regs[i]; + stq_p(xmm, env->xmm_regs[i].ZMM_Q(0)); - stq_p(xmm+8, env->xmm_regs[i].ZMM_Q(1)); - stq_p(ymmh, env->xmm_regs[i].ZMM_Q(2)); - stq_p(ymmh+8, env->xmm_regs[i].ZMM_Q(3)); - stq_p(zmmh, env->xmm_regs[i].ZMM_Q(4)); - stq_p(zmmh+8, env->xmm_regs[i].ZMM_Q(5)); - stq_p(zmmh+16, env->xmm_regs[i].ZMM_Q(6)); - stq_p(zmmh+24, env->xmm_regs[i].ZMM_Q(7)); + stq_p(xmm + 8, env->xmm_regs[i].ZMM_Q(1)); + } + + header->xstate_bv = env->xstate_bv; + + e = &x86_ext_save_areas[XSTATE_YMM_BIT]; + if (e->size && e->offset) { + XSaveAVX *avx; + + avx = buf + e->offset; + + for (i = 0; i < CPU_NB_REGS; i++) { + uint8_t *ymmh = avx->ymmh[i]; + + stq_p(ymmh, env->xmm_regs[i].ZMM_Q(2)); + stq_p(ymmh + 8, env->xmm_regs[i].ZMM_Q(3)); + } + } + + e = &x86_ext_save_areas[XSTATE_BNDREGS_BIT]; + if (e->size && e->offset) { + XSaveBNDREG *bndreg; + XSaveBNDCSR *bndcsr; + + f = &x86_ext_save_areas[XSTATE_BNDCSR_BIT]; + assert(f->size); + assert(f->offset); + + bndreg = buf + e->offset; + bndcsr = buf + f->offset; + + memcpy(&bndreg->bnd_regs, env->bnd_regs, + sizeof(env->bnd_regs)); + bndcsr->bndcsr = env->bndcs_regs; + } + + e = &x86_ext_save_areas[XSTATE_OPMASK_BIT]; + if (e->size && e->offset) { + XSaveOpmask *opmask; + XSaveZMM_Hi256 *zmm_hi256; +#ifdef TARGET_X86_64 + XSaveHi16_ZMM *hi16_zmm; +#endif + + f = &x86_ext_save_areas[XSTATE_ZMM_Hi256_BIT]; + assert(f->size); + assert(f->offset); + + opmask = buf + e->offset; + zmm_hi256 = buf + f->offset; + + memcpy(&opmask->opmask_regs, env->opmask_regs, + sizeof(env->opmask_regs)); + + for (i = 0; i < CPU_NB_REGS; i++) { + uint8_t *zmmh = zmm_hi256->zmm_hi256[i]; + + stq_p(zmmh, env->xmm_regs[i].ZMM_Q(4)); + stq_p(zmmh + 8, env->xmm_regs[i].ZMM_Q(5)); + stq_p(zmmh + 16, env->xmm_regs[i].ZMM_Q(6)); + stq_p(zmmh + 24, env->xmm_regs[i].ZMM_Q(7)); + } + +#ifdef TARGET_X86_64 + f = &x86_ext_save_areas[XSTATE_Hi16_ZMM_BIT]; + assert(f->size); + assert(f->offset); + + hi16_zmm = buf + f->offset; + + memcpy(&hi16_zmm->hi16_zmm, &env->xmm_regs[16], + 16 * sizeof(env->xmm_regs[16])); +#endif } #ifdef TARGET_X86_64 - memcpy(&xsave->hi16_zmm_state.hi16_zmm, &env->xmm_regs[16], - 16 * sizeof env->xmm_regs[16]); - memcpy(&xsave->pkru_state, &env->pkru, sizeof env->pkru); + e = &x86_ext_save_areas[XSTATE_PKRU_BIT]; + if (e->size && e->offset) { + XSavePKRU *pkru = buf + e->offset; + + memcpy(pkru, &env->pkru, sizeof(env->pkru)); + } #endif } void x86_cpu_xrstor_all_areas(X86CPU *cpu, const void *buf, uint32_t buflen) { CPUX86State *env = &cpu->env; - const X86XSaveArea *xsave = buf; + const ExtSaveArea *e, *f, *g; int i; + + const X86LegacyXSaveArea *legacy; + const X86XSaveHeader *header; uint16_t cwd, swd, twd; - assert(buflen >= sizeof(*xsave)); + e = &x86_ext_save_areas[XSTATE_FP_BIT]; - cwd = xsave->legacy.fcw; - swd = xsave->legacy.fsw; - twd = xsave->legacy.ftw; - env->fpop = xsave->legacy.fpop; + legacy = buf + e->offset; + header = buf + e->offset + sizeof(*legacy); + + cwd = legacy->fcw; + swd = legacy->fsw; + twd = legacy->ftw; + env->fpop = legacy->fpop; env->fpstt = (swd >> 11) & 7; env->fpus = swd; env->fpuc = cwd; for (i = 0; i < 8; ++i) { env->fptags[i] = !((twd >> i) & 1); } - env->fpip = xsave->legacy.fpip; - env->fpdp = xsave->legacy.fpdp; - env->mxcsr = xsave->legacy.mxcsr; - memcpy(env->fpregs, &xsave->legacy.fpregs, - sizeof env->fpregs); - env->xstate_bv = xsave->header.xstate_bv; - memcpy(env->bnd_regs, &xsave->bndreg_state.bnd_regs, - sizeof env->bnd_regs); - env->bndcs_regs = xsave->bndcsr_state.bndcsr; - memcpy(env->opmask_regs, &xsave->opmask_state.opmask_regs, - sizeof env->opmask_regs); + env->fpip = legacy->fpip; + env->fpdp = legacy->fpdp; + env->mxcsr = legacy->mxcsr; + memcpy(env->fpregs, &legacy->fpregs, + sizeof(env->fpregs)); for (i = 0; i < CPU_NB_REGS; i++) { - const uint8_t *xmm = xsave->legacy.xmm_regs[i]; - const uint8_t *ymmh = xsave->avx_state.ymmh[i]; - const uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i]; + const uint8_t *xmm = legacy->xmm_regs[i]; + env->xmm_regs[i].ZMM_Q(0) = ldq_p(xmm); - env->xmm_regs[i].ZMM_Q(1) = ldq_p(xmm+8); - env->xmm_regs[i].ZMM_Q(2) = ldq_p(ymmh); - env->xmm_regs[i].ZMM_Q(3) = ldq_p(ymmh+8); - env->xmm_regs[i].ZMM_Q(4) = ldq_p(zmmh); - env->xmm_regs[i].ZMM_Q(5) = ldq_p(zmmh+8); - env->xmm_regs[i].ZMM_Q(6) = ldq_p(zmmh+16); - env->xmm_regs[i].ZMM_Q(7) = ldq_p(zmmh+24); + env->xmm_regs[i].ZMM_Q(1) = ldq_p(xmm + 8); + } + + env->xstate_bv = header->xstate_bv; + + e = &x86_ext_save_areas[XSTATE_YMM_BIT]; + if (e->size && e->offset) { + const XSaveAVX *avx; + + avx = buf + e->offset; + for (i = 0; i < CPU_NB_REGS; i++) { + const uint8_t *ymmh = avx->ymmh[i]; + + env->xmm_regs[i].ZMM_Q(2) = ldq_p(ymmh); + env->xmm_regs[i].ZMM_Q(3) = ldq_p(ymmh + 8); + } + } + + e = &x86_ext_save_areas[XSTATE_BNDREGS_BIT]; + if (e->size && e->offset) { + const XSaveBNDREG *bndreg; + const XSaveBNDCSR *bndcsr; + + f = &x86_ext_save_areas[XSTATE_BNDCSR_BIT]; + assert(f->size); + assert(f->offset); + + bndreg = buf + e->offset; + bndcsr = buf + f->offset; + + memcpy(env->bnd_regs, &bndreg->bnd_regs, + sizeof(env->bnd_regs)); + env->bndcs_regs = bndcsr->bndcsr; + } + + e = &x86_ext_save_areas[XSTATE_OPMASK_BIT]; + if (e->size && e->offset) { + const XSaveOpmask *opmask; + const XSaveZMM_Hi256 *zmm_hi256; +#ifdef TARGET_X86_64 + const XSaveHi16_ZMM *hi16_zmm; +#endif + + f = &x86_ext_save_areas[XSTATE_ZMM_Hi256_BIT]; + assert(f->size); + assert(f->offset); + + g = &x86_ext_save_areas[XSTATE_Hi16_ZMM_BIT]; + assert(g->size); + assert(g->offset); + + opmask = buf + e->offset; + zmm_hi256 = buf + f->offset; +#ifdef TARGET_X86_64 + hi16_zmm = buf + g->offset; +#endif + + memcpy(env->opmask_regs, &opmask->opmask_regs, + sizeof(env->opmask_regs)); + + for (i = 0; i < CPU_NB_REGS; i++) { + const uint8_t *zmmh = zmm_hi256->zmm_hi256[i]; + + env->xmm_regs[i].ZMM_Q(4) = ldq_p(zmmh); + env->xmm_regs[i].ZMM_Q(5) = ldq_p(zmmh + 8); + env->xmm_regs[i].ZMM_Q(6) = ldq_p(zmmh + 16); + env->xmm_regs[i].ZMM_Q(7) = ldq_p(zmmh + 24); + } + +#ifdef TARGET_X86_64 + memcpy(&env->xmm_regs[16], &hi16_zmm->hi16_zmm, + 16 * sizeof(env->xmm_regs[16])); +#endif } #ifdef TARGET_X86_64 - memcpy(&env->xmm_regs[16], &xsave->hi16_zmm_state.hi16_zmm, - 16 * sizeof env->xmm_regs[16]); - memcpy(&env->pkru, &xsave->pkru_state, sizeof env->pkru); + e = &x86_ext_save_areas[XSTATE_PKRU_BIT]; + if (e->size && e->offset) { + const XSavePKRU *pkru; + + pkru = buf + e->offset; + memcpy(&env->pkru, pkru, sizeof(env->pkru)); + } #endif } From fea4500841024195ec701713e05b92ebf667f192 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Mon, 5 Jul 2021 11:46:31 +0100 Subject: [PATCH 41/76] target/i386: Populate x86_ext_save_areas offsets using cpuid where possible Rather than relying on the X86XSaveArea structure definition, determine the offset of XSAVE state areas using CPUID leaf 0xd where possible (KVM and HVF). Signed-off-by: David Edmondson Message-Id: <20210705104632.2902400-8-david.edmondson@oracle.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 13 +------------ target/i386/cpu.h | 2 +- target/i386/hvf/hvf-cpu.c | 29 +++++++++++++++++++++++++++++ target/i386/hvf/hvf.c | 6 ++++++ target/i386/kvm/kvm-cpu.c | 30 ++++++++++++++++++++++++++++++ target/i386/kvm/kvm.c | 7 +++++++ target/i386/tcg/tcg-cpu.c | 20 ++++++++++++++++++++ 7 files changed, 94 insertions(+), 13 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 13caa0de50..5f595a0d7e 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1304,48 +1304,37 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { }; #undef REGISTER -const ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { +ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { [XSTATE_FP_BIT] = { /* x87 FP state component is always enabled if XSAVE is supported */ .feature = FEAT_1_ECX, .bits = CPUID_EXT_XSAVE, - /* x87 state is in the legacy region of the XSAVE area */ - .offset = 0, .size = sizeof(X86LegacyXSaveArea) + sizeof(X86XSaveHeader), }, [XSTATE_SSE_BIT] = { /* SSE state component is always enabled if XSAVE is supported */ .feature = FEAT_1_ECX, .bits = CPUID_EXT_XSAVE, - /* SSE state is in the legacy region of the XSAVE area */ - .offset = 0, .size = sizeof(X86LegacyXSaveArea) + sizeof(X86XSaveHeader), }, [XSTATE_YMM_BIT] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX, - .offset = offsetof(X86XSaveArea, avx_state), .size = sizeof(XSaveAVX) }, [XSTATE_BNDREGS_BIT] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, - .offset = offsetof(X86XSaveArea, bndreg_state), .size = sizeof(XSaveBNDREG) }, [XSTATE_BNDCSR_BIT] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, - .offset = offsetof(X86XSaveArea, bndcsr_state), .size = sizeof(XSaveBNDCSR) }, [XSTATE_OPMASK_BIT] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, - .offset = offsetof(X86XSaveArea, opmask_state), .size = sizeof(XSaveOpmask) }, [XSTATE_ZMM_Hi256_BIT] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, - .offset = offsetof(X86XSaveArea, zmm_hi256_state), .size = sizeof(XSaveZMM_Hi256) }, [XSTATE_Hi16_ZMM_BIT] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, - .offset = offsetof(X86XSaveArea, hi16_zmm_state), .size = sizeof(XSaveHi16_ZMM) }, [XSTATE_PKRU_BIT] = { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU, - .offset = offsetof(X86XSaveArea, pkru_state), .size = sizeof(XSavePKRU) }, }; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index c9c0a34330..96b672f8bd 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1377,7 +1377,7 @@ typedef struct ExtSaveArea { #define XSAVE_STATE_AREA_COUNT (XSTATE_PKRU_BIT + 1) -extern const ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT]; +extern ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT]; typedef enum TPRAccess { TPR_ACCESS_READ, diff --git a/target/i386/hvf/hvf-cpu.c b/target/i386/hvf/hvf-cpu.c index 8fbc423888..333db59898 100644 --- a/target/i386/hvf/hvf-cpu.c +++ b/target/i386/hvf/hvf-cpu.c @@ -30,6 +30,33 @@ static void hvf_cpu_max_instance_init(X86CPU *cpu) hvf_get_supported_cpuid(0xC0000000, 0, R_EAX); } +static void hvf_cpu_xsave_init(void) +{ + static bool first = true; + int i; + + if (!first) { + return; + } + first = false; + + /* x87 and SSE states are in the legacy region of the XSAVE area. */ + x86_ext_save_areas[XSTATE_FP_BIT].offset = 0; + x86_ext_save_areas[XSTATE_SSE_BIT].offset = 0; + + for (i = XSTATE_SSE_BIT + 1; i < XSAVE_STATE_AREA_COUNT; i++) { + ExtSaveArea *esa = &x86_ext_save_areas[i]; + + if (esa->size) { + int sz = hvf_get_supported_cpuid(0xd, i, R_EAX); + if (sz != 0) { + assert(esa->size == sz); + esa->offset = hvf_get_supported_cpuid(0xd, i, R_EBX); + } + } + } +} + static void hvf_cpu_instance_init(CPUState *cs) { X86CPU *cpu = X86_CPU(cs); @@ -42,6 +69,8 @@ static void hvf_cpu_instance_init(CPUState *cs) if (cpu->max_features) { hvf_cpu_max_instance_init(cpu); } + + hvf_cpu_xsave_init(); } static void hvf_cpu_accel_class_init(ObjectClass *oc, void *data) diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index e62e8df028..79ba4ed93a 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -270,6 +270,12 @@ int hvf_arch_init_vcpu(CPUState *cpu) x86cpu->env.xsave_buf_len = 4096; x86cpu->env.xsave_buf = qemu_memalign(4096, x86cpu->env.xsave_buf_len); + /* + * The allocated storage must be large enough for all of the + * possible XSAVE state components. + */ + assert(hvf_get_supported_cpuid(0xd, 0, R_ECX) <= x86cpu->env.xsave_buf_len); + hv_vcpu_enable_native_msr(cpu->hvf->fd, MSR_STAR, 1); hv_vcpu_enable_native_msr(cpu->hvf->fd, MSR_LSTAR, 1); hv_vcpu_enable_native_msr(cpu->hvf->fd, MSR_CSTAR, 1); diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c index 00369c2000..bbe817764d 100644 --- a/target/i386/kvm/kvm-cpu.c +++ b/target/i386/kvm/kvm-cpu.c @@ -122,6 +122,34 @@ static void kvm_cpu_max_instance_init(X86CPU *cpu) kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); } +static void kvm_cpu_xsave_init(void) +{ + static bool first = true; + KVMState *s = kvm_state; + int i; + + if (!first) { + return; + } + first = false; + + /* x87 and SSE states are in the legacy region of the XSAVE area. */ + x86_ext_save_areas[XSTATE_FP_BIT].offset = 0; + x86_ext_save_areas[XSTATE_SSE_BIT].offset = 0; + + for (i = XSTATE_SSE_BIT + 1; i < XSAVE_STATE_AREA_COUNT; i++) { + ExtSaveArea *esa = &x86_ext_save_areas[i]; + + if (esa->size) { + int sz = kvm_arch_get_supported_cpuid(s, 0xd, i, R_EAX); + if (sz != 0) { + assert(esa->size == sz); + esa->offset = kvm_arch_get_supported_cpuid(s, 0xd, i, R_EBX); + } + } + } +} + static void kvm_cpu_instance_init(CPUState *cs) { X86CPU *cpu = X86_CPU(cs); @@ -141,6 +169,8 @@ static void kvm_cpu_instance_init(CPUState *cs) if (cpu->max_features) { kvm_cpu_max_instance_init(cpu); } + + kvm_cpu_xsave_init(); } static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 41b0764ab7..a85035492f 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -1891,6 +1891,13 @@ int kvm_arch_init_vcpu(CPUState *cs) env->xsave_buf_len = sizeof(struct kvm_xsave); env->xsave_buf = qemu_memalign(4096, env->xsave_buf_len); memset(env->xsave_buf, 0, env->xsave_buf_len); + + /* + * The allocated storage must be large enough for all of the + * possible XSAVE state components. + */ + assert(kvm_arch_get_supported_cpuid(kvm_state, 0xd, 0, R_ECX) + <= env->xsave_buf_len); } max_nested_state_len = kvm_max_nested_state_length(); diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c index 014ebea2f6..e96ec9bbcc 100644 --- a/target/i386/tcg/tcg-cpu.c +++ b/target/i386/tcg/tcg-cpu.c @@ -80,6 +80,24 @@ static void tcg_cpu_class_init(CPUClass *cc) cc->init_accel_cpu = tcg_cpu_init_ops; } +static void tcg_cpu_xsave_init(void) +{ +#define XO(bit, field) \ + x86_ext_save_areas[bit].offset = offsetof(X86XSaveArea, field); + + XO(XSTATE_FP_BIT, legacy); + XO(XSTATE_SSE_BIT, legacy); + XO(XSTATE_YMM_BIT, avx_state); + XO(XSTATE_BNDREGS_BIT, bndreg_state); + XO(XSTATE_BNDCSR_BIT, bndcsr_state); + XO(XSTATE_OPMASK_BIT, opmask_state); + XO(XSTATE_ZMM_Hi256_BIT, zmm_hi256_state); + XO(XSTATE_Hi16_ZMM_BIT, hi16_zmm_state); + XO(XSTATE_PKRU_BIT, pkru_state); + +#undef XO +} + /* * TCG-specific defaults that override all CPU models when using TCG */ @@ -93,6 +111,8 @@ static void tcg_cpu_instance_init(CPUState *cs) X86CPU *cpu = X86_CPU(cs); /* Special cases not set in the X86CPUDefinition structs: */ x86_cpu_apply_props(cpu, tcg_default_props); + + tcg_cpu_xsave_init(); } static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data) From 48e5c98a38920e088a00e43cf12a4881fceeb4cb Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Mon, 5 Jul 2021 11:46:32 +0100 Subject: [PATCH 42/76] target/i386: Move X86XSaveArea into TCG Given that TCG is now the only consumer of X86XSaveArea, move the structure definition and associated offset declarations and checks to a TCG specific header. Signed-off-by: David Edmondson Message-Id: <20210705104632.2902400-9-david.edmondson@oracle.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 57 ------------------------------------ target/i386/tcg/fpu_helper.c | 1 + target/i386/tcg/tcg-cpu.h | 57 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 57 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 96b672f8bd..0f7ddbfeae 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1305,48 +1305,6 @@ typedef struct XSavePKRU { uint32_t padding; } XSavePKRU; -#define XSAVE_FCW_FSW_OFFSET 0x000 -#define XSAVE_FTW_FOP_OFFSET 0x004 -#define XSAVE_CWD_RIP_OFFSET 0x008 -#define XSAVE_CWD_RDP_OFFSET 0x010 -#define XSAVE_MXCSR_OFFSET 0x018 -#define XSAVE_ST_SPACE_OFFSET 0x020 -#define XSAVE_XMM_SPACE_OFFSET 0x0a0 -#define XSAVE_XSTATE_BV_OFFSET 0x200 -#define XSAVE_AVX_OFFSET 0x240 -#define XSAVE_BNDREG_OFFSET 0x3c0 -#define XSAVE_BNDCSR_OFFSET 0x400 -#define XSAVE_OPMASK_OFFSET 0x440 -#define XSAVE_ZMM_HI256_OFFSET 0x480 -#define XSAVE_HI16_ZMM_OFFSET 0x680 -#define XSAVE_PKRU_OFFSET 0xa80 - -typedef struct X86XSaveArea { - X86LegacyXSaveArea legacy; - X86XSaveHeader header; - - /* Extended save areas: */ - - /* AVX State: */ - XSaveAVX avx_state; - - /* Ensure that XSaveBNDREG is properly aligned. */ - uint8_t padding[XSAVE_BNDREG_OFFSET - - sizeof(X86LegacyXSaveArea) - - sizeof(X86XSaveHeader) - - sizeof(XSaveAVX)]; - - /* MPX State: */ - XSaveBNDREG bndreg_state; - XSaveBNDCSR bndcsr_state; - /* AVX-512 State: */ - XSaveOpmask opmask_state; - XSaveZMM_Hi256 zmm_hi256_state; - XSaveHi16_ZMM hi16_zmm_state; - /* PKRU State: */ - XSavePKRU pkru_state; -} X86XSaveArea; - QEMU_BUILD_BUG_ON(sizeof(XSaveAVX) != 0x100); QEMU_BUILD_BUG_ON(sizeof(XSaveBNDREG) != 0x40); QEMU_BUILD_BUG_ON(sizeof(XSaveBNDCSR) != 0x40); @@ -1355,21 +1313,6 @@ QEMU_BUILD_BUG_ON(sizeof(XSaveZMM_Hi256) != 0x200); QEMU_BUILD_BUG_ON(sizeof(XSaveHi16_ZMM) != 0x400); QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fcw) != XSAVE_FCW_FSW_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.ftw) != XSAVE_FTW_FOP_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fpip) != XSAVE_CWD_RIP_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fpdp) != XSAVE_CWD_RDP_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.mxcsr) != XSAVE_MXCSR_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fpregs) != XSAVE_ST_SPACE_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.xmm_regs) != XSAVE_XMM_SPACE_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != XSAVE_AVX_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndreg_state) != XSAVE_BNDREG_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndcsr_state) != XSAVE_BNDCSR_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, opmask_state) != XSAVE_OPMASK_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, zmm_hi256_state) != XSAVE_ZMM_HI256_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, hi16_zmm_state) != XSAVE_HI16_ZMM_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, pkru_state) != XSAVE_PKRU_OFFSET); - typedef struct ExtSaveArea { uint32_t feature, bits; uint32_t offset, size; diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c index 4e11965067..74bbe94b80 100644 --- a/target/i386/tcg/fpu_helper.c +++ b/target/i386/tcg/fpu_helper.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include #include "cpu.h" +#include "tcg-cpu.h" #include "exec/helper-proto.h" #include "fpu/softfloat.h" #include "fpu/softfloat-macros.h" diff --git a/target/i386/tcg/tcg-cpu.h b/target/i386/tcg/tcg-cpu.h index 36bd300af0..53a8494455 100644 --- a/target/i386/tcg/tcg-cpu.h +++ b/target/i386/tcg/tcg-cpu.h @@ -19,6 +19,63 @@ #ifndef TCG_CPU_H #define TCG_CPU_H +#define XSAVE_FCW_FSW_OFFSET 0x000 +#define XSAVE_FTW_FOP_OFFSET 0x004 +#define XSAVE_CWD_RIP_OFFSET 0x008 +#define XSAVE_CWD_RDP_OFFSET 0x010 +#define XSAVE_MXCSR_OFFSET 0x018 +#define XSAVE_ST_SPACE_OFFSET 0x020 +#define XSAVE_XMM_SPACE_OFFSET 0x0a0 +#define XSAVE_XSTATE_BV_OFFSET 0x200 +#define XSAVE_AVX_OFFSET 0x240 +#define XSAVE_BNDREG_OFFSET 0x3c0 +#define XSAVE_BNDCSR_OFFSET 0x400 +#define XSAVE_OPMASK_OFFSET 0x440 +#define XSAVE_ZMM_HI256_OFFSET 0x480 +#define XSAVE_HI16_ZMM_OFFSET 0x680 +#define XSAVE_PKRU_OFFSET 0xa80 + +typedef struct X86XSaveArea { + X86LegacyXSaveArea legacy; + X86XSaveHeader header; + + /* Extended save areas: */ + + /* AVX State: */ + XSaveAVX avx_state; + + /* Ensure that XSaveBNDREG is properly aligned. */ + uint8_t padding[XSAVE_BNDREG_OFFSET + - sizeof(X86LegacyXSaveArea) + - sizeof(X86XSaveHeader) + - sizeof(XSaveAVX)]; + + /* MPX State: */ + XSaveBNDREG bndreg_state; + XSaveBNDCSR bndcsr_state; + /* AVX-512 State: */ + XSaveOpmask opmask_state; + XSaveZMM_Hi256 zmm_hi256_state; + XSaveHi16_ZMM hi16_zmm_state; + /* PKRU State: */ + XSavePKRU pkru_state; +} X86XSaveArea; + +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fcw) != XSAVE_FCW_FSW_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.ftw) != XSAVE_FTW_FOP_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fpip) != XSAVE_CWD_RIP_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fpdp) != XSAVE_CWD_RDP_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.mxcsr) != XSAVE_MXCSR_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fpregs) != XSAVE_ST_SPACE_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.xmm_regs) != XSAVE_XMM_SPACE_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != XSAVE_AVX_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndreg_state) != XSAVE_BNDREG_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndcsr_state) != XSAVE_BNDCSR_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, opmask_state) != XSAVE_OPMASK_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, zmm_hi256_state) != XSAVE_ZMM_HI256_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, hi16_zmm_state) != XSAVE_HI16_ZMM_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, pkru_state) != XSAVE_PKRU_OFFSET); + bool tcg_cpu_realizefn(CPUState *cs, Error **errp); #endif /* TCG_CPU_H */ From f08b65b651bca2eac543de694f866049e48fb242 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 15 Jun 2021 17:18:42 +0200 Subject: [PATCH 43/76] configure: drop vte-2.90 check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All currently supported distros have vte 0.37 or newer, which is where the ABI changed from 2.90 to 2.91. So drop support for the older ABI. Suggested-by: Daniel P. Berrangé Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/configure b/configure index e799d908a3..27841f82ed 100755 --- a/configure +++ b/configure @@ -2803,19 +2803,13 @@ fi # VTE probe if test "$vte" != "no"; then - vteminversion="0.32.0" if $pkg_config --exists "vte-2.91"; then - vtepackage="vte-2.91" - else - vtepackage="vte-2.90" - fi - if $pkg_config --exists "$vtepackage >= $vteminversion"; then - vte_cflags=$($pkg_config --cflags $vtepackage) - vte_libs=$($pkg_config --libs $vtepackage) - vteversion=$($pkg_config --modversion $vtepackage) + vte_cflags=$($pkg_config --cflags vte-2.91) + vte_libs=$($pkg_config --libs vte-2.91) + vteversion=$($pkg_config --modversion vte-2.91) vte="yes" elif test "$vte" = "yes"; then - feature_not_found "vte" "Install libvte-2.90/2.91 devel" + feature_not_found "vte" "Install libvte-2.91 devel" else vte="no" fi From c23d7b4e570ce7e63042a60f0747595f515c6822 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 11:31:35 +0200 Subject: [PATCH 44/76] configure, meson: convert vte detection to meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 29 ++++------------------------- meson.build | 16 ++++++++++------ meson_options.txt | 2 ++ 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/configure b/configure index 27841f82ed..fe86da4fdd 100755 --- a/configure +++ b/configure @@ -408,7 +408,7 @@ gnutls="auto" nettle="auto" gcrypt="auto" auth_pam="auto" -vte="$default_feature" +vte="auto" virglrenderer="$default_feature" tpm="$default_feature" libssh="$default_feature" @@ -1395,9 +1395,9 @@ for opt do ;; --disable-pvrdma) pvrdma="no" ;; - --disable-vte) vte="no" + --disable-vte) vte="disabled" ;; - --enable-vte) vte="yes" + --enable-vte) vte="enabled" ;; --disable-virglrenderer) virglrenderer="no" ;; @@ -2799,22 +2799,6 @@ EOF fi fi -########################################## -# VTE probe - -if test "$vte" != "no"; then - if $pkg_config --exists "vte-2.91"; then - vte_cflags=$($pkg_config --cflags vte-2.91) - vte_libs=$($pkg_config --libs vte-2.91) - vteversion=$($pkg_config --modversion vte-2.91) - vte="yes" - elif test "$vte" = "yes"; then - feature_not_found "vte" "Install libvte-2.91 devel" - else - vte="no" - fi -fi - ########################################## # RDMA needs OpenFabrics libraries if test "$rdma" != "no" ; then @@ -5482,11 +5466,6 @@ fi if test "$have_copy_file_range" = "yes" ; then echo "HAVE_COPY_FILE_RANGE=y" >> $config_host_mak fi -if test "$vte" = "yes" ; then - echo "CONFIG_VTE=y" >> $config_host_mak - echo "VTE_CFLAGS=$vte_cflags" >> $config_host_mak - echo "VTE_LIBS=$vte_libs" >> $config_host_mak -fi if test "$virglrenderer" = "yes" ; then echo "CONFIG_VIRGL=y" >> $config_host_mak echo "VIRGL_CFLAGS=$virgl_cflags" >> $config_host_mak @@ -6149,7 +6128,7 @@ if test "$skip_meson" = no; then -Dkvm=$kvm -Dhax=$hax -Dwhpx=$whpx -Dhvf=$hvf -Dnvmm=$nvmm \ -Dxen=$xen -Dxen_pci_passthrough=$xen_pci_passthrough -Dtcg=$tcg \ -Dcocoa=$cocoa -Dgtk=$gtk -Dmpath=$mpath -Dsdl=$sdl -Dsdl_image=$sdl_image \ - -Dlibusb=$libusb -Dsmartcard=$smartcard -Dusb_redir=$usb_redir \ + -Dlibusb=$libusb -Dsmartcard=$smartcard -Dusb_redir=$usb_redir -Dvte=$vte \ -Dvnc=$vnc -Dvnc_sasl=$vnc_sasl -Dvnc_jpeg=$vnc_jpeg -Dvnc_png=$vnc_png \ -Dgettext=$gettext -Dxkbcommon=$xkbcommon -Du2f=$u2f -Dvirtiofsd=$virtiofsd \ -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt -Dbrlapi=$brlapi \ diff --git a/meson.build b/meson.build index db6789af9c..b15c1ee4fd 100644 --- a/meson.build +++ b/meson.build @@ -860,6 +860,7 @@ endif gtk = not_found gtkx11 = not_found +vte = not_found if not get_option('gtk').auto() or (have_system and not cocoa.found()) gtk = dependency('gtk+-3.0', version: '>=3.22.0', method: 'pkg-config', @@ -871,14 +872,16 @@ if not get_option('gtk').auto() or (have_system and not cocoa.found()) required: false, kwargs: static_kwargs) gtk = declare_dependency(dependencies: [gtk, gtkx11]) + + if not get_option('vte').auto() or have_system + vte = dependency('vte-2.91', + method: 'pkg-config', + required: get_option('vte'), + kwargs: static_kwargs) + endif endif endif -vte = not_found -if 'CONFIG_VTE' in config_host - vte = declare_dependency(compile_args: config_host['VTE_CFLAGS'].split(), - link_args: config_host['VTE_LIBS'].split()) -endif x11 = not_found if gtkx11.found() x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found(), @@ -1208,6 +1211,7 @@ if glusterfs.found() config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat) endif config_host_data.set('CONFIG_GTK', gtk.found()) +config_host_data.set('CONFIG_VTE', vte.found()) config_host_data.set('CONFIG_LIBATTR', have_old_libattr) config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found()) config_host_data.set('CONFIG_EBPF', libbpf.found()) @@ -2756,7 +2760,7 @@ summary_info += {'SDL image support': sdl_image.found()} summary_info += {'GTK support': gtk.found()} summary_info += {'pixman': pixman.found()} # TODO: add back version -summary_info += {'VTE support': config_host.has_key('CONFIG_VTE')} +summary_info += {'VTE support': vte.found()} # TODO: add back version summary_info += {'slirp support': slirp_opt == 'disabled' ? false : slirp_opt} summary_info += {'libtasn1': tasn1.found()} diff --git a/meson_options.txt b/meson_options.txt index f7ec9bee27..8af42987f4 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -118,6 +118,8 @@ option('vnc_png', type : 'feature', value : 'auto', description: 'PNG compression for VNC server') option('vnc_sasl', type : 'feature', value : 'auto', description: 'SASL authentication for VNC server') +option('vte', type : 'feature', value : 'auto', + description: 'vte support for the gtk UI') option('xkbcommon', type : 'feature', value : 'auto', description: 'xkbcommon support') option('zstd', type : 'feature', value : 'auto', From 587d59d6ccd0e73bfe5689d9232804339aa09bdf Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 11:31:35 +0200 Subject: [PATCH 45/76] configure, meson: convert virgl detection to meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 35 ++++------------------------------- hw/display/meson.build | 6 +++--- meson.build | 10 ++++++---- meson_options.txt | 2 ++ 4 files changed, 15 insertions(+), 38 deletions(-) diff --git a/configure b/configure index fe86da4fdd..895192e0de 100755 --- a/configure +++ b/configure @@ -409,7 +409,7 @@ nettle="auto" gcrypt="auto" auth_pam="auto" vte="auto" -virglrenderer="$default_feature" +virglrenderer="auto" tpm="$default_feature" libssh="$default_feature" live_block_migration=${default_feature:-yes} @@ -1399,9 +1399,9 @@ for opt do ;; --enable-vte) vte="enabled" ;; - --disable-virglrenderer) virglrenderer="no" + --disable-virglrenderer) virglrenderer="disabled" ;; - --enable-virglrenderer) virglrenderer="yes" + --enable-virglrenderer) virglrenderer="enabled" ;; --disable-tpm) tpm="no" ;; @@ -4036,28 +4036,6 @@ EOF fi fi -########################################## -# virgl renderer probe - -if test "$virglrenderer" != "no" ; then - cat > $TMPC << EOF -#include -int main(void) { virgl_renderer_poll(); return 0; } -EOF - virgl_cflags=$($pkg_config --cflags virglrenderer 2>/dev/null) - virgl_libs=$($pkg_config --libs virglrenderer 2>/dev/null) - virgl_version=$($pkg_config --modversion virglrenderer 2>/dev/null) - if $pkg_config virglrenderer >/dev/null 2>&1 && \ - compile_prog "$virgl_cflags" "$virgl_libs" ; then - virglrenderer="yes" - else - if test "$virglrenderer" = "yes" ; then - feature_not_found "virglrenderer" - fi - virglrenderer="no" - fi -fi - ########################################## # capstone @@ -5466,11 +5444,6 @@ fi if test "$have_copy_file_range" = "yes" ; then echo "HAVE_COPY_FILE_RANGE=y" >> $config_host_mak fi -if test "$virglrenderer" = "yes" ; then - echo "CONFIG_VIRGL=y" >> $config_host_mak - echo "VIRGL_CFLAGS=$virgl_cflags" >> $config_host_mak - echo "VIRGL_LIBS=$virgl_libs" >> $config_host_mak -fi if test "$xen" = "enabled" ; then echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak @@ -6137,7 +6110,7 @@ if test "$skip_meson" = no; then -Drbd=$rbd -Dlzo=$lzo -Dsnappy=$snappy -Dlzfse=$lzfse \ -Dgnutls=$gnutls -Dnettle=$nettle -Dgcrypt=$gcrypt -Dauth_pam=$auth_pam \ -Dzstd=$zstd -Dseccomp=$seccomp -Dvirtfs=$virtfs -Dcap_ng=$cap_ng \ - -Dattr=$attr -Ddefault_devices=$default_devices \ + -Dattr=$attr -Ddefault_devices=$default_devices -Dvirglrenderer=$virglrenderer \ -Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \ -Dvhost_user_blk_server=$vhost_user_blk_server -Dmultiprocess=$multiprocess \ -Dfuse=$fuse -Dfuse_lseek=$fuse_lseek -Dguest_agent_msi=$guest_agent_msi -Dbpf=$bpf\ diff --git a/hw/display/meson.build b/hw/display/meson.build index e1f473c1df..1e6b707d3c 100644 --- a/hw/display/meson.build +++ b/hw/display/meson.build @@ -61,7 +61,7 @@ if config_all_devices.has_key('CONFIG_VIRTIO_GPU') hw_display_modules += {'virtio-gpu': virtio_gpu_ss} virtio_gpu_gl_ss = ss.source_set() - virtio_gpu_gl_ss.add(when: ['CONFIG_VIRTIO_GPU', 'CONFIG_VIRGL', opengl], + virtio_gpu_gl_ss.add(when: ['CONFIG_VIRTIO_GPU', virgl, opengl], if_true: [files('virtio-gpu-gl.c', 'virtio-gpu-virgl.c'), pixman, virgl]) hw_display_modules += {'virtio-gpu-gl': virtio_gpu_gl_ss} endif @@ -75,7 +75,7 @@ if config_all_devices.has_key('CONFIG_VIRTIO_PCI') hw_display_modules += {'virtio-gpu-pci': virtio_gpu_pci_ss} virtio_gpu_pci_gl_ss = ss.source_set() - virtio_gpu_pci_gl_ss.add(when: ['CONFIG_VIRTIO_GPU', 'CONFIG_VIRTIO_PCI', 'CONFIG_VIRGL', opengl], + virtio_gpu_pci_gl_ss.add(when: ['CONFIG_VIRTIO_GPU', 'CONFIG_VIRTIO_PCI', virgl, opengl], if_true: [files('virtio-gpu-pci-gl.c'), pixman]) hw_display_modules += {'virtio-gpu-pci-gl': virtio_gpu_pci_gl_ss} endif @@ -89,7 +89,7 @@ if config_all_devices.has_key('CONFIG_VIRTIO_VGA') hw_display_modules += {'virtio-vga': virtio_vga_ss} virtio_vga_gl_ss = ss.source_set() - virtio_vga_gl_ss.add(when: ['CONFIG_VIRTIO_VGA', 'CONFIG_VIRGL', opengl], + virtio_vga_gl_ss.add(when: ['CONFIG_VIRTIO_VGA', virgl, opengl], if_true: [files('virtio-vga-gl.c'), pixman]) hw_display_modules += {'virtio-vga-gl': virtio_vga_gl_ss} endif diff --git a/meson.build b/meson.build index b15c1ee4fd..84ffdb4599 100644 --- a/meson.build +++ b/meson.build @@ -471,9 +471,11 @@ if 'CONFIG_GBM' in config_host link_args: config_host['GBM_LIBS'].split()) endif virgl = not_found -if 'CONFIG_VIRGL' in config_host - virgl = declare_dependency(compile_args: config_host['VIRGL_CFLAGS'].split(), - link_args: config_host['VIRGL_LIBS'].split()) +if not get_option('virglrenderer').auto() or have_system + virgl = dependency('virglrenderer', + method: 'pkg-config', + required: get_option('virglrenderer'), + kwargs: static_kwargs) endif curl = not_found if not get_option('curl').auto() or have_block @@ -2768,7 +2770,7 @@ summary_info += {'PAM': pam.found()} summary_info += {'iconv support': iconv.found()} summary_info += {'curses support': curses.found()} # TODO: add back version -summary_info += {'virgl support': config_host.has_key('CONFIG_VIRGL')} +summary_info += {'virgl support': virgl.found()} summary_info += {'curl support': curl.found()} summary_info += {'Multipath support': mpathpersist.found()} summary_info += {'VNC support': vnc.found()} diff --git a/meson_options.txt b/meson_options.txt index 8af42987f4..a70aedb0eb 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -110,6 +110,8 @@ option('u2f', type : 'feature', value : 'auto', description: 'U2F emulation support') option('usb_redir', type : 'feature', value : 'auto', description: 'libusbredir support') +option('virglrenderer', type : 'feature', value : 'auto', + description: 'virgl rendering support') option('vnc', type : 'feature', value : 'enabled', description: 'VNC server') option('vnc_jpeg', type : 'feature', value : 'auto', From 83ef16821a41e540cec7a282374dcbfc1b2b0851 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 11:31:35 +0200 Subject: [PATCH 46/76] configure, meson: convert libdaxctl detection to meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 28 ++++------------------------ meson.build | 8 +++++--- meson_options.txt | 2 ++ 3 files changed, 11 insertions(+), 27 deletions(-) diff --git a/configure b/configure index 895192e0de..5b18f4fac3 100755 --- a/configure +++ b/configure @@ -433,7 +433,7 @@ plugins="no" fuzzing="no" rng_none="no" secret_keyring="$default_feature" -libdaxctl="$default_feature" +libdaxctl="auto" meson="" ninja="" skip_meson=no @@ -1534,9 +1534,9 @@ for opt do ;; --disable-keyring) secret_keyring="no" ;; - --enable-libdaxctl) libdaxctl=yes + --enable-libdaxctl) libdaxctl=disabled ;; - --disable-libdaxctl) libdaxctl=no + --disable-libdaxctl) libdaxctl=enabled ;; --enable-fuse) fuse="enabled" ;; @@ -4949,22 +4949,6 @@ if test "$libpmem" != "no"; then fi fi -########################################## -# check for libdaxctl - -if test "$libdaxctl" != "no"; then - if $pkg_config --atleast-version=57 "libdaxctl"; then - libdaxctl="yes" - libdaxctl_libs=$($pkg_config --libs libdaxctl) - libdaxctl_cflags=$($pkg_config --cflags libdaxctl) - else - if test "$libdaxctl" = "yes" ; then - feature_not_found "libdaxctl" "Install libdaxctl" - fi - libdaxctl="no" - fi -fi - ########################################## # check for slirp @@ -5738,11 +5722,6 @@ if test "$libpmem" = "yes" ; then echo "LIBPMEM_CFLAGS=$libpmem_cflags" >> $config_host_mak fi -if test "$libdaxctl" = "yes" ; then - echo "CONFIG_LIBDAXCTL=y" >> $config_host_mak - echo "LIBDAXCTL_LIBS=$libdaxctl_libs" >> $config_host_mak -fi - if test "$bochs" = "yes" ; then echo "CONFIG_BOCHS=y" >> $config_host_mak fi @@ -6108,6 +6087,7 @@ if test "$skip_meson" = no; then -Dcurl=$curl -Dglusterfs=$glusterfs -Dbzip2=$bzip2 -Dlibiscsi=$libiscsi \ -Dlibnfs=$libnfs -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\ -Drbd=$rbd -Dlzo=$lzo -Dsnappy=$snappy -Dlzfse=$lzfse \ + -Dlibdaxctl=$libdaxctl \ -Dgnutls=$gnutls -Dnettle=$nettle -Dgcrypt=$gcrypt -Dauth_pam=$auth_pam \ -Dzstd=$zstd -Dseccomp=$seccomp -Dvirtfs=$virtfs -Dcap_ng=$cap_ng \ -Dattr=$attr -Ddefault_devices=$default_devices -Dvirglrenderer=$virglrenderer \ diff --git a/meson.build b/meson.build index 84ffdb4599..e530829105 100644 --- a/meson.build +++ b/meson.build @@ -1011,8 +1011,10 @@ if 'CONFIG_LIBPMEM' in config_host link_args: config_host['LIBPMEM_LIBS'].split()) endif libdaxctl = not_found -if 'CONFIG_LIBDAXCTL' in config_host - libdaxctl = declare_dependency(link_args: config_host['LIBDAXCTL_LIBS'].split()) +if not get_option('libdaxctl').auto() or have_system + libdaxctl = dependency('libdaxctl', required: get_option('libdaxctl'), + version: '>=57', method: 'pkg-config', + kwargs: static_kwargs) endif tasn1 = not_found if gnutls.found() @@ -2821,7 +2823,7 @@ summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')} summary_info += {'libxml2': config_host.has_key('CONFIG_LIBXML2')} summary_info += {'capstone': capstone_opt == 'disabled' ? false : capstone_opt} summary_info += {'libpmem support': config_host.has_key('CONFIG_LIBPMEM')} -summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')} +summary_info += {'libdaxctl support': libdaxctl.found()} summary_info += {'libudev': libudev.found()} summary_info += {'FUSE lseek': fuse_lseek.found()} summary(summary_info, bool_yn: true, section: 'Dependencies') diff --git a/meson_options.txt b/meson_options.txt index a70aedb0eb..46180000fd 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -84,6 +84,8 @@ option('nettle', type : 'feature', value : 'auto', description: 'nettle cryptography support') option('gcrypt', type : 'feature', value : 'auto', description: 'libgcrypt cryptography support') +option('libdaxctl', type : 'feature', value : 'auto', + description: 'libdaxctl support') option('libudev', type : 'feature', value : 'auto', description: 'Use libudev to enumerate host devices') option('libusb', type : 'feature', value : 'auto', From e36e8c70f6d3ed844f4606f3f019d2ae808f0af1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 11:31:35 +0200 Subject: [PATCH 47/76] configure, meson: convert libpmem detection to meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 24 ++++-------------------- meson.build | 8 ++++---- meson_options.txt | 2 ++ 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/configure b/configure index 5b18f4fac3..51b8c3290a 100755 --- a/configure +++ b/configure @@ -427,7 +427,7 @@ qed=${default_feature:-yes} parallels=${default_feature:-yes} libxml2="$default_feature" debug_mutex="no" -libpmem="$default_feature" +libpmem="auto" default_devices="true" plugins="no" fuzzing="no" @@ -1504,9 +1504,9 @@ for opt do ;; --disable-debug-mutex) debug_mutex=no ;; - --enable-libpmem) libpmem=yes + --enable-libpmem) libpmem=disabled ;; - --disable-libpmem) libpmem=no + --disable-libpmem) libpmem=enabled ;; --enable-xkbcommon) xkbcommon="enabled" ;; @@ -4933,22 +4933,6 @@ EOF fi fi -########################################## -# check for libpmem - -if test "$libpmem" != "no"; then - if $pkg_config --exists "libpmem"; then - libpmem="yes" - libpmem_libs=$($pkg_config --libs libpmem) - libpmem_cflags=$($pkg_config --cflags libpmem) - else - if test "$libpmem" = "yes" ; then - feature_not_found "libpmem" "Install nvml or pmdk" - fi - libpmem="no" - fi -fi - ########################################## # check for slirp @@ -6087,7 +6071,7 @@ if test "$skip_meson" = no; then -Dcurl=$curl -Dglusterfs=$glusterfs -Dbzip2=$bzip2 -Dlibiscsi=$libiscsi \ -Dlibnfs=$libnfs -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\ -Drbd=$rbd -Dlzo=$lzo -Dsnappy=$snappy -Dlzfse=$lzfse \ - -Dlibdaxctl=$libdaxctl \ + -Dlibdaxctl=$libdaxctl -Dlibpmem=$libpmem \ -Dgnutls=$gnutls -Dnettle=$nettle -Dgcrypt=$gcrypt -Dauth_pam=$auth_pam \ -Dzstd=$zstd -Dseccomp=$seccomp -Dvirtfs=$virtfs -Dcap_ng=$cap_ng \ -Dattr=$attr -Ddefault_devices=$default_devices -Dvirglrenderer=$virglrenderer \ diff --git a/meson.build b/meson.build index e530829105..e301eda3a5 100644 --- a/meson.build +++ b/meson.build @@ -1006,9 +1006,9 @@ if not get_option('libusb').auto() or have_system endif libpmem = not_found -if 'CONFIG_LIBPMEM' in config_host - libpmem = declare_dependency(compile_args: config_host['LIBPMEM_CFLAGS'].split(), - link_args: config_host['LIBPMEM_LIBS'].split()) +if not get_option('libpmem').auto() or have_system + libpmem = dependency('libpmem', required: get_option('libpmem'), + method: 'pkg-config', kwargs: static_kwargs) endif libdaxctl = not_found if not get_option('libdaxctl').auto() or have_system @@ -2822,7 +2822,7 @@ summary_info += {'zstd support': zstd.found()} summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')} summary_info += {'libxml2': config_host.has_key('CONFIG_LIBXML2')} summary_info += {'capstone': capstone_opt == 'disabled' ? false : capstone_opt} -summary_info += {'libpmem support': config_host.has_key('CONFIG_LIBPMEM')} +summary_info += {'libpmem support': libpmem.found()} summary_info += {'libdaxctl support': libdaxctl.found()} summary_info += {'libudev': libudev.found()} summary_info += {'FUSE lseek': fuse_lseek.found()} diff --git a/meson_options.txt b/meson_options.txt index 46180000fd..b23174d0a1 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -86,6 +86,8 @@ option('gcrypt', type : 'feature', value : 'auto', description: 'libgcrypt cryptography support') option('libdaxctl', type : 'feature', value : 'auto', description: 'libdaxctl support') +option('libpmem', type : 'feature', value : 'auto', + description: 'libpmem support') option('libudev', type : 'feature', value : 'auto', description: 'Use libudev to enumerate host devices') option('libusb', type : 'feature', value : 'auto', From 53c22b68e3ecd1764dfd325baefea6acd0b1dc70 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 11:31:35 +0200 Subject: [PATCH 48/76] configure, meson: convert liburing detection to meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 28 ++++------------------------ meson.build | 9 +++++---- meson_options.txt | 2 ++ 3 files changed, 11 insertions(+), 28 deletions(-) diff --git a/configure b/configure index 51b8c3290a..4e016f671c 100755 --- a/configure +++ b/configure @@ -315,7 +315,7 @@ xen="$default_feature" xen_ctrl_version="$default_feature" xen_pci_passthrough="auto" linux_aio="$default_feature" -linux_io_uring="$default_feature" +linux_io_uring="auto" cap_ng="auto" attr="auto" xfs="$default_feature" @@ -1205,9 +1205,9 @@ for opt do ;; --enable-linux-aio) linux_aio="yes" ;; - --disable-linux-io-uring) linux_io_uring="no" + --disable-linux-io-uring) linux_io_uring="disabled" ;; - --enable-linux-io-uring) linux_io_uring="yes" + --enable-linux-io-uring) linux_io_uring="enabled" ;; --disable-attr) attr="disabled" ;; @@ -3334,21 +3334,6 @@ EOF linux_aio=no fi fi -########################################## -# linux-io-uring probe - -if test "$linux_io_uring" != "no" ; then - if $pkg_config liburing; then - linux_io_uring_cflags=$($pkg_config --cflags liburing) - linux_io_uring_libs=$($pkg_config --libs liburing) - linux_io_uring=yes - else - if test "$linux_io_uring" = "yes" ; then - feature_not_found "linux io_uring" "Install liburing devel" - fi - linux_io_uring=no - fi -fi ########################################## # TPM emulation is only on POSIX @@ -5421,11 +5406,6 @@ fi if test "$linux_aio" = "yes" ; then echo "CONFIG_LINUX_AIO=y" >> $config_host_mak fi -if test "$linux_io_uring" = "yes" ; then - echo "CONFIG_LINUX_IO_URING=y" >> $config_host_mak - echo "LINUX_IO_URING_CFLAGS=$linux_io_uring_cflags" >> $config_host_mak - echo "LINUX_IO_URING_LIBS=$linux_io_uring_libs" >> $config_host_mak -fi if test "$vhost_scsi" = "yes" ; then echo "CONFIG_VHOST_SCSI=y" >> $config_host_mak fi @@ -6071,7 +6051,7 @@ if test "$skip_meson" = no; then -Dcurl=$curl -Dglusterfs=$glusterfs -Dbzip2=$bzip2 -Dlibiscsi=$libiscsi \ -Dlibnfs=$libnfs -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\ -Drbd=$rbd -Dlzo=$lzo -Dsnappy=$snappy -Dlzfse=$lzfse \ - -Dlibdaxctl=$libdaxctl -Dlibpmem=$libpmem \ + -Dlibdaxctl=$libdaxctl -Dlibpmem=$libpmem -Dlinux_io_uring=$linux_io_uring \ -Dgnutls=$gnutls -Dnettle=$nettle -Dgcrypt=$gcrypt -Dauth_pam=$auth_pam \ -Dzstd=$zstd -Dseccomp=$seccomp -Dvirtfs=$virtfs -Dcap_ng=$cap_ng \ -Dattr=$attr -Ddefault_devices=$default_devices -Dvirglrenderer=$virglrenderer \ diff --git a/meson.build b/meson.build index e301eda3a5..5304744f2e 100644 --- a/meson.build +++ b/meson.build @@ -327,10 +327,11 @@ if have_system or have_tools endif libaio = cc.find_library('aio', required: false) zlib = dependency('zlib', required: true, kwargs: static_kwargs) + linux_io_uring = not_found -if 'CONFIG_LINUX_IO_URING' in config_host - linux_io_uring = declare_dependency(compile_args: config_host['LINUX_IO_URING_CFLAGS'].split(), - link_args: config_host['LINUX_IO_URING_LIBS'].split()) +if not get_option('linux_io_uring').auto() or have_block + linux_io_uring = dependency('liburing', required: get_option('linux_io_uring'), + method: 'pkg-config', kwargs: static_kwargs) endif libxml2 = not_found if 'CONFIG_LIBXML2' in config_host @@ -2785,7 +2786,7 @@ summary_info += {'brlapi support': brlapi.found()} summary_info += {'vde support': config_host.has_key('CONFIG_VDE')} summary_info += {'netmap support': config_host.has_key('CONFIG_NETMAP')} summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')} -summary_info += {'Linux io_uring support': config_host.has_key('CONFIG_LINUX_IO_URING')} +summary_info += {'Linux io_uring support': linux_io_uring.found()} summary_info += {'ATTR/XATTR support': libattr.found()} summary_info += {'RDMA support': config_host.has_key('CONFIG_RDMA')} summary_info += {'PVRDMA support': config_host.has_key('CONFIG_PVRDMA')} diff --git a/meson_options.txt b/meson_options.txt index b23174d0a1..6610c4dc64 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -92,6 +92,8 @@ option('libudev', type : 'feature', value : 'auto', description: 'Use libudev to enumerate host devices') option('libusb', type : 'feature', value : 'auto', description: 'libusb support for USB passthrough') +option('linux_io_uring', type : 'feature', value : 'auto', + description: 'Linux io_uring support') option('lzfse', type : 'feature', value : 'auto', description: 'lzfse support for DMG images') option('lzo', type : 'feature', value : 'auto', From c5b36c25c2fe1110cf8646ef02083c71757d6e00 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 11:31:35 +0200 Subject: [PATCH 49/76] configure, meson: convert libxml2 detection to meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 29 ++++------------------------- meson.build | 8 ++++---- meson_options.txt | 2 ++ 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/configure b/configure index 4e016f671c..341b74dd5e 100755 --- a/configure +++ b/configure @@ -425,7 +425,7 @@ vdi=${default_feature:-yes} vvfat=${default_feature:-yes} qed=${default_feature:-yes} parallels=${default_feature:-yes} -libxml2="$default_feature" +libxml2="auto" debug_mutex="no" libpmem="auto" default_devices="true" @@ -1419,9 +1419,9 @@ for opt do ;; --enable-numa) numa="yes" ;; - --disable-libxml2) libxml2="no" + --disable-libxml2) libxml2="disabled" ;; - --enable-libxml2) libxml2="yes" + --enable-libxml2) libxml2="enabled" ;; --disable-tcmalloc) tcmalloc="no" ;; @@ -3409,21 +3409,6 @@ EOF fi fi -########################################## -# libxml2 probe -if test "$libxml2" != "no" ; then - if $pkg_config --exists libxml-2.0; then - libxml2="yes" - libxml2_cflags=$($pkg_config --cflags libxml-2.0) - libxml2_libs=$($pkg_config --libs libxml-2.0) - else - if test "$libxml2" = "yes"; then - feature_not_found "libxml2" "Install libxml2 devel" - fi - libxml2="no" - fi -fi - # Check for inotify functions when we are building linux-user # emulator. This is done because older glibc versions don't # have syscall stubs for these implemented. In that case we @@ -5636,12 +5621,6 @@ if test "$have_rtnetlink" = "yes" ; then echo "CONFIG_RTNETLINK=y" >> $config_host_mak fi -if test "$libxml2" = "yes" ; then - echo "CONFIG_LIBXML2=y" >> $config_host_mak - echo "LIBXML2_CFLAGS=$libxml2_cflags" >> $config_host_mak - echo "LIBXML2_LIBS=$libxml2_libs" >> $config_host_mak -fi - if test "$replication" = "yes" ; then echo "CONFIG_REPLICATION=y" >> $config_host_mak fi @@ -6050,7 +6029,7 @@ if test "$skip_meson" = no; then -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt -Dbrlapi=$brlapi \ -Dcurl=$curl -Dglusterfs=$glusterfs -Dbzip2=$bzip2 -Dlibiscsi=$libiscsi \ -Dlibnfs=$libnfs -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\ - -Drbd=$rbd -Dlzo=$lzo -Dsnappy=$snappy -Dlzfse=$lzfse \ + -Drbd=$rbd -Dlzo=$lzo -Dsnappy=$snappy -Dlzfse=$lzfse -Dlibxml2=$libxml2 \ -Dlibdaxctl=$libdaxctl -Dlibpmem=$libpmem -Dlinux_io_uring=$linux_io_uring \ -Dgnutls=$gnutls -Dnettle=$nettle -Dgcrypt=$gcrypt -Dauth_pam=$auth_pam \ -Dzstd=$zstd -Dseccomp=$seccomp -Dvirtfs=$virtfs -Dcap_ng=$cap_ng \ diff --git a/meson.build b/meson.build index 5304744f2e..1216ac8f72 100644 --- a/meson.build +++ b/meson.build @@ -334,9 +334,9 @@ if not get_option('linux_io_uring').auto() or have_block method: 'pkg-config', kwargs: static_kwargs) endif libxml2 = not_found -if 'CONFIG_LIBXML2' in config_host - libxml2 = declare_dependency(compile_args: config_host['LIBXML2_CFLAGS'].split(), - link_args: config_host['LIBXML2_LIBS'].split()) +if not get_option('libxml2').auto() or have_block + libxml2 = dependency('libxml-2.0', required: get_option('libxml2'), + method: 'pkg-config', kwargs: static_kwargs) endif libnfs = not_found if not get_option('libnfs').auto() or have_block @@ -2821,7 +2821,7 @@ summary_info += {'bzip2 support': libbzip2.found()} summary_info += {'lzfse support': liblzfse.found()} summary_info += {'zstd support': zstd.found()} summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')} -summary_info += {'libxml2': config_host.has_key('CONFIG_LIBXML2')} +summary_info += {'libxml2': libxml2.found()} summary_info += {'capstone': capstone_opt == 'disabled' ? false : capstone_opt} summary_info += {'libpmem support': libpmem.found()} summary_info += {'libdaxctl support': libdaxctl.found()} diff --git a/meson_options.txt b/meson_options.txt index 6610c4dc64..a9a9b8f4c6 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -92,6 +92,8 @@ option('libudev', type : 'feature', value : 'auto', description: 'Use libudev to enumerate host devices') option('libusb', type : 'feature', value : 'auto', description: 'libusb support for USB passthrough') +option('libxml2', type : 'feature', value : 'auto', + description: 'libxml2 support for Parallels image format') option('linux_io_uring', type : 'feature', value : 'auto', description: 'Linux io_uring support') option('lzfse', type : 'feature', value : 'auto', From 69d8de7a2d7c3512f6f7762abd8c1c1b9b4044e4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 11:56:11 +0200 Subject: [PATCH 50/76] meson: sort existing compiler tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The next patches will add more compiler tests. Sort and group the existing tests, keeping similar cc.has_* tests together and sorting them alphabetically by macro name. This should make it easier to look for examples when adding new tests to meson.build. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- meson.build | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 1216ac8f72..53dfc2b4c6 100644 --- a/meson.build +++ b/meson.build @@ -1253,16 +1253,19 @@ config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0] config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1]) config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2]) +config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device) + +# has_header config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h')) config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h')) config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h')) +config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h')) config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h')) config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h')) -config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include ')) -config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device) -config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h')) +# has_function config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include ')) +config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include ')) ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST'] From 6d7c7c2d1d95cc6cdb56706bfa0446ad68e2b952 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 15:01:35 +0200 Subject: [PATCH 51/76] meson: store dependency('threads') in a variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can be useful for has_function checks. Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- meson.build | 3 ++- util/meson.build | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 53dfc2b4c6..e288e4c21c 100644 --- a/meson.build +++ b/meson.build @@ -164,6 +164,7 @@ endif multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled() libm = cc.find_library('m', required: false) +threads = dependency('threads') util = cc.find_library('util', required: false) winmm = [] socket = [] @@ -1999,7 +2000,7 @@ util_ss.add_all(trace_ss) util_ss = util_ss.apply(config_all, strict: false) libqemuutil = static_library('qemuutil', sources: util_ss.sources() + stub_ss.sources() + genh, - dependencies: [util_ss.dependencies(), libm, glib, socket, malloc, pixman]) + dependencies: [util_ss.dependencies(), libm, threads, glib, socket, malloc, pixman]) qemuutil = declare_dependency(link_with: libqemuutil, sources: genh + version_res) diff --git a/util/meson.build b/util/meson.build index 97fad44105..6af05a5716 100644 --- a/util/meson.build +++ b/util/meson.build @@ -1,4 +1,3 @@ -util_ss.add(dependency('threads')) util_ss.add(files('osdep.c', 'cutils.c', 'unicode.c', 'qemu-timer-common.c')) util_ss.add(when: 'CONFIG_ATOMIC64', if_false: files('atomic64.c')) util_ss.add(when: 'CONFIG_POSIX', if_true: files('aio-posix.c')) From ccd250aa2d8e214195d5cee37c1ddc58e123b821 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 12:50:17 +0200 Subject: [PATCH 52/76] configure, meson: move CONFIG_IVSHMEM to meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a duplicate of CONFIG_EVENTFD, handle it directly in meson.build. Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 8 -------- docs/devel/kconfig.rst | 2 +- meson.build | 5 +++-- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 341b74dd5e..a524104120 100755 --- a/configure +++ b/configure @@ -5037,11 +5037,6 @@ if test "$mingw32" = "yes" ; then done fi -# We can only support ivshmem if we have eventfd -if [ "$eventfd" = "yes" ]; then - ivshmem=yes -fi - # Probe for guest agent support/options if [ "$guest_agent" != "no" ]; then @@ -5639,9 +5634,6 @@ fi if test "$have_getrandom" = "yes" ; then echo "CONFIG_GETRANDOM=y" >> $config_host_mak fi -if test "$ivshmem" = "yes" ; then - echo "CONFIG_IVSHMEM=y" >> $config_host_mak -fi if test "$debug_mutex" = "yes" ; then echo "CONFIG_DEBUG_MUTEX=y" >> $config_host_mak fi diff --git a/docs/devel/kconfig.rst b/docs/devel/kconfig.rst index cb2d7ffac0..a1cdbec751 100644 --- a/docs/devel/kconfig.rst +++ b/docs/devel/kconfig.rst @@ -303,5 +303,5 @@ variable:: host_kconfig = \ ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \ ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \ - ('CONFIG_IVSHMEM' in config_host ? ['CONFIG_IVSHMEM=y'] : []) + \ + (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \ ... diff --git a/meson.build b/meson.build index e288e4c21c..b5dcc3d70e 100644 --- a/meson.build +++ b/meson.build @@ -1335,10 +1335,11 @@ if link_language == 'cpp' } endif +have_ivshmem = config_host.has_key('CONFIG_EVENTFD') host_kconfig = \ ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \ ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \ - ('CONFIG_IVSHMEM' in config_host ? ['CONFIG_IVSHMEM=y'] : []) + \ + (have_ivshmem ? ['CONFIG_IVSHMEM=y'] : []) + \ ('CONFIG_OPENGL' in config_host ? ['CONFIG_OPENGL=y'] : []) + \ (x11.found() ? ['CONFIG_X11=y'] : []) + \ ('CONFIG_VHOST_USER' in config_host ? ['CONFIG_VHOST_USER=y'] : []) + \ @@ -2489,7 +2490,7 @@ if have_tools install: true) endif - if 'CONFIG_IVSHMEM' in config_host + if have_ivshmem subdir('contrib/ivshmem-client') subdir('contrib/ivshmem-server') endif From e46bd55d9cbb45b4e6681dd91da0fca821e2ed9d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 11:57:04 +0200 Subject: [PATCH 53/76] configure: convert HAVE_BROKEN_SIZE_MAX to meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 17 ----------------- meson.build | 9 +++++++++ 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/configure b/configure index a524104120..98d6068941 100755 --- a/configure +++ b/configure @@ -2375,20 +2375,6 @@ if test "$softmmu" = "no"; then audio_drv_list="" fi -########################################## -# Some versions of Mac OS X incorrectly define SIZE_MAX -cat > $TMPC << EOF -#include -#include -int main(int argc, char *argv[]) { - return printf("%zu", SIZE_MAX); -} -EOF -have_broken_size_max=no -if ! compile_object -Werror ; then - have_broken_size_max=yes -fi - ########################################## # L2TPV3 probe @@ -5360,9 +5346,6 @@ if test "$gdbus_codegen" != "" ; then echo "GDBUS_CODEGEN=$gdbus_codegen" >> $config_host_mak fi echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak -if test "$have_broken_size_max" = "yes" ; then - echo "HAVE_BROKEN_SIZE_MAX=y" >> $config_host_mak -fi if test "$have_openpty" = "yes" ; then echo "HAVE_OPENPTY=y" >> $config_host_mak fi diff --git a/meson.build b/meson.build index b5dcc3d70e..79b5834266 100644 --- a/meson.build +++ b/meson.build @@ -1268,6 +1268,15 @@ config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h')) config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include ')) config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include ')) +# Some versions of Mac OS X incorrectly define SIZE_MAX +config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles(''' + #include + #include + int main(int argc, char *argv[]) { + return printf("%zu", SIZE_MAX); + }''', args: ['-Werror'])) + + ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST'] strings = ['HOST_DSOSUF', 'CONFIG_IASL'] From e66420ac6dc97e5f5afcb25a918cb5e7a5cd63f2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 12:10:05 +0200 Subject: [PATCH 54/76] configure: convert compiler tests to meson, part 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 364 ----------------------------------------------- meson.build | 41 +++++- util/meson.build | 4 +- 3 files changed, 43 insertions(+), 366 deletions(-) diff --git a/configure b/configure index 98d6068941..e2bf77f55d 100755 --- a/configure +++ b/configure @@ -3588,297 +3588,6 @@ EOF fi fi -# check for fallocate -fallocate=no -cat > $TMPC << EOF -#include - -int main(void) -{ - fallocate(0, 0, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - fallocate=yes -fi - -# check for fallocate hole punching -fallocate_punch_hole=no -cat > $TMPC << EOF -#include -#include - -int main(void) -{ - fallocate(0, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - fallocate_punch_hole=yes -fi - -# check that fallocate supports range zeroing inside the file -fallocate_zero_range=no -cat > $TMPC << EOF -#include -#include - -int main(void) -{ - fallocate(0, FALLOC_FL_ZERO_RANGE, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - fallocate_zero_range=yes -fi - -# check for posix_fallocate -posix_fallocate=no -cat > $TMPC << EOF -#include - -int main(void) -{ - posix_fallocate(0, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - posix_fallocate=yes -fi - -# check for sync_file_range -sync_file_range=no -cat > $TMPC << EOF -#include - -int main(void) -{ - sync_file_range(0, 0, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - sync_file_range=yes -fi - -# check for linux/fiemap.h and FS_IOC_FIEMAP -fiemap=no -cat > $TMPC << EOF -#include -#include -#include - -int main(void) -{ - ioctl(0, FS_IOC_FIEMAP, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - fiemap=yes -fi - -# check for dup3 -dup3=no -cat > $TMPC << EOF -#include - -int main(void) -{ - dup3(0, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - dup3=yes -fi - -# check for ppoll support -ppoll=no -cat > $TMPC << EOF -#include - -int main(void) -{ - struct pollfd pfd = { .fd = 0, .events = 0, .revents = 0 }; - ppoll(&pfd, 1, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - ppoll=yes -fi - -# check for prctl(PR_SET_TIMERSLACK , ... ) support -prctl_pr_set_timerslack=no -cat > $TMPC << EOF -#include - -int main(void) -{ - prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - prctl_pr_set_timerslack=yes -fi - -# check for epoll support -epoll=no -cat > $TMPC << EOF -#include - -int main(void) -{ - epoll_create(0); - return 0; -} -EOF -if compile_prog "" "" ; then - epoll=yes -fi - -# epoll_create1 is a later addition -# so we must check separately for its presence -epoll_create1=no -cat > $TMPC << EOF -#include - -int main(void) -{ - /* Note that we use epoll_create1 as a value, not as - * a function being called. This is necessary so that on - * old SPARC glibc versions where the function was present in - * the library but not declared in the header file we will - * fail the configure check. (Otherwise we will get a compiler - * warning but not an error, and will proceed to fail the - * qemu compile where we compile with -Werror.) - */ - return (int)(uintptr_t)&epoll_create1; -} -EOF -if compile_prog "" "" ; then - epoll_create1=yes -fi - -# check for sendfile support -sendfile=no -cat > $TMPC << EOF -#include - -int main(void) -{ - return sendfile(0, 0, 0, 0); -} -EOF -if compile_prog "" "" ; then - sendfile=yes -fi - -# check for timerfd support (glibc 2.8 and newer) -timerfd=no -cat > $TMPC << EOF -#include - -int main(void) -{ - return(timerfd_create(CLOCK_REALTIME, 0)); -} -EOF -if compile_prog "" "" ; then - timerfd=yes -fi - -# check for setns and unshare support -setns=no -cat > $TMPC << EOF -#include - -int main(void) -{ - int ret; - ret = setns(0, 0); - ret = unshare(0); - return ret; -} -EOF -if compile_prog "" "" ; then - setns=yes -fi - -# clock_adjtime probe -clock_adjtime=no -cat > $TMPC < -#include - -int main(void) -{ - return clock_adjtime(0, 0); -} -EOF -clock_adjtime=no -if compile_prog "" "" ; then - clock_adjtime=yes -fi - -# syncfs probe -syncfs=no -cat > $TMPC < - -int main(void) -{ - return syncfs(0); -} -EOF -syncfs=no -if compile_prog "" "" ; then - syncfs=yes -fi - -# Search for bswap_32 function -byteswap_h=no -cat > $TMPC << EOF -#include -int main(void) { return bswap_32(0); } -EOF -if compile_prog "" "" ; then - byteswap_h=yes -fi - -# Search for bswap32 function -bswap_h=no -cat > $TMPC << EOF -#include -#include -#include -int main(void) { return bswap32(0); } -EOF -if compile_prog "" "" ; then - bswap_h=yes -fi - -# Check whether we have openpty() in either libc or libutil -cat > $TMPC << EOF -extern int openpty(int *am, int *as, char *name, void *termp, void *winp); -int main(void) { return openpty(0, 0, 0, 0, 0); } -EOF - -have_openpty="no" -if compile_prog "" "" ; then - have_openpty="yes" -else - if compile_prog "" "-lutil" ; then - have_openpty="yes" - fi -fi - ########################################## # spice probe if test "$spice_protocol" != "no" ; then @@ -4114,19 +3823,6 @@ if compile_prog "" "" ; then st_atim=yes fi -########################################## -# check if we have sigev_notify_thread_id - -sigev_notify_thread_id=no -cat > $TMPC << EOF -#include -#include -int main(void) { return offsetof(struct sigevent, sigev_notify_thread_id); } -EOF -if compile_prog "" "" ; then - sigev_notify_thread_id=yes -fi - ########################################## # check if trace backend exists @@ -5265,54 +4961,6 @@ fi if test "$have_usbfs" = "yes" ; then echo "CONFIG_USBFS=y" >> $config_host_mak fi -if test "$fallocate" = "yes" ; then - echo "CONFIG_FALLOCATE=y" >> $config_host_mak -fi -if test "$fallocate_punch_hole" = "yes" ; then - echo "CONFIG_FALLOCATE_PUNCH_HOLE=y" >> $config_host_mak -fi -if test "$fallocate_zero_range" = "yes" ; then - echo "CONFIG_FALLOCATE_ZERO_RANGE=y" >> $config_host_mak -fi -if test "$posix_fallocate" = "yes" ; then - echo "CONFIG_POSIX_FALLOCATE=y" >> $config_host_mak -fi -if test "$sync_file_range" = "yes" ; then - echo "CONFIG_SYNC_FILE_RANGE=y" >> $config_host_mak -fi -if test "$fiemap" = "yes" ; then - echo "CONFIG_FIEMAP=y" >> $config_host_mak -fi -if test "$dup3" = "yes" ; then - echo "CONFIG_DUP3=y" >> $config_host_mak -fi -if test "$ppoll" = "yes" ; then - echo "CONFIG_PPOLL=y" >> $config_host_mak -fi -if test "$prctl_pr_set_timerslack" = "yes" ; then - echo "CONFIG_PRCTL_PR_SET_TIMERSLACK=y" >> $config_host_mak -fi -if test "$epoll" = "yes" ; then - echo "CONFIG_EPOLL=y" >> $config_host_mak -fi -if test "$epoll_create1" = "yes" ; then - echo "CONFIG_EPOLL_CREATE1=y" >> $config_host_mak -fi -if test "$sendfile" = "yes" ; then - echo "CONFIG_SENDFILE=y" >> $config_host_mak -fi -if test "$timerfd" = "yes" ; then - echo "CONFIG_TIMERFD=y" >> $config_host_mak -fi -if test "$setns" = "yes" ; then - echo "CONFIG_SETNS=y" >> $config_host_mak -fi -if test "$clock_adjtime" = "yes" ; then - echo "CONFIG_CLOCK_ADJTIME=y" >> $config_host_mak -fi -if test "$syncfs" = "yes" ; then - echo "CONFIG_SYNCFS=y" >> $config_host_mak -fi if test "$inotify" = "yes" ; then echo "CONFIG_INOTIFY=y" >> $config_host_mak fi @@ -5328,15 +4976,6 @@ fi if test "$st_atim" = "yes" ; then echo "HAVE_STRUCT_STAT_ST_ATIM=y" >> $config_host_mak fi -if test "$sigev_notify_thread_id" = "yes" ; then - echo "HAVE_SIGEV_NOTIFY_THREAD_ID=y" >> $config_host_mak -fi -if test "$byteswap_h" = "yes" ; then - echo "CONFIG_BYTESWAP_H=y" >> $config_host_mak -fi -if test "$bswap_h" = "yes" ; then - echo "CONFIG_MACHINE_BSWAP_H=y" >> $config_host_mak -fi if test "$gio" = "yes" ; then echo "CONFIG_GIO=y" >> $config_host_mak echo "GIO_CFLAGS=$gio_cflags" >> $config_host_mak @@ -5346,9 +4985,6 @@ if test "$gdbus_codegen" != "" ; then echo "GDBUS_CODEGEN=$gdbus_codegen" >> $config_host_mak fi echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak -if test "$have_openpty" = "yes" ; then - echo "HAVE_OPENPTY=y" >> $config_host_mak -fi # Work around a system header bug with some kernel/XFS header # versions where they both try to define 'struct fsxattr': diff --git a/meson.build b/meson.build index 79b5834266..29a050066e 100644 --- a/meson.build +++ b/meson.build @@ -1051,10 +1051,12 @@ endif # Check whether the glibc provides statx() -statx_test = ''' +gnu_source_prefix = ''' #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +''' +statx_test = gnu_source_prefix + ''' #include int main(void) { struct statx statxbuf; @@ -1257,6 +1259,7 @@ config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2] config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device) # has_header +config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h')) config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h')) config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h')) config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h')) @@ -1265,9 +1268,45 @@ config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h')) config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h')) # has_function +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_PPOLL', cc.has_function('ppoll')) config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include ')) +config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile')) +config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare')) +config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs')) +config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range')) +config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create')) +config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util)) config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include ')) +# has_header_symbol +config_host_data.set('CONFIG_BYTESWAP_H', + cc.has_header_symbol('byteswap.h', 'bswap_32')) +config_host_data.set('CONFIG_EPOLL_CREATE1', + cc.has_header_symbol('sys/epoll.h', 'epoll_create1')) +config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE', + cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and + cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE')) +config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE', + cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_ZERO_RANGE')) +config_host_data.set('CONFIG_FIEMAP', + cc.has_header('linux/fiemap.h') and + cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP')) +config_host_data.set('CONFIG_MACHINE_BSWAP_H', + cc.has_header_symbol('machine/bswap.h', 'bswap32', + prefix: '''#include + #include ''')) +config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK', + cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK')) + +# has_member +config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID', + cc.has_member('struct sigevent', 'sigev_notify_thread_id', + prefix: '#include ')) + # Some versions of Mac OS X incorrectly define SIZE_MAX config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles(''' #include diff --git a/util/meson.build b/util/meson.build index 6af05a5716..0ffd7f4bde 100644 --- a/util/meson.build +++ b/util/meson.build @@ -2,7 +2,9 @@ util_ss.add(files('osdep.c', 'cutils.c', 'unicode.c', 'qemu-timer-common.c')) util_ss.add(when: 'CONFIG_ATOMIC64', if_false: files('atomic64.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')) -util_ss.add(when: 'CONFIG_EPOLL_CREATE1', if_true: files('fdmon-epoll.c')) +if config_host_data.get('CONFIG_EPOLL_CREATE1') + util_ss.add(files('fdmon-epoll.c')) +endif util_ss.add(when: ['CONFIG_LINUX_IO_URING', linux_io_uring], if_true: files('fdmon-io_uring.c')) util_ss.add(when: 'CONFIG_POSIX', if_true: files('compatfd.c')) util_ss.add(when: 'CONFIG_POSIX', if_true: files('event_notifier-posix.c')) From ed3b3f1764b0deecc2d875ab897e5883ef42a615 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 12:14:48 +0200 Subject: [PATCH 55/76] configure: convert compiler tests to meson, part 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 49 ------------------------------------------------- meson.build | 5 +++++ 2 files changed, 5 insertions(+), 49 deletions(-) diff --git a/configure b/configure index e2bf77f55d..78f4a351d9 100755 --- a/configure +++ b/configure @@ -3783,46 +3783,6 @@ if compile_prog "" "" ; then posix_syslog=yes fi -########################################## -# check if we have sem_timedwait - -sem_timedwait=no -cat > $TMPC << EOF -#include -int main(void) { sem_t s; struct timespec t = {0}; return sem_timedwait(&s, &t); } -EOF -if compile_prog "" "" ; then - sem_timedwait=yes -fi - -########################################## -# check if we have strchrnul - -strchrnul=no -cat > $TMPC << EOF -#include -int main(void); -// Use a haystack that the compiler shouldn't be able to constant fold -char *haystack = (char*)&main; -int main(void) { return strchrnul(haystack, 'x') != &haystack[6]; } -EOF -if compile_prog "" "" ; then - strchrnul=yes -fi - -######################################### -# check if we have st_atim - -st_atim=no -cat > $TMPC << EOF -#include -#include -int main(void) { return offsetof(struct stat, st_atim); } -EOF -if compile_prog "" "" ; then - st_atim=yes -fi - ########################################## # check if trace backend exists @@ -4967,15 +4927,6 @@ fi if test "$inotify1" = "yes" ; then echo "CONFIG_INOTIFY1=y" >> $config_host_mak fi -if test "$sem_timedwait" = "yes" ; then - echo "CONFIG_SEM_TIMEDWAIT=y" >> $config_host_mak -fi -if test "$strchrnul" = "yes" ; then - echo "HAVE_STRCHRNUL=y" >> $config_host_mak -fi -if test "$st_atim" = "yes" ; then - echo "HAVE_STRUCT_STAT_ST_ATIM=y" >> $config_host_mak -fi if test "$gio" = "yes" ; then echo "CONFIG_GIO=y" >> $config_host_mak echo "GIO_CFLAGS=$gio_cflags" >> $config_host_mak diff --git a/meson.build b/meson.build index 29a050066e..4314b9b4c5 100644 --- a/meson.build +++ b/meson.build @@ -1274,12 +1274,14 @@ 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_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)) config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile')) config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare')) config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs')) config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range')) config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create')) config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util)) +config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul')) config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include ')) # has_header_symbol @@ -1306,6 +1308,9 @@ config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK', config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID', cc.has_member('struct sigevent', 'sigev_notify_thread_id', prefix: '#include ')) +config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM', + cc.has_member('struct stat', 'st_atim', + prefix: '#include ')) # Some versions of Mac OS X incorrectly define SIZE_MAX config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles(''' From be7e89f63f97c6e745f906bdafb0a6a0b070e720 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 12:02:00 +0200 Subject: [PATCH 56/76] configure: convert compiler tests to meson, part 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 87 ----------------------------------------------------- meson.build | 10 ++++++ 2 files changed, 10 insertions(+), 87 deletions(-) diff --git a/configure b/configure index 78f4a351d9..cf7f71fe40 100755 --- a/configure +++ b/configure @@ -4293,20 +4293,6 @@ if test "$fortify_source" != "no"; then fi fi -############################################### -# Check if copy_file_range is provided by glibc -have_copy_file_range=no -cat > $TMPC << EOF -#include -int main(void) { - copy_file_range(0, NULL, 0, NULL, 0, 0); - return 0; -} -EOF -if compile_prog "" "" ; then - have_copy_file_range=yes -fi - ########################################## # check if struct fsxattr is available via linux/fs.h @@ -4353,19 +4339,6 @@ else membarrier=no fi -########################################## -# check if rtnetlink.h exists and is useful -have_rtnetlink=no -cat > $TMPC << EOF -#include -int main(void) { - return IFLA_PROTO_DOWN; -} -EOF -if compile_prog "" "" ; then - have_rtnetlink=yes -fi - ########################################## # check for usable AF_VSOCK environment have_af_vsock=no @@ -4419,49 +4392,6 @@ then fi -################################################# -# check for sysmacros.h - -have_sysmacros=no -cat > $TMPC << EOF -#include -int main(void) { - return makedev(0, 0); -} -EOF -if compile_prog "" "" ; then - have_sysmacros=yes -fi - -########################################## -# check for utmpx.h, it is missing e.g. on OpenBSD - -have_utmpx=no -cat > $TMPC << EOF -#include -struct utmpx user_info; -int main(void) { - return 0; -} -EOF -if compile_prog "" "" ; then - have_utmpx=yes -fi - -########################################## -# check for getrandom() - -have_getrandom=no -cat > $TMPC << EOF -#include -int main(void) { - return getrandom(0, 0, GRND_NONBLOCK); -} -EOF -if compile_prog "" "" ; then - have_getrandom=yes -fi - ########################################## # checks for sanitizers @@ -4944,9 +4874,6 @@ echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak if test "$have_fsxattr" = "yes" ; then echo "HAVE_FSXATTR=y" >> $config_host_mak fi -if test "$have_copy_file_range" = "yes" ; then - echo "HAVE_COPY_FILE_RANGE=y" >> $config_host_mak -fi if test "$xen" = "enabled" ; then echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak @@ -5182,10 +5109,6 @@ if test "$pvrdma" = "yes" ; then echo "CONFIG_PVRDMA=y" >> $config_host_mak fi -if test "$have_rtnetlink" = "yes" ; then - echo "CONFIG_RTNETLINK=y" >> $config_host_mak -fi - if test "$replication" = "yes" ; then echo "CONFIG_REPLICATION=y" >> $config_host_mak fi @@ -5194,16 +5117,6 @@ if test "$have_af_vsock" = "yes" ; then echo "CONFIG_AF_VSOCK=y" >> $config_host_mak fi -if test "$have_sysmacros" = "yes" ; then - echo "CONFIG_SYSMACROS=y" >> $config_host_mak -fi - -if test "$have_utmpx" = "yes" ; then - echo "HAVE_UTMPX=y" >> $config_host_mak -fi -if test "$have_getrandom" = "yes" ; then - echo "CONFIG_GETRANDOM=y" >> $config_host_mak -fi if test "$debug_mutex" = "yes" ; then echo "CONFIG_DEBUG_MUTEX=y" >> $config_host_mak fi diff --git a/meson.build b/meson.build index 4314b9b4c5..5fec46bb65 100644 --- a/meson.build +++ b/meson.build @@ -1280,6 +1280,7 @@ config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_functio config_host_data.set('CONFIG_SYNCFS', cc.has_function('syncfs')) config_host_data.set('CONFIG_SYNC_FILE_RANGE', cc.has_function('sync_file_range')) config_host_data.set('CONFIG_TIMERFD', cc.has_function('timerfd_create')) +config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_range')) config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util)) config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul')) config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include ')) @@ -1297,12 +1298,21 @@ config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE', config_host_data.set('CONFIG_FIEMAP', cc.has_header('linux/fiemap.h') and cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP')) +config_host_data.set('CONFIG_GETRANDOM', + cc.has_function('getrandom') and + cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK')) config_host_data.set('CONFIG_MACHINE_BSWAP_H', cc.has_header_symbol('machine/bswap.h', 'bswap32', prefix: '''#include #include ''')) config_host_data.set('CONFIG_PRCTL_PR_SET_TIMERSLACK', cc.has_header_symbol('sys/prctl.h', 'PR_SET_TIMERSLACK')) +config_host_data.set('CONFIG_RTNETLINK', + cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN')) +config_host_data.set('CONFIG_SYSMACROS', + cc.has_header_symbol('sys/sysmacros.h', 'makedev')) +config_host_data.set('HAVE_UTMPX', + cc.has_header_symbol('utmpx.h', 'struct utmpx')) # has_member config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID', From e1fbd2c4ed8e61a3e0749f592a6d3423ec67980b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 12:02:00 +0200 Subject: [PATCH 57/76] configure: convert compiler tests to meson, part 4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And remove them from the summary, since now their outcome is verbosely included in the meson output. Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 137 ---------------------------------------------------- meson.build | 39 +++++++++++++-- 2 files changed, 34 insertions(+), 142 deletions(-) diff --git a/configure b/configure index cf7f71fe40..83168ceb52 100755 --- a/configure +++ b/configure @@ -3511,59 +3511,6 @@ elif test "$jemalloc" = "yes" ; then malloc=jemalloc fi -########################################## -# signalfd probe -signalfd="no" -cat > $TMPC << EOF -#include -#include -#include -int main(void) { return syscall(SYS_signalfd, -1, NULL, _NSIG / 8); } -EOF - -if compile_prog "" "" ; then - signalfd=yes -fi - -# check if optreset global is declared by -optreset="no" -cat > $TMPC << EOF -#include -int main(void) { return optreset; } -EOF - -if compile_prog "" "" ; then - optreset=yes -fi - -# check if eventfd is supported -eventfd=no -cat > $TMPC << EOF -#include - -int main(void) -{ - return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); -} -EOF -if compile_prog "" "" ; then - eventfd=yes -fi - -# check if memfd is supported -memfd=no -cat > $TMPC << EOF -#include - -int main(void) -{ - return memfd_create("foo", MFD_ALLOW_SEALING); -} -EOF -if compile_prog "" "" ; then - memfd=yes -fi - # check for usbfs have_usbfs=no if test "$linux_user" = "yes"; then @@ -3711,66 +3658,6 @@ case "$capstone" in ;; esac -########################################## -# check if we have fdatasync - -fdatasync=no -cat > $TMPC << EOF -#include -int main(void) { -#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 -return fdatasync(0); -#else -#error Not supported -#endif -} -EOF -if compile_prog "" "" ; then - fdatasync=yes -fi - -########################################## -# check if we have madvise - -madvise=no -cat > $TMPC << EOF -#include -#include -#include -int main(void) { return madvise(NULL, 0, MADV_DONTNEED); } -EOF -if compile_prog "" "" ; then - madvise=yes -fi - -########################################## -# check if we have posix_madvise - -posix_madvise=no -cat > $TMPC << EOF -#include -#include -int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); } -EOF -if compile_prog "" "" ; then - posix_madvise=yes -fi - -########################################## -# check if we have posix_memalign() - -posix_memalign=no -cat > $TMPC << EOF -#include -int main(void) { - void *p; - return posix_memalign(&p, 8, 8); -} -EOF -if compile_prog "" "" ; then - posix_memalign=yes -fi - ########################################## # check if we have posix_syslog @@ -4842,12 +4729,6 @@ fi if test "$splice" = "yes" ; then echo "CONFIG_SPLICE=y" >> $config_host_mak fi -if test "$eventfd" = "yes" ; then - echo "CONFIG_EVENTFD=y" >> $config_host_mak -fi -if test "$memfd" = "yes" ; then - echo "CONFIG_MEMFD=y" >> $config_host_mak -fi if test "$have_usbfs" = "yes" ; then echo "CONFIG_USBFS=y" >> $config_host_mak fi @@ -4922,27 +4803,9 @@ fi if test "$membarrier" = "yes" ; then echo "CONFIG_MEMBARRIER=y" >> $config_host_mak fi -if test "$signalfd" = "yes" ; then - echo "CONFIG_SIGNALFD=y" >> $config_host_mak -fi -if test "$optreset" = "yes" ; then - echo "HAVE_OPTRESET=y" >> $config_host_mak -fi if test "$tcg" = "enabled" -a "$tcg_interpreter" = "true" ; then echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak fi -if test "$fdatasync" = "yes" ; then - echo "CONFIG_FDATASYNC=y" >> $config_host_mak -fi -if test "$madvise" = "yes" ; then - echo "CONFIG_MADVISE=y" >> $config_host_mak -fi -if test "$posix_madvise" = "yes" ; then - echo "CONFIG_POSIX_MADVISE=y" >> $config_host_mak -fi -if test "$posix_memalign" = "yes" ; then - echo "CONFIG_POSIX_MEMALIGN=y" >> $config_host_mak -fi if test "$spice_protocol" = "yes" ; then echo "CONFIG_SPICE_PROTOCOL=y" >> $config_host_mak diff --git a/meson.build b/meson.build index 5fec46bb65..cb50a2e473 100644 --- a/meson.build +++ b/meson.build @@ -1272,6 +1272,7 @@ 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')) 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)) @@ -1311,6 +1312,8 @@ config_host_data.set('CONFIG_RTNETLINK', cc.has_header_symbol('linux/rtnetlink.h', 'IFLA_PROTO_DOWN')) config_host_data.set('CONFIG_SYSMACROS', cc.has_header_symbol('sys/sysmacros.h', 'makedev')) +config_host_data.set('HAVE_OPTRESET', + cc.has_header_symbol('getopt.h', 'optreset')) config_host_data.set('HAVE_UTMPX', cc.has_header_symbol('utmpx.h', 'struct utmpx')) @@ -1322,6 +1325,36 @@ config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM', cc.has_member('struct stat', 'st_atim', prefix: '#include ')) +config_host_data.set('CONFIG_EVENTFD', cc.compiles(''' + #include + int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }''')) +config_host_data.set('CONFIG_FDATASYNC', cc.compiles(gnu_source_prefix + ''' + #include + int main(void) { + #if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 + return fdatasync(0); + #else + #error Not supported + #endif + }''')) +config_host_data.set('CONFIG_MADVISE', cc.compiles(gnu_source_prefix + ''' + #include + #include + #include + int main(void) { return madvise(NULL, 0, MADV_DONTNEED); }''')) +config_host_data.set('CONFIG_MEMFD', cc.compiles(gnu_source_prefix + ''' + #include + int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }''')) +config_host_data.set('CONFIG_POSIX_MADVISE', cc.compiles(gnu_source_prefix + ''' + #include + #include + int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }''')) +config_host_data.set('CONFIG_SIGNALFD', cc.compiles(gnu_source_prefix + ''' + #include + #include + #include + int main(void) { return syscall(SYS_signalfd, -1, NULL, _NSIG / 8); }''')) + # Some versions of Mac OS X incorrectly define SIZE_MAX config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles(''' #include @@ -1398,7 +1431,7 @@ if link_language == 'cpp' } endif -have_ivshmem = config_host.has_key('CONFIG_EVENTFD') +have_ivshmem = config_host_data.get('CONFIG_EVENTFD') host_kconfig = \ ('CONFIG_TPM' in config_host ? ['CONFIG_TPM=y'] : []) + \ ('CONFIG_SPICE' in config_host ? ['CONFIG_SPICE=y'] : []) + \ @@ -2711,10 +2744,6 @@ summary_info += {'PIE': get_option('b_pie')} summary_info += {'static build': config_host.has_key('CONFIG_STATIC')} summary_info += {'malloc trim support': has_malloc_trim} summary_info += {'membarrier': config_host.has_key('CONFIG_MEMBARRIER')} -summary_info += {'fdatasync': config_host.has_key('CONFIG_FDATASYNC')} -summary_info += {'madvise': config_host.has_key('CONFIG_MADVISE')} -summary_info += {'posix_madvise': config_host.has_key('CONFIG_POSIX_MADVISE')} -summary_info += {'posix_memalign': config_host.has_key('CONFIG_POSIX_MEMALIGN')} summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')} summary_info += {'mutex debugging': config_host.has_key('CONFIG_DEBUG_MUTEX')} summary_info += {'memory allocator': get_option('malloc')} From a620fbe9ace71a89bd3d0c57a045b93a772070d5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 13:04:47 +0200 Subject: [PATCH 58/76] configure: convert compiler tests to meson, part 5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 101 ---------------------------------------------------- meson.build | 26 ++++++++++++++ 2 files changed, 26 insertions(+), 101 deletions(-) diff --git a/configure b/configure index 83168ceb52..1cac47399d 100755 --- a/configure +++ b/configure @@ -3395,92 +3395,6 @@ EOF fi fi -# Check for inotify functions when we are building linux-user -# emulator. This is done because older glibc versions don't -# have syscall stubs for these implemented. In that case we -# don't provide them even if kernel supports them. -# -inotify=no -cat > $TMPC << EOF -#include - -int -main(void) -{ - /* try to start inotify */ - return inotify_init(); -} -EOF -if compile_prog "" "" ; then - inotify=yes -fi - -inotify1=no -cat > $TMPC << EOF -#include - -int -main(void) -{ - /* try to start inotify */ - return inotify_init1(0); -} -EOF -if compile_prog "" "" ; then - inotify1=yes -fi - -# check if pipe2 is there -pipe2=no -cat > $TMPC << EOF -#include -#include - -int main(void) -{ - int pipefd[2]; - return pipe2(pipefd, O_CLOEXEC); -} -EOF -if compile_prog "" "" ; then - pipe2=yes -fi - -# check if accept4 is there -accept4=no -cat > $TMPC << EOF -#include -#include - -int main(void) -{ - accept4(0, NULL, NULL, SOCK_CLOEXEC); - return 0; -} -EOF -if compile_prog "" "" ; then - accept4=yes -fi - -# check if tee/splice is there. vmsplice was added same time. -splice=no -cat > $TMPC << EOF -#include -#include -#include - -int main(void) -{ - int len, fd = 0; - len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK); - splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE); - return 0; -} -EOF -if compile_prog "" "" ; then - splice=yes -fi - ########################################## # libnuma probe @@ -4720,24 +4634,9 @@ fi if test "$module_upgrades" = "yes"; then echo "CONFIG_MODULE_UPGRADES=y" >> $config_host_mak fi -if test "$pipe2" = "yes" ; then - echo "CONFIG_PIPE2=y" >> $config_host_mak -fi -if test "$accept4" = "yes" ; then - echo "CONFIG_ACCEPT4=y" >> $config_host_mak -fi -if test "$splice" = "yes" ; then - echo "CONFIG_SPLICE=y" >> $config_host_mak -fi if test "$have_usbfs" = "yes" ; then echo "CONFIG_USBFS=y" >> $config_host_mak fi -if test "$inotify" = "yes" ; then - echo "CONFIG_INOTIFY=y" >> $config_host_mak -fi -if test "$inotify1" = "yes" ; then - echo "CONFIG_INOTIFY1=y" >> $config_host_mak -fi if test "$gio" = "yes" ; then echo "CONFIG_GIO=y" >> $config_host_mak echo "GIO_CFLAGS=$gio_cflags" >> $config_host_mak diff --git a/meson.build b/meson.build index cb50a2e473..12162264db 100644 --- a/meson.build +++ b/meson.build @@ -1268,6 +1268,7 @@ config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h')) config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h')) # has_function +config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4')) 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')) @@ -1302,6 +1303,10 @@ config_host_data.set('CONFIG_FIEMAP', config_host_data.set('CONFIG_GETRANDOM', cc.has_function('getrandom') and cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK')) +config_host_data.set('CONFIG_INOTIFY', + cc.has_header_symbol('sys/inotify.h', 'inotify_init')) +config_host_data.set('CONFIG_INOTIFY1', + cc.has_header_symbol('sys/inotify.h', 'inotify_init1')) config_host_data.set('CONFIG_MACHINE_BSWAP_H', cc.has_header_symbol('machine/bswap.h', 'bswap32', prefix: '''#include @@ -1345,6 +1350,15 @@ config_host_data.set('CONFIG_MADVISE', cc.compiles(gnu_source_prefix + ''' config_host_data.set('CONFIG_MEMFD', cc.compiles(gnu_source_prefix + ''' #include int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }''')) +config_host_data.set('CONFIG_PIPE2', cc.compiles(gnu_source_prefix + ''' + #include + #include + + int main(void) + { + int pipefd[2]; + return pipe2(pipefd, O_CLOEXEC); + }''')) config_host_data.set('CONFIG_POSIX_MADVISE', cc.compiles(gnu_source_prefix + ''' #include #include @@ -1354,6 +1368,18 @@ config_host_data.set('CONFIG_SIGNALFD', cc.compiles(gnu_source_prefix + ''' #include #include int main(void) { return syscall(SYS_signalfd, -1, NULL, _NSIG / 8); }''')) +config_host_data.set('CONFIG_SPLICE', cc.compiles(gnu_source_prefix + ''' + #include + #include + #include + + int main(void) + { + int len, fd = 0; + len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK); + splice(STDIN_FILENO, NULL, fd, NULL, len, SPLICE_F_MOVE); + return 0; + }''')) # Some versions of Mac OS X incorrectly define SIZE_MAX config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles(''' From d47a8b3b692a06852bd70fd7832bd22adfcb2431 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 3 Jun 2021 12:02:00 +0200 Subject: [PATCH 59/76] configure: convert compiler tests to meson, part 6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel P. Berrangé Signed-off-by: Paolo Bonzini --- configure | 75 ----------------------------------------------------- meson.build | 11 ++++++++ 2 files changed, 11 insertions(+), 75 deletions(-) diff --git a/configure b/configure index 1cac47399d..0e487ae091 100755 --- a/configure +++ b/configure @@ -3763,65 +3763,6 @@ else # "$safe_stack" = "" fi fi -########################################## -# check if we have open_by_handle_at - -open_by_handle_at=no -cat > $TMPC << EOF -#include -#if !defined(AT_EMPTY_PATH) -# error missing definition -#else -int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); } -#endif -EOF -if compile_prog "" "" ; then - open_by_handle_at=yes -fi - -######################################## -# check if we have linux/magic.h - -linux_magic_h=no -cat > $TMPC << EOF -#include -int main(void) { - return 0; -} -EOF -if compile_prog "" "" ; then - linux_magic_h=yes -fi - -######################################## -# check if we have valgrind/valgrind.h - -valgrind_h=no -cat > $TMPC << EOF -#include -int main(void) { - return 0; -} -EOF -if compile_prog "" "" ; then - valgrind_h=yes -fi - -######################################## -# check if environ is declared - -has_environ=no -cat > $TMPC << EOF -#include -int main(void) { - environ = 0; - return 0; -} -EOF -if compile_prog "" "" ; then - has_environ=yes -fi - ######################################## # check if cpuid.h is usable. @@ -4761,18 +4702,6 @@ if test "$crypto_afalg" = "yes" ; then echo "CONFIG_AF_ALG=y" >> $config_host_mak fi -if test "$open_by_handle_at" = "yes" ; then - echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak -fi - -if test "$linux_magic_h" = "yes" ; then - echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak -fi - -if test "$valgrind_h" = "yes" ; then - echo "CONFIG_VALGRIND_H=y" >> $config_host_mak -fi - if test "$have_asan_iface_fiber" = "yes" ; then echo "CONFIG_ASAN_IFACE_FIBER=y" >> $config_host_mak fi @@ -4781,10 +4710,6 @@ if test "$have_tsan" = "yes" && test "$have_tsan_iface_fiber" = "yes" ; then echo "CONFIG_TSAN=y" >> $config_host_mak fi -if test "$has_environ" = "yes" ; then - echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak -fi - if test "$cpuid_h" = "yes" ; then echo "CONFIG_CPUID_H=y" >> $config_host_mak fi diff --git a/meson.build b/meson.build index 12162264db..1651496800 100644 --- a/meson.build +++ b/meson.build @@ -1260,6 +1260,8 @@ config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device) # has_header config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h')) +config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h')) +config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h')) config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h')) config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h')) config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h')) @@ -1292,6 +1294,8 @@ config_host_data.set('CONFIG_BYTESWAP_H', cc.has_header_symbol('byteswap.h', 'bswap_32')) config_host_data.set('CONFIG_EPOLL_CREATE1', cc.has_header_symbol('sys/epoll.h', 'epoll_create1')) +config_host_data.set('CONFIG_HAS_ENVIRON', + cc.has_header_symbol('unistd.h', 'environ', prefix: gnu_source_prefix)) config_host_data.set('CONFIG_FALLOCATE_PUNCH_HOLE', cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_PUNCH_HOLE') and cc.has_header_symbol('linux/falloc.h', 'FALLOC_FL_KEEP_SIZE')) @@ -1350,6 +1354,13 @@ config_host_data.set('CONFIG_MADVISE', cc.compiles(gnu_source_prefix + ''' config_host_data.set('CONFIG_MEMFD', cc.compiles(gnu_source_prefix + ''' #include int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }''')) +config_host_data.set('CONFIG_OPEN_BY_HANDLE', cc.compiles(gnu_source_prefix + ''' + #include + #if !defined(AT_EMPTY_PATH) + # error missing definition + #else + int main(void) { struct file_handle fh; return open_by_handle_at(0, &fh, 0); } + #endif''')) config_host_data.set('CONFIG_PIPE2', cc.compiles(gnu_source_prefix + ''' #include #include From 3bb6944585aa6f28b21265c88d86264e8e9f7e53 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 2 Nov 2020 11:08:07 -0500 Subject: [PATCH 60/76] qom: export more functions for use with non-UserCreatable objects Machines and accelerators are not user-creatable but they are going to share similar command-line parsing machinery. Export functions that will be used with -machine and -accel in softmmu/vl.c. Signed-off-by: Paolo Bonzini --- include/qom/object.h | 23 ++++++++++++++++ qom/object_interfaces.c | 58 +++++++++++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 16 deletions(-) diff --git a/include/qom/object.h b/include/qom/object.h index 6721cd312e..faae0d841f 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -861,6 +861,29 @@ static void do_qemu_init_ ## type_array(void) \ } \ type_init(do_qemu_init_ ## type_array) +/** + * type_print_class_properties: + * @type: a QOM class name + * + * Print the object's class properties to stdout or the monitor. + * Return whether an object was found. + */ +bool type_print_class_properties(const char *type); + +/** + * object_set_properties_from_keyval: + * @obj: a QOM object + * @qdict: a dictionary with the properties to be set + * @from_json: true if leaf values of @qdict are typed, false if they + * are strings + * @errp: pointer to error object + * + * For each key in the dictionary, parse the value string if needed, + * then set the corresponding property in @obj. + */ +void object_set_properties_from_keyval(Object *obj, const QDict *qdict, + bool from_json, Error **errp); + /** * object_class_dynamic_cast_assert: * @klass: The #ObjectClass to attempt to cast. diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c index 4479ee693a..ad9b56b59a 100644 --- a/qom/object_interfaces.c +++ b/qom/object_interfaces.c @@ -42,6 +42,44 @@ bool user_creatable_can_be_deleted(UserCreatable *uc) } } +static void object_set_properties_from_qdict(Object *obj, const QDict *qdict, + Visitor *v, Error **errp) +{ + const QDictEntry *e; + Error *local_err = NULL; + + if (!visit_start_struct(v, NULL, NULL, 0, &local_err)) { + goto out; + } + for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { + if (!object_property_set(obj, e->key, v, &local_err)) { + break; + } + } + if (!local_err) { + visit_check_struct(v, &local_err); + } + visit_end_struct(v, NULL); + +out: + if (local_err) { + error_propagate(errp, local_err); + } +} + +void object_set_properties_from_keyval(Object *obj, const QDict *qdict, + bool from_json, Error **errp) +{ + Visitor *v; + if (from_json) { + v = qobject_input_visitor_new(QOBJECT(qdict)); + } else { + v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); + } + object_set_properties_from_qdict(obj, qdict, v, errp); + visit_free(v); +} + Object *user_creatable_add_type(const char *type, const char *id, const QDict *qdict, Visitor *v, Error **errp) @@ -49,7 +87,6 @@ Object *user_creatable_add_type(const char *type, const char *id, ERRP_GUARD(); Object *obj; ObjectClass *klass; - const QDictEntry *e; Error *local_err = NULL; if (id != NULL && !id_wellformed(id)) { @@ -78,18 +115,7 @@ Object *user_creatable_add_type(const char *type, const char *id, assert(qdict); obj = object_new(type); - if (!visit_start_struct(v, NULL, NULL, 0, &local_err)) { - goto out; - } - for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { - if (!object_property_set(obj, e->key, v, &local_err)) { - break; - } - } - if (!local_err) { - visit_check_struct(v, &local_err); - } - visit_end_struct(v, NULL); + object_set_properties_from_qdict(obj, qdict, v, &local_err); if (local_err) { goto out; } @@ -178,7 +204,7 @@ static void user_creatable_print_types(void) g_slist_free(list); } -static bool user_creatable_print_type_properites(const char *type) +bool type_print_class_properties(const char *type) { ObjectClass *klass; ObjectPropertyIterator iter; @@ -224,7 +250,7 @@ bool user_creatable_print_help(const char *type, QemuOpts *opts) } if (qemu_opt_has_help_opt(opts)) { - return user_creatable_print_type_properites(type); + return type_print_class_properties(type); } return false; @@ -234,7 +260,7 @@ static void user_creatable_print_help_from_qdict(QDict *args) { const char *type = qdict_get_try_str(args, "qom-type"); - if (!type || !user_creatable_print_type_properites(type)) { + if (!type || !type_print_class_properties(type)) { user_creatable_print_types(); } } From 9176e800dbcb2636a2f24411eafc3c800e3455bd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 12 Nov 2020 08:40:11 -0500 Subject: [PATCH 61/76] keyval: introduce keyval_merge This patch introduces a function that merges two keyval-produced (or keyval-like) QDicts. It can be used to emulate the behavior of .merge_lists = true QemuOpts groups, merging -readconfig sections and command-line options in a single QDict, and also to implement -set. Signed-off-by: Paolo Bonzini --- include/qemu/option.h | 1 + tests/unit/test-keyval.c | 58 +++++++++++++++++++++++++++++ util/keyval.c | 80 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) diff --git a/include/qemu/option.h b/include/qemu/option.h index f73e0dc7d9..d89c66145a 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -149,5 +149,6 @@ QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list); QDict *keyval_parse(const char *params, const char *implied_key, bool *help, Error **errp); +void keyval_merge(QDict *old, const QDict *new, Error **errp); #endif diff --git a/tests/unit/test-keyval.c b/tests/unit/test-keyval.c index e20c07cf3e..af0581ae6c 100644 --- a/tests/unit/test-keyval.c +++ b/tests/unit/test-keyval.c @@ -747,6 +747,61 @@ static void test_keyval_visit_any(void) visit_free(v); } +static void test_keyval_merge_dict(void) +{ + QDict *first = keyval_parse("opt1=abc,opt2.sub1=def,opt2.sub2=ghi,opt3=xyz", + NULL, NULL, &error_abort); + QDict *second = keyval_parse("opt1=ABC,opt2.sub2=GHI,opt2.sub3=JKL", + NULL, NULL, &error_abort); + QDict *combined = keyval_parse("opt1=ABC,opt2.sub1=def,opt2.sub2=GHI,opt2.sub3=JKL,opt3=xyz", + NULL, NULL, &error_abort); + Error *err = NULL; + + keyval_merge(first, second, &err); + g_assert(!err); + g_assert(qobject_is_equal(QOBJECT(combined), QOBJECT(first))); + qobject_unref(first); + qobject_unref(second); + qobject_unref(combined); +} + +static void test_keyval_merge_list(void) +{ + QDict *first = keyval_parse("opt1.0=abc,opt2.0=xyz", + NULL, NULL, &error_abort); + QDict *second = keyval_parse("opt1.0=def", + NULL, NULL, &error_abort); + QDict *combined = keyval_parse("opt1.0=abc,opt1.1=def,opt2.0=xyz", + NULL, NULL, &error_abort); + Error *err = NULL; + + keyval_merge(first, second, &err); + g_assert(!err); + g_assert(qobject_is_equal(QOBJECT(combined), QOBJECT(first))); + qobject_unref(first); + qobject_unref(second); + qobject_unref(combined); +} + +static void test_keyval_merge_conflict(void) +{ + QDict *first = keyval_parse("opt2=ABC", + NULL, NULL, &error_abort); + QDict *second = keyval_parse("opt2.sub1=def,opt2.sub2=ghi", + NULL, NULL, &error_abort); + QDict *third = qdict_clone_shallow(first); + Error *err = NULL; + + keyval_merge(first, second, &err); + error_free_or_abort(&err); + keyval_merge(second, third, &err); + error_free_or_abort(&err); + + qobject_unref(first); + qobject_unref(second); + qobject_unref(third); +} + int main(int argc, char *argv[]) { g_test_init(&argc, &argv, NULL); @@ -760,6 +815,9 @@ int main(int argc, char *argv[]) g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional); g_test_add_func("/keyval/visit/alternate", test_keyval_visit_alternate); g_test_add_func("/keyval/visit/any", test_keyval_visit_any); + g_test_add_func("/keyval/merge/dict", test_keyval_merge_dict); + g_test_add_func("/keyval/merge/list", test_keyval_merge_list); + g_test_add_func("/keyval/merge/conflict", test_keyval_merge_conflict); g_test_run(); return 0; } diff --git a/util/keyval.c b/util/keyval.c index be34928813..9bc380686a 100644 --- a/util/keyval.c +++ b/util/keyval.c @@ -310,6 +310,86 @@ static char *reassemble_key(GSList *key) return g_string_free(s, FALSE); } +/* + * Recursive worker for keyval_merge. + * + * @str is the path that led to the * current dictionary (to be used for + * error messages). It is modified internally but restored before the + * function returns. + */ +static void keyval_do_merge(QDict *dest, const QDict *merged, GString *str, Error **errp) +{ + size_t save_len = str->len; + const QDictEntry *ent; + QObject *old_value; + + for (ent = qdict_first(merged); ent; ent = qdict_next(merged, ent)) { + old_value = qdict_get(dest, ent->key); + if (old_value) { + if (qobject_type(old_value) != qobject_type(ent->value)) { + error_setg(errp, "Parameter '%s%s' used inconsistently", + str->str, ent->key); + return; + } else if (qobject_type(ent->value) == QTYPE_QDICT) { + /* Merge sub-dictionaries. */ + g_string_append(str, ent->key); + g_string_append_c(str, '.'); + keyval_do_merge(qobject_to(QDict, old_value), + qobject_to(QDict, ent->value), + str, errp); + g_string_truncate(str, save_len); + continue; + } else if (qobject_type(ent->value) == QTYPE_QLIST) { + /* Append to old list. */ + QList *old = qobject_to(QList, old_value); + QList *new = qobject_to(QList, ent->value); + const QListEntry *item; + QLIST_FOREACH_ENTRY(new, item) { + qobject_ref(item->value); + qlist_append_obj(old, item->value); + } + continue; + } else { + assert(qobject_type(ent->value) == QTYPE_QSTRING); + } + } + + qobject_ref(ent->value); + qdict_put_obj(dest, ent->key, ent->value); + } +} + +/* Merge the @merged dictionary into @dest. + * + * The dictionaries are expected to be returned by the keyval parser, and + * therefore the only expected scalar type is the string. In case the same + * path is present in both @dest and @merged, the semantics are as follows: + * + * - lists are concatenated + * + * - dictionaries are merged recursively + * + * - for scalar values, @merged wins + * + * In case an error is reported, @dest may already have been modified. + * + * This function can be used to implement semantics analogous to QemuOpts's + * .merge_lists = true case, or to implement -set for options backed by QDicts. + * + * Note: while QemuOpts is commonly used so that repeated keys overwrite + * ("last one wins"), it can also be used so that repeated keys build up + * a list. keyval_merge() can only be used when the options' semantics are + * the former, not the latter. + */ +void keyval_merge(QDict *dest, const QDict *merged, Error **errp) +{ + GString *str; + + str = g_string_new(""); + keyval_do_merge(dest, merged, str, errp); + g_string_free(str, TRUE); +} + /* * Listify @cur recursively. * Replace QDicts whose keys are all valid list indexes by QLists. From c445909e1f3d5722ed26f067bbffed71cbefd711 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 2 Nov 2020 07:36:48 -0500 Subject: [PATCH 62/76] keyval: introduce keyval_parse_into Allow parsing multiple keyval sequences into the same dictionary. This will be used to simplify the parsing of the -M command line option, which is currently a .merge_lists = true QemuOpts group. Signed-off-by: Paolo Bonzini --- include/qemu/option.h | 2 ++ util/keyval.c | 43 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/include/qemu/option.h b/include/qemu/option.h index d89c66145a..fffb03d848 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -147,6 +147,8 @@ void qemu_opts_print_help(QemuOptsList *list, bool print_caption); void qemu_opts_free(QemuOptsList *list); QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list); +QDict *keyval_parse_into(QDict *qdict, const char *params, const char *implied_key, + bool *p_help, Error **errp); QDict *keyval_parse(const char *params, const char *implied_key, bool *help, Error **errp); void keyval_merge(QDict *old, const QDict *new, Error **errp); diff --git a/util/keyval.c b/util/keyval.c index 9bc380686a..904337c8a1 100644 --- a/util/keyval.c +++ b/util/keyval.c @@ -511,13 +511,14 @@ static QObject *keyval_listify(QDict *cur, GSList *key_of_cur, Error **errp) * If @p_help is not NULL, store whether help is requested there. * If @p_help is NULL and help is requested, fail. * - * On success, return a dictionary of the parsed keys and values. - * On failure, store an error through @errp and return NULL. + * On success, return @dict, now filled with the parsed keys and values. + * + * On failure, store an error through @errp and return NULL. Any keys + * and values parsed so far will be in @dict nevertheless. */ -QDict *keyval_parse(const char *params, const char *implied_key, - bool *p_help, Error **errp) +QDict *keyval_parse_into(QDict *qdict, const char *params, const char *implied_key, + bool *p_help, Error **errp) { - QDict *qdict = qdict_new(); QObject *listified; const char *s; bool help = false; @@ -526,7 +527,6 @@ QDict *keyval_parse(const char *params, const char *implied_key, while (*s) { s = keyval_parse_one(qdict, s, implied_key, &help, errp); if (!s) { - qobject_unref(qdict); return NULL; } implied_key = NULL; @@ -536,15 +536,42 @@ QDict *keyval_parse(const char *params, const char *implied_key, *p_help = help; } else if (help) { error_setg(errp, "Help is not available for this option"); - qobject_unref(qdict); return NULL; } listified = keyval_listify(qdict, NULL, errp); if (!listified) { - qobject_unref(qdict); return NULL; } assert(listified == QOBJECT(qdict)); return qdict; } + +/* + * Parse @params in QEMU's traditional KEY=VALUE,... syntax. + * + * If @implied_key, the first KEY= can be omitted. @implied_key is + * implied then, and VALUE can't be empty or contain ',' or '='. + * + * A parameter "help" or "?" without a value isn't added to the + * resulting dictionary, but instead is interpreted as help request. + * All other options are parsed and returned normally so that context + * specific help can be printed. + * + * If @p_help is not NULL, store whether help is requested there. + * If @p_help is NULL and help is requested, fail. + * + * On success, return a dictionary of the parsed keys and values. + * On failure, store an error through @errp and return NULL. + */ +QDict *keyval_parse(const char *params, const char *implied_key, + bool *p_help, Error **errp) +{ + QDict *qdict = qdict_new(); + QDict *ret = keyval_parse_into(qdict, params, implied_key, p_help, errp); + + if (!ret) { + qobject_unref(qdict); + } + return ret; +} From d8fb7d0969d5c32b3d1b9e20b63ec6c0abe80be4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 13 May 2021 11:28:34 -0400 Subject: [PATCH 63/76] vl: switch -M parsing to keyval Switch from QemuOpts to keyval. This enables the introduction of non-scalar machine properties, and JSON syntax in the future. For JSON syntax to be supported right now, we would have to consider what would happen if string-based dictionaries (produced by -M key=val) were to be merged with strongly-typed dictionaries (produced by -M {'key': 123}). The simplest way out is to never enter the situation, and only allow one -M option when JSON syntax is in use. However, we want options such as -smp to become syntactic sugar for -M, and this is a problem; as soon as -smp becomes a shortcut for -M, QEMU would forbid using -M '{....}' together with -smp. Therefore, allowing JSON syntax right now for -M would be a forward-compatibility nightmare and it would be impossible anyway to introduce -M incrementally in tools. Instead, support for JSON syntax is delayed until after the main options are converted to QOM compound properties. These include -boot, -acpitable, -smbios, -m, -semihosting-config, -rtc and -fw_cfg. Once JSON syntax is introduced, these options will _also_ be forbidden together with -M '{...}'. Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 315 ++++++++++++++++++++++++--------------------------- 1 file changed, 146 insertions(+), 169 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 7dd2d72d0b..f848abd31a 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -145,6 +145,8 @@ static const char *cpu_option; static const char *mem_path; static const char *incoming; static const char *loadvm; +static const char *accelerators; +static QDict *machine_opts_dict; static QTAILQ_HEAD(, ObjectOption) object_opts = QTAILQ_HEAD_INITIALIZER(object_opts); static ram_addr_t maxram_size; static uint64_t ram_slots; @@ -235,21 +237,6 @@ static QemuOptsList qemu_option_rom_opts = { }, }; -static QemuOptsList qemu_machine_opts = { - .name = "machine", - .implied_opt_name = "type", - .merge_lists = true, - .head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head), - .desc = { - /* - * no elements => accept any - * sanity checking will happen later - * when setting machine properties - */ - { } - }, -}; - static QemuOptsList qemu_accel_opts = { .name = "accel", .implied_opt_name = "accel", @@ -498,16 +485,6 @@ static QemuOptsList qemu_action_opts = { }, }; -/** - * Get machine options - * - * Returns: machine options (never null). - */ -static QemuOpts *qemu_get_machine_opts(void) -{ - return qemu_find_opts_singleton("machine"); -} - const char *qemu_get_vm_name(void) { return qemu_name; @@ -815,33 +792,6 @@ static MachineClass *find_default_machine(GSList *machines) return default_machineclass; } -static int machine_help_func(QemuOpts *opts, MachineState *machine) -{ - ObjectProperty *prop; - ObjectPropertyIterator iter; - - if (!qemu_opt_has_help_opt(opts)) { - return 0; - } - - object_property_iter_init(&iter, OBJECT(machine)); - while ((prop = object_property_iter_next(&iter))) { - if (!prop->set) { - continue; - } - - printf("%s.%s=%s", MACHINE_GET_CLASS(machine)->name, - prop->name, prop->type); - if (prop->description) { - printf(" (%s)\n", prop->description); - } else { - printf("\n"); - } - } - - return 1; -} - static void version(void) { printf("QEMU emulator version " QEMU_FULL_VERSION "\n" @@ -1554,33 +1504,31 @@ static gint machine_class_cmp(gconstpointer a, gconstpointer b) object_class_get_name(OBJECT_CLASS(mc1))); } -static MachineClass *machine_parse(const char *name, GSList *machines) +static void machine_help_func(const QDict *qdict) { - MachineClass *mc; - GSList *el; + GSList *machines, *el; + const char *type = qdict_get_try_str(qdict, "type"); - if (is_help_option(name)) { - printf("Supported machines are:\n"); - machines = g_slist_sort(machines, machine_class_cmp); - for (el = machines; el; el = el->next) { - MachineClass *mc = el->data; - if (mc->alias) { - printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, mc->name); - } - printf("%-20s %s%s%s\n", mc->name, mc->desc, - mc->is_default ? " (default)" : "", - mc->deprecation_reason ? " (deprecated)" : ""); + machines = object_class_get_list(TYPE_MACHINE, false); + if (type) { + ObjectClass *machine_class = OBJECT_CLASS(find_machine(type, machines)); + if (machine_class) { + type_print_class_properties(object_class_get_name(machine_class)); + return; } - exit(0); } - mc = find_machine(name, machines); - if (!mc) { - error_report("unsupported machine type"); - error_printf("Use -machine help to list supported machines\n"); - exit(1); + printf("Supported machines are:\n"); + machines = g_slist_sort(machines, machine_class_cmp); + for (el = machines; el; el = el->next) { + MachineClass *mc = el->data; + if (mc->alias) { + printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, mc->name); + } + printf("%-20s %s%s%s\n", mc->name, mc->desc, + mc->is_default ? " (default)" : "", + mc->deprecation_reason ? " (deprecated)" : ""); } - return mc; } static const char *pid_file; @@ -1633,32 +1581,31 @@ static const QEMUOption *lookup_opt(int argc, char **argv, return popt; } -static MachineClass *select_machine(void) +static MachineClass *select_machine(QDict *qdict, Error **errp) { + const char *optarg = qdict_get_try_str(qdict, "type"); GSList *machines = object_class_get_list(TYPE_MACHINE, false); - MachineClass *machine_class = find_default_machine(machines); - const char *optarg; - QemuOpts *opts; - Location loc; + MachineClass *machine_class; + Error *local_err = NULL; - loc_push_none(&loc); - - opts = qemu_get_machine_opts(); - qemu_opts_loc_restore(opts); - - optarg = qemu_opt_get(opts, "type"); if (optarg) { - machine_class = machine_parse(optarg, machines); + machine_class = find_machine(optarg, machines); + qdict_del(qdict, "type"); + if (!machine_class) { + error_setg(&local_err, "unsupported machine type"); + } + } else { + machine_class = find_default_machine(machines); + if (!machine_class) { + error_setg(&local_err, "No machine specified, and there is no default"); + } } - if (!machine_class) { - error_report("No machine specified, and there is no default"); - error_printf("Use -machine help to list supported machines\n"); - exit(1); - } - - loc_pop(&loc); g_slist_free(machines); + if (local_err) { + error_append_hint(&local_err, "Use -machine help to list supported machines\n"); + error_propagate(errp, local_err); + } return machine_class; } @@ -1677,42 +1624,70 @@ static int object_parse_property_opt(Object *obj, return 0; } -static int machine_set_property(void *opaque, - const char *name, const char *value, - Error **errp) +/* *Non*recursively replace underscores with dashes in QDict keys. */ +static void keyval_dashify(QDict *qdict, Error **errp) { - g_autofree char *qom_name = g_strdup(name); + const QDictEntry *ent, *next; char *p; - for (p = qom_name; *p; p++) { - if (*p == '_') { - *p = '-'; + for (ent = qdict_first(qdict); ent; ent = next) { + g_autofree char *new_key = NULL; + + next = qdict_next(qdict, ent); + if (!strchr(ent->key, '_')) { + continue; } + new_key = g_strdup(ent->key); + for (p = new_key; *p; p++) { + if (*p == '_') { + *p = '-'; + } + } + if (qdict_haskey(qdict, new_key)) { + error_setg(errp, "Conflict between '%s' and '%s'", ent->key, new_key); + return; + } + qobject_ref(ent->value); + qdict_put_obj(qdict, new_key, ent->value); + qdict_del(qdict, ent->key); } +} + +static void qemu_apply_legacy_machine_options(QDict *qdict) +{ + const char *value; + + keyval_dashify(qdict, &error_fatal); /* Legacy options do not correspond to MachineState properties. */ - if (g_str_equal(qom_name, "accel")) { - return 0; - } - if (g_str_equal(qom_name, "igd-passthru")) { - object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), qom_name, value, - false); - return 0; - } - if (g_str_equal(qom_name, "kvm-shadow-mem")) { - object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value, - false); - return 0; - } - if (g_str_equal(qom_name, "kernel-irqchip")) { - object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value, - false); - object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), qom_name, value, - false); - return 0; + value = qdict_get_try_str(qdict, "accel"); + if (value) { + accelerators = g_strdup(value); + qdict_del(qdict, "accel"); } - return object_parse_property_opt(opaque, name, value, "type", errp); + value = qdict_get_try_str(qdict, "igd-passthru"); + if (value) { + object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), "igd-passthru", value, + false); + qdict_del(qdict, "igd-passthru"); + } + + value = qdict_get_try_str(qdict, "kvm-shadow-mem"); + if (value) { + object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), "kvm-shadow-mem", value, + false); + qdict_del(qdict, "kvm-shadow-mem"); + } + + value = qdict_get_try_str(qdict, "kernel-irqchip"); + if (value) { + object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), "kernel-irqchip", value, + false); + object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), "kernel-irqchip", value, + false); + qdict_del(qdict, "kernel-irqchip"); + } } static void object_option_foreach_add(bool (*type_opt_predicate)(const char *)) @@ -1827,16 +1802,14 @@ static bool object_create_early(const char *type) return true; } -static void qemu_apply_machine_options(void) +static void qemu_apply_machine_options(QDict *qdict) { MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); - QemuOpts *machine_opts = qemu_get_machine_opts(); const char *boot_order = NULL; const char *boot_once = NULL; QemuOpts *opts; - qemu_opt_foreach(machine_opts, machine_set_property, current_machine, - &error_fatal); + object_set_properties_from_keyval(OBJECT(current_machine), qdict, false, &error_fatal); current_machine->ram_size = ram_size; current_machine->maxram_size = maxram_size; current_machine->ram_slots = ram_slots; @@ -1865,10 +1838,8 @@ static void qemu_apply_machine_options(void) current_machine->boot_once = boot_once; if (semihosting_enabled() && !semihosting_get_argc()) { - const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); - const char *kernel_cmdline = qemu_opt_get(machine_opts, "append") ?: ""; /* fall back to the -kernel/-append */ - semihosting_arg_fallback(kernel_filename, kernel_cmdline); + semihosting_arg_fallback(current_machine->kernel_filename, current_machine->kernel_cmdline); } } @@ -1924,8 +1895,7 @@ static void qemu_create_early_backends(void) /* * Note: we need to create audio and block backends before - * machine_set_property(), so machine properties can refer to - * them. + * setting machine properties, so they can be referred to. */ configure_blockdev(&bdo_queue, machine_class, snapshot); audio_init_audiodevs(); @@ -2091,16 +2061,14 @@ static void set_memory_options(MachineClass *mc) loc_pop(&loc); } -static void qemu_create_machine(MachineClass *machine_class) +static void qemu_create_machine(QDict *qdict) { + MachineClass *machine_class = select_machine(qdict, &error_fatal); object_set_machine_compat_props(machine_class->compat_props); set_memory_options(machine_class); current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class))); - if (machine_help_func(qemu_get_machine_opts(), current_machine)) { - exit(0); - } object_property_add_child(object_get_root(), "machine", OBJECT(current_machine)); object_property_add_child(container_get(OBJECT(current_machine), @@ -2131,8 +2099,12 @@ static void qemu_create_machine(MachineClass *machine_class) * specified either by the configuration file or by the command line. */ if (machine_class->default_machine_opts) { - qemu_opts_set_defaults(qemu_find_opts("machine"), - machine_class->default_machine_opts, 0); + QDict *default_opts = + keyval_parse(machine_class->default_machine_opts, NULL, NULL, + &error_abort); + object_set_properties_from_keyval(OBJECT(current_machine), default_opts, + false, &error_abort); + qobject_unref(default_opts); } } @@ -2154,7 +2126,8 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp) */ static bool is_qemuopts_group(const char *group) { - if (g_str_equal(group, "object")) { + if (g_str_equal(group, "object") || + g_str_equal(group, "machine")) { return false; } return true; @@ -2167,6 +2140,13 @@ static void qemu_record_config_group(const char *group, QDict *dict, Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(dict)); object_option_add_visitor(v); visit_free(v); + } else if (g_str_equal(group, "machine")) { + /* + * Cannot merge string-valued and type-safe dictionaries, so JSON + * is not accepted yet for -M. + */ + assert(!from_json); + keyval_merge(machine_opts_dict, dict, errp); } else { abort(); } @@ -2297,13 +2277,11 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp) static void configure_accelerators(const char *progname) { - const char *accelerators; bool init_failed = false; qemu_opts_foreach(qemu_find_opts("icount"), do_configure_icount, NULL, &error_fatal); - accelerators = qemu_opt_get(qemu_get_machine_opts(), "accel"); if (QTAILQ_EMPTY(&qemu_accel_opts.head)) { char **accel_list, **tmp; @@ -2391,12 +2369,11 @@ static void create_default_memdev(MachineState *ms, const char *path) &error_fatal); } -static void qemu_validate_options(void) +static void qemu_validate_options(const QDict *machine_opts) { - QemuOpts *machine_opts = qemu_get_machine_opts(); - const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); - const char *initrd_filename = qemu_opt_get(machine_opts, "initrd"); - const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); + const char *kernel_filename = qdict_get_try_str(machine_opts, "kernel"); + const char *initrd_filename = qdict_get_try_str(machine_opts, "initrd"); + const char *kernel_cmdline = qdict_get_try_str(machine_opts, "append"); if (kernel_filename == NULL) { if (kernel_cmdline != NULL) { @@ -2736,7 +2713,6 @@ void qemu_init(int argc, char **argv, char **envp) qemu_add_opts(&qemu_trace_opts); qemu_plugin_add_opts(); qemu_add_opts(&qemu_option_rom_opts); - qemu_add_opts(&qemu_machine_opts); qemu_add_opts(&qemu_accel_opts); qemu_add_opts(&qemu_mem_opts); qemu_add_opts(&qemu_smp_opts); @@ -2777,6 +2753,7 @@ void qemu_init(int argc, char **argv, char **envp) } } + machine_opts_dict = qdict_new(); if (userconfig) { qemu_read_default_config_file(&error_fatal); } @@ -2866,8 +2843,7 @@ void qemu_init(int argc, char **argv, char **envp) parse_display(optarg); break; case QEMU_OPTION_nographic: - olist = qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "graphics=off", false); + qdict_put_str(machine_opts_dict, "graphics", "off"); nographic = true; dpy.type = DISPLAY_TYPE_NONE; break; @@ -2891,16 +2867,16 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_kernel: - qemu_opts_set(qemu_find_opts("machine"), "kernel", optarg, &error_abort); + qdict_put_str(machine_opts_dict, "kernel", optarg); break; case QEMU_OPTION_initrd: - qemu_opts_set(qemu_find_opts("machine"), "initrd", optarg, &error_abort); + qdict_put_str(machine_opts_dict, "initrd", optarg); break; case QEMU_OPTION_append: - qemu_opts_set(qemu_find_opts("machine"), "append", optarg, &error_abort); + qdict_put_str(machine_opts_dict, "append", optarg); break; case QEMU_OPTION_dtb: - qemu_opts_set(qemu_find_opts("machine"), "dtb", optarg, &error_abort); + qdict_put_str(machine_opts_dict, "dtb", optarg); break; case QEMU_OPTION_cdrom: drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS); @@ -3010,7 +2986,7 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_bios: - qemu_opts_set(qemu_find_opts("machine"), "firmware", optarg, &error_abort); + qdict_put_str(machine_opts_dict, "firmware", optarg); break; case QEMU_OPTION_singlestep: singlestep = 1; @@ -3281,17 +3257,20 @@ void qemu_init(int argc, char **argv, char **envp) preconfig_requested = true; break; case QEMU_OPTION_enable_kvm: - olist = qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "accel=kvm", false); + qdict_put_str(machine_opts_dict, "accel", "kvm"); break; case QEMU_OPTION_M: case QEMU_OPTION_machine: - olist = qemu_find_opts("machine"); - opts = qemu_opts_parse_noisily(olist, optarg, true); - if (!opts) { - exit(1); + { + bool help; + + keyval_parse_into(machine_opts_dict, optarg, "type", &help, &error_fatal); + if (help) { + machine_help_func(machine_opts_dict); + exit(EXIT_SUCCESS); + } + break; } - break; case QEMU_OPTION_accel: accel_opts = qemu_opts_parse_noisily(qemu_find_opts("accel"), optarg, true); @@ -3318,12 +3297,10 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_usb: - olist = qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "usb=on", false); + qdict_put_str(machine_opts_dict, "usb", "on"); break; case QEMU_OPTION_usbdevice: - olist = qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "usb=on", false); + qdict_put_str(machine_opts_dict, "usb", "on"); add_device_config(DEV_USB, optarg); break; case QEMU_OPTION_device: @@ -3342,12 +3319,10 @@ void qemu_init(int argc, char **argv, char **envp) vnc_parse(optarg); break; case QEMU_OPTION_no_acpi: - olist = qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "acpi=off", false); + qdict_put_str(machine_opts_dict, "acpi", "off"); break; case QEMU_OPTION_no_hpet: - olist = qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "hpet=off", false); + qdict_put_str(machine_opts_dict, "hpet", "off"); break; case QEMU_OPTION_no_reboot: olist = qemu_find_opts("action"); @@ -3600,7 +3575,7 @@ void qemu_init(int argc, char **argv, char **envp) */ loc_set_none(); - qemu_validate_options(); + qemu_validate_options(machine_opts_dict); qemu_process_sugar_options(); /* @@ -3633,7 +3608,7 @@ void qemu_init(int argc, char **argv, char **envp) configure_rtc(qemu_find_opts_singleton("rtc")); - qemu_create_machine(select_machine()); + qemu_create_machine(machine_opts_dict); suspend_mux_open(); @@ -3641,12 +3616,14 @@ void qemu_init(int argc, char **argv, char **envp) qemu_create_default_devices(); qemu_create_early_backends(); - qemu_apply_machine_options(); + qemu_apply_legacy_machine_options(machine_opts_dict); + qemu_apply_machine_options(machine_opts_dict); + qobject_unref(machine_opts_dict); phase_advance(PHASE_MACHINE_CREATED); /* * Note: uses machine properties such as kernel-irqchip, must run - * after machine_set_property(). + * after qemu_apply_machine_options. */ configure_accelerators(argv[0]); phase_advance(PHASE_ACCEL_CREATED); From fe68090e8fbd6e831aaf3fc3bb0459c5cccf14cf Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 13 May 2021 09:03:48 -0400 Subject: [PATCH 64/76] machine: add smp compound property Make -smp syntactic sugar for a compound property "-machine smp.{cores,threads,cpu,...}". machine_smp_parse is replaced by the setter for the property. numa-test will now cover the new syntax, while other tests still use -smp. Signed-off-by: Paolo Bonzini --- hw/core/machine.c | 108 +++++++++++++++++++++------------------- include/hw/boards.h | 1 - softmmu/vl.c | 33 +++++++++--- tests/qtest/numa-test.c | 22 ++++---- 4 files changed, 95 insertions(+), 69 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index ca69f0343a..57c18f909a 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -19,6 +19,7 @@ #include "hw/loader.h" #include "qapi/error.h" #include "qapi/qapi-visit-common.h" +#include "qapi/qapi-visit-machine.h" #include "qapi/visitor.h" #include "hw/sysbus.h" #include "sysemu/cpus.h" @@ -799,6 +800,57 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp) ms->smp.sockets = sockets; } +static void machine_get_smp(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + MachineState *ms = MACHINE(obj); + SMPConfiguration *config = &(SMPConfiguration){ + .has_cores = true, .cores = ms->smp.cores, + .has_sockets = true, .sockets = ms->smp.sockets, + .has_dies = true, .dies = ms->smp.dies, + .has_threads = true, .threads = ms->smp.threads, + .has_cpus = true, .cpus = ms->smp.cpus, + .has_maxcpus = true, .maxcpus = ms->smp.max_cpus, + }; + if (!visit_type_SMPConfiguration(v, name, &config, &error_abort)) { + return; + } +} + +static void machine_set_smp(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + MachineClass *mc = MACHINE_GET_CLASS(obj); + MachineState *ms = MACHINE(obj); + SMPConfiguration *config; + ERRP_GUARD(); + + if (!visit_type_SMPConfiguration(v, name, &config, errp)) { + return; + } + + mc->smp_parse(ms, config, errp); + if (errp) { + goto out_free; + } + + /* sanity-check smp_cpus and max_cpus against mc */ + if (ms->smp.cpus < mc->min_cpus) { + error_setg(errp, "Invalid SMP CPUs %d. The min CPUs " + "supported by machine '%s' is %d", + ms->smp.cpus, + mc->name, mc->min_cpus); + } else if (ms->smp.max_cpus > mc->max_cpus) { + error_setg(errp, "Invalid SMP CPUs %d. The max CPUs " + "supported by machine '%s' is %d", + current_machine->smp.max_cpus, + mc->name, mc->max_cpus); + } + +out_free: + qapi_free_SMPConfiguration(config); +} + static void machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -838,6 +890,12 @@ static void machine_class_init(ObjectClass *oc, void *data) object_class_property_set_description(oc, "dumpdtb", "Dump current dtb to a file and quit"); + object_class_property_add(oc, "smp", "SMPConfiguration", + machine_get_smp, machine_set_smp, + NULL, NULL); + object_class_property_set_description(oc, "smp", + "CPU topology"); + object_class_property_add(oc, "phandle-start", "int", machine_get_phandle_start, machine_set_phandle_start, NULL, NULL); @@ -1126,56 +1184,6 @@ MemoryRegion *machine_consume_memdev(MachineState *machine, return ret; } -bool machine_smp_parse(MachineState *ms, QemuOpts *opts, Error **errp) -{ - MachineClass *mc = MACHINE_GET_CLASS(ms); - ERRP_GUARD(); - - if (opts) { - SMPConfiguration config = { - .has_cpus = !!qemu_opt_get(opts, "cpus"), - .cpus = qemu_opt_get_number(opts, "cpus", 0), - .has_sockets = !!qemu_opt_get(opts, "sockets"), - .sockets = qemu_opt_get_number(opts, "sockets", 0), - .has_dies = !!qemu_opt_get(opts, "dies"), - .dies = qemu_opt_get_number(opts, "dies", 0), - .has_cores = !!qemu_opt_get(opts, "cores"), - .cores = qemu_opt_get_number(opts, "cores", 0), - .has_threads = !!qemu_opt_get(opts, "threads"), - .threads = qemu_opt_get_number(opts, "threads", 0), - .has_maxcpus = !!qemu_opt_get(opts, "maxcpus"), - .maxcpus = qemu_opt_get_number(opts, "maxcpus", 0), - }; - - mc->smp_parse(ms, &config, errp); - if (*errp) { - return false; - } - } - - /* sanity-check smp_cpus and max_cpus against mc */ - if (ms->smp.cpus < mc->min_cpus) { - error_setg(errp, "Invalid SMP CPUs %d. The min CPUs " - "supported by machine '%s' is %d", - ms->smp.cpus, - mc->name, mc->min_cpus); - return false; - } else if (ms->smp.max_cpus > mc->max_cpus) { - error_setg(errp, "Invalid SMP CPUs %d. The max CPUs " - "supported by machine '%s' is %d", - current_machine->smp.max_cpus, - mc->name, mc->max_cpus); - return false; - } - - if (ms->smp.cpus > 1) { - Error *blocker = NULL; - error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp"); - replay_add_blocker(blocker); - } - return true; -} - void machine_run_board_init(MachineState *machine) { MachineClass *machine_class = MACHINE_GET_CLASS(machine); diff --git a/include/hw/boards.h b/include/hw/boards.h index 1eae4427e8..accd6eff35 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -26,7 +26,6 @@ OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE) extern MachineState *current_machine; void machine_run_board_init(MachineState *machine); -bool machine_smp_parse(MachineState *ms, QemuOpts *opts, Error **errp); bool machine_usb(MachineState *machine); int machine_phandle_start(MachineState *machine); bool machine_dump_guest_core(MachineState *machine); diff --git a/softmmu/vl.c b/softmmu/vl.c index f848abd31a..a50c8575a1 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1531,6 +1531,25 @@ static void machine_help_func(const QDict *qdict) } } +static void +machine_parse_property_opt(QemuOptsList *opts_list, const char *propname, + const char *arg, Error **errp) +{ + QDict *opts, *prop; + bool help = false; + ERRP_GUARD(); + + prop = keyval_parse(arg, opts_list->implied_opt_name, &help, errp); + if (help) { + qemu_opts_print_help(opts_list, true); + return; + } + opts = qdict_new(); + qdict_put(opts, propname, prop); + keyval_merge(machine_opts_dict, opts, errp); + qobject_unref(opts); +} + static const char *pid_file; static Notifier qemu_unlink_pidfile_notifier; @@ -1841,6 +1860,12 @@ static void qemu_apply_machine_options(QDict *qdict) /* fall back to the -kernel/-append */ semihosting_arg_fallback(current_machine->kernel_filename, current_machine->kernel_cmdline); } + + if (current_machine->smp.cpus > 1) { + Error *blocker = NULL; + error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp"); + replay_add_blocker(blocker); + } } static void qemu_create_early_backends(void) @@ -2091,9 +2116,6 @@ static void qemu_create_machine(QDict *qdict) qemu_set_hw_version(machine_class->hw_version); } - machine_smp_parse(current_machine, - qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal); - /* * Get the default machine options from the machine if it is not already * specified either by the configuration file or by the command line. @@ -3310,10 +3332,7 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_smp: - if (!qemu_opts_parse_noisily(qemu_find_opts("smp-opts"), - optarg, true)) { - exit(1); - } + machine_parse_property_opt(qemu_find_opts("smp-opts"), "smp", optarg, &error_fatal); break; case QEMU_OPTION_vnc: vnc_parse(optarg); diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c index dc0ec571ca..c677cd63c4 100644 --- a/tests/qtest/numa-test.c +++ b/tests/qtest/numa-test.c @@ -25,7 +25,7 @@ static void test_mon_explicit(const void *data) g_autofree char *s = NULL; g_autofree char *cli = NULL; - cli = make_cli(data, "-smp 8 -numa node,nodeid=0,memdev=ram,cpus=0-3 " + cli = make_cli(data, "-machine smp.cpus=8 -numa node,nodeid=0,memdev=ram,cpus=0-3 " "-numa node,nodeid=1,cpus=4-7"); qts = qtest_init(cli); @@ -42,7 +42,7 @@ static void test_def_cpu_split(const void *data) g_autofree char *s = NULL; g_autofree char *cli = NULL; - cli = make_cli(data, "-smp 8 -numa node,memdev=ram -numa node"); + cli = make_cli(data, "-machine smp.cpus=8 -numa node,memdev=ram -numa node"); qts = qtest_init(cli); s = qtest_hmp(qts, "info numa"); @@ -58,7 +58,7 @@ static void test_mon_partial(const void *data) g_autofree char *s = NULL; g_autofree char *cli = NULL; - cli = make_cli(data, "-smp 8 " + cli = make_cli(data, "-machine smp.cpus=8 " "-numa node,nodeid=0,memdev=ram,cpus=0-1 " "-numa node,nodeid=1,cpus=4-5 "); qts = qtest_init(cli); @@ -86,7 +86,7 @@ static void test_query_cpus(const void *data) QTestState *qts; g_autofree char *cli = NULL; - cli = make_cli(data, "-smp 8 -numa node,memdev=ram,cpus=0-3 " + cli = make_cli(data, "-machine smp.cpus=8 -numa node,memdev=ram,cpus=0-3 " "-numa node,cpus=4-7"); qts = qtest_init(cli); cpus = get_cpus(qts, &resp); @@ -124,7 +124,7 @@ static void pc_numa_cpu(const void *data) QTestState *qts; g_autofree char *cli = NULL; - cli = make_cli(data, "-cpu pentium -smp 8,sockets=2,cores=2,threads=2 " + cli = make_cli(data, "-cpu pentium -machine smp.cpus=8,smp.sockets=2,smp.cores=2,smp.threads=2 " "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 " "-numa cpu,node-id=1,socket-id=0 " "-numa cpu,node-id=0,socket-id=1,core-id=0 " @@ -177,7 +177,7 @@ static void spapr_numa_cpu(const void *data) QTestState *qts; g_autofree char *cli = NULL; - cli = make_cli(data, "-smp 4,cores=4 " + cli = make_cli(data, "-machine smp.cpus=4,smp.cores=4 " "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 " "-numa cpu,node-id=0,core-id=0 " "-numa cpu,node-id=0,core-id=1 " @@ -222,7 +222,7 @@ static void aarch64_numa_cpu(const void *data) QTestState *qts; g_autofree char *cli = NULL; - cli = make_cli(data, "-smp 2 " + cli = make_cli(data, "-machine smp.cpus=2 " "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 " "-numa cpu,node-id=1,thread-id=0 " "-numa cpu,node-id=0,thread-id=1"); @@ -265,7 +265,7 @@ static void pc_dynamic_cpu_cfg(const void *data) QTestState *qs; g_autofree char *cli = NULL; - cli = make_cli(data, "-nodefaults --preconfig -smp 2"); + cli = make_cli(data, "-nodefaults --preconfig -machine smp.cpus=2"); qs = qtest_init(cli); /* create 2 numa nodes */ @@ -324,7 +324,7 @@ static void pc_hmat_build_cfg(const void *data) g_autofree char *cli = NULL; cli = make_cli(data, "-nodefaults --preconfig -machine hmat=on " - "-smp 2,sockets=2 " + "-machine smp.cpus=2,smp.sockets=2 " "-m 128M,slots=2,maxmem=1G " "-object memory-backend-ram,size=64M,id=m0 " "-object memory-backend-ram,size=64M,id=m1 " @@ -453,7 +453,7 @@ static void pc_hmat_off_cfg(const void *data) g_autofree char *cli = NULL; cli = make_cli(data, "-nodefaults --preconfig " - "-smp 2,sockets=2 " + "-machine smp.cpus=2,smp.sockets=2 " "-m 128M,slots=2,maxmem=1G " "-object memory-backend-ram,size=64M,id=m0,prealloc=y " "-object memory-backend-ram,size=64M,id=m1 " @@ -492,7 +492,7 @@ static void pc_hmat_erange_cfg(const void *data) g_autofree char *cli = NULL; cli = make_cli(data, "-nodefaults --preconfig -machine hmat=on " - "-smp 2,sockets=2 " + "-machine smp.cpus=2,smp.sockets=2 " "-m 128M,slots=2,maxmem=1G " "-object memory-backend-ram,size=64M,id=m0 " "-object memory-backend-ram,size=64M,id=m1 " From 904806c69bd4e013491550d05f5c2cbdba9a9b38 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 11 Nov 2020 09:03:37 -0500 Subject: [PATCH 65/76] qemu-option: remove now-dead code -M was the sole user of qemu_opts_set and qemu_opts_set_defaults, remove them and the arguments that they used. Signed-off-by: Paolo Bonzini --- include/qemu/option.h | 3 --- tests/unit/test-qemu-opts.c | 35 ------------------------- util/qemu-option.c | 51 ++++++++----------------------------- 3 files changed, 10 insertions(+), 79 deletions(-) diff --git a/include/qemu/option.h b/include/qemu/option.h index fffb03d848..306bf07575 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -119,7 +119,6 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists, Error **errp); void qemu_opts_reset(QemuOptsList *list); void qemu_opts_loc_restore(QemuOpts *opts); -bool qemu_opts_set(QemuOptsList *list, const char *name, const char *value, Error **errp); const char *qemu_opts_id(QemuOpts *opts); void qemu_opts_set_id(QemuOpts *opts, char *id); void qemu_opts_del(QemuOpts *opts); @@ -130,8 +129,6 @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params, bool permit_abbrev); QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, bool permit_abbrev, Error **errp); -void qemu_opts_set_defaults(QemuOptsList *list, const char *params, - int permit_abbrev); QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, Error **errp); QDict *qemu_opts_to_qdict_filtered(QemuOpts *opts, QDict *qdict, diff --git a/tests/unit/test-qemu-opts.c b/tests/unit/test-qemu-opts.c index 6568e31a72..828d40e928 100644 --- a/tests/unit/test-qemu-opts.c +++ b/tests/unit/test-qemu-opts.c @@ -410,40 +410,6 @@ static void test_qemu_opts_reset(void) g_assert(opts == NULL); } -static void test_qemu_opts_set(void) -{ - QemuOptsList *list; - QemuOpts *opts; - const char *opt; - - list = qemu_find_opts("opts_list_04"); - g_assert(list != NULL); - g_assert(QTAILQ_EMPTY(&list->head)); - g_assert_cmpstr(list->name, ==, "opts_list_04"); - - /* should not find anything at this point */ - opts = qemu_opts_find(list, NULL); - g_assert(opts == NULL); - - /* implicitly create opts and set str3 value */ - qemu_opts_set(list, "str3", "value", &error_abort); - g_assert(!QTAILQ_EMPTY(&list->head)); - - /* get the just created opts */ - opts = qemu_opts_find(list, NULL); - g_assert(opts != NULL); - - /* check the str3 value */ - opt = qemu_opt_get(opts, "str3"); - g_assert_cmpstr(opt, ==, "value"); - - qemu_opts_del(opts); - - /* should not find anything at this point */ - opts = qemu_opts_find(list, NULL); - g_assert(opts == NULL); -} - static int opts_count_iter(void *opaque, const char *name, const char *value, Error **errp) { @@ -1041,7 +1007,6 @@ int main(int argc, char *argv[]) g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size); g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset); g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset); - g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set); g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse); g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool); g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number); diff --git a/util/qemu-option.c b/util/qemu-option.c index 4944015a25..ee78e42216 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -479,19 +479,14 @@ int qemu_opt_unset(QemuOpts *opts, const char *name) } } -static QemuOpt *opt_create(QemuOpts *opts, const char *name, char *value, - bool prepend) +static QemuOpt *opt_create(QemuOpts *opts, const char *name, char *value) { QemuOpt *opt = g_malloc0(sizeof(*opt)); opt->name = g_strdup(name); opt->str = value; opt->opts = opts; - if (prepend) { - QTAILQ_INSERT_HEAD(&opts->head, opt, next); - } else { - QTAILQ_INSERT_TAIL(&opts->head, opt, next); - } + QTAILQ_INSERT_TAIL(&opts->head, opt, next); return opt; } @@ -518,7 +513,7 @@ static bool opt_validate(QemuOpt *opt, Error **errp) bool qemu_opt_set(QemuOpts *opts, const char *name, const char *value, Error **errp) { - QemuOpt *opt = opt_create(opts, name, g_strdup(value), false); + QemuOpt *opt = opt_create(opts, name, g_strdup(value)); if (!opt_validate(opt, errp)) { qemu_opt_del(opt); @@ -662,15 +657,6 @@ void qemu_opts_loc_restore(QemuOpts *opts) loc_restore(&opts->loc); } -bool qemu_opts_set(QemuOptsList *list, const char *name, const char *value, Error **errp) -{ - QemuOpts *opts; - - assert(list->merge_lists); - opts = qemu_opts_create(list, NULL, 0, &error_abort); - return qemu_opt_set(opts, name, value, errp); -} - const char *qemu_opts_id(QemuOpts *opts) { return opts->id; @@ -811,7 +797,7 @@ static const char *get_opt_name_value(const char *params, } static bool opts_do_parse(QemuOpts *opts, const char *params, - const char *firstname, bool prepend, + const char *firstname, bool warn_on_flag, bool *help_wanted, Error **errp) { char *option, *value; @@ -833,7 +819,7 @@ static bool opts_do_parse(QemuOpts *opts, const char *params, continue; } - opt = opt_create(opts, option, value, prepend); + opt = opt_create(opts, option, value); g_free(option); if (!opt_validate(opt, errp)) { qemu_opt_del(opt); @@ -889,11 +875,11 @@ bool has_help_option(const char *params) bool qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname, Error **errp) { - return opts_do_parse(opts, params, firstname, false, false, NULL, errp); + return opts_do_parse(opts, params, firstname, false, NULL, errp); } static QemuOpts *opts_parse(QemuOptsList *list, const char *params, - bool permit_abbrev, bool defaults, + bool permit_abbrev, bool warn_on_flag, bool *help_wanted, Error **errp) { const char *firstname; @@ -903,21 +889,13 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, assert(!permit_abbrev || list->implied_opt_name); firstname = permit_abbrev ? list->implied_opt_name : NULL; - /* - * This code doesn't work for defaults && !list->merge_lists: when - * params has no id=, and list has an element with !opts->id, it - * appends a new element instead of returning the existing opts. - * However, we got no use for this case. Guard against possible - * (if unlikely) future misuse: - */ - assert(!defaults || list->merge_lists); opts = qemu_opts_create(list, id, !list->merge_lists, errp); g_free(id); if (opts == NULL) { return NULL; } - if (!opts_do_parse(opts, params, firstname, defaults, + if (!opts_do_parse(opts, params, firstname, warn_on_flag, help_wanted, errp)) { qemu_opts_del(opts); return NULL; @@ -936,7 +914,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, bool permit_abbrev, Error **errp) { - return opts_parse(list, params, permit_abbrev, false, false, NULL, errp); + return opts_parse(list, params, permit_abbrev, false, NULL, errp); } /** @@ -954,7 +932,7 @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params, QemuOpts *opts; bool help_wanted = false; - opts = opts_parse(list, params, permit_abbrev, false, true, + opts = opts_parse(list, params, permit_abbrev, true, opts_accepts_any(list) ? NULL : &help_wanted, &err); if (!opts) { @@ -968,15 +946,6 @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params, return opts; } -void qemu_opts_set_defaults(QemuOptsList *list, const char *params, - int permit_abbrev) -{ - QemuOpts *opts; - - opts = opts_parse(list, params, permit_abbrev, true, false, NULL, NULL); - assert(opts); -} - static bool qemu_opts_from_qdict_entry(QemuOpts *opts, const QDictEntry *entry, Error **errp) From 3983a767e3d85008c1fb4b8618ac67bf5aee7527 Mon Sep 17 00:00:00 2001 From: John Arbuckle Date: Mon, 5 Jul 2021 15:53:28 -0400 Subject: [PATCH 66/76] Set icon for QEMU binary on Mac OS Before switching the build system over to Meson, an icon was added to the QEMU binary on Mac OS. This patch adds back that feature; it piggybacks on the existing scripts/entitlement.sh, which already does in-place changes to the executable on Darwin. Signed-off-by: John Arbuckle Message-Id: <20210705195328.36442-1-programmingkidx@gmail.com> Signed-off-by: Paolo Bonzini --- meson.build | 15 ++++++++++----- scripts/entitlement.sh | 10 +++++++++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/meson.build b/meson.build index 1651496800..8b61fdb4be 100644 --- a/meson.build +++ b/meson.build @@ -2507,8 +2507,7 @@ foreach target : target_dirs endif foreach exe: execs exe_name = exe['name'] - exe_sign = 'CONFIG_HVF' in config_target - if exe_sign + if targetos == 'darwin' exe_name += '-unsigned' endif @@ -2522,7 +2521,13 @@ foreach target : target_dirs link_args: link_args, gui_app: exe['gui']) - if exe_sign + if 'CONFIG_HVF' in config_target + entitlements = meson.current_source_dir() / 'accel/hvf/entitlements.plist' + else + entitlements = '/dev/null' + endif + if targetos == 'darwin' + icon = meson.current_source_dir() / 'pc-bios/qemu.rsrc' emulators += {exe['name'] : custom_target(exe['name'], depends: emulator, output: exe['name'], @@ -2530,14 +2535,14 @@ foreach target : target_dirs meson.current_source_dir() / 'scripts/entitlement.sh', meson.current_build_dir() / exe_name, meson.current_build_dir() / exe['name'], - meson.current_source_dir() / 'accel/hvf/entitlements.plist' + entitlements, icon ]) } meson.add_install_script('scripts/entitlement.sh', '--install', get_option('bindir') / exe_name, get_option('bindir') / exe['name'], - meson.current_source_dir() / 'accel/hvf/entitlements.plist') + entitlements, icon) else emulators += {exe['name']: emulator} endif diff --git a/scripts/entitlement.sh b/scripts/entitlement.sh index f7aaaf2766..d2a7079ce3 100755 --- a/scripts/entitlement.sh +++ b/scripts/entitlement.sh @@ -11,6 +11,7 @@ fi SRC="$1" DST="$2" ENTITLEMENT="$3" +ICON="$4" if $in_place; then trap 'rm "$DST.tmp"' exit @@ -20,6 +21,13 @@ else cd "$MESON_INSTALL_DESTDIR_PREFIX" fi -codesign --entitlements "$ENTITLEMENT" --force -s - "$SRC" +if test "$ENTITLEMENT" != '/dev/null'; then + codesign --entitlements "$ENTITLEMENT" --force -s - "$SRC" +fi + +# Add the QEMU icon to the binary on Mac OS +Rez -append "$ICON" -o "$SRC" +SetFile -a C "$SRC" + mv -f "$SRC" "$DST" trap '' exit From 7ca6f2ad375d32e81844788dbc2b05a04cc391b5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 6 Jul 2021 08:59:01 +0200 Subject: [PATCH 67/76] config-host.mak: remove unused compiler-related lines Most of the build is not done via Makefiles, therefore the toolchain variables are mostly unused. They are still used by tests/tcg and pc-bios/roms, but most of them are not needed there. Signed-off-by: Paolo Bonzini --- configure | 10 ---------- meson.build | 1 - 2 files changed, 11 deletions(-) diff --git a/configure b/configure index 0e487ae091..650d9c0735 100755 --- a/configure +++ b/configure @@ -521,9 +521,6 @@ query_pkg_config() { pkg_config=query_pkg_config sdl2_config="${SDL2_CONFIG-${cross_prefix}sdl2-config}" -# If the user hasn't specified ARFLAGS, default to 'rv', just as make does. -ARFLAGS="${ARFLAGS-rv}" - # default flags for all hosts # We use -fwrapv to tell the compiler that we require a C dialect where # left shift of signed integers is well defined and has the expected @@ -4917,19 +4914,12 @@ echo "HOST_CC=$host_cc" >> $config_host_mak if $iasl -h > /dev/null 2>&1; then echo "CONFIG_IASL=$iasl" >> $config_host_mak fi -echo "CXX=$cxx" >> $config_host_mak -echo "OBJCC=$objcc" >> $config_host_mak echo "AR=$ar" >> $config_host_mak -echo "ARFLAGS=$ARFLAGS" >> $config_host_mak echo "AS=$as" >> $config_host_mak echo "CCAS=$ccas" >> $config_host_mak echo "CPP=$cpp" >> $config_host_mak echo "OBJCOPY=$objcopy" >> $config_host_mak echo "LD=$ld" >> $config_host_mak -echo "RANLIB=$ranlib" >> $config_host_mak -echo "NM=$nm" >> $config_host_mak -echo "PKG_CONFIG=$pkg_config_exe" >> $config_host_mak -echo "WINDRES=$windres" >> $config_host_mak echo "CFLAGS_NOPIE=$CFLAGS_NOPIE" >> $config_host_mak echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak echo "QEMU_CXXFLAGS=$QEMU_CXXFLAGS" >> $config_host_mak diff --git a/meson.build b/meson.build index 8b61fdb4be..7e12de01be 100644 --- a/meson.build +++ b/meson.build @@ -2765,7 +2765,6 @@ if targetos == 'windows' summary_info += {'Windows SDK': config_host['WIN_SDK']} endif endif -summary_info += {'ARFLAGS': config_host['ARFLAGS']} summary_info += {'CFLAGS': ' '.join(get_option('c_args') + ['-O' + get_option('optimization')] + (get_option('debug') ? ['-g'] : []))} From cb46938c45144045c1ae278abb05b6a1cf2de445 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Tue, 6 Jul 2021 11:50:15 +0800 Subject: [PATCH 68/76] linux-user/elfload: Implement ELF_HWCAP for RISC-V Set I, M, A, F, D and C bit for hwcap if misa is set. Signed-off-by: Kito Cheng Reviewed-by: Richard Henderson Message-Id: <20210706035015.122899-1-kito.cheng@sifive.com> Signed-off-by: Laurent Vivier --- linux-user/elfload.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 598ab8aa13..42ef2a1148 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1434,6 +1434,19 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, #define ELF_CLASS ELFCLASS64 #endif +#define ELF_HWCAP get_elf_hwcap() + +static uint32_t get_elf_hwcap(void) +{ +#define MISA_BIT(EXT) (1 << (EXT - 'A')) + RISCVCPU *cpu = RISCV_CPU(thread_cpu); + uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A') + | MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C'); + + return cpu->env.misa & mask; +#undef MISA_BIT +} + static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) { From 7aa9fe3a520266cbbe16c249381fe542f9e4c6a4 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Mon, 21 Jun 2021 11:32:59 +0200 Subject: [PATCH 69/76] linux-user: fill ppid field in /proc/self/stat Signed-off-by: Andreas Schwab Reviewed-by: Laurent Vivier Message-Id: Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 64bbf331b2..3bc06d178e 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7956,6 +7956,9 @@ static int open_self_stat(void *cpu_env, int fd) gchar *bin = g_strrstr(ts->bprm->argv[0], "/"); bin = bin ? bin + 1 : ts->bprm->argv[0]; g_string_printf(buf, "(%.15s) ", bin); + } else if (i == 3) { + /* ppid */ + g_string_printf(buf, FMT_pid " ", getppid()); } else if (i == 27) { /* stack bottom */ g_string_printf(buf, TARGET_ABI_FMT_ld " ", ts->info->start_stack); From a46955ff61104d13e5769a47a1b4e0f78dd1c70d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 6 Jul 2021 16:48:58 -0700 Subject: [PATCH 70/76] linux-user: Fix style problems in linuxload.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-Id: <20210706234932.356913-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/linuxload.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c index a27e1d0d8b..9d4eb5e94b 100644 --- a/linux-user/linuxload.c +++ b/linux-user/linuxload.c @@ -1,59 +1,57 @@ /* Code for loading Linux executables. Mostly linux kernel code. */ #include "qemu/osdep.h" - #include "qemu.h" #define NGROUPS 32 /* ??? This should really be somewhere else. */ -abi_long memcpy_to_target(abi_ulong dest, const void *src, - unsigned long len) +abi_long memcpy_to_target(abi_ulong dest, const void *src, unsigned long len) { void *host_ptr; host_ptr = lock_user(VERIFY_WRITE, dest, len, 0); - if (!host_ptr) + if (!host_ptr) { return -TARGET_EFAULT; + } memcpy(host_ptr, src, len); unlock_user(host_ptr, dest, 1); return 0; } -static int count(char ** vec) +static int count(char **vec) { - int i; + int i; - for(i = 0; *vec; i++) { + for (i = 0; *vec; i++) { vec++; } - - return(i); + return i; } static int prepare_binprm(struct linux_binprm *bprm) { - struct stat st; + struct stat st; int mode; int retval; - if(fstat(bprm->fd, &st) < 0) { - return(-errno); + if (fstat(bprm->fd, &st) < 0) { + return -errno; } mode = st.st_mode; - if(!S_ISREG(mode)) { /* Must be regular file */ - return(-EACCES); + if (!S_ISREG(mode)) { /* Must be regular file */ + return -EACCES; } - if(!(mode & 0111)) { /* Must have at least one execute bit set */ - return(-EACCES); + if (!(mode & 0111)) { /* Must have at least one execute bit set */ + return -EACCES; } bprm->e_uid = geteuid(); bprm->e_gid = getegid(); /* Set-uid? */ - if(mode & S_ISUID) { + if (mode & S_ISUID) { bprm->e_uid = st.st_uid; } @@ -125,8 +123,8 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, } int loader_exec(int fdexec, const char *filename, char **argv, char **envp, - struct target_pt_regs * regs, struct image_info *infop, - struct linux_binprm *bprm) + struct target_pt_regs *regs, struct image_info *infop, + struct linux_binprm *bprm) { int retval; @@ -139,7 +137,7 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp, retval = prepare_binprm(bprm); - if(retval>=0) { + if (retval >= 0) { if (bprm->buf[0] == 0x7f && bprm->buf[1] == 'E' && bprm->buf[2] == 'L' @@ -157,11 +155,11 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp, } } - if(retval>=0) { + if (retval >= 0) { /* success. Initialize important registers */ do_init_thread(regs, infop); return retval; } - return(retval); + return retval; } From f5f35cec5a08e3b16bff482e8fe1578f62dd3e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 4 Jul 2021 20:37:44 +0200 Subject: [PATCH 71/76] linux-user/alpha: Handle TARGET_EWOULDBLOCK as TARGET_EAGAIN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux kernel defines EWOULDBLOCK as EAGAIN (since before v2.6.12-rc2). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20210704183755.655002-2-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- linux-user/alpha/target_syscall.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-user/alpha/target_syscall.h b/linux-user/alpha/target_syscall.h index fd389422e3..4e6f936056 100644 --- a/linux-user/alpha/target_syscall.h +++ b/linux-user/alpha/target_syscall.h @@ -44,6 +44,8 @@ struct target_pt_regs { #define UNAME_MACHINE "alpha" #define UNAME_MINIMUM_RELEASE "2.6.32" +#undef TARGET_EWOULDBLOCK +#define TARGET_EWOULDBLOCK TARGET_EAGAIN /* Operation would block */ #undef TARGET_EDEADLK #define TARGET_EDEADLK 11 #undef TARGET_EAGAIN From db10481c00e5787c57523579c2571791a5bffb38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 4 Jul 2021 20:37:45 +0200 Subject: [PATCH 72/76] linux-user/hppa: Handle TARGET_EWOULDBLOCK as TARGET_EAGAIN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux kernel defines EWOULDBLOCK as EAGAIN (since before v2.6.12-rc2). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20210704183755.655002-3-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- linux-user/hppa/target_syscall.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-user/hppa/target_syscall.h b/linux-user/hppa/target_syscall.h index f34e05edb5..97a095656d 100644 --- a/linux-user/hppa/target_syscall.h +++ b/linux-user/hppa/target_syscall.h @@ -27,6 +27,8 @@ struct target_pt_regs { #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 +#undef TARGET_EWOULDBLOCK +#define TARGET_EWOULDBLOCK TARGET_EAGAIN /* Operation would block */ #undef TARGET_ENOMSG #define TARGET_ENOMSG 35 #undef TARGET_EIDRM From bc3359f7395bbc0a50ac1499948a028b885a207c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 4 Jul 2021 20:37:46 +0200 Subject: [PATCH 73/76] linux-user/mips: Handle TARGET_EWOULDBLOCK as TARGET_EAGAIN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux kernel defines EWOULDBLOCK as EAGAIN (since before v2.6.12-rc2). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20210704183755.655002-4-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- linux-user/mips/target_syscall.h | 2 ++ linux-user/mips64/target_syscall.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h index dd6fd7af8e..3e558fdb4b 100644 --- a/linux-user/mips/target_syscall.h +++ b/linux-user/mips/target_syscall.h @@ -21,6 +21,8 @@ struct target_pt_regs { }; /* Target errno definitions taken from asm-mips/errno.h */ +#undef TARGET_EWOULDBLOCK +#define TARGET_EWOULDBLOCK TARGET_EAGAIN /* Operation would block */ #undef TARGET_ENOMSG #define TARGET_ENOMSG 35 /* Identifier removed */ #undef TARGET_EIDRM diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_syscall.h index 8594955eec..c54374c5a2 100644 --- a/linux-user/mips64/target_syscall.h +++ b/linux-user/mips64/target_syscall.h @@ -18,6 +18,8 @@ struct target_pt_regs { }; /* Target errno definitions taken from asm-mips/errno.h */ +#undef TARGET_EWOULDBLOCK +#define TARGET_EWOULDBLOCK TARGET_EAGAIN /* Operation would block */ #undef TARGET_ENOMSG #define TARGET_ENOMSG 35 /* Identifier removed */ #undef TARGET_EIDRM From 04b853935f96bec799c9bd5f1e2e1343213df187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 4 Jul 2021 20:37:49 +0200 Subject: [PATCH 74/76] linux-user/alpha: Remove hardcoded tabs (code style) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are going to move this code, fix its style first. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20210704183755.655002-7-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- linux-user/alpha/target_syscall.h | 196 +++++++++++++++--------------- 1 file changed, 97 insertions(+), 99 deletions(-) diff --git a/linux-user/alpha/target_syscall.h b/linux-user/alpha/target_syscall.h index 4e6f936056..13a71f35ea 100644 --- a/linux-user/alpha/target_syscall.h +++ b/linux-user/alpha/target_syscall.h @@ -47,196 +47,194 @@ struct target_pt_regs { #undef TARGET_EWOULDBLOCK #define TARGET_EWOULDBLOCK TARGET_EAGAIN /* Operation would block */ #undef TARGET_EDEADLK -#define TARGET_EDEADLK 11 +#define TARGET_EDEADLK 11 #undef TARGET_EAGAIN -#define TARGET_EAGAIN 35 +#define TARGET_EAGAIN 35 #undef TARGET_EINPROGRESS -#define TARGET_EINPROGRESS 36 +#define TARGET_EINPROGRESS 36 #undef TARGET_EALREADY -#define TARGET_EALREADY 37 +#define TARGET_EALREADY 37 #undef TARGET_ENOTSOCK -#define TARGET_ENOTSOCK 38 +#define TARGET_ENOTSOCK 38 #undef TARGET_EDESTADDRREQ -#define TARGET_EDESTADDRREQ 39 +#define TARGET_EDESTADDRREQ 39 #undef TARGET_EMSGSIZE -#define TARGET_EMSGSIZE 40 +#define TARGET_EMSGSIZE 40 #undef TARGET_EPROTOTYPE -#define TARGET_EPROTOTYPE 41 +#define TARGET_EPROTOTYPE 41 #undef TARGET_ENOPROTOOPT -#define TARGET_ENOPROTOOPT 42 +#define TARGET_ENOPROTOOPT 42 #undef TARGET_EPROTONOSUPPORT -#define TARGET_EPROTONOSUPPORT 43 +#define TARGET_EPROTONOSUPPORT 43 #undef TARGET_ESOCKTNOSUPPORT -#define TARGET_ESOCKTNOSUPPORT 44 +#define TARGET_ESOCKTNOSUPPORT 44 #undef TARGET_EOPNOTSUPP -#define TARGET_EOPNOTSUPP 45 +#define TARGET_EOPNOTSUPP 45 #undef TARGET_EPFNOSUPPORT -#define TARGET_EPFNOSUPPORT 46 +#define TARGET_EPFNOSUPPORT 46 #undef TARGET_EAFNOSUPPORT -#define TARGET_EAFNOSUPPORT 47 +#define TARGET_EAFNOSUPPORT 47 #undef TARGET_EADDRINUSE -#define TARGET_EADDRINUSE 48 +#define TARGET_EADDRINUSE 48 #undef TARGET_EADDRNOTAVAIL -#define TARGET_EADDRNOTAVAIL 49 +#define TARGET_EADDRNOTAVAIL 49 #undef TARGET_ENETDOWN -#define TARGET_ENETDOWN 50 +#define TARGET_ENETDOWN 50 #undef TARGET_ENETUNREACH -#define TARGET_ENETUNREACH 51 +#define TARGET_ENETUNREACH 51 #undef TARGET_ENETRESET -#define TARGET_ENETRESET 52 +#define TARGET_ENETRESET 52 #undef TARGET_ECONNABORTED -#define TARGET_ECONNABORTED 53 +#define TARGET_ECONNABORTED 53 #undef TARGET_ECONNRESET -#define TARGET_ECONNRESET 54 +#define TARGET_ECONNRESET 54 #undef TARGET_ENOBUFS -#define TARGET_ENOBUFS 55 +#define TARGET_ENOBUFS 55 #undef TARGET_EISCONN -#define TARGET_EISCONN 56 +#define TARGET_EISCONN 56 #undef TARGET_ENOTCONN -#define TARGET_ENOTCONN 57 +#define TARGET_ENOTCONN 57 #undef TARGET_ESHUTDOWN -#define TARGET_ESHUTDOWN 58 +#define TARGET_ESHUTDOWN 58 #undef TARGET_ETOOMANYREFS -#define TARGET_ETOOMANYREFS 59 +#define TARGET_ETOOMANYREFS 59 #undef TARGET_ETIMEDOUT -#define TARGET_ETIMEDOUT 60 +#define TARGET_ETIMEDOUT 60 #undef TARGET_ECONNREFUSED -#define TARGET_ECONNREFUSED 61 +#define TARGET_ECONNREFUSED 61 #undef TARGET_ELOOP -#define TARGET_ELOOP 62 +#define TARGET_ELOOP 62 #undef TARGET_ENAMETOOLONG -#define TARGET_ENAMETOOLONG 63 +#define TARGET_ENAMETOOLONG 63 #undef TARGET_EHOSTDOWN -#define TARGET_EHOSTDOWN 64 +#define TARGET_EHOSTDOWN 64 #undef TARGET_EHOSTUNREACH -#define TARGET_EHOSTUNREACH 65 +#define TARGET_EHOSTUNREACH 65 #undef TARGET_ENOTEMPTY -#define TARGET_ENOTEMPTY 66 -// Unused 67 +#define TARGET_ENOTEMPTY 66 +/* Unused 67 */ #undef TARGET_EUSERS -#define TARGET_EUSERS 68 +#define TARGET_EUSERS 68 #undef TARGET_EDQUOT -#define TARGET_EDQUOT 69 +#define TARGET_EDQUOT 69 #undef TARGET_ESTALE -#define TARGET_ESTALE 70 +#define TARGET_ESTALE 70 #undef TARGET_EREMOTE -#define TARGET_EREMOTE 71 -// Unused 72-76 +#define TARGET_EREMOTE 71 +/* Unused 72-76 */ #undef TARGET_ENOLCK -#define TARGET_ENOLCK 77 +#define TARGET_ENOLCK 77 #undef TARGET_ENOSYS -#define TARGET_ENOSYS 78 -// Unused 79 +#define TARGET_ENOSYS 78 +/* Unused 79 */ #undef TARGET_ENOMSG -#define TARGET_ENOMSG 80 +#define TARGET_ENOMSG 80 #undef TARGET_EIDRM -#define TARGET_EIDRM 81 +#define TARGET_EIDRM 81 #undef TARGET_ENOSR -#define TARGET_ENOSR 82 +#define TARGET_ENOSR 82 #undef TARGET_ETIME -#define TARGET_ETIME 83 +#define TARGET_ETIME 83 #undef TARGET_EBADMSG -#define TARGET_EBADMSG 84 +#define TARGET_EBADMSG 84 #undef TARGET_EPROTO -#define TARGET_EPROTO 85 +#define TARGET_EPROTO 85 #undef TARGET_ENODATA -#define TARGET_ENODATA 86 +#define TARGET_ENODATA 86 #undef TARGET_ENOSTR -#define TARGET_ENOSTR 87 +#define TARGET_ENOSTR 87 #undef TARGET_ECHRNG -#define TARGET_ECHRNG 88 +#define TARGET_ECHRNG 88 #undef TARGET_EL2NSYNC -#define TARGET_EL2NSYNC 89 +#define TARGET_EL2NSYNC 89 #undef TARGET_EL3HLT -#define TARGET_EL3HLT 90 +#define TARGET_EL3HLT 90 #undef TARGET_EL3RST -#define TARGET_EL3RST 91 +#define TARGET_EL3RST 91 #undef TARGET_ENOPKG -#define TARGET_ENOPKG 92 +#define TARGET_ENOPKG 92 #undef TARGET_ELNRNG -#define TARGET_ELNRNG 93 +#define TARGET_ELNRNG 93 #undef TARGET_EUNATCH -#define TARGET_EUNATCH 94 +#define TARGET_EUNATCH 94 #undef TARGET_ENOCSI -#define TARGET_ENOCSI 95 +#define TARGET_ENOCSI 95 #undef TARGET_EL2HLT -#define TARGET_EL2HLT 96 +#define TARGET_EL2HLT 96 #undef TARGET_EBADE -#define TARGET_EBADE 97 +#define TARGET_EBADE 97 #undef TARGET_EBADR -#define TARGET_EBADR 98 +#define TARGET_EBADR 98 #undef TARGET_EXFULL -#define TARGET_EXFULL 99 +#define TARGET_EXFULL 99 #undef TARGET_ENOANO -#define TARGET_ENOANO 100 +#define TARGET_ENOANO 100 #undef TARGET_EBADRQC -#define TARGET_EBADRQC 101 +#define TARGET_EBADRQC 101 #undef TARGET_EBADSLT -#define TARGET_EBADSLT 102 -// Unused 103 +#define TARGET_EBADSLT 102 +/* Unused 103 */ #undef TARGET_EBFONT -#define TARGET_EBFONT 104 +#define TARGET_EBFONT 104 #undef TARGET_ENONET -#define TARGET_ENONET 105 +#define TARGET_ENONET 105 #undef TARGET_ENOLINK -#define TARGET_ENOLINK 106 +#define TARGET_ENOLINK 106 #undef TARGET_EADV -#define TARGET_EADV 107 +#define TARGET_EADV 107 #undef TARGET_ESRMNT -#define TARGET_ESRMNT 108 +#define TARGET_ESRMNT 108 #undef TARGET_ECOMM -#define TARGET_ECOMM 109 +#define TARGET_ECOMM 109 #undef TARGET_EMULTIHOP -#define TARGET_EMULTIHOP 110 +#define TARGET_EMULTIHOP 110 #undef TARGET_EDOTDOT -#define TARGET_EDOTDOT 111 +#define TARGET_EDOTDOT 111 #undef TARGET_EOVERFLOW -#define TARGET_EOVERFLOW 112 +#define TARGET_EOVERFLOW 112 #undef TARGET_ENOTUNIQ -#define TARGET_ENOTUNIQ 113 +#define TARGET_ENOTUNIQ 113 #undef TARGET_EBADFD -#define TARGET_EBADFD 114 +#define TARGET_EBADFD 114 #undef TARGET_EREMCHG -#define TARGET_EREMCHG 115 +#define TARGET_EREMCHG 115 #undef TARGET_EILSEQ -#define TARGET_EILSEQ 116 - -// Same as default 117-121 - +#define TARGET_EILSEQ 116 +/* Same as default 117-121 */ #undef TARGET_ELIBACC -#define TARGET_ELIBACC 122 +#define TARGET_ELIBACC 122 #undef TARGET_ELIBBAD -#define TARGET_ELIBBAD 123 +#define TARGET_ELIBBAD 123 #undef TARGET_ELIBSCN -#define TARGET_ELIBSCN 124 +#define TARGET_ELIBSCN 124 #undef TARGET_ELIBMAX -#define TARGET_ELIBMAX 125 +#define TARGET_ELIBMAX 125 #undef TARGET_ELIBEXEC -#define TARGET_ELIBEXEC 126 +#define TARGET_ELIBEXEC 126 #undef TARGET_ERESTART -#define TARGET_ERESTART 127 +#define TARGET_ERESTART 127 #undef TARGET_ESTRPIPE -#define TARGET_ESTRPIPE 128 +#define TARGET_ESTRPIPE 128 #undef TARGET_ENOMEDIUM -#define TARGET_ENOMEDIUM 129 +#define TARGET_ENOMEDIUM 129 #undef TARGET_EMEDIUMTYPE -#define TARGET_EMEDIUMTYPE 130 +#define TARGET_EMEDIUMTYPE 130 #undef TARGET_ECANCELED -#define TARGET_ECANCELED 131 +#define TARGET_ECANCELED 131 #undef TARGET_ENOKEY -#define TARGET_ENOKEY 132 +#define TARGET_ENOKEY 132 #undef TARGET_EKEYEXPIRED -#define TARGET_EKEYEXPIRED 133 +#define TARGET_EKEYEXPIRED 133 #undef TARGET_EKEYREVOKED -#define TARGET_EKEYREVOKED 134 +#define TARGET_EKEYREVOKED 134 #undef TARGET_EKEYREJECTED -#define TARGET_EKEYREJECTED 135 +#define TARGET_EKEYREJECTED 135 #undef TARGET_EOWNERDEAD -#define TARGET_EOWNERDEAD 136 +#define TARGET_EOWNERDEAD 136 #undef TARGET_ENOTRECOVERABLE -#define TARGET_ENOTRECOVERABLE 137 +#define TARGET_ENOTRECOVERABLE 137 #undef TARGET_ERFKILL -#define TARGET_ERFKILL 138 +#define TARGET_ERFKILL 138 #undef TARGET_EHWPOISON #define TARGET_EHWPOISON 139 From c632ea1dd90313bc360b9de9d5014c2167f4d038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 4 Jul 2021 20:37:54 +0200 Subject: [PATCH 75/76] linux-user/syscall: Remove hardcoded tabs (code style) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are going to move this code, fix its style first. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20210704183755.655002-12-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 188 +++++++++++++++++++++---------------------- 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3bc06d178e..2e826206d2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -519,112 +519,112 @@ static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = { * minus the errnos that are not actually generic to all archs. */ static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = { - [EAGAIN] = TARGET_EAGAIN, - [EIDRM] = TARGET_EIDRM, - [ECHRNG] = TARGET_ECHRNG, - [EL2NSYNC] = TARGET_EL2NSYNC, - [EL3HLT] = TARGET_EL3HLT, - [EL3RST] = TARGET_EL3RST, - [ELNRNG] = TARGET_ELNRNG, - [EUNATCH] = TARGET_EUNATCH, - [ENOCSI] = TARGET_ENOCSI, - [EL2HLT] = TARGET_EL2HLT, - [EDEADLK] = TARGET_EDEADLK, - [ENOLCK] = TARGET_ENOLCK, - [EBADE] = TARGET_EBADE, - [EBADR] = TARGET_EBADR, - [EXFULL] = TARGET_EXFULL, - [ENOANO] = TARGET_ENOANO, - [EBADRQC] = TARGET_EBADRQC, - [EBADSLT] = TARGET_EBADSLT, - [EBFONT] = TARGET_EBFONT, - [ENOSTR] = TARGET_ENOSTR, - [ENODATA] = TARGET_ENODATA, - [ETIME] = TARGET_ETIME, - [ENOSR] = TARGET_ENOSR, - [ENONET] = TARGET_ENONET, - [ENOPKG] = TARGET_ENOPKG, - [EREMOTE] = TARGET_EREMOTE, - [ENOLINK] = TARGET_ENOLINK, - [EADV] = TARGET_EADV, - [ESRMNT] = TARGET_ESRMNT, - [ECOMM] = TARGET_ECOMM, - [EPROTO] = TARGET_EPROTO, - [EDOTDOT] = TARGET_EDOTDOT, - [EMULTIHOP] = TARGET_EMULTIHOP, - [EBADMSG] = TARGET_EBADMSG, - [ENAMETOOLONG] = TARGET_ENAMETOOLONG, - [EOVERFLOW] = TARGET_EOVERFLOW, - [ENOTUNIQ] = TARGET_ENOTUNIQ, - [EBADFD] = TARGET_EBADFD, - [EREMCHG] = TARGET_EREMCHG, - [ELIBACC] = TARGET_ELIBACC, - [ELIBBAD] = TARGET_ELIBBAD, - [ELIBSCN] = TARGET_ELIBSCN, - [ELIBMAX] = TARGET_ELIBMAX, - [ELIBEXEC] = TARGET_ELIBEXEC, - [EILSEQ] = TARGET_EILSEQ, - [ENOSYS] = TARGET_ENOSYS, - [ELOOP] = TARGET_ELOOP, - [ERESTART] = TARGET_ERESTART, - [ESTRPIPE] = TARGET_ESTRPIPE, - [ENOTEMPTY] = TARGET_ENOTEMPTY, - [EUSERS] = TARGET_EUSERS, - [ENOTSOCK] = TARGET_ENOTSOCK, - [EDESTADDRREQ] = TARGET_EDESTADDRREQ, - [EMSGSIZE] = TARGET_EMSGSIZE, - [EPROTOTYPE] = TARGET_EPROTOTYPE, - [ENOPROTOOPT] = TARGET_ENOPROTOOPT, - [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT, - [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT, - [EOPNOTSUPP] = TARGET_EOPNOTSUPP, - [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT, - [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT, - [EADDRINUSE] = TARGET_EADDRINUSE, - [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL, - [ENETDOWN] = TARGET_ENETDOWN, - [ENETUNREACH] = TARGET_ENETUNREACH, - [ENETRESET] = TARGET_ENETRESET, - [ECONNABORTED] = TARGET_ECONNABORTED, - [ECONNRESET] = TARGET_ECONNRESET, - [ENOBUFS] = TARGET_ENOBUFS, - [EISCONN] = TARGET_EISCONN, - [ENOTCONN] = TARGET_ENOTCONN, - [EUCLEAN] = TARGET_EUCLEAN, - [ENOTNAM] = TARGET_ENOTNAM, - [ENAVAIL] = TARGET_ENAVAIL, - [EISNAM] = TARGET_EISNAM, - [EREMOTEIO] = TARGET_EREMOTEIO, + [EAGAIN] = TARGET_EAGAIN, + [EIDRM] = TARGET_EIDRM, + [ECHRNG] = TARGET_ECHRNG, + [EL2NSYNC] = TARGET_EL2NSYNC, + [EL3HLT] = TARGET_EL3HLT, + [EL3RST] = TARGET_EL3RST, + [ELNRNG] = TARGET_ELNRNG, + [EUNATCH] = TARGET_EUNATCH, + [ENOCSI] = TARGET_ENOCSI, + [EL2HLT] = TARGET_EL2HLT, + [EDEADLK] = TARGET_EDEADLK, + [ENOLCK] = TARGET_ENOLCK, + [EBADE] = TARGET_EBADE, + [EBADR] = TARGET_EBADR, + [EXFULL] = TARGET_EXFULL, + [ENOANO] = TARGET_ENOANO, + [EBADRQC] = TARGET_EBADRQC, + [EBADSLT] = TARGET_EBADSLT, + [EBFONT] = TARGET_EBFONT, + [ENOSTR] = TARGET_ENOSTR, + [ENODATA] = TARGET_ENODATA, + [ETIME] = TARGET_ETIME, + [ENOSR] = TARGET_ENOSR, + [ENONET] = TARGET_ENONET, + [ENOPKG] = TARGET_ENOPKG, + [EREMOTE] = TARGET_EREMOTE, + [ENOLINK] = TARGET_ENOLINK, + [EADV] = TARGET_EADV, + [ESRMNT] = TARGET_ESRMNT, + [ECOMM] = TARGET_ECOMM, + [EPROTO] = TARGET_EPROTO, + [EDOTDOT] = TARGET_EDOTDOT, + [EMULTIHOP] = TARGET_EMULTIHOP, + [EBADMSG] = TARGET_EBADMSG, + [ENAMETOOLONG] = TARGET_ENAMETOOLONG, + [EOVERFLOW] = TARGET_EOVERFLOW, + [ENOTUNIQ] = TARGET_ENOTUNIQ, + [EBADFD] = TARGET_EBADFD, + [EREMCHG] = TARGET_EREMCHG, + [ELIBACC] = TARGET_ELIBACC, + [ELIBBAD] = TARGET_ELIBBAD, + [ELIBSCN] = TARGET_ELIBSCN, + [ELIBMAX] = TARGET_ELIBMAX, + [ELIBEXEC] = TARGET_ELIBEXEC, + [EILSEQ] = TARGET_EILSEQ, + [ENOSYS] = TARGET_ENOSYS, + [ELOOP] = TARGET_ELOOP, + [ERESTART] = TARGET_ERESTART, + [ESTRPIPE] = TARGET_ESTRPIPE, + [ENOTEMPTY] = TARGET_ENOTEMPTY, + [EUSERS] = TARGET_EUSERS, + [ENOTSOCK] = TARGET_ENOTSOCK, + [EDESTADDRREQ] = TARGET_EDESTADDRREQ, + [EMSGSIZE] = TARGET_EMSGSIZE, + [EPROTOTYPE] = TARGET_EPROTOTYPE, + [ENOPROTOOPT] = TARGET_ENOPROTOOPT, + [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT, + [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT, + [EOPNOTSUPP] = TARGET_EOPNOTSUPP, + [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT, + [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT, + [EADDRINUSE] = TARGET_EADDRINUSE, + [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL, + [ENETDOWN] = TARGET_ENETDOWN, + [ENETUNREACH] = TARGET_ENETUNREACH, + [ENETRESET] = TARGET_ENETRESET, + [ECONNABORTED] = TARGET_ECONNABORTED, + [ECONNRESET] = TARGET_ECONNRESET, + [ENOBUFS] = TARGET_ENOBUFS, + [EISCONN] = TARGET_EISCONN, + [ENOTCONN] = TARGET_ENOTCONN, + [EUCLEAN] = TARGET_EUCLEAN, + [ENOTNAM] = TARGET_ENOTNAM, + [ENAVAIL] = TARGET_ENAVAIL, + [EISNAM] = TARGET_EISNAM, + [EREMOTEIO] = TARGET_EREMOTEIO, [EDQUOT] = TARGET_EDQUOT, - [ESHUTDOWN] = TARGET_ESHUTDOWN, - [ETOOMANYREFS] = TARGET_ETOOMANYREFS, - [ETIMEDOUT] = TARGET_ETIMEDOUT, - [ECONNREFUSED] = TARGET_ECONNREFUSED, - [EHOSTDOWN] = TARGET_EHOSTDOWN, - [EHOSTUNREACH] = TARGET_EHOSTUNREACH, - [EALREADY] = TARGET_EALREADY, - [EINPROGRESS] = TARGET_EINPROGRESS, - [ESTALE] = TARGET_ESTALE, - [ECANCELED] = TARGET_ECANCELED, - [ENOMEDIUM] = TARGET_ENOMEDIUM, - [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE, + [ESHUTDOWN] = TARGET_ESHUTDOWN, + [ETOOMANYREFS] = TARGET_ETOOMANYREFS, + [ETIMEDOUT] = TARGET_ETIMEDOUT, + [ECONNREFUSED] = TARGET_ECONNREFUSED, + [EHOSTDOWN] = TARGET_EHOSTDOWN, + [EHOSTUNREACH] = TARGET_EHOSTUNREACH, + [EALREADY] = TARGET_EALREADY, + [EINPROGRESS] = TARGET_EINPROGRESS, + [ESTALE] = TARGET_ESTALE, + [ECANCELED] = TARGET_ECANCELED, + [ENOMEDIUM] = TARGET_ENOMEDIUM, + [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE, #ifdef ENOKEY - [ENOKEY] = TARGET_ENOKEY, + [ENOKEY] = TARGET_ENOKEY, #endif #ifdef EKEYEXPIRED - [EKEYEXPIRED] = TARGET_EKEYEXPIRED, + [EKEYEXPIRED] = TARGET_EKEYEXPIRED, #endif #ifdef EKEYREVOKED - [EKEYREVOKED] = TARGET_EKEYREVOKED, + [EKEYREVOKED] = TARGET_EKEYREVOKED, #endif #ifdef EKEYREJECTED - [EKEYREJECTED] = TARGET_EKEYREJECTED, + [EKEYREJECTED] = TARGET_EKEYREJECTED, #endif #ifdef EOWNERDEAD - [EOWNERDEAD] = TARGET_EOWNERDEAD, + [EOWNERDEAD] = TARGET_EOWNERDEAD, #endif #ifdef ENOTRECOVERABLE - [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE, + [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE, #endif #ifdef ENOMSG [ENOMSG] = TARGET_ENOMSG, From eba61056e4cca7cb187f3795ef19679d9f333428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 6 Jul 2021 15:57:43 +0100 Subject: [PATCH 76/76] tests/tcg: generalise the disabling of the signals test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It turns out you push down in one place and failures pop-up elsewhere. Especially on CI. Disable for now for all targets. Signed-off-by: Alex Bennée Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- tests/tcg/hppa/Makefile.target | 3 --- tests/tcg/multiarch/Makefile.target | 6 ++++++ tests/tcg/s390x/Makefile.target | 3 --- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/tcg/hppa/Makefile.target b/tests/tcg/hppa/Makefile.target index 71791235f6..473864d1d4 100644 --- a/tests/tcg/hppa/Makefile.target +++ b/tests/tcg/hppa/Makefile.target @@ -5,6 +5,3 @@ # On parisc Linux supports 4K/16K/64K (but currently only 4k works) EXTRA_RUNS+=run-test-mmap-4096 # run-test-mmap-16384 run-test-mmap-65536 -# There is a race that causes this to fail about 1% of the time -run-signals: signals - $(call skip-test, $<, "BROKEN awaiting vdso support") diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index 3f283eabe6..d57a115873 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -32,6 +32,12 @@ threadcount: LDFLAGS+=-lpthread signals: LDFLAGS+=-lrt -lpthread +# This triggers failures on s390x hosts about 4% of the time +# This triggers failures for hppa-linux about 1% of the time +run-signals: signals + $(call skip-test, $<, "BROKEN awaiting sigframe clean-ups and vdso support") + + # We define the runner for test-mmap after the individual # architectures have defined their supported pages sizes. If no # additional page sizes are defined we only run the default test. diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 0036b8a505..5d3de1b27a 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -9,6 +9,3 @@ TESTS+=pack TESTS+=mvo TESTS+=mvc -# This triggers failures on s390x hosts about 4% of the time -run-signals: signals - $(call skip-test, $<, "BROKEN awaiting sigframe clean-ups")