1 /*
2 * Setup VirtIO backend. This is intended to interact with a VirtIO
3 * backend that is watching xenstore, and create new VirtIO devices
4 * with the parameter found in xenstore (VirtIO frontend don't
5 * interact with xenstore.)
6 *
7 * Copyright (C) 2022 Linaro Ltd.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; version 2.1 only. with the special
12 * exception on linking described in file LICENSE.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
18 */
19
20 #include "libxl_internal.h"
21
libxl__device_virtio_setdefault(libxl__gc * gc,uint32_t domid,libxl_device_virtio * virtio,bool hotplug)22 static int libxl__device_virtio_setdefault(libxl__gc *gc, uint32_t domid,
23 libxl_device_virtio *virtio,
24 bool hotplug)
25 {
26 int rc;
27
28 rc = libxl__resolve_domid(gc, virtio->backend_domname,
29 &virtio->backend_domid);
30 if (rc < 0) return rc;
31
32 libxl_defbool_setdefault(&virtio->grant_usage,
33 virtio->backend_domid != LIBXL_TOOLSTACK_DOMID);
34
35 return 0;
36 }
37
libxl__device_from_virtio(libxl__gc * gc,uint32_t domid,libxl_device_virtio * virtio,libxl__device * device)38 static int libxl__device_from_virtio(libxl__gc *gc, uint32_t domid,
39 libxl_device_virtio *virtio,
40 libxl__device *device)
41 {
42 device->backend_devid = virtio->devid;
43 device->backend_domid = virtio->backend_domid;
44 device->devid = virtio->devid;
45 device->domid = domid;
46
47 device->backend_kind = LIBXL__DEVICE_KIND_VIRTIO;
48 device->kind = LIBXL__DEVICE_KIND_VIRTIO;
49
50 return 0;
51 }
52
libxl__set_xenstore_virtio(libxl__gc * gc,uint32_t domid,libxl_device_virtio * virtio,flexarray_t * back,flexarray_t * front,flexarray_t * ro_front)53 static int libxl__set_xenstore_virtio(libxl__gc *gc, uint32_t domid,
54 libxl_device_virtio *virtio,
55 flexarray_t *back, flexarray_t *front,
56 flexarray_t *ro_front)
57 {
58 const char *transport = libxl_virtio_transport_to_string(virtio->transport);
59
60 flexarray_append_pair(back, "irq", GCSPRINTF("%u", virtio->irq));
61 flexarray_append_pair(back, "base", GCSPRINTF("%#"PRIx64, virtio->base));
62 flexarray_append_pair(back, "type", GCSPRINTF("%s", virtio->type));
63 flexarray_append_pair(back, "transport", GCSPRINTF("%s", transport));
64 flexarray_append_pair(back, "grant_usage",
65 libxl_defbool_val(virtio->grant_usage) ? "1" : "0");
66
67 return 0;
68 }
69
libxl__virtio_from_xenstore(libxl__gc * gc,const char * libxl_path,libxl_devid devid,libxl_device_virtio * virtio)70 static int libxl__virtio_from_xenstore(libxl__gc *gc, const char *libxl_path,
71 libxl_devid devid,
72 libxl_device_virtio *virtio)
73 {
74 const char *be_path, *tmp = NULL;
75 int rc;
76
77 virtio->devid = devid;
78
79 rc = libxl__xs_read_mandatory(gc, XBT_NULL,
80 GCSPRINTF("%s/backend", libxl_path),
81 &be_path);
82 if (rc) goto out;
83
84 rc = libxl__backendpath_parse_domid(gc, be_path, &virtio->backend_domid);
85 if (rc) goto out;
86
87 rc = libxl__xs_read_checked(gc, XBT_NULL,
88 GCSPRINTF("%s/irq", be_path), &tmp);
89 if (rc) goto out;
90
91 if (tmp) {
92 virtio->irq = strtoul(tmp, NULL, 0);
93 }
94
95 tmp = NULL;
96 rc = libxl__xs_read_checked(gc, XBT_NULL,
97 GCSPRINTF("%s/base", be_path), &tmp);
98 if (rc) goto out;
99
100 if (tmp) {
101 virtio->base = strtoul(tmp, NULL, 0);
102 }
103
104 tmp = NULL;
105 rc = libxl__xs_read_checked(gc, XBT_NULL,
106 GCSPRINTF("%s/transport", be_path), &tmp);
107 if (rc) goto out;
108
109 if (tmp) {
110 if (!strcmp(tmp, "mmio")) {
111 virtio->transport = LIBXL_VIRTIO_TRANSPORT_MMIO;
112 } else {
113 return ERROR_INVAL;
114 }
115 }
116
117 tmp = NULL;
118 rc = libxl__xs_read_checked(gc, XBT_NULL,
119 GCSPRINTF("%s/grant_usage", be_path), &tmp);
120 if (rc) goto out;
121
122 if (tmp) {
123 libxl_defbool_set(&virtio->grant_usage, strtoul(tmp, NULL, 0));
124 }
125
126 tmp = NULL;
127 rc = libxl__xs_read_checked(gc, XBT_NULL,
128 GCSPRINTF("%s/type", be_path), &tmp);
129 if (rc) goto out;
130
131 if (tmp) {
132 int len = sizeof(VIRTIO_DEVICE_TYPE_GENERIC) - 1;
133
134 if (!strncmp(tmp, VIRTIO_DEVICE_TYPE_GENERIC, len)) {
135 virtio->type = libxl__strdup(NOGC, tmp);
136 } else {
137 return ERROR_INVAL;
138 }
139 }
140
141 out:
142 return rc;
143 }
144
145 static LIBXL_DEFINE_UPDATE_DEVID(virtio)
146
147 #define libxl__add_virtios NULL
148 #define libxl_device_virtio_compare NULL
149
150 DEFINE_DEVICE_TYPE_STRUCT(virtio, VIRTIO, virtios,
151 .set_xenstore_config = (device_set_xenstore_config_fn_t)
152 libxl__set_xenstore_virtio,
153 .from_xenstore = (device_from_xenstore_fn_t)libxl__virtio_from_xenstore,
154 .skip_attach = 1
155 );
156
157 /*
158 * Local variables:
159 * mode: C
160 * c-basic-offset: 4
161 * indent-tabs-mode: nil
162 * End:
163 */
164