xref: /openbmc/qemu/hw/xen/xen-backend.c (revision 3e34860a3a03f969ad0720ec9c12ea10e88738a6)
1a783f8adSPaul Durrant /*
2a783f8adSPaul Durrant  * Copyright (c) 2018  Citrix Systems Inc.
3a783f8adSPaul Durrant  *
4a783f8adSPaul Durrant  * This work is licensed under the terms of the GNU GPL, version 2 or later.
5a783f8adSPaul Durrant  * See the COPYING file in the top-level directory.
6a783f8adSPaul Durrant  */
7a783f8adSPaul Durrant 
8a783f8adSPaul Durrant #include "qemu/osdep.h"
9a783f8adSPaul Durrant #include "qemu/error-report.h"
10a783f8adSPaul Durrant #include "qapi/error.h"
11a783f8adSPaul Durrant #include "hw/xen/xen-backend.h"
12a783f8adSPaul Durrant #include "hw/xen/xen-bus.h"
13a783f8adSPaul Durrant 
14a783f8adSPaul Durrant typedef struct XenBackendImpl {
15a783f8adSPaul Durrant     const char *type;
16a783f8adSPaul Durrant     XenBackendDeviceCreate create;
17a783f8adSPaul Durrant     XenBackendDeviceDestroy destroy;
18a783f8adSPaul Durrant } XenBackendImpl;
19a783f8adSPaul Durrant 
20a783f8adSPaul Durrant struct XenBackendInstance {
21a783f8adSPaul Durrant     QLIST_ENTRY(XenBackendInstance) entry;
22a783f8adSPaul Durrant     const XenBackendImpl *impl;
23a783f8adSPaul Durrant     XenBus *xenbus;
24a783f8adSPaul Durrant     char *name;
25a783f8adSPaul Durrant     XenDevice *xendev;
26a783f8adSPaul Durrant };
27a783f8adSPaul Durrant 
xen_backend_table_get(void)28a783f8adSPaul Durrant static GHashTable *xen_backend_table_get(void)
29a783f8adSPaul Durrant {
30a783f8adSPaul Durrant     static GHashTable *table;
31a783f8adSPaul Durrant 
32a783f8adSPaul Durrant     if (table == NULL) {
33a783f8adSPaul Durrant         table = g_hash_table_new(g_str_hash, g_str_equal);
34a783f8adSPaul Durrant     }
35a783f8adSPaul Durrant 
36a783f8adSPaul Durrant     return table;
37a783f8adSPaul Durrant }
38a783f8adSPaul Durrant 
xen_backend_table_add(XenBackendImpl * impl)39a783f8adSPaul Durrant static void xen_backend_table_add(XenBackendImpl *impl)
40a783f8adSPaul Durrant {
41a783f8adSPaul Durrant     g_hash_table_insert(xen_backend_table_get(), (void *)impl->type, impl);
42a783f8adSPaul Durrant }
43a783f8adSPaul Durrant 
xen_backend_table_keys(unsigned int * count)44c4583c8cSPaul Durrant static const char **xen_backend_table_keys(unsigned int *count)
45c4583c8cSPaul Durrant {
46c4583c8cSPaul Durrant     return (const char **)g_hash_table_get_keys_as_array(
47c4583c8cSPaul Durrant         xen_backend_table_get(), count);
48c4583c8cSPaul Durrant }
49c4583c8cSPaul Durrant 
xen_backend_table_lookup(const char * type)50a783f8adSPaul Durrant static const XenBackendImpl *xen_backend_table_lookup(const char *type)
51a783f8adSPaul Durrant {
52a783f8adSPaul Durrant     return g_hash_table_lookup(xen_backend_table_get(), type);
53a783f8adSPaul Durrant }
54a783f8adSPaul Durrant 
xen_backend_register(const XenBackendInfo * info)55a783f8adSPaul Durrant void xen_backend_register(const XenBackendInfo *info)
56a783f8adSPaul Durrant {
57a783f8adSPaul Durrant     XenBackendImpl *impl = g_new0(XenBackendImpl, 1);
58a783f8adSPaul Durrant 
59a783f8adSPaul Durrant     g_assert(info->type);
60a783f8adSPaul Durrant 
61a783f8adSPaul Durrant     if (xen_backend_table_lookup(info->type)) {
62a783f8adSPaul Durrant         error_report("attempt to register duplicate Xen backend type '%s'",
63a783f8adSPaul Durrant                      info->type);
64a783f8adSPaul Durrant         abort();
65a783f8adSPaul Durrant     }
66a783f8adSPaul Durrant 
67a783f8adSPaul Durrant     if (!info->create) {
68a783f8adSPaul Durrant         error_report("backend type '%s' has no creator", info->type);
69a783f8adSPaul Durrant         abort();
70a783f8adSPaul Durrant     }
71a783f8adSPaul Durrant 
72a783f8adSPaul Durrant     impl->type = info->type;
73a783f8adSPaul Durrant     impl->create = info->create;
74a783f8adSPaul Durrant     impl->destroy = info->destroy;
75a783f8adSPaul Durrant 
76a783f8adSPaul Durrant     xen_backend_table_add(impl);
77a783f8adSPaul Durrant }
78a783f8adSPaul Durrant 
xen_backend_get_types(unsigned int * count)79c4583c8cSPaul Durrant const char **xen_backend_get_types(unsigned int *count)
80c4583c8cSPaul Durrant {
81c4583c8cSPaul Durrant     return xen_backend_table_keys(count);
82c4583c8cSPaul Durrant }
83c4583c8cSPaul Durrant 
84a783f8adSPaul Durrant static QLIST_HEAD(, XenBackendInstance) backend_list;
85a783f8adSPaul Durrant 
xen_backend_list_add(XenBackendInstance * backend)86a783f8adSPaul Durrant static void xen_backend_list_add(XenBackendInstance *backend)
87a783f8adSPaul Durrant {
88a783f8adSPaul Durrant     QLIST_INSERT_HEAD(&backend_list, backend, entry);
89a783f8adSPaul Durrant }
90a783f8adSPaul Durrant 
xen_backend_list_find(XenDevice * xendev)91a783f8adSPaul Durrant static XenBackendInstance *xen_backend_list_find(XenDevice *xendev)
92a783f8adSPaul Durrant {
93a783f8adSPaul Durrant     XenBackendInstance *backend;
94a783f8adSPaul Durrant 
95a783f8adSPaul Durrant     QLIST_FOREACH(backend, &backend_list, entry) {
96a783f8adSPaul Durrant         if (backend->xendev == xendev) {
97a783f8adSPaul Durrant             return backend;
98a783f8adSPaul Durrant         }
99a783f8adSPaul Durrant     }
100a783f8adSPaul Durrant 
101a783f8adSPaul Durrant     return NULL;
102a783f8adSPaul Durrant }
103a783f8adSPaul Durrant 
xen_backend_exists(const char * type,const char * name)104*eb6ae7a6SDavid Woodhouse bool xen_backend_exists(const char *type, const char *name)
105*eb6ae7a6SDavid Woodhouse {
106*eb6ae7a6SDavid Woodhouse     const XenBackendImpl *impl = xen_backend_table_lookup(type);
107*eb6ae7a6SDavid Woodhouse     XenBackendInstance *backend;
108*eb6ae7a6SDavid Woodhouse 
109*eb6ae7a6SDavid Woodhouse     if (!impl) {
110*eb6ae7a6SDavid Woodhouse         return false;
111*eb6ae7a6SDavid Woodhouse     }
112*eb6ae7a6SDavid Woodhouse 
113*eb6ae7a6SDavid Woodhouse     QLIST_FOREACH(backend, &backend_list, entry) {
114*eb6ae7a6SDavid Woodhouse         if (backend->impl == impl && !strcmp(backend->name, name)) {
115*eb6ae7a6SDavid Woodhouse             return true;
116*eb6ae7a6SDavid Woodhouse         }
117*eb6ae7a6SDavid Woodhouse     }
118*eb6ae7a6SDavid Woodhouse 
119*eb6ae7a6SDavid Woodhouse     return false;
120*eb6ae7a6SDavid Woodhouse }
121*eb6ae7a6SDavid Woodhouse 
xen_backend_list_remove(XenBackendInstance * backend)122a783f8adSPaul Durrant static void xen_backend_list_remove(XenBackendInstance *backend)
123a783f8adSPaul Durrant {
124a783f8adSPaul Durrant     QLIST_REMOVE(backend, entry);
125a783f8adSPaul Durrant }
126a783f8adSPaul Durrant 
xen_backend_device_create(XenBus * xenbus,const char * type,const char * name,QDict * opts,Error ** errp)127a783f8adSPaul Durrant void xen_backend_device_create(XenBus *xenbus, const char *type,
128a783f8adSPaul Durrant                                const char *name, QDict *opts, Error **errp)
129a783f8adSPaul Durrant {
1301de7096dSVladimir Sementsov-Ogievskiy     ERRP_GUARD();
131a783f8adSPaul Durrant     const XenBackendImpl *impl = xen_backend_table_lookup(type);
132a783f8adSPaul Durrant     XenBackendInstance *backend;
133a783f8adSPaul Durrant 
134a783f8adSPaul Durrant     if (!impl) {
135a783f8adSPaul Durrant         return;
136a783f8adSPaul Durrant     }
137a783f8adSPaul Durrant 
138a783f8adSPaul Durrant     backend = g_new0(XenBackendInstance, 1);
139a783f8adSPaul Durrant     backend->xenbus = xenbus;
140a783f8adSPaul Durrant     backend->name = g_strdup(name);
141a783f8adSPaul Durrant 
1421de7096dSVladimir Sementsov-Ogievskiy     impl->create(backend, opts, errp);
143a783f8adSPaul Durrant 
144a783f8adSPaul Durrant     backend->impl = impl;
145a783f8adSPaul Durrant     xen_backend_list_add(backend);
146a783f8adSPaul Durrant }
147a783f8adSPaul Durrant 
xen_backend_get_bus(XenBackendInstance * backend)148a783f8adSPaul Durrant XenBus *xen_backend_get_bus(XenBackendInstance *backend)
149a783f8adSPaul Durrant {
150a783f8adSPaul Durrant     return backend->xenbus;
151a783f8adSPaul Durrant }
152a783f8adSPaul Durrant 
xen_backend_get_name(XenBackendInstance * backend)153a783f8adSPaul Durrant const char *xen_backend_get_name(XenBackendInstance *backend)
154a783f8adSPaul Durrant {
155a783f8adSPaul Durrant     return backend->name;
156a783f8adSPaul Durrant }
157a783f8adSPaul Durrant 
xen_backend_set_device(XenBackendInstance * backend,XenDevice * xendev)158a783f8adSPaul Durrant void xen_backend_set_device(XenBackendInstance *backend,
159a783f8adSPaul Durrant                             XenDevice *xendev)
160a783f8adSPaul Durrant {
161a783f8adSPaul Durrant     g_assert(!backend->xendev);
162a783f8adSPaul Durrant     backend->xendev = xendev;
163a783f8adSPaul Durrant }
164a783f8adSPaul Durrant 
xen_backend_get_device(XenBackendInstance * backend)165a783f8adSPaul Durrant XenDevice *xen_backend_get_device(XenBackendInstance *backend)
166a783f8adSPaul Durrant {
167a783f8adSPaul Durrant     return backend->xendev;
168a783f8adSPaul Durrant }
169a783f8adSPaul Durrant 
170a783f8adSPaul Durrant 
xen_backend_try_device_destroy(XenDevice * xendev,Error ** errp)171a783f8adSPaul Durrant bool xen_backend_try_device_destroy(XenDevice *xendev, Error **errp)
172a783f8adSPaul Durrant {
173a783f8adSPaul Durrant     XenBackendInstance *backend = xen_backend_list_find(xendev);
174a783f8adSPaul Durrant     const XenBackendImpl *impl;
175a783f8adSPaul Durrant 
176a783f8adSPaul Durrant     if (!backend) {
177a783f8adSPaul Durrant         return false;
178a783f8adSPaul Durrant     }
179a783f8adSPaul Durrant 
180a783f8adSPaul Durrant     impl = backend->impl;
181*eb6ae7a6SDavid Woodhouse     if (backend->xendev) {
182a783f8adSPaul Durrant         impl->destroy(backend, errp);
183*eb6ae7a6SDavid Woodhouse     }
184a783f8adSPaul Durrant 
185a783f8adSPaul Durrant     xen_backend_list_remove(backend);
186a783f8adSPaul Durrant     g_free(backend->name);
187a783f8adSPaul Durrant     g_free(backend);
188a783f8adSPaul Durrant 
189a783f8adSPaul Durrant     return true;
190a783f8adSPaul Durrant }
191