diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/meson.build | 2 | ||||
-rw-r--r-- | util/module.c | 200 | ||||
-rw-r--r-- | util/trace-events | 4 |
3 files changed, 118 insertions, 88 deletions
diff --git a/util/meson.build b/util/meson.build index 0ffd7f4..779f413 100644 --- a/util/meson.build +++ b/util/meson.build @@ -5,7 +5,7 @@ util_ss.add(when: 'CONFIG_POSIX', if_true: files('fdmon-poll.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: 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')) util_ss.add(when: 'CONFIG_POSIX', if_true: files('mmap-alloc.c')) diff --git a/util/module.c b/util/module.c index eee8ff2..6bb4ad9 100644 --- a/util/module.c +++ b/util/module.c @@ -20,9 +20,11 @@ #include "qemu/queue.h" #include "qemu/module.h" #include "qemu/cutils.h" +#include "qemu/config-file.h" #ifdef CONFIG_MODULE_UPGRADES #include "qemu-version.h" #endif +#include "trace.h" typedef struct ModuleEntry { @@ -110,6 +112,38 @@ void module_call_init(module_init_type type) } #ifdef CONFIG_MODULES + +static const QemuModinfo module_info_stub[] = { { + /* end of list */ +} }; +static const QemuModinfo *module_info = module_info_stub; +static const char *module_arch; + +void module_init_info(const QemuModinfo *info) +{ + module_info = info; +} + +void module_allow_arch(const char *arch) +{ + module_arch = arch; +} + +static bool module_check_arch(const QemuModinfo *modinfo) +{ + if (modinfo->arch) { + if (!module_arch) { + /* no arch set -> ignore all */ + return false; + } + if (strcmp(module_arch, modinfo->arch) != 0) { + /* mismatch */ + return false; + } + } + return true; +} + static int module_load_file(const char *fname, bool mayfail, bool export_symbols) { GModule *g_module; @@ -164,6 +198,7 @@ static int module_load_file(const char *fname, bool mayfail, bool export_symbols ret = 0; } + trace_module_load_module(fname); QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) { QTAILQ_REMOVE(&dso_init_list, e, node); g_free(e); @@ -171,28 +206,6 @@ static int module_load_file(const char *fname, bool mayfail, bool export_symbols out: return ret; } - -static const struct { - const char *name; - const char *dep; -} module_deps[] = { - { "audio-spice", "ui-spice-core" }, - { "chardev-spice", "ui-spice-core" }, - { "hw-display-qxl", "ui-spice-core" }, - { "ui-spice-app", "ui-spice-core" }, - { "ui-spice-app", "chardev-spice" }, - - { "hw-display-virtio-gpu-gl", "hw-display-virtio-gpu" }, - { "hw-display-virtio-gpu-pci-gl", "hw-display-virtio-gpu-pci" }, - { "hw-display-virtio-vga-gl", "hw-display-virtio-vga" }, - -#ifdef CONFIG_OPENGL - { "ui-egl-headless", "ui-opengl" }, - { "ui-gtk", "ui-opengl" }, - { "ui-sdl", "ui-opengl" }, - { "ui-spice-core", "ui-opengl" }, -#endif -}; #endif bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) @@ -208,9 +221,11 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) char *dirs[5]; char *module_name; int i = 0, n_dirs = 0; - int ret, dep; + int ret; bool export_symbols = false; static GHashTable *loaded_modules; + const QemuModinfo *modinfo; + const char **sl; if (!g_module_supported()) { fprintf(stderr, "Module is not supported by system.\n"); @@ -223,23 +238,37 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) module_name = g_strdup_printf("%s%s", prefix, lib_name); - for (dep = 0; dep < ARRAY_SIZE(module_deps); dep++) { - if (strcmp(module_name, module_deps[dep].name) == 0) { - /* we depend on another module */ - module_load_one("", module_deps[dep].dep, false); - } - if (strcmp(module_name, module_deps[dep].dep) == 0) { - /* another module depends on us */ - export_symbols = true; - } - } - if (g_hash_table_contains(loaded_modules, module_name)) { g_free(module_name); return true; } g_hash_table_add(loaded_modules, module_name); + for (modinfo = module_info; modinfo->name != NULL; modinfo++) { + if (modinfo->arch) { + if (strcmp(modinfo->name, module_name) == 0) { + if (!module_check_arch(modinfo)) { + return false; + } + } + } + if (modinfo->deps) { + if (strcmp(modinfo->name, module_name) == 0) { + /* we depend on other module(s) */ + for (sl = modinfo->deps; *sl != NULL; sl++) { + module_load_one("", *sl, false); + } + } else { + for (sl = modinfo->deps; *sl != NULL; sl++) { + if (strcmp(module_name, *sl) == 0) { + /* another module depends on us */ + export_symbols = true; + } + } + } + } + } + search_dir = getenv("QEMU_MODULE_DIR"); if (search_dir != NULL) { dirs[n_dirs++] = g_strdup_printf("%s", search_dir); @@ -282,80 +311,77 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) return success; } -/* - * Building devices and other qom objects modular is mostly useful in - * case they have dependencies to external shared libraries, so we can - * cut down the core qemu library dependencies. Which is the case for - * only a very few devices & objects. - * - * So with the expectation that this will be rather the exception than - * the rule and the list will not gain that many entries, go with a - * simple manually maintained list for now. - * - * The list must be sorted by module (module_load_qom_all() needs this). - */ -static struct { - const char *type; - const char *prefix; - const char *module; -} const qom_modules[] = { - { "ccid-card-passthru", "hw-", "usb-smartcard" }, - { "ccid-card-emulated", "hw-", "usb-smartcard" }, - { "usb-redir", "hw-", "usb-redirect" }, - { "qxl-vga", "hw-", "display-qxl" }, - { "qxl", "hw-", "display-qxl" }, - { "virtio-gpu-device", "hw-", "display-virtio-gpu" }, - { "virtio-gpu-gl-device", "hw-", "display-virtio-gpu-gl" }, - { "vhost-user-gpu", "hw-", "display-virtio-gpu" }, - { "virtio-gpu-pci-base", "hw-", "display-virtio-gpu-pci" }, - { "virtio-gpu-pci", "hw-", "display-virtio-gpu-pci" }, - { "virtio-gpu-gl-pci", "hw-", "display-virtio-gpu-pci-gl" }, - { "vhost-user-gpu-pci", "hw-", "display-virtio-gpu-pci" }, - { "virtio-gpu-ccw", "hw-", "s390x-virtio-gpu-ccw" }, - { "virtio-vga-base", "hw-", "display-virtio-vga" }, - { "virtio-vga", "hw-", "display-virtio-vga" }, - { "virtio-vga-gl", "hw-", "display-virtio-vga-gl" }, - { "vhost-user-vga", "hw-", "display-virtio-vga" }, - { "chardev-braille", "chardev-", "baum" }, - { "chardev-spicevmc", "chardev-", "spice" }, - { "chardev-spiceport", "chardev-", "spice" }, -}; +#ifdef CONFIG_MODULES static bool module_loaded_qom_all; void module_load_qom_one(const char *type) { - int i; + const QemuModinfo *modinfo; + const char **sl; if (!type) { return; } - for (i = 0; i < ARRAY_SIZE(qom_modules); i++) { - if (strcmp(qom_modules[i].type, type) == 0) { - module_load_one(qom_modules[i].prefix, - qom_modules[i].module, - false); - return; + + trace_module_lookup_object_type(type); + for (modinfo = module_info; modinfo->name != NULL; modinfo++) { + if (!modinfo->objs) { + continue; + } + if (!module_check_arch(modinfo)) { + continue; + } + for (sl = modinfo->objs; *sl != NULL; sl++) { + if (strcmp(type, *sl) == 0) { + module_load_one("", modinfo->name, false); + } } } } void module_load_qom_all(void) { - int i; + const QemuModinfo *modinfo; if (module_loaded_qom_all) { return; } - for (i = 0; i < ARRAY_SIZE(qom_modules); i++) { - if (i > 0 && (strcmp(qom_modules[i - 1].module, - qom_modules[i].module) == 0 && - strcmp(qom_modules[i - 1].prefix, - qom_modules[i].prefix) == 0)) { - /* one module implementing multiple types -> load only once */ + + for (modinfo = module_info; modinfo->name != NULL; modinfo++) { + if (!modinfo->objs) { + continue; + } + if (!module_check_arch(modinfo)) { continue; } - module_load_one(qom_modules[i].prefix, qom_modules[i].module, true); + module_load_one("", modinfo->name, false); } module_loaded_qom_all = true; } + +void qemu_load_module_for_opts(const char *group) +{ + const QemuModinfo *modinfo; + const char **sl; + + for (modinfo = module_info; modinfo->name != NULL; modinfo++) { + if (!modinfo->opts) { + continue; + } + for (sl = modinfo->opts; *sl != NULL; sl++) { + if (strcmp(group, *sl) == 0) { + module_load_one("", modinfo->name, false); + } + } + } +} + +#else + +void module_allow_arch(const char *arch) {} +void qemu_load_module_for_opts(const char *group) {} +void module_load_qom_one(const char *type) {} +void module_load_qom_all(void) {} + +#endif diff --git a/util/trace-events b/util/trace-events index 806cac1..c8f53d7 100644 --- a/util/trace-events +++ b/util/trace-events @@ -100,3 +100,7 @@ uffd_create_fd_api_failed(int err) "errno: %i" uffd_create_fd_api_noioctl(uint64_t ioctl_req, uint64_t ioctl_supp) "ioctl_req: 0x%" PRIx64 "ioctl_supp: 0x%" PRIx64 uffd_register_memory_failed(void *addr, uint64_t length, uint64_t mode, int err) "addr: %p length: %" PRIu64 " mode: 0x%" PRIx64 " errno: %i" uffd_unregister_memory_failed(void *addr, uint64_t length, int err) "addr: %p length: %" PRIu64 " errno: %i" + +# module.c +module_load_module(const char *name) "file %s" +module_lookup_object_type(const char *name) "name %s" |