1baacf047SPaolo Bonzini /*
2baacf047SPaolo Bonzini * QEMU Module Infrastructure
3baacf047SPaolo Bonzini *
4baacf047SPaolo Bonzini * Copyright IBM, Corp. 2009
5baacf047SPaolo Bonzini *
6baacf047SPaolo Bonzini * Authors:
7baacf047SPaolo Bonzini * Anthony Liguori <aliguori@us.ibm.com>
8baacf047SPaolo Bonzini *
9baacf047SPaolo Bonzini * This work is licensed under the terms of the GNU GPL, version 2. See
10baacf047SPaolo Bonzini * the COPYING file in the top-level directory.
11baacf047SPaolo Bonzini *
12baacf047SPaolo Bonzini * Contributions after 2012-01-13 are licensed under the terms of the
13baacf047SPaolo Bonzini * GNU GPL, version 2 or (at your option) any later version.
14baacf047SPaolo Bonzini */
15baacf047SPaolo Bonzini
16aafd7584SPeter Maydell #include "qemu/osdep.h"
17aa0d1f44SPaolo Bonzini #ifdef CONFIG_MODULES
18e26110cfSFam Zheng #include <gmodule.h>
19aa0d1f44SPaolo Bonzini #endif
20baacf047SPaolo Bonzini #include "qemu/queue.h"
21baacf047SPaolo Bonzini #include "qemu/module.h"
221b934064SPaolo Bonzini #include "qemu/cutils.h"
235111edafSGerd Hoffmann #include "qemu/config-file.h"
24c551fb0bSClaudio Fontana #include "qapi/error.h"
25bd83c861SChristian Ehrhardt #ifdef CONFIG_MODULE_UPGRADES
26bd83c861SChristian Ehrhardt #include "qemu-version.h"
27bd83c861SChristian Ehrhardt #endif
28819b8b13SGerd Hoffmann #include "trace.h"
29baacf047SPaolo Bonzini
30baacf047SPaolo Bonzini typedef struct ModuleEntry
31baacf047SPaolo Bonzini {
32baacf047SPaolo Bonzini void (*init)(void);
33baacf047SPaolo Bonzini QTAILQ_ENTRY(ModuleEntry) node;
34e26110cfSFam Zheng module_init_type type;
35baacf047SPaolo Bonzini } ModuleEntry;
36baacf047SPaolo Bonzini
37baacf047SPaolo Bonzini typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
38baacf047SPaolo Bonzini
39baacf047SPaolo Bonzini static ModuleTypeList init_type_list[MODULE_INIT_MAX];
4046a07579SAlexander Bulekov static bool modules_init_done[MODULE_INIT_MAX];
41baacf047SPaolo Bonzini
42e26110cfSFam Zheng static ModuleTypeList dso_init_list;
43e26110cfSFam Zheng
init_lists(void)44e26110cfSFam Zheng static void init_lists(void)
45baacf047SPaolo Bonzini {
46baacf047SPaolo Bonzini static int inited;
47baacf047SPaolo Bonzini int i;
48baacf047SPaolo Bonzini
49baacf047SPaolo Bonzini if (inited) {
50baacf047SPaolo Bonzini return;
51baacf047SPaolo Bonzini }
52baacf047SPaolo Bonzini
53baacf047SPaolo Bonzini for (i = 0; i < MODULE_INIT_MAX; i++) {
54baacf047SPaolo Bonzini QTAILQ_INIT(&init_type_list[i]);
55baacf047SPaolo Bonzini }
56baacf047SPaolo Bonzini
57e26110cfSFam Zheng QTAILQ_INIT(&dso_init_list);
58e26110cfSFam Zheng
59baacf047SPaolo Bonzini inited = 1;
60baacf047SPaolo Bonzini }
61baacf047SPaolo Bonzini
62baacf047SPaolo Bonzini
find_type(module_init_type type)63baacf047SPaolo Bonzini static ModuleTypeList *find_type(module_init_type type)
64baacf047SPaolo Bonzini {
65e26110cfSFam Zheng init_lists();
66baacf047SPaolo Bonzini
679be38598SEduardo Habkost return &init_type_list[type];
68baacf047SPaolo Bonzini }
69baacf047SPaolo Bonzini
register_module_init(void (* fn)(void),module_init_type type)70baacf047SPaolo Bonzini void register_module_init(void (*fn)(void), module_init_type type)
71baacf047SPaolo Bonzini {
72baacf047SPaolo Bonzini ModuleEntry *e;
73baacf047SPaolo Bonzini ModuleTypeList *l;
74baacf047SPaolo Bonzini
75baacf047SPaolo Bonzini e = g_malloc0(sizeof(*e));
76baacf047SPaolo Bonzini e->init = fn;
77e26110cfSFam Zheng e->type = type;
78baacf047SPaolo Bonzini
79baacf047SPaolo Bonzini l = find_type(type);
80baacf047SPaolo Bonzini
81baacf047SPaolo Bonzini QTAILQ_INSERT_TAIL(l, e, node);
82baacf047SPaolo Bonzini }
83baacf047SPaolo Bonzini
register_dso_module_init(void (* fn)(void),module_init_type type)84e26110cfSFam Zheng void register_dso_module_init(void (*fn)(void), module_init_type type)
85e26110cfSFam Zheng {
86e26110cfSFam Zheng ModuleEntry *e;
87e26110cfSFam Zheng
88e26110cfSFam Zheng init_lists();
89e26110cfSFam Zheng
90e26110cfSFam Zheng e = g_malloc0(sizeof(*e));
91e26110cfSFam Zheng e->init = fn;
92e26110cfSFam Zheng e->type = type;
93e26110cfSFam Zheng
94e26110cfSFam Zheng QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
95e26110cfSFam Zheng }
96e26110cfSFam Zheng
module_call_init(module_init_type type)97baacf047SPaolo Bonzini void module_call_init(module_init_type type)
98baacf047SPaolo Bonzini {
99baacf047SPaolo Bonzini ModuleTypeList *l;
100baacf047SPaolo Bonzini ModuleEntry *e;
101baacf047SPaolo Bonzini
10246a07579SAlexander Bulekov if (modules_init_done[type]) {
10346a07579SAlexander Bulekov return;
10446a07579SAlexander Bulekov }
10546a07579SAlexander Bulekov
106baacf047SPaolo Bonzini l = find_type(type);
107baacf047SPaolo Bonzini
108baacf047SPaolo Bonzini QTAILQ_FOREACH(e, l, node) {
109baacf047SPaolo Bonzini e->init();
110baacf047SPaolo Bonzini }
11146a07579SAlexander Bulekov
11246a07579SAlexander Bulekov modules_init_done[type] = true;
113baacf047SPaolo Bonzini }
114e26110cfSFam Zheng
115e26110cfSFam Zheng #ifdef CONFIG_MODULES
1165ebbfeccSGerd Hoffmann
1175ebbfeccSGerd Hoffmann static const QemuModinfo module_info_stub[] = { {
1185ebbfeccSGerd Hoffmann /* end of list */
1195ebbfeccSGerd Hoffmann } };
1205ebbfeccSGerd Hoffmann static const QemuModinfo *module_info = module_info_stub;
121d7795d3cSGerd Hoffmann static const char *module_arch;
1225ebbfeccSGerd Hoffmann
module_init_info(const QemuModinfo * info)1235ebbfeccSGerd Hoffmann void module_init_info(const QemuModinfo *info)
1245ebbfeccSGerd Hoffmann {
1255ebbfeccSGerd Hoffmann module_info = info;
1265ebbfeccSGerd Hoffmann }
1275ebbfeccSGerd Hoffmann
module_allow_arch(const char * arch)128d7795d3cSGerd Hoffmann void module_allow_arch(const char *arch)
129d7795d3cSGerd Hoffmann {
130d7795d3cSGerd Hoffmann module_arch = arch;
131d7795d3cSGerd Hoffmann }
132d7795d3cSGerd Hoffmann
module_check_arch(const QemuModinfo * modinfo)133d7795d3cSGerd Hoffmann static bool module_check_arch(const QemuModinfo *modinfo)
134d7795d3cSGerd Hoffmann {
135d7795d3cSGerd Hoffmann if (modinfo->arch) {
136d7795d3cSGerd Hoffmann if (!module_arch) {
137d7795d3cSGerd Hoffmann /* no arch set -> ignore all */
138d7795d3cSGerd Hoffmann return false;
139d7795d3cSGerd Hoffmann }
140d7795d3cSGerd Hoffmann if (strcmp(module_arch, modinfo->arch) != 0) {
141d7795d3cSGerd Hoffmann /* mismatch */
142d7795d3cSGerd Hoffmann return false;
143d7795d3cSGerd Hoffmann }
144d7795d3cSGerd Hoffmann }
145d7795d3cSGerd Hoffmann return true;
146d7795d3cSGerd Hoffmann }
147d7795d3cSGerd Hoffmann
148c551fb0bSClaudio Fontana /*
149c551fb0bSClaudio Fontana * module_load_dso: attempt to load an existing dso file
150c551fb0bSClaudio Fontana *
151c551fb0bSClaudio Fontana * fname: full pathname of the file to load
152c551fb0bSClaudio Fontana * export_symbols: if true, add the symbols to the global name space
153c551fb0bSClaudio Fontana * errp: error to set.
154c551fb0bSClaudio Fontana *
155c551fb0bSClaudio Fontana * Return value: true on success, false on error, and errp will be set.
156c551fb0bSClaudio Fontana */
module_load_dso(const char * fname,bool export_symbols,Error ** errp)157c551fb0bSClaudio Fontana static bool module_load_dso(const char *fname, bool export_symbols,
158c551fb0bSClaudio Fontana Error **errp)
159e26110cfSFam Zheng {
160e26110cfSFam Zheng GModule *g_module;
161e26110cfSFam Zheng void (*sym)(void);
162e26110cfSFam Zheng ModuleEntry *e, *next;
163c551fb0bSClaudio Fontana int flags;
164e26110cfSFam Zheng
165e26110cfSFam Zheng assert(QTAILQ_EMPTY(&dso_init_list));
166e26110cfSFam Zheng
167546323bdSGerd Hoffmann flags = 0;
1686f13fa7aSGerd Hoffmann if (!export_symbols) {
1696f13fa7aSGerd Hoffmann flags |= G_MODULE_BIND_LOCAL;
1706f13fa7aSGerd Hoffmann }
1716f13fa7aSGerd Hoffmann g_module = g_module_open(fname, flags);
172e26110cfSFam Zheng if (!g_module) {
173c551fb0bSClaudio Fontana error_setg(errp, "failed to open module: %s", g_module_error());
174c551fb0bSClaudio Fontana return false;
175e26110cfSFam Zheng }
176e26110cfSFam Zheng if (!g_module_symbol(g_module, DSO_STAMP_FUN_STR, (gpointer *)&sym)) {
177c551fb0bSClaudio Fontana error_setg(errp, "failed to initialize module: %s", fname);
178c551fb0bSClaudio Fontana /*
179c551fb0bSClaudio Fontana * Print some info if this is a QEMU module (but from different build),
180c551fb0bSClaudio Fontana * this will make debugging user problems easier.
181c551fb0bSClaudio Fontana */
182e26110cfSFam Zheng if (g_module_symbol(g_module, "qemu_module_dummy", (gpointer *)&sym)) {
183c551fb0bSClaudio Fontana error_append_hint(errp,
184c551fb0bSClaudio Fontana "Only modules from the same build can be loaded.\n");
185e26110cfSFam Zheng }
186e26110cfSFam Zheng g_module_close(g_module);
187c551fb0bSClaudio Fontana return false;
188c551fb0bSClaudio Fontana }
189c551fb0bSClaudio Fontana
190e26110cfSFam Zheng QTAILQ_FOREACH(e, &dso_init_list, node) {
19188d88798SMarc Mari e->init();
192e26110cfSFam Zheng register_module_init(e->init, e->type);
193e26110cfSFam Zheng }
194819b8b13SGerd Hoffmann trace_module_load_module(fname);
195e26110cfSFam Zheng QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) {
196e26110cfSFam Zheng QTAILQ_REMOVE(&dso_init_list, e, node);
197e26110cfSFam Zheng g_free(e);
198e26110cfSFam Zheng }
199c551fb0bSClaudio Fontana return true;
200e26110cfSFam Zheng }
201e26110cfSFam Zheng
module_load(const char * prefix,const char * name,Error ** errp)202c551fb0bSClaudio Fontana int module_load(const char *prefix, const char *name, Error **errp)
203e26110cfSFam Zheng {
204c551fb0bSClaudio Fontana int rv = -1;
205bd83c861SChristian Ehrhardt #ifdef CONFIG_MODULE_UPGRADES
206bd83c861SChristian Ehrhardt char *version_dir;
207bd83c861SChristian Ehrhardt #endif
208900610e6Sryang const char *search_dir;
209267514b3SBruce Rogers char *dirs[5];
210dffa41b4SFam Zheng char *module_name;
211900610e6Sryang int i = 0, n_dirs = 0;
2126f13fa7aSGerd Hoffmann bool export_symbols = false;
213dffa41b4SFam Zheng static GHashTable *loaded_modules;
214e897b9a7SGerd Hoffmann const QemuModinfo *modinfo;
215e897b9a7SGerd Hoffmann const char **sl;
216e26110cfSFam Zheng
217e26110cfSFam Zheng if (!g_module_supported()) {
218c551fb0bSClaudio Fontana error_setg(errp, "%s", "this platform does not support GLib modules");
219c551fb0bSClaudio Fontana return -1;
220e26110cfSFam Zheng }
221e26110cfSFam Zheng
222dffa41b4SFam Zheng if (!loaded_modules) {
223dffa41b4SFam Zheng loaded_modules = g_hash_table_new(g_str_hash, g_str_equal);
224dffa41b4SFam Zheng }
225dffa41b4SFam Zheng
226c551fb0bSClaudio Fontana /* allocate all resources managed by the out: label here */
227c551fb0bSClaudio Fontana module_name = g_strdup_printf("%s%s", prefix, name);
228dffa41b4SFam Zheng
22964e16fbbSMarc-André Lureau if (g_hash_table_contains(loaded_modules, module_name)) {
230dffa41b4SFam Zheng g_free(module_name);
231c551fb0bSClaudio Fontana return 2; /* module already loaded */
232dffa41b4SFam Zheng }
23364e16fbbSMarc-André Lureau g_hash_table_add(loaded_modules, module_name);
234dffa41b4SFam Zheng
235900610e6Sryang search_dir = getenv("QEMU_MODULE_DIR");
236900610e6Sryang if (search_dir != NULL) {
237900610e6Sryang dirs[n_dirs++] = g_strdup_printf("%s", search_dir);
238900610e6Sryang }
2391b934064SPaolo Bonzini dirs[n_dirs++] = get_relocated_path(CONFIG_QEMU_MODDIR);
240bd83c861SChristian Ehrhardt
241bd83c861SChristian Ehrhardt #ifdef CONFIG_MODULE_UPGRADES
242bd83c861SChristian Ehrhardt version_dir = g_strcanon(g_strdup(QEMU_PKGVERSION),
243bd83c861SChristian Ehrhardt G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "+-.~",
244bd83c861SChristian Ehrhardt '_');
245bd83c861SChristian Ehrhardt dirs[n_dirs++] = g_strdup_printf("/var/run/qemu/%s", version_dir);
246bd83c861SChristian Ehrhardt #endif
247900610e6Sryang assert(n_dirs <= ARRAY_SIZE(dirs));
248900610e6Sryang
249c551fb0bSClaudio Fontana /* end of resources managed by the out: label */
250c551fb0bSClaudio Fontana
251c551fb0bSClaudio Fontana for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
252c551fb0bSClaudio Fontana if (modinfo->arch) {
253c551fb0bSClaudio Fontana if (strcmp(modinfo->name, module_name) == 0) {
254c551fb0bSClaudio Fontana if (!module_check_arch(modinfo)) {
255c551fb0bSClaudio Fontana error_setg(errp, "module arch does not match: "
256c551fb0bSClaudio Fontana "expected '%s', got '%s'", module_arch, modinfo->arch);
257c551fb0bSClaudio Fontana goto out;
258c551fb0bSClaudio Fontana }
259c551fb0bSClaudio Fontana }
260c551fb0bSClaudio Fontana }
261c551fb0bSClaudio Fontana if (modinfo->deps) {
262c551fb0bSClaudio Fontana if (strcmp(modinfo->name, module_name) == 0) {
263c551fb0bSClaudio Fontana /* we depend on other module(s) */
264c551fb0bSClaudio Fontana for (sl = modinfo->deps; *sl != NULL; sl++) {
265c551fb0bSClaudio Fontana int subrv = module_load("", *sl, errp);
266c551fb0bSClaudio Fontana if (subrv <= 0) {
267c551fb0bSClaudio Fontana rv = subrv;
268c551fb0bSClaudio Fontana goto out;
269c551fb0bSClaudio Fontana }
270c551fb0bSClaudio Fontana }
271c551fb0bSClaudio Fontana } else {
272c551fb0bSClaudio Fontana for (sl = modinfo->deps; *sl != NULL; sl++) {
273c551fb0bSClaudio Fontana if (strcmp(module_name, *sl) == 0) {
274c551fb0bSClaudio Fontana /* another module depends on us */
275c551fb0bSClaudio Fontana export_symbols = true;
276c551fb0bSClaudio Fontana }
277c551fb0bSClaudio Fontana }
278c551fb0bSClaudio Fontana }
279e26110cfSFam Zheng }
280e26110cfSFam Zheng }
281e26110cfSFam Zheng
282c551fb0bSClaudio Fontana for (i = 0; i < n_dirs; i++) {
283c551fb0bSClaudio Fontana char *fname = g_strdup_printf("%s/%s%s",
284c551fb0bSClaudio Fontana dirs[i], module_name, CONFIG_HOST_DSOSUF);
285c551fb0bSClaudio Fontana int ret = access(fname, F_OK);
286c551fb0bSClaudio Fontana if (ret != 0 && (errno == ENOENT || errno == ENOTDIR)) {
287c551fb0bSClaudio Fontana /*
288c551fb0bSClaudio Fontana * if we don't find the module in this dir, try the next one.
289c551fb0bSClaudio Fontana * If we don't find it in any dir, that can be fine too: user
290c551fb0bSClaudio Fontana * did not install the module. We will return 0 in this case
291c551fb0bSClaudio Fontana * with no error set.
292c551fb0bSClaudio Fontana */
293c551fb0bSClaudio Fontana g_free(fname);
294c551fb0bSClaudio Fontana continue;
295c551fb0bSClaudio Fontana } else if (ret != 0) {
296c551fb0bSClaudio Fontana /* most common is EACCES here */
297c551fb0bSClaudio Fontana error_setg_errno(errp, errno, "error trying to access %s", fname);
298c551fb0bSClaudio Fontana } else if (module_load_dso(fname, export_symbols, errp)) {
299c551fb0bSClaudio Fontana rv = 1; /* module successfully loaded */
300c551fb0bSClaudio Fontana }
301c551fb0bSClaudio Fontana g_free(fname);
302c551fb0bSClaudio Fontana goto out;
303c551fb0bSClaudio Fontana }
304c551fb0bSClaudio Fontana rv = 0; /* module not found */
305c551fb0bSClaudio Fontana
306c551fb0bSClaudio Fontana out:
307c551fb0bSClaudio Fontana if (rv <= 0) {
30881d8ccb1SMarc-André Lureau g_hash_table_remove(loaded_modules, module_name);
309638be478SPan Nengyuan g_free(module_name);
31081d8ccb1SMarc-André Lureau }
311900610e6Sryang for (i = 0; i < n_dirs; i++) {
312e26110cfSFam Zheng g_free(dirs[i]);
313e26110cfSFam Zheng }
314c551fb0bSClaudio Fontana return rv;
315e26110cfSFam Zheng }
31628457744SGerd Hoffmann
31728457744SGerd Hoffmann static bool module_loaded_qom_all;
31828457744SGerd Hoffmann
module_load_qom(const char * type,Error ** errp)319c551fb0bSClaudio Fontana int module_load_qom(const char *type, Error **errp)
32028457744SGerd Hoffmann {
3219f4a0f09SGerd Hoffmann const QemuModinfo *modinfo;
3229f4a0f09SGerd Hoffmann const char **sl;
323c551fb0bSClaudio Fontana int rv = 0;
32428457744SGerd Hoffmann
325d87350b0SGerd Hoffmann if (!type) {
326c551fb0bSClaudio Fontana error_setg(errp, "%s", "type is NULL");
327c551fb0bSClaudio Fontana return -1;
328d87350b0SGerd Hoffmann }
3299f4a0f09SGerd Hoffmann
330819b8b13SGerd Hoffmann trace_module_lookup_object_type(type);
3319f4a0f09SGerd Hoffmann for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
3329f4a0f09SGerd Hoffmann if (!modinfo->objs) {
3339f4a0f09SGerd Hoffmann continue;
3349f4a0f09SGerd Hoffmann }
335ab0cfc3dSGerd Hoffmann if (!module_check_arch(modinfo)) {
336ab0cfc3dSGerd Hoffmann continue;
337ab0cfc3dSGerd Hoffmann }
3389f4a0f09SGerd Hoffmann for (sl = modinfo->objs; *sl != NULL; sl++) {
3399f4a0f09SGerd Hoffmann if (strcmp(type, *sl) == 0) {
340c551fb0bSClaudio Fontana if (rv > 0) {
341c551fb0bSClaudio Fontana error_setg(errp, "multiple modules providing '%s'", type);
342c551fb0bSClaudio Fontana return -1;
343c551fb0bSClaudio Fontana }
344c551fb0bSClaudio Fontana rv = module_load("", modinfo->name, errp);
345c551fb0bSClaudio Fontana if (rv < 0) {
346c551fb0bSClaudio Fontana return rv;
3479f4a0f09SGerd Hoffmann }
34828457744SGerd Hoffmann }
34928457744SGerd Hoffmann }
35028457744SGerd Hoffmann }
351c551fb0bSClaudio Fontana return rv;
352c551fb0bSClaudio Fontana }
35328457744SGerd Hoffmann
module_load_qom_all(void)35428457744SGerd Hoffmann void module_load_qom_all(void)
35528457744SGerd Hoffmann {
3569f4a0f09SGerd Hoffmann const QemuModinfo *modinfo;
35728457744SGerd Hoffmann
35828457744SGerd Hoffmann if (module_loaded_qom_all) {
35928457744SGerd Hoffmann return;
36028457744SGerd Hoffmann }
3619f4a0f09SGerd Hoffmann
3629f4a0f09SGerd Hoffmann for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
363*940d802bSAlexander Ivanov Error *local_err = NULL;
3649f4a0f09SGerd Hoffmann if (!modinfo->objs) {
36528457744SGerd Hoffmann continue;
36628457744SGerd Hoffmann }
367ab0cfc3dSGerd Hoffmann if (!module_check_arch(modinfo)) {
368ab0cfc3dSGerd Hoffmann continue;
369ab0cfc3dSGerd Hoffmann }
370c551fb0bSClaudio Fontana if (module_load("", modinfo->name, &local_err) < 0) {
371c551fb0bSClaudio Fontana error_report_err(local_err);
372c551fb0bSClaudio Fontana }
37328457744SGerd Hoffmann }
37428457744SGerd Hoffmann module_loaded_qom_all = true;
37528457744SGerd Hoffmann }
3769f4a0f09SGerd Hoffmann
qemu_load_module_for_opts(const char * group)3775111edafSGerd Hoffmann void qemu_load_module_for_opts(const char *group)
3785111edafSGerd Hoffmann {
3795111edafSGerd Hoffmann const QemuModinfo *modinfo;
3805111edafSGerd Hoffmann const char **sl;
3815111edafSGerd Hoffmann
3825111edafSGerd Hoffmann for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
3835111edafSGerd Hoffmann if (!modinfo->opts) {
3845111edafSGerd Hoffmann continue;
3855111edafSGerd Hoffmann }
3865111edafSGerd Hoffmann for (sl = modinfo->opts; *sl != NULL; sl++) {
3875111edafSGerd Hoffmann if (strcmp(group, *sl) == 0) {
388c551fb0bSClaudio Fontana Error *local_err = NULL;
389c551fb0bSClaudio Fontana if (module_load("", modinfo->name, &local_err) < 0) {
390c551fb0bSClaudio Fontana error_report_err(local_err);
391c551fb0bSClaudio Fontana }
3925111edafSGerd Hoffmann }
3935111edafSGerd Hoffmann }
3945111edafSGerd Hoffmann }
3955111edafSGerd Hoffmann }
3965111edafSGerd Hoffmann
3979f4a0f09SGerd Hoffmann #else
3989f4a0f09SGerd Hoffmann
module_allow_arch(const char * arch)399d7795d3cSGerd Hoffmann void module_allow_arch(const char *arch) {}
qemu_load_module_for_opts(const char * group)4005111edafSGerd Hoffmann void qemu_load_module_for_opts(const char *group) {}
module_load(const char * prefix,const char * name,Error ** errp)401c551fb0bSClaudio Fontana int module_load(const char *prefix, const char *name, Error **errp) { return 2; }
module_load_qom(const char * type,Error ** errp)402c551fb0bSClaudio Fontana int module_load_qom(const char *type, Error **errp) { return 2; }
module_load_qom_all(void)4039f4a0f09SGerd Hoffmann void module_load_qom_all(void) {}
4049f4a0f09SGerd Hoffmann
4059f4a0f09SGerd Hoffmann #endif
406