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