xref: /qemu/include/hw/xen/xen_backend_ops.h (revision 83ecdb18)
1 /*
2  * QEMU Xen backend support
3  *
4  * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5  *
6  * Authors: David Woodhouse <dwmw2@infradead.org>
7  *
8  * This work is licensed under the terms of the GNU GPL, version 2 or later.
9  * See the COPYING file in the top-level directory.
10  */
11 
12 #ifndef QEMU_XEN_BACKEND_OPS_H
13 #define QEMU_XEN_BACKEND_OPS_H
14 
15 #include "hw/xen/xen.h"
16 #include "hw/xen/interface/xen.h"
17 #include "hw/xen/interface/io/xenbus.h"
18 
19 /*
20  * For the time being, these operations map fairly closely to the API of
21  * the actual Xen libraries, e.g. libxenevtchn. As we complete the migration
22  * from XenLegacyDevice back ends to the new XenDevice model, they may
23  * evolve to slightly higher-level APIs.
24  *
25  * The internal emulations do not emulate the Xen APIs entirely faithfully;
26  * only enough to be used by the Xen backend devices. For example, only one
27  * event channel can be bound to each handle, since that's sufficient for
28  * the device support (only the true Xen HVM backend uses more). And the
29  * behaviour of unmask() and pending() is different too because the device
30  * backends don't care.
31  */
32 
33 typedef struct xenevtchn_handle xenevtchn_handle;
34 typedef int xenevtchn_port_or_error_t;
35 typedef uint32_t evtchn_port_t;
36 typedef uint16_t domid_t;
37 typedef uint32_t grant_ref_t;
38 
39 #define XEN_PAGE_SHIFT       12
40 #define XEN_PAGE_SIZE        (1UL << XEN_PAGE_SHIFT)
41 #define XEN_PAGE_MASK        (~(XEN_PAGE_SIZE - 1))
42 
43 #ifndef xen_rmb
44 #define xen_rmb() smp_rmb()
45 #endif
46 #ifndef xen_wmb
47 #define xen_wmb() smp_wmb()
48 #endif
49 #ifndef xen_mb
50 #define xen_mb() smp_mb()
51 #endif
52 
53 struct evtchn_backend_ops {
54     xenevtchn_handle *(*open)(void);
55     int (*bind_interdomain)(xenevtchn_handle *xc, uint32_t domid,
56                             evtchn_port_t guest_port);
57     int (*unbind)(xenevtchn_handle *xc, evtchn_port_t port);
58     int (*close)(struct xenevtchn_handle *xc);
59     int (*get_fd)(struct xenevtchn_handle *xc);
60     int (*notify)(struct xenevtchn_handle *xc, evtchn_port_t port);
61     int (*unmask)(struct xenevtchn_handle *xc, evtchn_port_t port);
62     int (*pending)(struct xenevtchn_handle *xc);
63 };
64 
65 extern struct evtchn_backend_ops *xen_evtchn_ops;
66 
67 static inline xenevtchn_handle *qemu_xen_evtchn_open(void)
68 {
69     if (!xen_evtchn_ops) {
70         return NULL;
71     }
72     return xen_evtchn_ops->open();
73 }
74 
75 static inline int qemu_xen_evtchn_bind_interdomain(xenevtchn_handle *xc,
76                                                    uint32_t domid,
77                                                    evtchn_port_t guest_port)
78 {
79     if (!xen_evtchn_ops) {
80         return -ENOSYS;
81     }
82     return xen_evtchn_ops->bind_interdomain(xc, domid, guest_port);
83 }
84 
85 static inline int qemu_xen_evtchn_unbind(xenevtchn_handle *xc,
86                                          evtchn_port_t port)
87 {
88     if (!xen_evtchn_ops) {
89         return -ENOSYS;
90     }
91     return xen_evtchn_ops->unbind(xc, port);
92 }
93 
94 static inline int qemu_xen_evtchn_close(xenevtchn_handle *xc)
95 {
96     if (!xen_evtchn_ops) {
97         return -ENOSYS;
98     }
99     return xen_evtchn_ops->close(xc);
100 }
101 
102 static inline int qemu_xen_evtchn_fd(xenevtchn_handle *xc)
103 {
104     if (!xen_evtchn_ops) {
105         return -ENOSYS;
106     }
107     return xen_evtchn_ops->get_fd(xc);
108 }
109 
110 static inline int qemu_xen_evtchn_notify(xenevtchn_handle *xc,
111                                          evtchn_port_t port)
112 {
113     if (!xen_evtchn_ops) {
114         return -ENOSYS;
115     }
116     return xen_evtchn_ops->notify(xc, port);
117 }
118 
119 static inline int qemu_xen_evtchn_unmask(xenevtchn_handle *xc,
120                                          evtchn_port_t port)
121 {
122     if (!xen_evtchn_ops) {
123         return -ENOSYS;
124     }
125     return xen_evtchn_ops->unmask(xc, port);
126 }
127 
128 static inline int qemu_xen_evtchn_pending(xenevtchn_handle *xc)
129 {
130     if (!xen_evtchn_ops) {
131         return -ENOSYS;
132     }
133     return xen_evtchn_ops->pending(xc);
134 }
135 
136 typedef struct xengntdev_handle xengnttab_handle;
137 
138 typedef struct XenGrantCopySegment {
139     union {
140         void *virt;
141         struct {
142             uint32_t ref;
143             off_t offset;
144         } foreign;
145     } source, dest;
146     size_t len;
147 } XenGrantCopySegment;
148 
149 #define XEN_GNTTAB_OP_FEATURE_MAP_MULTIPLE  (1U << 0)
150 
151 struct gnttab_backend_ops {
152     uint32_t features;
153     xengnttab_handle *(*open)(void);
154     int (*close)(xengnttab_handle *xgt);
155     int (*grant_copy)(xengnttab_handle *xgt, bool to_domain, uint32_t domid,
156                       XenGrantCopySegment *segs, uint32_t nr_segs,
157                       Error **errp);
158     int (*set_max_grants)(xengnttab_handle *xgt, uint32_t nr_grants);
159     void *(*map_refs)(xengnttab_handle *xgt, uint32_t count, uint32_t domid,
160                       uint32_t *refs, int prot);
161     int (*unmap)(xengnttab_handle *xgt, void *start_address, uint32_t *refs,
162                  uint32_t count);
163 };
164 
165 extern struct gnttab_backend_ops *xen_gnttab_ops;
166 
167 static inline bool qemu_xen_gnttab_can_map_multi(void)
168 {
169     return xen_gnttab_ops &&
170         !!(xen_gnttab_ops->features & XEN_GNTTAB_OP_FEATURE_MAP_MULTIPLE);
171 }
172 
173 static inline xengnttab_handle *qemu_xen_gnttab_open(void)
174 {
175     if (!xen_gnttab_ops) {
176         return NULL;
177     }
178     return xen_gnttab_ops->open();
179 }
180 
181 static inline int qemu_xen_gnttab_close(xengnttab_handle *xgt)
182 {
183     if (!xen_gnttab_ops) {
184         return -ENOSYS;
185     }
186     return xen_gnttab_ops->close(xgt);
187 }
188 
189 static inline int qemu_xen_gnttab_grant_copy(xengnttab_handle *xgt,
190                                              bool to_domain, uint32_t domid,
191                                              XenGrantCopySegment *segs,
192                                              uint32_t nr_segs, Error **errp)
193 {
194     if (!xen_gnttab_ops) {
195         return -ENOSYS;
196     }
197 
198     return xen_gnttab_ops->grant_copy(xgt, to_domain, domid, segs, nr_segs,
199                                       errp);
200 }
201 
202 static inline int qemu_xen_gnttab_set_max_grants(xengnttab_handle *xgt,
203                                                  uint32_t nr_grants)
204 {
205     if (!xen_gnttab_ops) {
206         return -ENOSYS;
207     }
208     return xen_gnttab_ops->set_max_grants(xgt, nr_grants);
209 }
210 
211 static inline void *qemu_xen_gnttab_map_refs(xengnttab_handle *xgt,
212                                              uint32_t count, uint32_t domid,
213                                              uint32_t *refs, int prot)
214 {
215     if (!xen_gnttab_ops) {
216         return NULL;
217     }
218     return xen_gnttab_ops->map_refs(xgt, count, domid, refs, prot);
219 }
220 
221 static inline int qemu_xen_gnttab_unmap(xengnttab_handle *xgt,
222                                         void *start_address, uint32_t *refs,
223                                         uint32_t count)
224 {
225     if (!xen_gnttab_ops) {
226         return -ENOSYS;
227     }
228     return xen_gnttab_ops->unmap(xgt, start_address, refs, count);
229 }
230 
231 struct foreignmem_backend_ops {
232     void *(*map)(uint32_t dom, void *addr, int prot, size_t pages,
233                  xen_pfn_t *pfns, int *errs);
234     int (*unmap)(void *addr, size_t pages);
235 };
236 
237 extern struct foreignmem_backend_ops *xen_foreignmem_ops;
238 
239 static inline void *qemu_xen_foreignmem_map(uint32_t dom, void *addr, int prot,
240                                             size_t pages, xen_pfn_t *pfns,
241                                             int *errs)
242 {
243     if (!xen_foreignmem_ops) {
244         return NULL;
245     }
246     return xen_foreignmem_ops->map(dom, addr, prot, pages, pfns, errs);
247 }
248 
249 static inline int qemu_xen_foreignmem_unmap(void *addr, size_t pages)
250 {
251     if (!xen_foreignmem_ops) {
252         return -ENOSYS;
253     }
254     return xen_foreignmem_ops->unmap(addr, pages);
255 }
256 
257 typedef void (*xs_watch_fn)(void *opaque, const char *path);
258 
259 struct qemu_xs_handle;
260 struct qemu_xs_watch;
261 typedef uint32_t xs_transaction_t;
262 
263 #define XBT_NULL 0
264 
265 #define XS_PERM_NONE  0x00
266 #define XS_PERM_READ  0x01
267 #define XS_PERM_WRITE 0x02
268 
269 struct xenstore_backend_ops {
270     struct qemu_xs_handle *(*open)(void);
271     void (*close)(struct qemu_xs_handle *h);
272     char *(*get_domain_path)(struct qemu_xs_handle *h, unsigned int domid);
273     char **(*directory)(struct qemu_xs_handle *h, xs_transaction_t t,
274                         const char *path, unsigned int *num);
275     void *(*read)(struct qemu_xs_handle *h, xs_transaction_t t,
276                   const char *path, unsigned int *len);
277     bool (*write)(struct qemu_xs_handle *h, xs_transaction_t t,
278                   const char *path, const void *data, unsigned int len);
279     bool (*create)(struct qemu_xs_handle *h, xs_transaction_t t,
280                    unsigned int owner, unsigned int domid,
281                    unsigned int perms, const char *path);
282     bool (*destroy)(struct qemu_xs_handle *h, xs_transaction_t t,
283                const char *path);
284     struct qemu_xs_watch *(*watch)(struct qemu_xs_handle *h, const char *path,
285                                    xs_watch_fn fn, void *opaque);
286     void (*unwatch)(struct qemu_xs_handle *h, struct qemu_xs_watch *w);
287     xs_transaction_t (*transaction_start)(struct qemu_xs_handle *h);
288     bool (*transaction_end)(struct qemu_xs_handle *h, xs_transaction_t t,
289                             bool abort);
290 };
291 
292 extern struct xenstore_backend_ops *xen_xenstore_ops;
293 
294 static inline struct qemu_xs_handle *qemu_xen_xs_open(void)
295 {
296     if (!xen_xenstore_ops) {
297         return NULL;
298     }
299     return xen_xenstore_ops->open();
300 }
301 
302 static inline void qemu_xen_xs_close(struct qemu_xs_handle *h)
303 {
304     if (!xen_xenstore_ops) {
305         return;
306     }
307     xen_xenstore_ops->close(h);
308 }
309 
310 static inline char *qemu_xen_xs_get_domain_path(struct qemu_xs_handle *h,
311                                                 unsigned int domid)
312 {
313     if (!xen_xenstore_ops) {
314         return NULL;
315     }
316     return xen_xenstore_ops->get_domain_path(h, domid);
317 }
318 
319 static inline char **qemu_xen_xs_directory(struct qemu_xs_handle *h,
320                                            xs_transaction_t t, const char *path,
321                                            unsigned int *num)
322 {
323     if (!xen_xenstore_ops) {
324         return NULL;
325     }
326     return xen_xenstore_ops->directory(h, t, path, num);
327 }
328 
329 static inline void *qemu_xen_xs_read(struct qemu_xs_handle *h,
330                                      xs_transaction_t t, const char *path,
331                                      unsigned int *len)
332 {
333     if (!xen_xenstore_ops) {
334         return NULL;
335     }
336     return xen_xenstore_ops->read(h, t, path, len);
337 }
338 
339 static inline bool qemu_xen_xs_write(struct qemu_xs_handle *h,
340                                      xs_transaction_t t, const char *path,
341                                      const void *data, unsigned int len)
342 {
343     if (!xen_xenstore_ops) {
344         return false;
345     }
346     return xen_xenstore_ops->write(h, t, path, data, len);
347 }
348 
349 static inline bool qemu_xen_xs_create(struct qemu_xs_handle *h,
350                                       xs_transaction_t t, unsigned int owner,
351                                       unsigned int domid, unsigned int perms,
352                                       const char *path)
353 {
354     if (!xen_xenstore_ops) {
355         return false;
356     }
357     return xen_xenstore_ops->create(h, t, owner, domid, perms, path);
358 }
359 
360 static inline bool qemu_xen_xs_destroy(struct qemu_xs_handle *h,
361                                        xs_transaction_t t, const char *path)
362 {
363     if (!xen_xenstore_ops) {
364         return false;
365     }
366     return xen_xenstore_ops->destroy(h, t, path);
367 }
368 
369 static inline struct qemu_xs_watch *qemu_xen_xs_watch(struct qemu_xs_handle *h,
370                                                       const char *path,
371                                                       xs_watch_fn fn,
372                                                       void *opaque)
373 {
374     if (!xen_xenstore_ops) {
375         return NULL;
376     }
377     return xen_xenstore_ops->watch(h, path, fn, opaque);
378 }
379 
380 static inline void qemu_xen_xs_unwatch(struct qemu_xs_handle *h,
381                                        struct qemu_xs_watch *w)
382 {
383     if (!xen_xenstore_ops) {
384         return;
385     }
386     xen_xenstore_ops->unwatch(h, w);
387 }
388 
389 static inline xs_transaction_t qemu_xen_xs_transaction_start(struct qemu_xs_handle *h)
390 {
391     if (!xen_xenstore_ops) {
392         return XBT_NULL;
393     }
394     return xen_xenstore_ops->transaction_start(h);
395 }
396 
397 static inline bool qemu_xen_xs_transaction_end(struct qemu_xs_handle *h,
398                                                xs_transaction_t t, bool abort)
399 {
400     if (!xen_xenstore_ops) {
401         return false;
402     }
403     return xen_xenstore_ops->transaction_end(h, t, abort);
404 }
405 
406 void setup_xen_backend_ops(void);
407 
408 #endif /* QEMU_XEN_BACKEND_OPS_H */
409